Once again, I am stuck. What's the best way to handle projectile collisions if you have more than one type of enemy? Most of the freely available scripts I've seen assign a hitbox to each enemy but only have one type of enemy. Charbile's Hatful Adventure uses slicecollide, NPC refs and global IDs to see which enemy was hit, which I understand, but seems slightly more convoluted.
EDIT: I should add, since my game is based on sniping monsters, I'm not convinced I actually need more than one monster on the map at once, if that makes a difference.
Monster/NPC collisions
Moderators: marionline, SDHawk
- Bob the Hamster
- Lord of the Slimes
- Posts: 7741
- Joined: Tue Oct 16, 2007 2:34 pm
- Location: Hamster Republic (Ontario Enclave)
- Contact:
Re: Monster/NPC collisions
It might help to share some of your current projectile collision script.
It sounds like you already have something that works for a single enemy type, and want to extend it without overcomplicating it
It sounds like you already have something that works for a single enemy type, and want to extend it without overcomplicating it
-
Bluefeather42
- Slime Knight
- Posts: 115
- Joined: Fri Jan 13, 2023 1:13 am
Re: Monster/NPC collisions
I've been away from this project for a couple months, so I threw in some of the code from CHA to try out. It technically works. The arrow hits the monster, both the arrow and the monster are deleted, but I get a script error since projectileeachtick is still trying to run. I'm guessing I'll have to change the projectile code a little more or I've got some dumb error I've missed.
Code: Select all
define constant(12345, sli:dataslice)
include,globvar.hss
include,util.hss
################################################################################
# Projectiles - From the OHRRPGCE wiki. Modified by removing the "arc" functionality.
# Start a new projectile on an arcing path.
# Speed is the ground speed in pixels per tick.
# x distance and y distance is how far you want to shoot the projectile, relative
# to the initial position (like "move slice by").
# z distance is used when shooting at a target with a different height, e.g. aiming
# at the top of a tree or up a cliff. Positive z distance means shooting upwards
script, fire projectile, slice, speed, x distance, y distance, begin
variable(dist, time)
dist := sqrt(xdistance ^ 2 + ydistance ^ 2)
# Calculate time-in-air, in ticks
time := (dist + speed / 2) / speed
if (time <= 0) then (time := 1)
# Save some other necessary data
prj:x100 := slicex(slice) * 100
prj:y100 := slicey(slice) * 100
prj:v_x100 := xdistance * 100 / time
prj:v_y100 := ydistance * 100 / time
prj:time := time
save projectile data(create data slice(slice))
end
# Update the position of a projectile slice. Needs to be called every tick.
# Returns true if still in flight, or false if the projectile has reached the end.
script, projectile eachtick, slice, begin
variable(dataslice, hit)
dataslice := lookup slice(sli:dataslice, slice)
if (dataslice == false) then (script error($99="Couldn't find projectile data slice"))
load projectile data(dataslice)
if (prj:time <= 0) then (exit returning(false)) # Already finished
prj:time -= 1
prj:x100 += prj:v_x100
prj:y100 += prj:v_y100
save projectile data(dataslice)
# Add 50 to round to nearest pixel
put slice(slice, (prj:x100 + 50) / 100, (prj:y100 + 50) / 100)
return (prj:time > 0)
variable(j)
for(j, 0, findCollidingSlice(lookupSlice(sl:walkaboutLayer), slice, getCount, false, true)--1) do(
hit := findCollidingSlice(lookupSlice(sl:walkaboutLayer), slice, j, false, true)
if(npcReferenceFromSlice(hit) && getNPCPool(npcReferenceFromSlice(hit)) == pool:global) then(
# Damage enemy/npc
damagecritter(npcReferenceFromSlice(hit))
freeSlice(slice)
exitScript()
)
)
end
# Set this to the correct map layer, above the hero
define constant(sl:map layer4, projectile layer)
define constant(80, arrow distance)
script, vecX, dir, dist, begin
switch (dir) do (
case (up, down) do (return (0))
case (right) do (return (dist))
case (left) do (return (-1 * dist))
)
end
script, vecY, dir, dist, begin
switch (dir) do (
case (left, right) do (return (0))
case (down) do (return (dist))
case (up) do (return (-1 * dist))
)
end
################################################################################
# Here is one way to run the scripts above: by using a timer.
# Each projectile in the air will need a different timer and a different global variable.
defineconstant(1000, sli:projectile)
defineconstant(15, timer:arrow1)
globalvariable(1, arrow1)
globalvariable(2, canshoot)
script, fire arrow1, begin
set timer(4, 1, 8, set hero picture (0, 0))
arrow1 := load walkabout sprite(2)
setparent(arrow1, lookupslice(projectile layer))
put slice(arrow1, heropixelx, heropixely)
if (hero direction(0) == 0) then (
set sprite frame(arrow1, 1)
) else if (hero direction(0) == 1) then (
set sprite frame(arrow1, 3)
) else if (hero direction(0) == 2) then (
set sprite frame(arrow1, 5)
) else (
set sprite frame(arrow1, 7)
)
variable(x, y)
x := vecX(herodirection, arrow distance) # Find the position 60 pixels ahead of the player
y := vecY(herodirection, arrow distance)
set timer(2, 0, 1, fire projectile(arrow1, 8, x, y)) # 8 pixel/tick, timer added by me
set timer(timer:arrow1, 0, 1, @arrow1 eachtick)
stealth -= 10
end
script, arrow1 eachtick, timer id, begin
if (projectile eachtick(arrow1)) then (
## Still in the air, run timer again
set timer(timer id, 0) # Restarts the timer with a count of 0 (next tick)
) else (
set timer(timer:arrow1, 0, 2, freeslice(arrow1))
canshoot := true
)
end
...
script, damagecritter, ref, begin
# add more stuff later, this is just for testing purposes now
destroy NPC(ref)
exit script()
end
-
Bluefeather42
- Slime Knight
- Posts: 115
- Joined: Fri Jan 13, 2023 1:13 am
Re: Monster/NPC collisions
After having thought about it for a while I am definitely going to have only a single monster on the map at a time, so I'll probably just make a single hitbox for projectiles to collide with and use slice extras for the stats.