ID:1723759
 
Keywords: abilites, projectile
(See the best response by Neimo.)
Code:
obj/projectile
proc
projectile_fire(var/target_lock = FALSE)
//code homing system here
if(target_lock && owner.target)
while(owner)
if(get_dist(src, owner.target) > 1)
src.dir = get_dir(src, owner.target)
step(src, owner.target)

else src.Bump(owner.target)

sleep(world.tick_lag * src.delay)


else walk(src, src.owner.dir, world.tick_lag * src.delay)

spawn(duration) del(src)


ability/quincy/skill
klavier
name = "Klavier"
cooldown = 60
icon_state = "klavier"

perform(mob/a)
if(a.race.info != "Quincy") return
if(a.weapon != "Quincy Bow") return

var/obj/projectile/P1 = new/obj/projectile/quincy/arrow
var/obj/projectile/P2 = new P1.type
var/obj/projectile/P3 = new P1.type

P1.owner = a
P2.owner = a
P3.owner = a

P1.dir = a.dir
P2.dir = a.dir
P3.dir = a.dir

if(a.dir == NORTH || a.dir == SOUTH)
P1.loc = locate(a.x , a.y, a.z)
P2.loc = locate(a.x - 1 , a.y, a.z)
P3.loc = locate(a.x + 1 , a.y, a.z)

else if(a.dir == EAST || a.dir == WEST)
P1.loc = locate(a.x , a.y, a.z)
P2.loc = locate(a.x , a.y + 1, a.z)
P3.loc = locate(a.x , a.y - 1, a.z)

spawn() P1.projectile_fire()
spawn() P2.projectile_fire()
spawn() P3.projectile_fire()


Problem description: Greetings, there must be a better way to do this. This is nothing but repetitive code. In addition what if I want this to fire 3 more times? 3 Arrows every 2 seconds or so.

-Regards
You can set the loc, dir, and owner of the projectile in obj/projectile/New() and call projectile_fire() from the New() proc. Also, if you are creating a projectile in front of the user, you can use get_step(ref, dir) without having those excess lines of code. If you set up the projectiles like that, all you have to do is something similar to:

new/obj/projectile/arrow(loc, dir, usr)
loc being the location
dir being the direction
usr being the owner
In response to Neimo
I see what you are saying but that only works for one projectile if I am not mistaken. What I want to do, is have multiple projectiles placed at once depending on the users direction. Imagine firing 3 arrows side by side at once.
So then you'd do exactly that, and everything I said previously wouldn't hinder your ability to do that.

spawn() new/obj/projectile/arrow(get_step(usr, usr.dir), dir, usr)
spawn() new/obj/projectile/arrow(get_step(usr, turn(usr.dir, -45)), dir, usr)
spawn() new/obj/projectile/arrow(get_step(usr, turn(usr.dir, 45)), dir, usr)
In response to Neimo
Alright so I have attempted this and now I have problem with the direction of the projectile movement. They seem to go flow South no matter what direction I am facing.

var/obj/projectile/P1 = new/obj/projectile/quincy/arrow(get_step(a, a.dir), dir, a)
var/obj/projectile/P2 = new/obj/projectile/quincy/arrow(get_step(a, turn(a.dir, -45)), dir, a)
var/obj/projectile/P3 = new/obj/projectile/quincy/arrow(get_step(a, turn(a.dir, 45)), dir, a)

obj/projectile
New(mob/a, loc, dir)

src.dir = turn(a.dir, 180)
src.owner = a
src.projectile_fire()

..()

proc

projectile_fire(var/target_lock = FALSE)
//code homing system here
if(target_lock && owner.target)
while(owner)
if(get_dist(src, owner.target) > 1)
src.dir = get_dir(src, owner.target)
step(src, owner.target)

else src.Bump(owner.target)

sleep(world.tick_lag * src.delay)


else walk(src, src.owner.dir, world.tick_lag * src.delay)

spawn(duration) del(src)


Another thing, how can I avoid these warnings? It seems that I can just leave them as they are and they will still work properly.

//Quincy\race_quincy_1.2.dm:81:warning: P1: variable defined but not used
//Quincy\race_quincy_1.2.dm:82:warning: P2: variable defined but not used
//Quincy\race_quincy_1.2.dm:83:warning: P3: variable defined but not used


Thank you in advance
In response to Luchasi
If you look at the previous post I had, you don't have to create to reference the projectile you are creating. You are passing the arguments correctly, but reading them wrong in New().

New(loc, dir, mob/owner)
src.loc = loc
src.dir = dir
src.owner = owner
// this is how it should read
It worked beautifully thank you so very much for your help and time.
Best response
No problem, if you have any other questions don't hesitate to ask! :)
This may be trivial, and I am going a bit off topic (or at least I think I am), but I was looking at your homing system and based on what I've seen you could get the same results using walk_towards(). The only difference is, if the target changed, your projectile would still continue towards it's original target.

    proc

projectile_fire(var/target_lock = FALSE)
//code homing system here
if(target_lock && owner.target)
walk_towards(src,owner.target,world.tick_lag * src.delay)

else walk(src, src.owner.dir, world.tick_lag * src.delay)

spawn(duration) del(src)


Using walk_towards will make an atom/movable gradually step in the direction between it and it's destination, and if both atom's have density, it collides [calling Bump()].

If for some reason you don't wish to use walk_towards(), I would like to point out that you've accidently used step incorrectly (or so I'm assuming). You have
step(src,owner.target)
When I think you meant,
step(src,src.dir)


Again, a bit off topic, but I noticed those two things and figured I'd share.
In response to Ss4toby
Thank you for your response and I am glad that you pointed that out. I like to avoid while loops as much as possible. Thank you for that.