ID:1300611
 
(See the best response by Koriami.)
Problem description:
I'm trying to add a loop into my target system while will scan for if the target attacks, and if so it changes the reticle icon_state. I doing so, I've created an infinite loop, but it also doesn't do what I want it to. I'm wondering if it's even possible to change the icon state of an image.

Code:
mob/player/proc

Target(mob/T)
var/image/I = image('Target Reticle.dmi', T,"Neutral")

//If no target, target normally.
if(!usr.targeting)

usr.targeting = 1
usr.target = T
usr.client.images += I
view()<< "[usr] [pick(targettext1, targettext2, targettext3, targettext4)] [T]."


//If player has a target already, then drop it, and target new selection.
else
for(I in usr.client.images)
del(I)
usr.targeting = 1
usr.target = T
usr.client.images += I
view()<< "[usr] [pick(targettext1, targettext2, targettext3, targettext4)] [T]."

while(usr.target == T)
if(T.attack())
I.icon_state= "Hostile"


That's the loop I'm trying to run, and I understand why it's an infinite loop, but what's the best way to mitigate this and also get it to work?
First thing I will say, remove "usr." since this is a proc and not a verb. The proc runs directly from the mob. So it will automatically call any variables/procs from "src", or the mob.

So instead of
usr.targeting = 1

use
targeting = 1


Also, what exactly is the problem? You only mentioned that it doesn't do what it is supposed to do. I might be able to help with that if I know what exactly it isn't accomplishing.
Well, I've created an infinite loop with while() which causes run-time error and lags the game.

Infinite loop suspected--switching proc to background.
If it is not an infinite loop, either do 'set background=1' or set world.loop_checks=0.
proc name: Target (/mob/player/proc/Target)
usr: Khye (/mob/player)
src: Khye (/mob/player)
call stack:
Khye (/mob/player): Target(the human (/mob/npc/human))
Guest-2798058652 (/client): Click(the human (/mob/npc/human), the grass (9,9,1) (/turf/grass), "Main Window.map1", "icon-x=17;icon-y=17;left=1;scr...")



Additionally, it doesn't change the icon state of the target reticle like I would like it to. When you target someone, it lays an image of a target reticle over them. What I'd like is for the color of the reticle to change when someone attacks.
Mind showing the attack() proc? And the infinite loop is, as you said, from your while() statement. It will run consistently while usr.target == T is true. So, if this will happen for prolonged periods of time, try something else.
mob/proc/TargetCheck(mob/M,image/I)
var/image/I2
if(!target == M) return //ends the proc so it does not loop while M is not your target.
if(M.attack())
if(I)
if(I.icon == 'Target Reticle.dmi'&&I.icon_state == "Neutral")
del(I)
I2 = image('Target Reticle.dmi',M,"Hostile")
src<< I2
spawn(1)
TargetCheck(M,I2)


And then simply call TargetCheck(M) once and it will loop so long as M is your target. But it should loop without bringing up the "Infinite loop" error.
Here is the attack verb as of right now:

mob/verb

attack()
set name = "Attack"
if(usr.busy == 0)
if(usr.chi>maxchi/100)
for(var/mob/m in get_step(src, usr.dir))
if(m.health> 0)
usr.busy = 1
usr.attacking = 1
m.Factor_LF()
usr.Factor_LF()
flick("punch1",src)
var/dmg = ((usr.lf/usr.baself)*usr.str)/((m.lf/m.baself)*m.end)
if(dmg<0)
dmg = 0
m.Damage(dmg,m,usr)
m.Factor_LF()
usr.chi-= maxchi/100
usr.Factor_LF()
spawn(14)
usr.busy = 0
usr.attacking = 0


Now, I put a proc in like and called it within the Target proc. I also placed a text output in it to make sure it was looping, and it is. However, the target reticle still isn't being changed.
Alright, so your attack() verb doesn't return any value so calling if(T.attack()) does nothing. Try doing if(T.attacking) instead.
I switched that a few minutes ago, and it's still doing nothing.

Now, I put a few MORE text outputs to basically tell me how far into the proc that it's making it.

Threat_Warning(mob/T,image/I)
src<< output("Threat warning on.[T] is targeting you.", "View")
var/image/I2
if(!target == T) return //Ends the proc so it does not loop when M stops being the target
if(T.attacking)
src<< output("Phase 1.", "View")
if(I)
src<< output("Phase 2.", "View")
if(I.icon == 'Target Reticle.dmi'&&I.icon_state == "Neutral")
src<< output("Phase 3.", "View")
del(I)
I2 = image('Target Reticle.dmi',T,"Hostile")
src<< I2
spawn(1)
Threat_Warning(T,I2)


It's not even outputting "Phase 1", but it does constantly repost "Threat warning on."
Try creating a mob that has its attacking variable always set to 1 and target it. Does it still not get to Phase 1?
I just did and it makes it to Phase 1. The reticle turns red and everything...But it doesn't ouput "Phase 2" and "Phase 3" which is also odd...
Khye wrote:
Additionally, it doesn't change the icon state of the target reticle like I would like it to. When you target someone, it lays an image of a target reticle over them. What I'd like is for the color of the reticle to change when someone attacks.

So change the mouse pointer?

Khye wrote:
        if(!target == T) return //Ends the proc so it does not loop when M stops being the target


This is your problem. Your placement of the ! is wrong. You are telling the compiler "If !target(Which will return 1 if there is no value for target, 0 otherwise) is T, return"

You need to tell it "If target does not equal T, return", which is this:
if(target != T) return
Can't believe I made that mistake. Thanks Albro.
No problem. Also, as an alternative that still resembles your method, Khye, you can use parenthesis:
if(!(target == T))
Thank you. I corrected that. But it's still not running all the way through the proc. It appears to get stopped at "if(T.attacking)" unless the mob's attacking var is already preset to 1.

Is it possible that the attacking var is being toggled by the attack verb quicker than this proc can actually pick up on it?
Best response
indent it:
spawn(14)
usr.busy = 0
usr.attacking = 0

Without the last 2 lines being indented they will run like normal, without the pause
Okay awesome. Now the proc is making it to phase 1 without presetting the attacking of the mob to 1. It wasn't making it to Phase 2 or 3 because of the "if(I)". Instead I swapped that out for "for(I in client.images)". Now I should be able to get this to work the way I'd like. Thank you guys.
In response to Khye
Khye wrote:
It wasn't making it to Phase 2 or 3 because of the "if(I)". Instead I swapped that out for "for(I in client.images)".
If it wasn't reading it because of "if(I)", then maybe you weren't including the image when you called the proc?
Threat_Warning(M, I)

The reason I chose to use "if(I)" instead of "for(I in client.images)" is because in the future if you add more than just that reticle to client.images then you will have to cycle through all that is in there and check to see if it is the reticle.
Just to point out.

while(usr.target == T)
if(T.attack())
I.icon_state= "Hostile"


Should have a sleep() inside it. That was the initial error. On a side note while(usr&&T&&usr.target==T) would work better imo.
Wouldn't work BETTER, but it does provide from safety checking. Lol