ID:1402969
 
So I have been trying to make a slash and pierce strike. The Piercing moves just fine, but I cant figure out how to move the slash in a full circle around the user, such as a whirlwind attack. Also the Crossed() code I added doesn't seem to activate at all.

mob
proc
Slashing(weapon) //Setup a Slashing attack
if (Active("Melee Attack"))
return
Attacking = 1
var/Attack/Melee/Slashing/A = new(src.loc)
A.step_x = step_x
A.step_y = step_y
A.Attacker = src
A.dir=src.dir
if (weapon == "Right")
if (RWeapon)
A.Dist = RWeapon.Slashing+R.Slashing
else
A.Dist = R.Slashing
if (A.Dist)
if (dir == NORTH)
step(A,NORTHEAST,20)
sleep(1)
step(A,WEST,16)
sleep(1)
step(A,WEST,16)
A.dir = NORTHWEST
sleep(1)
else if (dir == EAST)
step(A,SOUTHEAST,20)
sleep(1)
step(A,NORTH,16)
sleep(1)
step(A,NORTH,16)
A.dir = NORTHEAST
sleep(1)
else if (dir == WEST)
step(A,NORTHWEST,20)
sleep(1)
step(A,SOUTH,16)
sleep(1)
step(A,SOUTH,16)
A.dir = SOUTHWEST
sleep(1)
else if (dir == SOUTH)
step(A,SOUTHWEST,20)
sleep(1)
step(A,EAST,16)
sleep(1)
step(A,EAST,16)
A.dir = SOUTHEAST
sleep(1)
else if (weapon == "Left")
A.Dist = LWeapon.Slashing+L.Slashing
if (A.Dist)
if (dir == NORTH)
step(A,NORTHWEST,20)
sleep(1)
step(A,EAST,16)
sleep(1)
step(A,EAST,16)
A.dir = NORTHEAST
sleep(1)
else if (dir == EAST)
step(A,NORTHEAST,20)
sleep(1)
step(A,SOUTH,16)
sleep(1)
step(A,SOUTH,16)
A.dir = SOUTHEAST
sleep(1)
else if (dir == WEST)
step(A,SOUTHWEST,20)
sleep(1)
step(A,SOUTH,16)
sleep(1)
step(A,SOUTH,16)
A.dir = NORTHWEST
sleep(1)
else if (dir == SOUTH)
step(A,SOUTHEAST,20)
sleep(1)
step(A,WEST,16)
sleep(1)
step(A,WEST,16)
A.dir = SOUTHEAST
sleep(1)
Attacking = 0
del A

The code above is what I'm using for a basic 1 tile slash attack, unfortunately this seems a bit choppy. My hope is to find a way to set up different sizes of attacks from 1 to 8 tiles, representing a single tile in front of the attack to a full 360 degree attack. The problem is keeping the attack centered at the front o the attacker.
Below is some additional code used with the above code.

Attack
parent_type = /obj/

var
Dist = 0 // How far the attack will travel

mob/Attacker //The person who started the Attack

Melee
icon = 'MeleeAttack.dmi'

Slashing
icon_state = "Slash"
step_size = 16
mob
verb
Slashing_Strike()
if (RWeapon)
Slashing("Right")
if (LWeapon)
Slashing("Left")
if (!LWeapon && !RWeapon)
return
mob
proc
Hit(mob/Defender)
return 1
Damage(mob/Defender)


The other problem is when the attack passes over a mob it doesn't activate the attack. Below is the code that should cause damage. I'm not sure if Im calling it in the wrong spot or if I did something wrong.
mob
Crossed(M)
if (M == typesof(/Attack))
var/Attack/A = M
if (Hit(src))
var/dmg = A.Attacker.Damage(src)
world << "[A.Attacker] hits [src]."
StatusLose(A.Attacker,dmg,"Health")
A.Dist-= 2
return 1
else
..()


Any help would be much appreciated.
Well at first glance, it seems like you have no idea what a switch statement is. And then it also seems like your code will utterly fail if the person attacking is facing a diagonal direction (I don't know if you disabled that somewhere else in your code).

And then at second glance, it appears your Dist variable is given some value and then never used for anything other than checking if it has a value other than 0/null. I don't know if this is intended, but it doesn't seem like it.
I am not sure what the functional difference is between a switch and if, else if and else statements being used. I understand I can add multiple variable checks in the if sequence of statements and that's about it. If you could explain a little more on how this can improve what I am doing that would be very helpful.
Dist only has it setup for the value of 1. I am not really sure how to go about what I am trying to do. Here is a summary.
mob
proc
Slashing(weapon)
if (Active("Melee Attack"))
return
Attacking = 1
var/Attack/Melee/Slashing/A = new(src.loc)
A.step_x = step_x
A.step_y = step_y
A.Attacker = src
A.dir=src.dir
var/icon/I = new(A.icon)
if (weapon == "Right")
if (RWeapon)
A.Dist = RWeapon.Slashing+R.Slashing
else
A.Dist = R.Slashing
switch(A.Dist)
if (1)
//attack a single tiled area just off center of the attacker.
if (dir == NORTH)
/*
as far as I know each direction will have
to be setup separately to maintain the
movement effect of the slashing object.
*/

step(A,NORTHEAST,20)
I.Turn(-45)
A.icon = I
sleep(2)
step(A,WEST,16)
I.Turn(45)
A.icon = I
sleep(2)
step(A,WEST,16)
I.Turn(45)
A.icon = I
sleep(2)
else if (dir == EAST)

else if (dir == WEST)

else if (dir == SOUTH)

else if (dir == NORTHEAST)

else if (dir == NORTHWEST)

else if (dir == SOUTHEAST)

else if (dir == SOUTHWEST)
if (2)
//attack 2 tiles infront of the attacker.
if (3)
//attack all 3 tiles infront of the attacker.
if (4)
//attack the 3 tiles infront of the attacker and half a tile on each side of the attacker.
if (5)
//attack the 3 tiles infront of the attacker and the tiles on both sides of the attacker.
if (6)
//attack the 3 tiles infront of the attacker, the tiles beside the attacker, and cover half a tile on either side of the attacker in the back.
if (7)
//attack all the tiles around the attacker except the one directly behind them.
if (8)
//attack all the tiles around the attacker.
else if (weapon == "Left")
A.Dist = LWeapon.Slashing+L.Slashing
//reverse all the directions so the attack comes from the left.

The attacks need to be in one slashing motion, from right to left and from left to right. I didn't add in the cross directions yet since I wasn't sure of what I was doing, but yes they need to be included.
Does that explain things better?
The functional difference between if blocks and a switch statement is that switch statements are faster, and should be used in place of if blocks that just test the same variable(s) every time.

I would look up the get_step() proc because it seems like it'll do what you want it to do in terms of obtaining tiles in front of the player.

You could also look up the turn() proc and combine it with the get_step() proc to do your sword movement or whatever instead of manually making the sword move for each individual direction.

So to summarize...

1. Write yourself a proc that will compile a list of turfs that are X number of steps in front of a reference atom, and return that list. You can have this proc take a distance argument, or have the proc calculate the distance first, and then proceed to fetch turfs. It doesn't matter either way.

2. Using the get_step() proc and turn() proc, you can achieve relative sword movement based on the direction of the player, and won't have to manually move the sword after testing to see which direction the player is in.
I'll give it a look. thanks
There's a way to get the right numbers on all the dirs using an algorithm. For your example, you could:
                            var/obj/end = new(loc)
end.dir = turn(dir,45)
step(end,end.dir,20)
dir = turn(dir,-45)
step(A,dir,20)
sleep(2)
dir = turn(dir,45)
step_towards(A,end,16)
sleep(2)
dir = turn(dir,45)
step_towards(A,end,16)
sleep(2)
A.loc = null
end.loc = null


I would suggest premaking A as a large icon and setting its dir only once rather than editing its icon. It's a good rule of thumb to only use icon procs when you absolutely have to.
so after messing with what you both gave me for a while I have come up with this.
mob
proc
Slashing(weapon) //Setup a Slashing attack
if (Active("Melee Attack"))
return
Attacking = 1
var/Attack/Melee/Slashing/A = new(loc)
A.step_x = step_x
A.step_y = step_y
A.Attacker = src
if (weapon == "Right")
if (RWeapon)
A.Dist = RWeapon.Slashing+R.Slashing
else
A.Dist = R.Slashing
switch(A.Dist)
if (1)
A.dir = turn(dir,-45)
A.loc = get_step(src,A.dir)
var/obj/end = new(loc)
end.dir = turn(dir,45)
end.loc = get_step(src,end.dir)
step_towards(A,end,16)
A.dir = turn(dir,45)
sleep(2)
step_towards(A,end,16)
A.dir = turn(dir,-90)
sleep(2)
del end
if (2)
A.dir = turn(dir,-45)
A.loc = get_step(src,A.dir)
var/obj/end = new(loc)
end.dir = turn(dir,45)
end.loc = get_step(src,end.dir)
step_towards(A,end,16)
A.dir = turn(dir,45)
sleep(2)
step_towards(A,end,16)
sleep(2)
step_towards(A,end,16)
A.dir = turn(dir,-90)
sleep(2)
del end

unfortunately it has a few problems. The first is that the Diagonal directions don't work properly. They move in the wrong direction and seem to not change there dir variable.
The second being that every 3-4 times I attempt to attack it will get stuck in the spot it starts in. Any ideas why this is occurring?
(edit) the second problem seems to have to do with how the mob is position but I don't really understand why it prevents the attack from moving.
ok so I figured out what I did wrong. I used dir where I should have used A.dir. So can someone help me with the second part of my question, which is "Why doesn't Crossed work?"
mob
Crossed(M)
if (M == typesof(/Attack))
var/Attack/A = M
if (Hit(src))
var/dmg = A.Attacker.Damage(src)
world << "[A.Attacker] hits [src]."
StatusLose(A.Attacker,dmg,"Health")
A.Dist-= 2
return 1
else
..()


Is Crossed() not the right proc to use or did I do something wrong?
StatusLose(A.Attacker,dmg,"Health")


shouldn't this be

StatusLose(src,dmg,"Health")
?

Doesn't make sense for you to check for health lost for the attacker
yes it should, but that doesn't really explain why the world output message doesn't display either. thanks for catching that though.