HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Proof-reading Script: Plague Zombie

12-29-2008, 01:58 PM#1
Archmage Owenalacaster
A few months ago I tinkered with making Zombies that reanimate when killed, and then figured out how to make them spread a zombifying disease and decay when they reanimate. I succeeded, whoo, then grew bored and engaged reality.

Anyway, a few weeks ago I returned to scripting. and after looking over my work realized how messy and inefficient it was. I've been retooling since then. I dropped the decay, added scripted damage (instead of ability-caused damage) and have housed the mess in a nice library with reconfigurable constants.

Now for the sake of efficiency and my further education, I invite a proof-read of the code. Obviously, I welcome constructive criticism and suggestions for additions (or subtractions).

UPDATE: Replaced the old with the new.
Expand JASS:
12-29-2008, 02:26 PM#2
Zerzax
For one thing, you can condense your big ole conditions into one line ones:
Collapse JASS:
    return GetUnitAbilityLevel( GetAttacker(), PLAGUE_ABILITY ) > 0 or GetUnitAbilityLevel( GetTriggerUnit(), PLAGUE_BUFF ) == 0 or IsUnitType(GetTriggerUnit(), UNIT_TYPE_UNDEAD) == false or .....

You get the point. Also, to avoid all those GetTriggerUnit() function calls you might want to just set a global for just this condition, that way at the beginning of your condition you set it and the one-line condition runs without all those extra GetTriggerUnit()'s. Just an idea.

Also, use GetWidgetLife() instead of GetUnitState, I think it's just more efficient and easier to write. I'll post this now and take another look.

EDIT: And I just noticed you were using waits in a short interval, within a loop. I'd recommend using timers for this, more specifically TimerUtils. It will associate that player ID you want to the timer and be MUCH more efficient, safe, and precise than using TriggerSleepAction.
12-29-2008, 02:37 PM#3
moyack
You can use only one trigger in the init part:

Expand JASS:

* In the function TrigAction you don't need to null the player variable, player handles are constant data and null the variable is useless.

Hmm, you're using Kattana's handle vars, you can replace it with Table which allow a shorter syntax.
12-29-2008, 05:45 PM#4
Archmage Owenalacaster
Quote:
Originally Posted by Zerzax
For one thing, you can condense your big ole conditions into one line ones...

You get the point. Also, to avoid all those GetTriggerUnit() function calls you might want to just set a global for just this condition, that way at the beginning of your condition you set it and the one-line condition runs without all those extra GetTriggerUnit()'s. Just an idea.

Also, use GetWidgetLife() instead of GetUnitState, I think it's just more efficient and easier to write. I'll post this now and take another look.

EDIT: And I just noticed you were using waits in a short interval, within a loop. I'd recommend using timers for this, more specifically TimerUtils. It will associate that player ID you want to the timer and be MUCH more efficient, safe, and precise than using TriggerSleepAction.
Conditions trimmed but not one-lined, multiple GetTriggerUnit calls replaced with local unit variable which I null before return, and I see no value in storing it in a global.

GetWidgetLife replaces GetUnitState.

TriggerSleepAction replaced with TimerUtils and private function SafeWait:
Expand JASS:
However, I do not use it to store any data.

Quote:
Originally Posted by moyack
You can use only one trigger in the init part...

* In the function TrigAction you don't need to null the player variable, player handles are constant data and null the variable is useless.

Hmm, you're using Kattana's handle vars, you can replace it with Table which allow a shorter syntax.

Initial local trigger made singular as per your suggestion.

I thought, since player extends handle, that the pointer would not be autocleaned and would leak. Am I mistaken?

And I'm not using Kattana's handle vars. Not that I'm aware of anyway.

EDIT: Update the script in the first post.
12-29-2008, 07:15 PM#5
Zerzax
I like the way you remade the condition. Also, instead of writing
SomeCondition == false
or
SomeConditiion == true

You can write
SomeCondition
or
not SomeCondition

Player does extend handle but because every player handle is permanent there is no need to force the handle count to decrement, it will never be destroyed.

I still think it would be a good idea to use TimerUtils more completely and use a structure, and associate structure instances to a timer. The timer would run periodically and reference that structural instance on each iteration. Really up to you though, especially since you are only damaging. I try to avoid waits, despite their ease of use and simplicity

EDIT: I think Moyack means gamecache usage in general. If you are going to use gamecache, I would recommend Table like he said.
12-30-2008, 09:36 PM#6
Archmage Owenalacaster
I've been debugging the conditions. During tests, the infection would only spread to humans (read: Damage_TrigCondition was returning false). Which is difficult to comprehend, since I don't perform a race check.
EDIT 2: The triggers weren't getting registered for Neutral Hostile and other neutral players. Fixed.

Thanks for the information on the player handles. That's one less line of code.

I've not to date written a struct before, so I'm a bit nervous. I shall need to look over other scripts to get an idea of how it ought to work. However, it was my understanding that TriggerSleepAction is safe when used in conjunction with a timer, since checking the timeRemaining avoids the problems otherwise encountered with dual-processors. That said, I would still like to learn how to use periodic timers to reference struct instances.

I've considered using globals to store the two triggers, since a player may want to disable one or the other during the course of a game.

I read about Table, but I do not immediately see it's use to this library. Since I only use the gamecache to store an integer for the player index, I think making this library require a whole other system would be superfluous. Are there any potential bugs or other dangers of which I ought to be aware that Table resolves?

With each test, I debug the script (PlagueZombie is the only one giving me trouble so far) and debug the AI (both players run smoothly, but stupidly), both of which are JASS. This effectively doubles the time between my updates. I should have something to show within about an hour.

EDIT: New Damage_TrigCondition
Expand JASS:

EDIT 3: Added settings for timed life and food use, set triggers to global values.

EDIT 4: Updated the first post again.

One issue still looms that I shall need to address. The damage trigger fires when a unit is attacked, but before it is hit by the attack. This is silly when projectiles and missing is involved.
12-30-2008, 10:09 PM#7
Zerzax
I think you can use Anitarf's Adamage for that: http://wc3campaigns.net/showthread.php?t=102079

Or some attack detection system.

Also, for going into vJASS and structs in particular, Vexorian has a good tutorial for struct basics.