ID:271973
 
I was wondering how to program in range attacks. As in, I push a button and then a beam is shot out in front of me untill it hits something to dense (and the dense thing, if a mob, taking damage).
Demon_F0rce wrote:
I was wondering how to program in range attacks. As in, I push a button and then a beam is shot out in front of me until it hits something to dense (and the dense thing, if a mob, taking damage).

First you'll need a beam object.
obj/projectile    // Using a projectile subtype so 
density=1 // similar objects like bullets,
// arrows, or darts can be added easily.
beam
icon='my_beam.dmi'


Easy enough, now we can give players the ability to create the beam. Use get_step() to place it in front of the player.

mob/verb/shoot_beam()
new /obj/projectile/beam(get_step(src, src.dir))


Compile and run and you've got yourself a beam that shoots out of the player. Doesn't move yet, but it's a good start. =) Did I mention that I like that you were specific with your request? Very nice to see. Oh right, moving on to movement.

Since all this projectile is meant to do is move, we'll put that on the object itself. Since it's going to need to know which direction to move (and you'll probably want to know who shot it when it destroys someone, etc.) we'll add some more parameters to the projectiles New() proc while we're there.

obj/projectile
var/mob/shooter

New(start_loc, direction, shooter, delay)
src.shooter=shooter
if(!Move(start_loc,direction)) del src
spawn(delay)
while(step(src, direction))
sleep(delay)
del src


This part is a little more in-depth so allow me to explain. First we're letting the projectile know who shot it. Then, instead of creating the object in front of the shooter, we create it outside of the map (creation is technically done in the verb with new) and move it to it's starting location. This is so Bump() will be called (which we will use in a bit to damage any mobs that were hit) if needed, and as needed, the projectile can be deleted. Then there's the loop.

step() will attempt to move a mob or obj one tile in a certain direction, if it moves the proc will return a TRUE value (1). If it doesn't it will return a FALSE value (0). So what the loop is saying is while the object can still move forward sleep for a bit then try again. Now whenever the projectile stops moving (whether it's bumped something or reached the end of the map) the loop will exit and the projectile will be deleted.

Of course, now we have to change our verb to reflect the new additions. If you'll notice I'm now using named arguments, this will prevent Dream Seeker from creating the object at the location of the first argument because it sees all of my arguments as used.

mob/verb/shoot_beam()
new /obj/projectile/beam(start_loc=get_step(src, src.dir), direction=src.dir, shooter=src, delay=10)


Now if you run it you should have a projectile that moves in a straight line and disappears when it hits something. One thing left, killing! >=D

  Bump(atom/A)
if(ismob(A))
var/mob/victim=A
world<<"[shooter] hit [victim]!"
// else
// world<<"Wasn't a mob, maybe it was a tree. What are you [A]?"


I've done some type casting for you, but I have no idea what your variables for health are so I can't hurt the victim. It would be something like victim.hp-=10 (or victim.TakeDamage(10) if you're using a really robust system), and shooter should get some experience for hitting the mark don't you think? ;)

To wrap up I've condensed it and added some spiffy new attacks. =)

obj/projectile    // Using a projectile subtype so 
// similar objects like bullets,
// arrows, or darts can be added easily.

beam
icon='my_beam.dmi'


density=1
var/mob/shooter


New(start_loc, direction, shooter, delay)
src.shooter=shooter
if(!Move(start_loc, direction)) del src // The initial move is here in case someone is on the first tile.
spawn(delay)
while(step(src, direction))
sleep(delay)
del src

Bump(atom/A)
if(ismob(A))
var/mob/victim=A
world<<"[shooter] hit [victim]!"
// else
// world<<"Wasn't a mob, maybe it was a tree. What are you [A]?"

mob/verb/shoot_beam()
new /obj/projectile/beam(start_loc=get_step(src, src.dir), direction=src.dir, shooter=src, delay=10)


mob/verb/panic_attack()
for(var/shots=3; shots>0; shots--)
src.dir=pick(NORTH, SOUTH, EAST, WEST)
new /obj/projectile/beam(start_loc=get_step(src, src.dir), direction=src.dir, shooter=src, delay=10)
sleep(10)

mob/verb/overkill()
new /obj/projectile/beam(start_loc=get_step(src, NORTH), direction=NORTH, shooter=src, delay=10)
new /obj/projectile/beam(start_loc=get_step(src, SOUTH), direction=SOUTH, shooter=src, delay=10)
new /obj/projectile/beam(start_loc=get_step(src, EAST), direction=EAST, shooter=src, delay=10)
new /obj/projectile/beam(start_loc=get_step(src, WEST), direction=WEST, shooter=src, delay=10)


Happy killing!
In response to YMIHere
Well, I've had to modify it a little and it's not working. I can't see why, so can you help me out a bit more please?

obj/projectile    // Using a projectile subtype so 
// similar objects like bullets,
// arrows, or darts can be added easily.

Flippendo
icon='Spells.dmi'
icon_state = "flip"


density=1
var/mob/shooter


New(start_loc, direction, shooter, delay)
src.shooter=shooter
if(!Move(start_loc, direction)) del src // The initial move is here in case someone is on the first tile.
spawn(delay)
while(step(src, direction))
sleep(delay)
del src

Bump(atom/A)
if(ismob(A))
var/mob/victim=A
view(A)<<"[shooter] hit [victim]!"
victim.hp -= 5
else
view(A)<<"[shooter]'s Flippendo missed their intended target and hit [A]!"

//The above program was shown to me by YMIHere


mob/Spell
verb
Flippendo()
set category = "Spells"
if(wandout == 1)
if(confound == 1)
usr.random=rand(1,2)
if(random == 1)
view(usr) << "[usr]: Flippendo!"
new /obj/projectile/Flippendo(start_loc=get_step(src, src.dir), direction=src.dir, shooter=src, delay=10)
if(random == 2)
usr << "You raise your wand, only to find the spell leave your grasp"
return
else
view(usr) << "[usr]: Flippendo!"
else
usr << "You must have your wand out!"
In response to Demon_F0rce
What isn't working, is it just not shooting or will it not compile? I used spaces as my indentation so if it's giving you indentation errors you might have snuck a tab in while editing (it's probably better to tab it all anyway).

obj/projectile    // Using a projectile subtype so 
// similar objects like bullets,
// arrows, or darts can be added easily.

Flippendo
icon='Spells.dmi'
icon_state = "flip"


density=1
var/mob/shooter


New(start_loc, direction, shooter, delay)
src.shooter=shooter
if(!Move(start_loc, direction)) del src // The initial move is here in case someone is on the first tile.
spawn(delay)
while(step(src, direction))
sleep(delay)
del src

Bump(atom/A)
if(ismob(A))
var/mob/victim=A
view(A)<<"[shooter] hit [victim]!"
victim.hp -= 5
else
view(A)<<"[shooter]'s Flippendo missed their intended target and hit [A]!"


If that doesn't work for you double check the icon and icon state names. It still works for me.
In response to YMIHere
It simply wont shoot. I've tried with everything retabbed and still there's nothing. Even when I fixed up the problem that Spells.dmi was in a folder so it should be Icons/Spells.dmi.
In response to Demon_F0rce
Does the player say Flippendo {edit: and if he does are you sure it's the one where he actually shoots?}? Have you overridden any higher level atom or objs New() proc and forgotten to call ..()?
In response to YMIHere
The player just says Flippendo and nothing happens after that, and there's only one verb. As far as I know, no. I've shown you the whole program with it and nothing seems to be wrong from my perspective. Maybe I've mucked it up when I put it into the verb, I dont know.
In response to Demon_F0rce
That's just one of the reasons you shouldn't just copy code found or given to you. Learn how his code works and make your own, better suited to your game and wants, etc.
In response to Demon_F0rce
There are two places in the verb where the player says flippendo though, and only one that fires the beam. Try adding some debug text.

mob/Spell
verb
Flippendo()
set category = "Spells"
if(wandout == 1)
if(confound == 1)
usr.random=rand(1,2)
if(random == 1)
view(usr) << "[usr]: Flippendo!"
new /obj/projectile/Flippendo(start_loc=get_step(src, src.dir), direction=src.dir, shooter=src, delay=10)
if(random == 2)
usr << "You raise your wand, only to find the spell leave your grasp"
return
else
view(usr) << "[usr]: Flippendo!.. or so it would seem, but I'm not firing anything because confound does not equal 1."
else
usr << "You must have your wand out!"


Of course this should probably be cleaned up a bit.
mob/Spell
verb
Flippendo()
set category = "Spells"
if(wandout)
if(confound)
if(prob(50))
view(usr) << "[usr]: Flippendo!"
new /obj/projectile/Flippendo(start_loc=get_step(src, src.dir), direction=src.dir, shooter=src, delay=10)
else
usr << "You raise your wand, only to find the spell leave your grasp"
else
view(usr) << "[usr]: Flippendo!.. or so it would seem, but I'm not firing anything because confound is FALSE."
else
usr << "You must have your wand out!"
In response to YMIHere
Ah yes, it's working now. That teaches me for not looking at what I've done more closely >_<. Well, thanks for your help YMIHere!
In response to Kaioken
yes but you can get more use to the different versions of the code i like to mess around and stuff

In response to Kozuma3
Look at the damn date before you reply and dig up ancient topics for no reason. :\