ID:1677392
 
(See the best response by Sonnet Raven.)
Hello, i am having trouble with a procedure including using for(). i made it so that unless Wet is >0 it doesnt work which what i want, it also only affects two people also.

PROBLEM: when it kills two mobs (using a simple death proc which deletes npcs and respawns users)
it will afflict 2 more Wet people so 4 in total. but only if the first two were deleted. how do i stop this? i only want i to affect 2 people at a time, ive tried re-writting, and using break and continue but no luck.

MY DIAGNOSIS: i think that when the mobs are deleted in death() that M1 or M2 becomes null because the mob gets deleted? ive tried to fix it on this theory but my attempts, it leads me to beleive im wrong.

PS:basic timer is just a timer from my attempt to fix the problem, i really has no effect besides a delay between uses.
Code:
obj
Jutsu
var/Jdamage
Hurt_wets
icon = 'SHOP.dmi'
icon_state = "Sand_B"
jutsu = 1
Jlevel = 1
Click()
Hurt_wets()
verb
Hurt_wets()
var/mob/M2
var/mob/M1
var/damage = usr.chakrapower + 50
for(var/mob/M in ohearers())
if(src.basictimer==0)
if(M.Wet > 0)
if(M1 == null)
if(M1 == null)
if(M != M2)
M1 = M
if(M1.Wet == 1)
var/fdmg = damage
fdmg -= M1.clothing_defence
fdmg -= M1.defence
if(fdmg <0)
fdmg = 0
else
M1.health -= fdmg
M1.Wet = 0
flick("blood_splat",M1)
usr<<"happned[damage]"
M1.DeathCheck()
spawn(1)
if(M1 == null)
M1 = 1
spawn(9)
M1 = null
if(M2 == null)
if(M2 == null)
if(M != M1)
M2 = M
if(M2.Wet == 1)
var/FDMG = damage
FDMG -= M2.clothing_defence
FDMG -= M2.defence
if(FDMG <0)
FDMG = 0
else
M2.health -= FDMG
M2.Wet = 0
flick("blood_splat",M2)
usr<<"happned[damage]"
M2.DeathCheck()
spawn(1)
if(M2 == null)
M2 = 1
spawn(9)
M2 = null
else
break

PLEASE HELP ME, THANK-YOU for reading.
Best response
First off, why are you checking for null values on M1 and M2? You already know they're going to be null since you haven't defined them yet by giving them a value.

Secondly, why are you checking the exact same expression twice with if(M1 == null) and the same with M2? It's completely unnecessary and wastes resources by testing the exact same case twice.

Thirdly, to get to the root of your problem, you're using a for() loop in the completely wrong way. If you want to target two mobs in a for() loop doing one at a time, a quick and dirty way might look like this:

//... stuff before here
var/count = 2 //How many mobs you want to target
var/list/myhearers = ohearers(src, 10) //create a list of mobs in the range
var/mob/M //setup your mob variable
for(var/i=1; i<=count; i++) //A for loop for indexing lists or counting numbers.
M = myhearers[i] //Indexes the list you made of mobs in your range and sets M to the next one in the list.
M.hp -= damage //Do your damage calculations
M.deathcheck() //Do your death check


You'll have to do a little more work if you want it to calculate the distance and hit only the closest targets, but that's the basic jist of it. In its current state, it'll only hit the mobs with the lowest x and y position values, because those are the first mobs in the list.

Calculating mob distances is easy, you just take the whole list of myhearers and cycle through each one, getting the total distance from the centre. I suggest the Pythagorean Theorem since trig is always helpful. Make a list of the closest 2 mobs and use that. If two or more mobs share the same total distance, just pick one at random.

As for your code, I have no idea what it's even supposed to be doing, much less what it's actually doing. I think it would do you some good to hit the books back at square one and take it slowly.
Thankyou, i was trying to use those two vars to fix my problem i should have dismatled it before i put it on, i was using for() wrong like you said, ill just use the getdist proc for the distance. i am making a shonen jump game set in a naruto world, what you just helped me with shark dome. thank-you.
In response to Deidarac4
You know, I'm so used to C++ that I forget that there's a getdist proc... I feel like a caveman scratching out the collective works of Shakespear on a cave wall with a flint rock.
sorry to bother again, everything works great exept one thing i am trying to make a statment to not run the proc if no ones around, and by saying if(M in ohearers(usr,8)) and also a range of others statments would work,if i use if it wont run the proc at all, but if i use for instead of if it works (looping it alot of times obviously).....

so i pretty i cant create an instance for when there are no people around... i also left the other for infront of the other for now because it closest to what i want.
so please, what i am doing wrong in my for/if statement i need it to make the procedure false and stop it. *GRRR it should work!*

                Sand_Burial()
var/mob/M
var/maxC = 2 //How many mobs you want to target
var/list/myhearers = ohearers(usr)//create a list of mobs in the range//setup your mob variable
for(M in myhearers) for(var/i=1, i<=maxC, i++) //A for loop for indexing lists or counting numbers.

M = myhearers[i]//Indexes the list you made of mobs in your range and sets M to the next one in the list.
usr <<"hit[M]"
if(!myhearers) return


Just test whether the list is empty or not when you generate it. That should fix it up.
In response to Sonnet Raven
To iterate through a list:
for(var/[type]/[var name] in [list])
// [var name] is a [type] in [list]

// e.g.
for(var/mob/m in ohearers())
usr << "i see [m]"

To iterate through the first 2 items in a list:
var myhearers[] = ohearers()
for(var/i in 1 to min(2, myhearers.len))
var mob/m = myhearers[i]
usr << "[m] hears me"

ohearers() will never return null. If it's empty, the list will be empty, and the for() loop won't have anything to iterate through, so the loop just won't run.

The min() returns the least of the two numbers. If myhearers has 1 person in it, the loop will run for i = 1 only. If myhearers is empty (myhearers.len == 0), the loop won't run at all. If myhearers contains more than 2 people, it will run from i = 1 to 2.
In response to Kaiochao
Kaiochao wrote:
To iterate through a list:
> for(var/[type]/[var name] in [list])
> // [var name] is a [type] in [list]
>
> // e.g.
> for(var/mob/m in ohearers())
> usr << "i see [m]"
>

To iterate through the first 2 items in a list:
> var myhearers[] = ohearers()
> for(var/i in 1 to min(2, myhearers.len))
> var mob/m = myhearers[i]
> usr << "[m] hears me"
>

ohearers() will never return null. If it's empty, the list will be empty, and the for() loop won't have anything to iterate through, so the loop just won't run.

The min() returns the least of the two numbers. If myhearers has 1 person in it, the loop will run for i = 1 only. If myhearers is empty (myhearers.len == 0), the loop won't run at all. If myhearers contains more than 2 people, it will run from i = 1 to 2.

I never end up using the to keyword, but it's nice, along with the min() proc. Thanks, Kai.
Thankyou for all the help guys, and that explanation on irritating lists really cleared everything up, thankyou again.