HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

UnitStatus

11-14-2009, 04:11 PM#1
Rising_Dusk
UnitStatus Library

Background:
This is a library that allows the user to stun units, silence units, disarm units, ensnare units, and disable units (as a replacement for pausing units). I was originally going to include this in the IBS, but after a lot of thinking I decided it is most useful standalone. These effects are very frequently needed by mapmakers and spellmakers, but are rather complicated and unwieldy to inline directly. I trust that this library will simplify (within reason) these common operations for spell-makers and system-makers alike.

Requirements:Requirements (Optional):Code:
Expand Library:

Function List:
This library provides the following functions to the user.
  • function StunUnit takes unit whichUnit, boolean flag returns boolean
  • function StunUnitTimed takes unit whichUnit, real duration returns boolean
  • function SilenceUnit takes unit whichUnit, boolean flag returns boolean
  • function SilenceUnitTimed takes unit whichUnit, real duration returns boolean
  • function DisarmUnit takes unit whichUnit, boolean flag returns boolean
  • function DisarmUnitTimed takes unit whichUnit, real duration returns boolean
  • function EnsnareUnit takes unit whichUnit, boolean flag returns boolean
  • function EnsnareUnitTimed takes unit whichUnit, real duration returns boolean
  • function DisableUnit takes unit whichUnit, boolean flag returns boolean
  • function DisableUnitTimed takes unit whichUnit, real duration returns boolean
I made xebasic an optional requirement because I believe that xe should only ever be mandatory with spells and that we shouldn't force users to use it if they don't want to. However, xe is useful in this library for it's dummy unit raw id. If xe is in your map, the xe dummy type will be used, otherwise the included constant raw id dummy will be used.

Attached is a testmap that shows this working. Notice that there are spell immune units, flying units, spellcasters, units that attack ground, morphing units, and invisible units. Feel free to try the status effects on all of them. Any issues that exist with the status effects are detailed in the documentation and are impossible to workaround, otherwise the status effects will work on all units.

Enjoy!
Attached Files
File type: w3xUnitStatusTestMap.w3x (67.3 KB)
11-14-2009, 04:55 PM#2
Bobo_The_Kodo
Add a "disable unit" option thing that will won't screw up together with the stun for use instead of pausing units in a jump/charge/something spell. Because pausing units is lame
11-14-2009, 06:01 PM#3
Viikuna-
Yeah. Also adding silence, attack disable and movement disable would be cool.

Dont know why, lols. Maybe because those are like lil parts of the whole stun effect.

Would be cool. And people who need stun control like this, probably need same kind of stuff for those things too.
11-14-2009, 07:23 PM#4
Rising_Dusk
I was actually thinking of doing that. If I do, it will come with some limitations as to the types of buffs the user can use, but I suspect that would be okay since custom buff systems do exist.

A list of things I use frequently and cannot be (easily, if at all) reproduced without using dummy spells:
  • StunUnit
  • DisableUnit
  • SilenceUnit
  • DisableUnitAttack
Can you think of any others? (Don't include things like Sleep or Polymorph, those really aren't that useful and can be done with some hackery in triggers)

EDIT:
I also feel like Stun and Silence are special cases. For many spells, you want to stun or silence a unit for a fixed duration. In the cases of DisableUnit or DisableUnitAttack, these are run more like PauseUnit(MyUnit, BooleanToTurnOnOff). I will create their syntaxes to represent that.
11-14-2009, 08:06 PM#5
Viikuna-
Actually I think all these should be DoSomething( unit, boolean )

But instead of working like blizzard natives they shoudl add/decerease some counter integer:

Collapse JASS:

function StunUnit takes unit u, boolean b returns nothing
   local integer id=GetUnitId(u) 
   if b then
     if StunCount[id]>=0 and not Stunned[id]  then
           // do stun stuff
          set Stunned[id]=true
     endif
      set StunCount[id]=StunCount[id]+1 
   else
         set StunCount[id]=StunCount[id]-1
         if StunCount[id]<=0 and Stunned[id]  then
                 // do un-stun stuff
                set Stunned[id]=false
         endif
    endif
endfunction




Buff systems are to do timed effect stuff and buff systems only. This system should be just to apply some effects on units. ( Anyways, thats how I would do it. )
11-15-2009, 02:28 PM#6
Rising_Dusk
Errr, no. I'm sorry, but things like Stun have durations associated to them, not booleans. One of the biggest uses this library has is that it supports duration-driven stuns. Removing that would be like removing Set/GetTimerData from TimerUtils.
Quote:
Originally Posted by Viikuna-
Buff systems are to do timed effect stuff and buff systems only.
Yes, but stun shouldn't be hard-coded into a buff system, especially if it'd end up name-conflicting some script such as this one. Stun is 'special', it works in a very predictable way that doesn't need the interface of a buff system. It just needs a duration.
Quote:
Originally Posted by Viikuna-
Expand JASS:
This is always such a sticky method. It's great for maps that are designed to work for it, but what if no matter what I want to undisable a unit right now? If the disable unit true call has been made too many times, then there's no way to always undisable the unit without some hackery loop of fail.
11-15-2009, 03:18 PM#7
Tot
Quote:
Originally Posted by Rising_Dusk
I was actually thinking of doing that. If I do, it will come with some limitations as to the types of buffs the user can use, but I suspect that would be okay since custom buff systems do exist.

A list of things I use frequently and cannot be (easily, if at all) reproduced without using dummy spells:
  • StunUnit
  • DisableUnit
  • SilenceUnit
  • DisableUnitAttack
Can you think of any others? (Don't include things like Sleep or Polymorph, those really aren't that useful and can be done with some hackery in triggers)

EDIT:
I also feel like Stun and Silence are special cases. For many spells, you want to stun or silence a unit for a fixed duration. In the cases of DisableUnit or DisableUnitAttack, these are run more like PauseUnit(MyUnit, BooleanToTurnOnOff). I will create their syntaxes to represent that.

I'd add a boolean and a timed version for stun/disabe/silence/disableattack

Better Explanation


e.g. Stun
function StunUnit takes unit u, boolean true returns boolean stuns/unstuns the unit u, returns false if unit wasn't stunned/can't be stunned

function StunUnitTimed takes unit u, real duration returns boolean stunns the unit u for duration sec, returns false if the unit can't be stunned



Insetead of making a Silance and a DisableUnitAttack thing, make something like blizz cloud or silence spells have (an integer, which determines what is done (silence, no ranged, no meele, ...) - nah, some bitflag thingy)
11-15-2009, 06:48 PM#8
Viikuna-
Quote:
It's great for maps that are designed to work for it, but what if no matter what I want to undisable a unit right now?

Well, usually you would just remove all buffs that cause stun effects, but I do get your point: User might wanna make unit resistant to stun effects, without removing buffs that cause stun, since those buffs might do some other stuff too, like damage over time or stuff.


You could make that function take integers instead of boolean, so you could do something like -10000 or +10000 stuff, which should be enough to make unit either not stunned or stunned no matter how many buffs with stunning or anti stunning effects it has. ( But yea, it does look pretty ugly, though. It would be cool to figgure out some nicer syntax for this stuff )

The problem with this method is that unit always has only one stun instance, the one with longest duration.
In some cases we might wanna track those other stun instances too, even though unit can only be stunned or not stunned, and not for example stunned 3 times, which would be like more stunned than stunned 2 times lols.

For example, if you want to cut some buffs duration to half and this buff causes the stun effect that is currently stunning the unit, we should be able to somehow find the buff that causes this second longest stun duration, so we can apply this second longest stun duration to this unit.

( In case that this remaining half of longest stun duration is less than duration of this second longest stun duration. )

Or same thing if buff causing the longest stun effect is dispelled. The second longest stun effect should still be there.



( I hope that this complicated explanation of mine makes any sense )
11-15-2009, 07:58 PM#9
Rising_Dusk
Yes, I guess you could just set a given unit's count to 0 and remove the buff if you wanted to remove it all.
Quote:
Originally Posted by Viikuna-
The problem with this method is that unit always has only one stun instance, the one with longest duration.
In some cases we might wanna track those other stun instances too, even though unit can only be stunned or not stunned, and not for example stunned 3 times, which would be like more stunned than stunned 2 times lols.

For example, if you want to cut some buffs duration to half and this buff causes the stun effect that is currently stunning the unit, we should be able to somehow find the buff that causes this second longest stun duration, so we can apply this second longest stun duration to this unit.
Collapse JASS:
call RemoveStun(u)
call StunUnit(u, NewShorterDuration)
If you'd really want to "set" stun duration without doing what I showed just above, then I could introduce a very simple "SetStunDuration" function. Really, the counter method works I guess, but it's no faster than my current method if you factor in that stuns need durations.

I'll use the counter method for things like disabling a unit or whatever, since it is good for those cases where durations don't matter.
11-15-2009, 09:26 PM#10
Anitarf
Quote:
Originally Posted by Rising_Dusk
Collapse JASS:
call RemoveStun(u)
call StunUnit(u, NewShorterDuration)
That will not work correctly if there is another buff on the unit causing the stun effect with a longer duration remaining.
11-15-2009, 09:40 PM#11
Rising_Dusk
Quote:
Originally Posted by Anitarf
That will not work correctly if there is another buff on the unit causing the stun effect with a longer duration remaining.
The whole point of his issue with my method was to reduce the duration of the stun.
11-15-2009, 09:51 PM#12
Anitarf
Quote:
Originally Posted by Rising_Dusk
The whole point of his issue with my method was to reduce the duration of the stun.
The way I understood it, he wanted to reduce the duration of one source of the stun. Doing that in a map where other stun sources may be present is the tricky part, you would need some sort of a refcounted buff to accomplish that.
11-15-2009, 09:59 PM#13
Rising_Dusk
But how does that even make sense to reduce the duration of only one source? A unit is either stunned for X seconds or not, that's the only way it makes sense to me. I see what you're saying for like, non-duration stuns, but...
11-15-2009, 10:13 PM#14
Anitarf
Stun (and status effects in general) could be applied in more ways than just the standard "stun for X seconds" format of WC3.

Consider some type of "fear" buff that stuns the unit as long as a big enemy unit is in range. Then that big enemy unit is killed or driven off, or the buff is dispelled: the stun source is thus removed, but that doesn't necessarily mean the unit should be de-stunned, since another similar effect could still be keeping it stunned. The stun status effect should only be removed once the last source is removed, which calls calls for some sort of buff with a reference counter.
11-15-2009, 10:41 PM#15
Rising_Dusk
Hrm, yes, I see. So that means that the library should support both timed stuns and this StunUnit(u, true) syntax. Both of these would be refcounted and stuff then.