ID:1240403
 
(See the best response by Albro1.)
Code:
mob
var/tmp/Beaming = 0
Move(NewLoc, Dir)
if(!Beaming) return ..()
dir = Dir

/*

Ki Types: Blast, Beam, Blast Charge (Just Charge)

Beam: RP Pause required for attacking players
Blast: Makes use of targeting
Blast Charge: Immobilizes user & Makes them less responsive to attacks


--- Blast ---
Blast: If targeting, a special *semi-homing behavior is used
* Blasts home in if the target is within a range of directions relative to itself
1. Target is North of Blast: Home
2. Target is East of Blast: Home
3. Target is Southeast of Blast: Trail away, Homing breaks
4. Target is South of Blast: Trail away, Homing breaks

Deflection: 50 * ((Attacker.BP * Attacker.Accuracy) / (BP * Agility))
Reflection: 50 * (((Attacker.BP * Attacker.Accuracy) / (BP * Agility)) / 1.25)

Refire: 1 per sec (Mastered)
Damage: max(0, (Attacker.BP * Attacker.Strength) / (BP * Durability) / 5)


*/


Projectile
parent_type = /obj
density = 0
Grabbable = 0
Attackable = 0

proc
position(mob/m, s = 16)
loc = m.loc
dir = m.dir
var x = m.step_x, y = m.step_y
if(m.dir & NORTH) y += s
if(m.dir & SOUTH) y -= s
if(m.dir & WEST) x -= s
if(m.dir & EAST) x += s
step_x = x
step_y = y

collide()
// expand later

Bump(atom/a)
..(a)
collide(a)

Blast
step_size = 32
Standing = 1
bound_x = 11
bound_y = 12
bound_width = 11
bound_height = 7
icon = 'Blast1.dmi'

New(mob/ref)
if(!ismob(ref)) del src
..(ref)
position(ref)
life()

Move()
..()
if(dir & NORTH) if(y == world.maxy) del src
if(dir & SOUTH) if(y == 1) del src
if(dir & WEST) if(x == 1) del src
if(dir & EAST) if(x == world.maxx) del src

collide(atom/a)
// damage stuff
del src

proc
life()
for()
sleep(1)
step(src, src.dir)


Beam
step_size = 32
icon = 'Beam1.dmi'
icon_state = "Body"
var Projectile/Beam/childobject
var obj/Skills/Beam/creator

New(l, obj/Skills/Beam/s)
..(l)
creator = s

collide()
if((creator.head == src) && childobject)
childobject.make_head()
del src

proc
add_link(hcreator)
var Projectile/Beam/tl = src
while(tl.childobject) tl = tl.childobject
var Projectile/Beam/b = new(tl.loc, hcreator)
b.icon_state = "Tail"
tl.childobject = b
b.step_x = tl.step_x
b.step_y = tl.step_y
tl.icon_state = "Body"

make_head()
icon_state = "Head"
spawn() head_life()

head_life()
while(src)
sleep(1)
step(src, dir)
if(creator.beaming) add_link(creator)

Move()
var oloc = loc
. = ..()
if(childobject && .) childobject.Move(oloc)
if(!childobject) icon_state = "Tail"


Charge

obj
Skills
Blast
Mastery = 1
var
Mastery_P = 1
Click()
usr.blast()

Beam
var
beaming = 0
Projectile/Beam/head
Click()
usr.beam(src)

Charge // later defined

Explosion // later

mob
proc

blast()
new /Projectile/Blast(src)

beam(obj/Skills/Beam/b)
if(!b) return
if(b.beaming) b.beaming = 0
else
b.beaming = 1
spawn() beaming(b)

beaming(obj/Skills/Beam/b)
b.head = new /Projectile/Beam(src, b)
b.head.position(src, 32)
spawn() b.head.head_life()
while(b.beaming)
sleep(1)
// do stuff


Problem description:

Well, I coded up a little Projectile setup, and in the end it ultimately ended up having issues. Some issues it has are the head not showing up in the right place (shows at the tail until you release the beam, in which case it turns into a tail).

Sometimes it loses it's alignment, and furthermore it faces the wrong direction in some cases.

I'm less looking for a, "you did this wrong", and more looking for some better logic behind putting this all together, since it's getting increasingly complicated, when it seems like it doesn't need to be.

Best response
You aren't calling position() in Beam/New().

Also, here's a problem that causes your head object to not be the right icon state:
add_link(hcreator)
var Projectile/Beam/tl = src
while(tl.childobject) tl = tl.childobject
var Projectile/Beam/b = new(tl.loc, hcreator)
b.icon_state = "Tail"
tl.childobject = b
b.step_x = tl.step_x
b.step_y = tl.step_y
tl.icon_state = "Body"


Specifically, this line:
tl.icon_state = "Body"


Following this code, the head tile will stay as tl (Because it doesn't have a childobject). Just add a check to make sure tl isn't src.
In response to Albro1
Hey, good catch on that last bit. The position part works better if I add it there. I still end up with some odd things though, meaning the position. Also, I end up with like 30 beam objects that bug up and get stuck in front of the shooter, haha.

Here's the modification:

        New(l, obj/Skills/Beam/s)
..(l)
creator = s
var mob/m = s.loc
if(ismob(m)) position(m, 32)

---

proc
add_link(hcreator)
var Projectile/Beam/tl = src
while(tl.childobject) tl = tl.childobject
var Projectile/Beam/b = new(tl.loc, hcreator)
b.icon_state = "Tail"
tl.childobject = b
if(tl != src) tl.icon_state = "Body"
After a lot of fiddling, I decided that linked object approach isn't worth the effort and ditched it. With the new way I still have some bugs, primarily the tail almost never changing into the body, and the head sometimes not appearing, it seems to be primarily when travelling East, sometimes North. West almost always has the head oddly enough.

Here's the code;

Projectile
parent_type = /obj
density = 0
Grabbable = 0
Attackable = 0
// copy stats
var
BP = 0
Strength = 0
Ki = 0
Accuracy = 0
Agility = 0
maker



proc
position(atom/movable/m, s = 16)
loc = m.loc
dir = m.dir
var x = m.step_x, y = m.step_y
if(m.dir & NORTH) y += s
if(m.dir & SOUTH) y -= s
if(m.dir & WEST) x -= s
if(m.dir & EAST) x += s
step_x = x
step_y = y

collide()


set_vars(mob/c)
BP = c.BP
Strength = c.Strength
Ki = c.Ki
Accuracy = c.Accuracy
Agility = c.Agility
maker = c.real_name

life()

Cross(atom/a)
. = ..(a)
if(istype(a, /Projectile/Blast))
var Projectile/Blast/b = a
// if(b.dir != dir) return 0
if(b.maker == maker) return 1

Move()
. = ..()
if(dir & NORTH) if(y == world.maxy) del src
if(dir & SOUTH) if(y == 1) del src
if(dir & WEST) if(x == 1) del src
if(dir & EAST) if(x == world.maxx) del src

Bump(atom/a)
..(a)
collide(a)

Beam
step_size = 32
icon = 'Beam1.dmi'
icon_state = "Tail"

New(l, obj/Skills/Beam/s)
..(l)
var mob/m = s.loc
dir = m.dir
maker = m.key
if(ismob(m)) position(m, 32)
set_vars(m)
spawn() life()

Cross(atom/a)
var Projectile/Beam/b
if(istype(a, /Projectile/Beam)) b = a
if(b.maker == maker && icon_state == "Tail") icon_state = "Body"
. = ..(a)


collide(atom/a)
if(istype(a, /Projectile/Beam))
var Projectile/Beam/b = a
if(a.dir != dir) del src
if(b.maker == maker) return
// inset damage instructions
del src


life()
walk(src, dir, 1)


Move()
. = ..()
var turf/t = get_step(src, dir)
var r = 0
for(var/Projectile/Beam/b in t)
r++
break
if(!r) icon_state = "Head"

-----

mob

var/tmp/Beaming = 0
Move(NewLoc, Dir)
if(!Beaming) return ..()
dir = Dir

proc

beam(obj/Skills/Beam/b)
if(!b) return
b.beaming = !b.beaming
if(b.beaming) spawn() beaming(b)

beaming(obj/Skills/Beam/b)
while(b.beaming)
new /Projectile/Beam/(src, b)
sleep(1)


Any ideas whats wrong with the logic here?
One thing I noticed is the density;you would need both to be dense in order to bump into one another.
Try using Cross() instead of Bump()
oh crap, i forgot to make these dense, lmfao.

Anyhow, all the actual icon modifications happen in Move() and Cross(), what did you have in mind?