ID:2396792
 
Code:
    testprojectile
icon = 'test.dmi'
density = 1
step_size = 16
Bump(atom/A)
if(istype(A,/mob))
var/mob/D = A
loc = D.loc //make it pierce
if(istype(D,/mob/combative))
//damage stuff here
if(istype(A,/turf))
var/turf/T = A
if(T.density)
object_pool(0)
if(istype(A,/obj))
var/obj/T = A
if(T.density)
ProjectileBump(T)


Problem description:

I'm using pixel movement.

I'm trying to make projectiles able to pierce and remain along their original trajectory. When I do loc=D.loc, it moves the projectile off it's original trajectory, but continues moving. Is there a way to keep it on it's same position relative to it's position on a tile and have it also pass through dense atoms?
You probably want to ditch density and move from Bump() to Crossed() and Cross(), which are far, far more useful, especially in pixel movement situations.
:O

I can use those for all my collisions?
You'll want to handle both the projectile hitting something and something hitting the projectile, but yes, they're quite useful for collision handling.
If A is a projectile, and B is a player the projectile would hit, how would we go about doing this?

I would put Crossed() under the player?

Sorry, I've never used Crossed() or Cross() for collisions
You'd probably want it under both, actually. Crossed() is called when something overlaps something else through Move().

So if the player runs into the projectile you'd be handling that in the player's Crossed(), if the projectile hits the player it would be handled under the projectile's Crossed().

You'd probably want to generalize that into something like a Hit() proc or something that gets called by both instances, and maybe keep track of who has been hit by the projectile so you don't get cases where both Crossed() calls fire (which is possible).

projectile
Crossed(atom/A)
world << "[A] has crossed [src]"

player
Crossed(atom/A)
world << "[A] has crossed [src]"


As a simple way to see what's happening where.
I have several hundred different projectiles coded. I'd have to account for all of them under Crossed()?
Not if you programmed them properly and they're all under a single parent type.

projectile
proc/Hit(mob/M)
M << "You have been hit by [src]!"

Crossed(atom/A)
if(ismob(A)) Hit(A)

mob/player
Crossed(atom/A)
if(istype(A,/projectile))
var/projectile/projectile = A
projectile.Hit(src)


Then you'd have your projectiles setup like

projectile
one
two
three


And if you need special stuff to happen inside of an individual child's Hit()

projectile
one
two
Hit(mob/M)
M << "Two is special!"
..()
three

I smell a lot of work ahead of me. Bring it on!

Thanks for the response, I'll likely run into issues, so I'll probably be back here asking for more help :P
Is it necessary to have Crossed() on the projectile as well? Because if the player and the projectile are running at each other, isn't it possible that two Hit()s will occur?
Is it necessary to have Crossed() on the projectile as well? Because if the player and the projectile are running at each other, isn't it possible that two Hit()s will occur?

Yes to both. Duplicate hits and entry denial is something you need to implement yourself.

...If I may, I often recommend the implementation of a low-level reciprocal to Cross/Crossed/Uncross/Uncrossed hooks.

This directly makes implementing this kind of system much less painful.