ID:791585
 
(See the best response by LordAndrew.)
Code:mob/verb
Attack(mob/M in get_step(src,usr.dir))
set category = "Taijutsu"
damage(usr, M)
var/damage = usr.Taijutsu
M.Stamina -= damage
usr << "<b>You attack [M] by [damage]!</b>"
oview() << "[usr] attacks [M] by [damage]!"

Well there's no errors in the code but I can hit mysel.I've tried with eveything in mind but didn't work Mind some help?plz (I want not to hit myself)xD


Well, you are always going to be within get_step() since you are at a distance of 0, so you will always be in the list that it returns. So, you want to remove yourself from that list or make a check to see if the target is the source and return.
I want to remove myself from the list how can I do that?please
Show your damage() proc please?
proc
damage(mob/attacker, mob/defender)
var/damage = attacker.Taijutsu
defender.Stamina -= damage
defender.DeathCheck()
if(attacker.client) // check to see if the attacker is a player and not an NPC
attacker.Exp += defender.exp_give
levelUp(attacker)
levelUp(mob/M)
if(M.Exp >= M.Max_Exp)
M.Exp -= M.Max_Exp
M.Level += 1
M << "<b><font color = red>[M.name]</font color> leveled up to level <font color = red>[M.Level]</font color>!"
This is it..
Just add a safety check.

proc/damage(mob/attacker, mob/defender)
if(attacker == defender)
return FALSE
Still can hit myself when I'm near (not in dir) of another mob
In DM, there are definitions that translate to other values.

FALSE translates to 0.
TRUE translates to 1.

Using these in a return statement can give you easier control over some things. For example:
proc/check_thing()
if(preliminary_check())
do_stuff()
proc/preliminary_check()
if(x)
return TRUE
return FALSE


So now, in preliminary_check(), if x exists, it returns TRUE. If it doesn't, then it keeps going down into the code, which means it returns FALSE. No need for an else statement there. Then, in check_thing(), it does if(preliminary_check()). Basically, it's checking if there is a positive value in the if() statement. So, if preliminary_check() returns FALSE(0), then the if() statement will fail and the code will move on. If preliminary_check() returns TRUE(1), then the if() statement will execute.

Do you understand a little better now?
Yeah thanks and I've added the check thingy and I can still hit myself O_o
That's because calling damage() isn't going to stop the rest of the verb. It will just stop the damage. Add a check in the verb.
if(M == usr)
return
Didn't understand that o.o
You are calling damage() in your Attack verb. Stopping damage() isn't going to stop the verb from outputting later on in its code. So add the check to see if the attacker is the defender in the Attack verb. Use the snippet I used above.

You could also do:
Attack(mob/M in get_step(usr, usr.dir) - usr)


get_step() returns a /list of all of the atoms 0-1 step away from you. You are included in this list. So, the code is telling it to take you out of the list.
that way seems more easy but i get error(when running it and I use the verb) and it doesn't attack
error:runtime error: type mismatch: the grass (2,1,1) (/turf/grass) - Andy (/mob)
proc name:
usr: Andy (/mob)
src: Andy (/mob)
call stack:
Andy (/mob): ()


Note: Just adding the - usr thingy

I may quit just for this T_T
In response to Andy24
Best response
Not quite sure why you're making Attack accept an argument like that. You could do:

mob
verb
Attack()
for(var/mob/m in get_step(src, dir))
if(m == src) continue

world << "[src] hits [m]!"

// damage stuff here etc
thx!! it worked
Mightymo wrote:
Well, you are always going to be within get_step() since you are at a distance of 0, so you will always be in the list that it returns. So, you want to remove yourself from that list or make a check to see if the target is the source and return.

This is wrong. Everyone who responded with this in mind was also wrong.

Not to sound rude or anything, but I don't know any other way to say it.

src would never be within the turf -- that's what it returns, a turf -- returned by get_step(src, anyDirection). If you were ever within the contents of a turf in some direction from yourself, you would literally not be in the turf you're in right now, which would be impossible as you are calling get_step(src, someDirection) from where you are right now.

The short and simple answer here is that you are not hitting yourself. What you are probably doing is attacking a mob with the same name, or something like that, but you certainly should not be capable of hitting yourself with this code simply because of what I said early. You aren't gonna be in the turf returned by get_step(), if it returns any turf at all.

I would probably not use LordAndrew's implementation here, simply because I don't like the idea of hitting multiple enemies with 1 button press (unless there's a good reason for it). That's a design question which isn't present in your original example. You say this is fine for you, but if you want to stick with allowing the user to choose an enemy to attack if there happens to be two enemies on the tile in front of them, I'd like you to go ahead and tell me what you mean when you say you are hitting yourself.

[edit]
I've taken the liberty of testing this a SECOND time, just to see if what Andy is saying is even remotely possible.

From what I can tell, from time to time, I can in fact attack myself despite the fact that I shouldn't be able to. I made two test cases to determine what was going on, and I can't really figure out why in the world it is letting me attack myself.

mob
verb
attack(mob/mob in get_step(usr, usr.dir))
world << "[src] attacks [mob]"

test()
var/turf/stepper = get_step(usr, usr.dir)
src << "Is my loc the turf I'm facing? [loc == stepper]" // will always be 0, obviously.
src << "Am I in my loc? [src in loc]" // will always be 1.
src << "Am I in the turf I'm facing? [src in stepper]" // will always be 0.


If you walk about and click attack, from time to time it will let you hit yourself. Just take a step in some direction and hit the attack verb. If it lets you hit yourself, you will be able to hit yourself consistently while standing there. If you press the test verb, though, it will tell you that you are in fact not in the turf in front of you (as expected). If you take a few more steps, hitting attack every step, you will sometimes also not be able to attack yourself. In this scenario, hit the test verb again. Same responses.

This honestly seems like a bug of some kind. I don't really know how to describe it.

[edit #2]
After realizing I left the new map-related stuff it adds to any new environments, it is probably the case that pixel movement is causing this.
mob
verb
Attack()
for(var/mob/M in get_step(src,dir))
set category = "Taijutsu"
if(M==src) continue
damage(usr,M)
var/damage = usr.Taijutsu
M.Stamina -= damage
usr << "<b>You attack [M] by [damage]!</b>"
oview() << "[usr] attacks [M] by [damage]!"


This is what I coded didn't use LordAndrew's completele since i like to make the codes myself xD.But it works I can't hit myself and tested with moire than 1 mob near me and it just attack the one I want to attack (the dir I am in..)So is fine i guess thanks all you guys again.
In response to Andy24
Andy24 wrote:
This is what I coded didn't use LordAndrew's completele since i like to make the codes myself xD.But it works I can't hit myself and tested with moire than 1 mob near me and it just attack the one I want to attack (the dir I am in..)So is fine i guess thanks all you guys again.

There are a few problems with this, including that it's a bit redundant. set category should be at the top of the verb, before everything else. Also, what is the purpose of damage(usr, M), if you're just calculating the damage again and attacking them again?

Anyway... you are apparently using pixel movement, and I'm pretty sure there are other alternatives to getting who is in front of you if that's the case.
In response to Andy24
Andy24 wrote:
proc
> damage(mob/attacker, mob/defender)
> var/damage = attacker.Taijutsu
> defender.Stamina -= damage
> defender.DeathCheck()
> if(attacker.client) // check to see if the attacker is a player and not an NPC
> attacker.Exp += defender.exp_give
> levelUp(attacker)
> levelUp(mob/M)
> if(M.Exp >= M.Max_Exp)
> M.Exp -= M.Max_Exp
> M.Level += 1
> M << "<b><font color = red>[M.name]</font color> leveled up to level <font color = red>[M.Level]</font color>!"
This is it..

This looks familiar. I wrote this for you, if I'm right. In another topic you had.