HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Elusive bug, any bright ideas?

08-01-2007, 07:24 PM#1
NightBreeze
There is a bug in a spell I've made that I can't seem to fix. I think it's best if I explain the spell first. The idea is that the hero that casts it creates a sandstorm (hence the name). I use mana shield as a dummy ability (which does nothing), catch the order and use it to run the casting function. This function creates a periodic timer which updates the sandstorm. In the timerfunction, 10 effects are created each iteration. I use 2 different effects: the sandstorm and the sandwall. The sandstorm are little effects of sand around the hero, 9 in total, which disappear after 2 seconds. The sandwall is a big sandexplosion that dissipates after 5 seconds. After the effects have been created, I gather all the units around the hero in a group using a certain condition (it just checks if the unit is NOT the hero). OK so we have that group, then I store the location of the sandwall on the timer and iterate through all the past stored sandwall locations. The if/else is used so that when the runtime of the timer exceeds the time a single sandwall exists, that that sandstorm's location is no longer looped through. I gather all the units around a sandstorm's location and put them in the big 'slowgroup' if they are not already in it. Then when I'm done with that, I slow all the units in the slowgroup and store it on the timer (the group). That group is put in the oldslowgroup local at the start of the iteration and those which are in that group, but not in the new slowgroup are unslowed. The last part of the function which should be understood is that when sandstorm is deactivated, the timer has to keep running until the last sandwall has disappeared. That is why I use the 'stopruntimes' integer and sandstorming boolean (that is also used for something else, but that's not of any importance). When it is stopped, the timerfunction doesn't create effects, but keeps on slowing and unslowing.

OK that should give you some direction when reading the code.

Now for the problem. When I run this function, I get some red lines that tell me how many groups have been created and how many are undestroyed. Naturally a lot of groups have been created but I (think I've) made sure that the function has no leaking groups. This seems to be the case, since the debug says that there are very few undestroyed groups and all of which are not in use by the updatefunction. Now, there are 2 things going on here. When I run the ability for like..5+ seconds, it starts to lag. It doesn't seem to have anything to do with the amound of effects created, because when I set it so that it creates 5x as many effects, there is no more lag than usual. The weird thing is however that when I switch sandstorm off (the effects created are still there), the lag disappears completely in under a second. I have no idea why this is happening.

The second strange thing is that when the hero which is sandstorming approaches a unit for the first time, the screen freezes for about 2 seconds. After that, it never happens again. Not even when I switch sandstorm off/on and approach a unit again. This would seem to have something to do with the slowing/cursing part of the skill. Since the hero is always present when casting sandstorm, but is not grouped because of the condition, it seems that when casting the cursing spell for the first time causes lag...? I've used dummy casters and spells in a lot of different abilities, but never ever got this much lag.

Do you have any ideas? I've tried to be as thorough as I can but I can imagine I left crucial information out. I hope you can help me. I've included the map as well, the hero in question is the Crypt Lord. Pay no attention to the other heroes, since more than half of them still posess some bugs

Thanks in advance.

Collapse JASS:
//SandStorm==================================================================================
constant function Sandstorm takes nothing returns integer
    local integer i = 'A01W'
    return i
endfunction

constant function SandstormCurseBuff takes nothing returns integer
    local integer i = 'B016'
    return i
endfunction

function SandstormTargetSlowRemove takes nothing returns nothing
    local unit target = GetEnumUnit()
    local real slow = GetHandleReal(target, "sandstormslow")
    call Msg("Slow removed on target, sandstormslow on target was " + R2S(slow))
    call UnitRemoveAbility(target, SandstormCurseBuff())
    call SetUnitMoveSpeed(target, GetUnitMoveSpeed(target)+slow)
    set target = null
endfunction

function SandstormCancel takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local timer sandt = GetHandleTimer(hero, "sandt")
    local group slowgroup
    call Msg("SandStormCancel runs")
    if sandt == null then
        call Msg("OMG WHERE IS TEH TIMERZ!?!/11")               //obvious debug
    endif
    call SetHandleBoolean(hero, "sandstorming", false)
    call TriggerSleepAction(5)
    set slowgroup = GetHandleGroup(sandt, "slowgroup")
    call PauseTimer(sandt)
    call DestroyTimer(sandt)
    call ForGroup(slowgroup, function SandstormTargetSlowRemove)
    call DestroyGroup(slowgroup)
    set slowgroup = null
    set hero = null
    set sandt = null
endfunction

function SandstormTargetSlow takes nothing returns nothing
    local unit target = GetEnumUnit()
    local unit hero = udg_tempunit
    local real slow = udg_tempreal
    local integer abillevel = R2I(I2R(GetUnitAbilityLevel(hero, Sandstorm())) / GetHeroLevel(hero) * 10)
    call Msg(I2S(abillevel))
    call Msg("SandstormTargetSlow runs")
    if (GetUnitAbilityLevel(target, udg_buffs[36]) == 0) then
        call CastWidgetAbility(GetOwningPlayer(hero), 36, abillevel, target, 0.0)
        call SetUnitMoveSpeed(target, GetUnitMoveSpeed(target) - slow)
        call SetHandleReal(target, "sandstormslow", slow)
        call Msg("Target slowed")  
    endif
    set target = null
    set hero = null
endfunction

function SandstormSlowCondition takes nothing returns boolean
    local unit target = GetFilterUnit()
    local unit hero = udg_tempunit
    local boolean validtarget
    set validtarget = TargetTypeConditionEasy(target, hero, 0,0,0,0,0,0,0,0,0,0,2)
    call Msg("SandstormSlowCondition runs")
    if validtarget then
        call Msg("Valid target found")
    endif
    return validtarget
endfunction

function SandwallGroupAdd takes nothing returns nothing
    local unit target = GetEnumUnit()
    local group swgroup = udg_tempgroup
    call Msg("SandwallGroupAdd runs")
    if not IsUnitInGroup(target, swgroup) then
        call GroupAddUnit(swgroup, target)
        call Msg("Unit added to sandwallslowgroup")
    endif
    set udg_tempgroup = swgroup
    set swgroup = null
endfunction

function SandstormUpdate takes nothing returns nothing
    local timer sandt = GetExpiredTimer()
    local unit hero = GetHandleUnit(sandt, "hero")
    local real herox = GetWidgetX(hero)
    local real heroy = GetWidgetY(hero)
    local real sandslow = I2R(GetUnitAbilityLevel(hero, Sandstorm())) / I2R(GetHeroLevel(hero)) * 500.0
    local real dt = GetHandleReal(sandt, "sanddt")
    local integer timesrun = GetHandleInt(sandt, "timesrun")
    local integer stoptimesrun = GetHandleInt(sandt, "stoptimesrun")
    local real stoptime = stoptimesrun * dt
    local real runtime = timesrun * dt
    local effect sandstorm
    local real sandstormdelay = 2
    local effect sandwall
    local real sandwalldelay = 5
    local real sandwallx
    local real sandwally
    local real sandwallradius = 350
    local real effdist = 80
    
    local group closeslowgroup = CreateGroup()
    local group sandwallslowgroup = CreateGroup()
    local group oldslowgroup = GetHandleGroup(sandt, "slowgroup")    
    local group slowgroup = CreateGroup()
    local group tempswgroup = CreateGroup()

    local integer a = 1
    local integer i = 0
    local integer debugint
    
    call Msg("SandstormUpdate runs")
    
    if oldslowgroup == null then
        call Msg("oldslowgroup is null at start of update")
    endif
    
    set timesrun = timesrun + 1
    call SetHandleInt(sandt, "timesrun", timesrun)
    set runtime = timesrun * dt
    
    if GetHandleBoolean(hero, "sandstorming") then    
        //Creating all the effects
        set sandwall = AddSpecialEffect("war3mapImported\\SandAura.MDX", herox, heroy)
        call DestroyEffectWait(sandwall, sandwalldelay)
        set sandstorm = AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", herox, heroy) 
        call DestroyEffectWait(sandstorm, sandstormdelay)
        loop
            exitwhen i == 8
            set sandstorm = AddSpecialEffect("Objects\\Spawnmodels\\Undead\\ImpaleTargetDust\\ImpaleTargetDust.mdl", herox + effdist * Cos(i * 0.25  * bj_PI) , heroy  + effdist * Sin(i * 0.25  * bj_PI)) 
            call DestroyEffectWait(sandstorm, sandstormdelay)
            set i = i + 1
        endloop
    
        call Msg("Sandstorm effects created")
                
        //Storing the location of this iteration's sandwall
        call SetHandleReal(hero, "sandwallx" + I2S(timesrun), herox)
        call SetHandleReal(hero, "sandwally" + I2S(timesrun), heroy)
        
        
        //Collecting the units around the hero that have to be slowed
        set udg_tempunit = hero
        call GroupEnumUnitsInRange(closeslowgroup, herox, heroy, effdist+30, Condition(function SandstormSlowCondition))
        
        call Msg("closeslowgroup made")    
    else 
         set stoptimesrun = stoptimesrun + 1
         call SetHandleInt(sandt, "stoptimesrun", stoptimesrun)
         set stoptime = stoptimesrun * dt
    endif
        
    
    //Filling the group of units around the sandwalls
    if runtime > sandwalldelay then
        set a = R2I((runtime - sandwalldelay)/dt)
        call Msg("runtime > sandwalldelay")
        call Msg("stoptimesrun is " + I2S(stoptimesrun))
        set debugint = 0
        loop
            set debugint = debugint + 1
            exitwhen a > timesrun - stoptimesrun
            call Msg("groupadd loops loc # " + I2S(a))
            set sandwallx = GetHandleReal(hero, "sandwallx" + I2S(a))
            set sandwally = GetHandleReal(hero, "sandwally" + I2S(a))
            call Msg("sandwallx is " + R2S(sandwallx) + ", sandwally is " + R2S(sandwally))
            set udg_tempunit = hero
            call GroupEnumUnitsInRange(tempswgroup, sandwallx, sandwally, sandwallradius, Condition(function SandstormSlowCondition))
            set udg_tempgroup = sandwallslowgroup
            call ForGroup(tempswgroup, function SandwallGroupAdd)
            call GroupClear(tempswgroup)
            set sandwallslowgroup = udg_tempgroup
            set a = a + 1
        endloop
        call Msg("# of loops was.."+I2S(debugint))
    else
        call Msg("runtime <= sandwalldelay")
        loop
            exitwhen a > timesrun - stoptimesrun
            call Msg("groupadd loops loc # " + I2S(a))
            set sandwallx = GetHandleReal(hero, "sandwallx" + I2S(a))
            set sandwally = GetHandleReal(hero, "sandwally" + I2S(a))
            call Msg("sandwallx is " + R2S(sandwallx) + ", sandwally is " + R2S(sandwally))
            set udg_tempunit = hero
            call GroupEnumUnitsInRange(tempswgroup, sandwallx, sandwally, sandwallradius, Condition(function SandstormSlowCondition))
            set udg_tempgroup = sandwallslowgroup
            call ForGroup(tempswgroup, function SandwallGroupAdd)
            call GroupClear(tempswgroup)
            set sandwallslowgroup = udg_tempgroup
            set a = a + 1
        endloop
    endif

    call Msg("groupadd loop finished")
    
    call GroupAddGroup(closeslowgroup, slowgroup)
    call GroupAddGroup(sandwallslowgroup, slowgroup)
    set udg_tempunit = hero
    set udg_tempreal = sandslow
    call ForGroup(oldslowgroup, function SandstormTargetSlowRemove)
    call ForGroup(slowgroup, function SandstormTargetSlow)
    call SetHandleHandle(sandt, "slowgroup", slowgroup)
    
    call DestroyGroup(closeslowgroup)
    call DestroyGroup(sandwallslowgroup)
    call DestroyGroup(oldslowgroup)
    call DestroyGroup(tempswgroup)
    
    set closeslowgroup = null
    set sandwallslowgroup = null
    set oldslowgroup = null
    set slowgroup = null
    set tempswgroup = null
    set sandt = null
    set hero = null
    set sandwall = null
    set sandstorm = null
endfunction

function SandstormCast takes nothing returns nothing
    local unit hero = GetTriggerUnit()
    local timer sandt = CreateTimer()
    local timer sandslowt = CreateTimer()
    local real sanddt = 0.3
    call Msg("SandstormCast runs")
    call SetHandleHandle(sandt, "hero", hero)
    call SetHandleHandle(hero, "sandt", sandt)
    call SetHandleBoolean(hero, "sandstorming", true)
    call SetHandleReal(sandt, "sanddt", sanddt)
    call TimerStart(sandt, sanddt, true, function SandstormUpdate)
    set hero = null
    set sandt = null
    set sandslowt = null
endfunction
Attached Files
File type: w3xTestMapThom v2.1.w3x (689.9 KB)
08-01-2007, 07:34 PM#2
cohadar
I am not sure if you should call functions with waits in a periodic timer.

Here is a general solution for you:
1. Install newGen
2. Put all spell data in struct
3. attach the struct to a timer

using zillion handles on a timer can only confuse you and make it easy to make mistakes.
08-01-2007, 07:39 PM#3
NightBreeze
I am already using newgen and the functions that are being called with waits use executefunc(). Besides that.. I don't find anything confusing about the amount of handles used here. Isn't that a bit offtopic?
08-01-2007, 07:52 PM#4
cohadar
Actually it is not off topic, you asked for a bright ideas remember

See the thing is this, when you pass handles directly
if you have 10 handles you have to do
10 set functions on a timer

call SetHandleHandle(sandt, "hero", hero)
call SetHandleHandle(hero, "sandt", sandt)
call SetHandleBoolean(hero, "sandstorming", true
...

and then declare 10 local variables
and then do 10 get functions

and by the time you complete you code has 3 pages
and you havent even started to code the spell.

If on the other hand you use structs,
you just fill the struct in init function
set struct to a timer
in periodic get struct from a timer
and tada.. you can use all 10 variables without problems,
witch is more it will be a LOT faster than
using gamecache 10 times in every period

So bottom line:
smaller code = easier to find errors
faster code = no lag

All you have to do is forget about handle vars and start using structs.

All the pros do it.. so think about it.
08-01-2007, 08:57 PM#5
NightBreeze
I guess you have a point. I don't mind the coding at all, but I can't argue that it's not easier using a struct. I'm just used to using the jasscraft syntax checker and the structs get compiled into 'normal' code anyway.. still a bit faster yes, but not even close to causing this kind of lag. The readability of the code is perfect for me, even more so if I throw in some comments. However I suppose I could get used to the structs as well and it's easier to read for other people. So I think I'll agree with you on this one :) Not that big a deal though, since there are only like.. 4-5 variables being stored.

And yes, you were right about the bright ideas. Sincerest apologies for my rudeness.

p.s. I have been coding jass for less than 2 weeks now, still trying to figure out the style I want.
08-01-2007, 09:07 PM#6
cohadar
Thanks for apologizing it makes a world a better place.

Also I would like to say that it is sometimes easier to write your spells down on paper, not the code of course, but a sketch of where things should go.
It really helps with spells involving geometry.
08-01-2007, 09:16 PM#7
moyack
First some comments:

Collapse JASS:
constant function Sandstorm takes nothing returns integer
    local integer i = 'A01W'
    return i
endfunction
Can be written as:
Collapse JASS:
constant function Sandstorm takes nothing returns integer
    return 'A01W'
endfunction

About your problem, it's similar to one situation that happens to me with one spell that which manages too much effects, groups and effects which are variable in amount. the problem is that you have to abuse of game cache and in some way or another, the type casting tends to fail, in a random way. why this happens?? At the moment I don't know.

My solution: use vJASS and the beautiful structs.
08-01-2007, 09:32 PM#8
cohadar
Quote:
Originally Posted by moyack
the problem is that you have to abuse of game cache and in some way or another, the type casting tends to fail, in a random way. why this happens?? At the moment I don't know.

I do.
when you store handles to a game cache without keeping
the original handle in game memory
after some time the game will recycle that handle number
and when you return the handle from memory it will point to a location
that is now occupied by another handle.

And as we all now 2 things cannot be at the same place
in the same time unless they are subatomic pi-mesons

That is why people say I2H is a nono,
and that is another reason why using structs is better than handle vars,
structs are simply integers, they are not handles,
therefore they cannot get garbled.
(I said garbled because I didn't want to say fucked up)
08-01-2007, 09:50 PM#9
NightBreeze
Quote:
Originally Posted by cohadar
Thanks for apologizing it makes a world a better place.

Also I would like to say that it is sometimes easier to write your spells down on paper, not the code of course, but a sketch of where things should go.
It really helps with spells involving geometry.

Hmm yeah thanks for the tip but I already do that :)

Quote:
Originally Posted by moyack
First some comments:

JASS:
constant function Sandstorm takes nothing returns integer
local integer i = 'A01W'
return i
endfunctionCan be written as: JASS:
constant function Sandstorm takes nothing returns integer
return 'A01W'
endfunction
About your problem, it's similar to one situation that happens to me with one spell that which manages too much effects, groups and effects which are variable in amount. the problem is that you have to abuse of game cache and in some way or another, the type casting tends to fail, in a random way. why this happens?? At the moment I don't know.

My solution: use vJASS and the beautiful structs.

I seem to recall that that didn't work for the constant function, but I believe you.

About the second you said.. that isn't really of much help to me. You're just saying that I use gamecache too much. I don't really have any evidence that I'm overloading it.. I have other spells that use it just as much and there are no problems with misplaced pointers or whatever. I've tested that dilligently with messages. Furthermore, from what I know of structs, they don't hold that big an advantage over using the gamecache that it could solve this problem. Besides, the lag is really strange. Maybe you should try my testmap (it's the crypt lord)

Quote:
Originally Posted by cohadar
I do.
when you store handles to a game cache without keeping
the original handle in game memory
after some time the game will recycle that handle number
and when you return the handle from memory it will point to a location
that is now occupied by another handle.

And as we all now 2 things cannot be at the same place
in the same time unless they are subatomic pi-mesons

That is why people say I2H is a nono,
and that is another reason why using structs is better than handle vars,
structs are simply integers, they are not handles,
therefore they cannot get garbled.
(I said garbled because I didn't want to say fucked up)

I know this and I know it's an explanation for the fucking up of handle vars, but there's still no reason I can assume that that's the problem here :/ I use the handle var system throughout the entire map with abilities that are more complex than this one. I won't argue with you that the handlevar system has its limits and that structs could be better, but I still have no reason to think that that's what's causing it... there are no misplaced variables or wrong pointers, it just lags... as if its leaking, but it's not leaking.

The reason I'm saying this is that even though it may be worth a shot if all else fails, I hope you can continue to think of a different cause/solution besides using structs... it's just unlikely that it will solve anything
08-01-2007, 10:09 PM#10
moyack
Quote:
Originally Posted by NightBreeze
I seem to recall that that didn't work for the constant function, but I believe you.

About the second you said.. that isn't really of much help to me. You're just saying that I use gamecache too much. I don't really have any evidence that I'm overloading it.. I have other spells that use it just as much and there are no problems with misplaced pointers or whatever. I've tested that dilligently with messages. Furthermore, from what I know of structs, they don't hold that big an advantage over using the gamecache that it could solve this problem. Besides, the lag is really strange. Maybe you should try my testmap (it's the crypt lord)
Sorry if I disappoint you, but believe, when you have bugs which happens randomly and your spell manage several types of handles (effects, lightnings, groups, etc) via gamecache, it seems that in some points is missing or overwrites the data, to be honest I still don't know what's wrong.

I've solved my problem learning structs, with them I was able to simplify the spell greatly, and now I access directly the handles instead calling them indirectly by type casting (I2H nightmare).

I'll check your spell this night (I'm at the office right now) and I'll see if I can help you in any way.
08-01-2007, 10:32 PM#11
NightBreeze
Quote:
Originally Posted by moyack
Sorry if I disappoint you, but believe, when you have bugs which happens randomly and your spell manage several types of handles (effects, lightnings, groups, etc) via gamecache, it seems that in some points is missing or overwrites the data, to be honest I still don't know what's wrong.

I've solved my problem learning structs, with them I was able to simplify the spell greatly, and now I access directly the handles instead calling them indirectly by type casting (I2H nightmare).

I'll check your spell this night (I'm at the office right now) and I'll see if I can help you in any way.

I hope you will look carefully through my code, because I feel pretty confident that I coded it cleanly. They aren't just random bugs, they are very recognizable, distinct amounts of lag. I really doubt it's as simple as saying "it has too many handles and gamecache abuse, use structs". If it was leaking lag (which I had earlier in the construction of this spell), you could give the same argument about my code. I think it's too short-sighted to say that the handlevars system is fucking up, period. If that were true, I should be able to notice it in functionality. Every iteration, every variable is as it should be... It looks and smells like a leak, but I can't find it.

What problem did you solve?
08-01-2007, 10:48 PM#12
Vexorian
Quote:
I think it's too short-sighted to say that the handlevars system is fucking up

It is not handle var's fault, it is blizzard's they didn't really expect the ref counter on handles to be compatible with things like i2h so things mess up.

..
Recipe for chaos
- Creating and destroying timers.
- Attaching things to timers and loading them using i2h (or equivalents)
- Using executefunc in a timer function so it has waits.
- Destroying the timer somewhere in between.

In short you are doing a lot of things that cause issues, it is not your fault and as one of the guys that first used handle vars must say that it is not handle vars' fault either, but global arrays tend to resist more against these things than handle vars, and structs use global arrays, so ...
08-01-2007, 10:59 PM#13
moyack
... use Jass New Jen Pack now and enjoy the pleasure of structs :)
08-01-2007, 11:20 PM#14
NightBreeze
Quote:
Originally Posted by Vexorian
It is not handle var's fault, it is blizzard's they didn't really expect the ref counter on handles to be compatible with things like i2h so things mess up.

..
Recipe for chaos
- Creating and destroying timers.
- Attaching things to timers and loading them using i2h (or equivalents)
- Using executefunc in a timer function so it has waits.
- Destroying the timer somewhere in between.

In short you are doing a lot of things that cause issues, it is not your fault and as one of the guys that first used handle vars must say that it is not handle vars' fault either, but global arrays tend to resist more against these things than handle vars, and structs use global arrays, so ...


I guess I can't get around the fact that chaos can ensue when you code stuff my way. However, could you be a bit more concrete? If only for my learning process. Do you have any idea what 'these things' are or what exactly goes wrong when doing the things you described above. I understand that one could label it as 'risky' business because everything that involves timing is error-prone and hard to debug, but I honestly don't understand what could go wrong in this situation. Perhaps you could take a look at my map and see what kind of lag I am talking about? I am curious if you'll keep your opinion about what's causing this. Again, I am convinced that this could be a more messy way of coding than using structs, but still.. I don't get it. It can't be a pointer problem, it doesn't look like a leaking problem. The cancelling of the sandstorm ability destroys the timer and the group and somehow fixes all the lag almost instantly. That about rules out the leaking possibility and would lead me to believe that, over time, the amount of work that has to be done each iteration is too big. But I've checked with messages how much he does (the amount of GroupEnumUnitsInRange with the sandwall's locations) and it doesn't increase past a certain limit.

I guess it's just curiosity now (especially since I use this structure throughout my entire map and have always been able to fix timing issues or storing issues). Maybe there's also still a part of me that believes in this system and doesn't think the structs will fix it :)

One final question: "global arrays tend to resist more against these things than handle vars". What things? General weirdo functionality bugs? Lagging issues? Pointer problems? Timing problems?

I would like to thank everyone for their time btw :) A lot of responses in only a few hours.
08-02-2007, 07:14 AM#15
cohadar
See the reason none of us can be more specific about what is your problem is simply because we don't know.
And it is impossible to know, bugs connected with I2H are just too elusive
and even if all the code seems to work sometimes it does not.

If you are interested why exactly is it so random here is the answer:

The thing that fucks up handles is handle recycler (garbage collector)
and it works in a separate thread from your code.
That means that it can do stuff to handles at the same time as your code
(and since these 2 thread are not synchronized ...)

As for the lag:
gamecache is sensitive to order in witch you restore variables from it.
Also note that gamecache is actually a file on your hard disk.
when you do stuff like
call SetHandleBoolean(hero, "sandstorming", true)
he writes that somewhere in file,
sandstorming | true
and when you do a get he needs to find a line in file that has
"sandstorming" and return the value to you.

wc3 is accessing hard disc for other reasons also,
if for example heroes or effects or whatever is not preloaded
the first time you use it in a game wc3 will access the hard disk to
read that data from your map (no it does not load the whole map at startup)

So to conclude, I don't know what exactly is wrong with your spell,
and frankly I don't wanna know, I am trying to forget handle vars.

Learn structs -
* it will be easier to make spells,
* it will not lag
* and when you have a problem you will get help more likely