• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Revivable Units v1.3.3b

  • Like
Reactions: QuantumMatter
  • Toggle any unit type per player or for all players
  • Option to allow normal training for other players
  • Option to show a configurable dissipate effect on death (default)
  • Show a configurable revive effect
  • Revivable unit types are limited to one unit (optional)

API

Note that in order to use the GUI configuration, you also need all the triggers in the "Revive Config Functions" category, as well as all the variables and their initial values.

NOTE: Don't forget that units have to be added to a building (e.g. Altar) manually in order to build them.
  • SetUnitsGUI
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Footman for All Players --------
      • Set UnitType = Footman
      • Set Players = AllPlayers
      • Trigger - Run AddType <gen> (ignoring conditions)
      • -------- Grunt for All Players except Player 2 (blue) --------
      • Set UnitType = Grunt
      • Set Players = AllPlayers
      • Trigger - Run AddType <gen> (ignoring conditions)
      • Set Players = (Player number of Player 2 (Blue))
      • Trigger - Run RemoveType <gen> (ignoring conditions)
      • -------- Ghoul for Player 1 (red) --------
      • Set UnitType = Ghoul
      • Set Players = (Player number of Player 1 (Red))
      • Trigger - Run AddType <gen> (ignoring conditions)
      • -------- Ghoul available normally for other players --------
      • Set AllowAll = True
      • Trigger - Run AllowNormalTraining <gen> (ignoring conditions)
      • -------- Archer for Player 2 (blue) --------
      • Set UnitType = Archer
      • Set Players = (Player number of Player 2 (Blue))
      • Trigger - Run AddType <gen> (ignoring conditions)
      • -------- Fel Stalker for Player 1 & 2 (red & blue) --------
      • Set UnitType = Fel Stalker
      • Set Players = (Player number of Player 1 (Red))
      • Trigger - Run AddType <gen> (ignoring conditions)
      • Set Players = (Player number of Player 2 (Blue))
      • Trigger - Run AddType <gen> (ignoring conditions)
      • -------- Fel Stalker can be trained more than once for Player 1 (red) --------
      • Set Players = (Player number of Player 1 (Red))
      • Set AllowMultiple = True
      • Trigger - Run AllowMultiple <gen> (ignoring conditions)
      • -------- Priest (Blood Mage model) for Player 1 (red) - using Dissipate animation --------
      • Set UnitType = Priest
      • Set Players = (Player number of Player 1 (Red))
      • Trigger - Run AddType <gen> (ignoring conditions)
      • Trigger - Run HasDissAnim <gen> (ignoring conditions)


NOTE: Anything left to default can be deleted, since defaults are already set in the code. Only included here for demonstration.
  • ConfigureDissipateGUI
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Configure the Dissipate Effect --------
      • -------- -- These are the default settings --------
      • Set confDelay = 3.00
      • Set confOpacity = 200
      • Set confDuration = 2.00
      • Set confIncrement = 0.03
      • Set confHeight = 530.00
      • Trigger - Run ConfigureDissipate <gen> (ignoring conditions)
      • -------- Set Dissipate Effect per race --------
      • -------- -- These are the default settings --------
      • -------- -- Only Undead has a dissipate model w/ sound --------
      • Set Race = Undead
      • Set EffectString = Objects\Spawnmodels\Undead\UndeadDissipate\UndeadDissipate.mdl
      • Set Sound = No sound
      • Trigger - Run ConfigureDissSFX <gen> (ignoring conditions)
      • -------- -- Rest has no dissipate model, so setup sound --------
      • Set Race = Human
      • Set EffectString = <Empty String>
      • Set Sound = HumanDissipate1 <gen>
      • Trigger - Run ConfigureDissSFX <gen> (ignoring conditions)
      • Set Race = Orc
      • Set EffectString = <Empty String>
      • Set Sound = OrcDissipate1 <gen>
      • Trigger - Run ConfigureDissSFX <gen> (ignoring conditions)
      • Set Race = Night Elf
      • Set EffectString = <Empty String>
      • Set Sound = NightElfDissipate1 <gen>
      • Trigger - Run ConfigureDissSFX <gen> (ignoring conditions)
      • -------- -- Demon doesn't have its own diss sound --------
      • Set Race = Demon
      • Set EffectString = <Empty String>
      • Set Sound = HumanDissipate1 <gen>
      • Trigger - Run ConfigureDissSFX <gen> (ignoring conditions)
      • -------- -- 11 possible races (1 - Human, 2 - Orc, 3 - Undead, 4 - Nightelf, 5 - Demon, 7 - Other, 11 - Naga) --------
      • For each (Integer A) from 6 to 11, do (Actions)
        • Loop - Actions
          • Custom script: set udg_Race = ConvertRace(bj_forLoopAIndex)
          • Set EffectString = <Empty String>
          • Set Sound = HumanDissipate1 <gen>
          • Trigger - Run ConfigureDissSFX <gen> (ignoring conditions)


NOTE: Anything left to default can be deleted, since defaults are already set in the code. Only included here for demonstration.
  • ConfigureReviveGUI
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Set Revive Effect per race --------
      • -------- -- These are the default settings --------
      • -------- -- Revive effects have sound attached, except Demon --------
      • Set Race = Human
      • Set EffectString = Abilities\Spells\Human\ReviveHuman\ReviveHuman.mdl
      • Set Sound = No sound
      • Trigger - Run ConfigureRevSFX <gen> (ignoring conditions)
      • Set Race = Orc
      • Set EffectString = Abilities\Spells\Orc\ReviveOrc\ReviveOrc.mdl
      • Set Sound = No sound
      • Trigger - Run ConfigureRevSFX <gen> (ignoring conditions)
      • Set Race = Undead
      • Set EffectString = Abilities\Spells\Undead\ReviveUndead\ReviveUndead.mdl
      • Set Sound = No sound
      • Trigger - Run ConfigureRevSFX <gen> (ignoring conditions)
      • Set Race = Night Elf
      • Set EffectString = Abilities\Spells\NightElf\ReviveNightElf\ReviveNightElf.mdl
      • Set Sound = No sound
      • Trigger - Run ConfigureRevSFX <gen> (ignoring conditions)
      • Set Race = Demon
      • Set EffectString = Abilities\Spells\Demon\ReviveDemon\ReviveDemon.mdl
      • Set Sound = ReviveHuman <gen>
      • Trigger - Run ConfigureRevSFX <gen> (ignoring conditions)
      • -------- -- 11 possible races (1 - Human, 2 - Orc, 3 - Undead, 4 - Nightelf, 5 - Demon, 7 - Other, 11 - Naga) --------
      • For each (Integer A) from 6 to 11, do (Actions)
        • Loop - Actions
          • Custom script: set udg_Race = ConvertRace(bj_forLoopAIndex)
          • Set EffectString = Abilities\Spells\Human\ReviveHuman\ReviveHuman.mdl
          • Set Sound = No sound
          • Trigger - Run ConfigureRevSFX <gen> (ignoring conditions)


NOTE: Both abilFly AND abilSelect must be set before running ConfigureAbilities. If both are left to default, no need to set them here as long as ConfigureAbilities is not run. The default meld abilities do not need to be added here, so they can be deleted. They are only included here to demonstrate how to add custom meld abilities.
  • ConfigureAbilitiesGUI
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- These are the default settings --------
      • -------- Set Fly Ability (used to lift unit during dissipate) --------
      • Set abilFly = Storm Crow Form
      • -------- Set Locust Ability (used to make unit unselectable) --------
      • Custom script: set udg_abilSelect = 'Aloc'
      • Trigger - Run ConfigureAbilities <gen> (ignoring conditions)
      • -------- Add Meld Abilities (removed on death) --------
      • Set abilMeld = Shadow Meld
      • Trigger - Run RemoveAbilOnDeath <gen> (ignoring conditions)
      • Set abilMeld = Shadow Meld (Instant)
      • Trigger - Run RemoveAbilOnDeath <gen> (ignoring conditions)
      • Set abilMeld = Shadow Meld (Akama)
      • Trigger - Run RemoveAbilOnDeath <gen> (ignoring conditions)




You can use these functions either in a "Custom script" or in plain JASS custom text.
For JASS configuration, you do not need any of the triggers in the "Revive Config Functions" category, nor any of the variables.


NOTE: Don't forget that units have be added to a building (e.g. Altar) manually in order to build them.
  • SetUnitsJASS
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Footman for All Players --------
      • Custom script: call SetTypeRevivable('hfoo', 16)
      • -------- Grunt for All Players except Player 2 (blue) --------
      • Custom script: call SetTypeRevivable('ogru', 16)
      • Custom script: call UnsetTypeRevivable('ogru', 1)
      • -------- Ghoul for Player 1 (red) --------
      • Custom script: call SetTypeRevivable('ugho', 0)
      • -------- Ghoul available normally for other players --------
      • Custom script: call AllowNormalTraining('ugho', true)
      • -------- Archer for Player 2 (blue) --------
      • Custom script: call SetTypeRevivable('earc', 1)
      • -------- Fel Stalker for Player 1 & 2 (red & blue) --------
      • Custom script: call SetTypeRevivable('nfel', 0)
      • Custom script: call SetTypeRevivable('nfel', 1)
      • -------- Fel Stalker can be trained more than once for Player 1 (red) --------
      • Custom script: call AllowMultiple('nfel', 0, true)
      • -------- Priest (Blood Mage model) for Player 1 (red) - using Dissipate animation --------
      • Custom script: call SetTypeRevivable('hmpr', 0)
      • Custom script: call SetTypeHasDissipate('hmpr', true)


NOTE: Anything left to default can be deleted, since defaults are already set in the code. Only included here for demonstration.
  • ConfigureDissipateJASS
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Configure the Dissipate Effect --------
      • -------- -- These are the default settings --------
      • Custom script: call ConfigureDissipate(3, 200, 2, 0.03, 530)
      • -------- Set Dissipate Effect per race --------
      • -------- -- These are the default settings --------
      • -------- -- Only Undead has a dissipate model w/ sound --------
      • Custom script: call ConfigureDissSFX(RACE_UNDEAD, "Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl", null)
      • -------- -- Rest has no dissipate model, so setup sound --------
      • Custom script: call ConfigureDissSFX(RACE_HUMAN, null, gg_snd_HumanDissipate1)
      • Custom script: call ConfigureDissSFX(RACE_ORC, null, gg_snd_OrcDissipate1)
      • Custom script: call ConfigureDissSFX(RACE_NIGHTELF, null, gg_snd_NightElfDissipate1)
      • -------- -- Demon doesn't have its own diss sound --------
      • Custom script: call ConfigureDissSFX(RACE_DEMON, null, gg_snd_HumanDissipate1)
      • -------- -- 11 possible races (1 - Human, 2 - Orc, 3 - Undead, 4 - Nightelf, 5 - Demon, 7 - Other, 11 - Naga) --------
      • For each (Integer A) from 6 to 11, do (Actions)
        • Loop - Actions
          • Custom script: call ConfigureDissSFX(ConvertRace(bj_forLoopAIndex), null, gg_snd_HumanDissipate1)


NOTE: Anything left to default can be deleted, since defaults are already set in the code. Only included here for demonstration.
  • ConfigureReviveJASS
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Set Revive Effect per race --------
      • -------- -- These are the default settings --------
      • -------- -- Revive effects have sound attached, except Demon --------
      • Custom script: call ConfigureRevSFX(RACE_HUMAN, "Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl", null)
      • Custom script: call ConfigureRevSFX(RACE_ORC, "Abilities\\Spells\\Orc\\ReviveOrc\\ReviveOrc.mdl", null)
      • Custom script: call ConfigureRevSFX(RACE_UNDEAD, "Abilities\\Spells\\Undead\\ReviveUndead\\ReviveUndead.mdl", null)
      • Custom script: call ConfigureRevSFX(RACE_NIGHTELF, "Abilities\\Spells\\NightElf\\ReviveNightElf\\ReviveNightElf.mdl", null)
      • Custom script: call ConfigureRevSFX(RACE_DEMON, "Abilities\\Spells\\Demon\\ReviveDemon\\ReviveDemon.mdl", gg_snd_ReviveHuman)
      • -------- -- 11 possible races (1 - Human, 2 - Orc, 3 - Undead, 4 - Nightelf, 5 - Demon, 7 - Other, 11 - Naga) --------
      • For each (Integer A) from 6 to 11, do (Actions)
        • Loop - Actions
          • Custom script: call ConfigureRevSFX(ConvertRace(bj_forLoopAIndex), "Abilities\\Spells\\Human\\ReviveHuman\\ReviveHuman.mdl", null)


NOTE: Anything left to default can be deleted, since defaults are already set in the code. Only included here for demonstration.
  • ConfigureAbilitiesJASS
    • Events
    • Conditions
    • Actions
      • -------- These are the default settings --------
      • -------- Add Meld Abilities (removed on death) --------
      • Custom script: call RemoveAbilOnDeath('Ashm')
      • Custom script: call RemoveAbilOnDeath('Sshm')
      • Custom script: call RemoveAbilOnDeath('Ahid')
      • -------- Set Fly Ability (used to lift unit during dissipate) --------
      • Custom script: call SetFlyAbil('Arav')
      • -------- Set Locust Ability (used to make unit unselectable) --------
      • Custom script: call SetSelectAbil('Aloc')



Test Map Info
  • Chat commands:
    • "kill footman", "kill grunt", "kill ghoul", "kill archer", "kill stalker", "kill priest" and "kill hero".
  • Use the "warpten" cheat to speed up training
  • There are some enemies north-west of the starting location

Thanks to BPower, Bribe, DracoL1ch, KILLCIDE, PurgeandFire, Wietlol for their help.


1.3.3b
  • Fixed death messages still being displayed when AllowMultiple enabled
1.3.3
  • Added function AllowMultiple which allows players to train multiple units of a revivable type (and disables death message)
1.3.2
  • 24-player support
1.3.1
  • Fixed a bug that caused the dummy unit to engage enemies instead of playing the death/dissipate sequence (by pausing it)
  • GetPlayerColor renamed to GetPlayerColorString (GetPlayerColor is a native function)
1.3
  • Overhauled dissipate and revive sound and effects (code & config)
  • AllowAllPlayers renamed to AllowNormalTraining
  • AddMeldAbil renamed to RemoveAbilOnDeath
  • Dying unit is now hidden instead of removed
1.2.5
  • Fixed potential leak in Dissipate_Effect
  • Using player variable instead of calling Player(iPlayer) twice in InitRevivable
1.2.4
  • Changed default values for dissipate effect
  • No longer playing Dissipate sound when unit-type has dissipate animation (dissipate animation should have the sound effect in the model)
1.2.3
  • Small changes for very slightly increased efficiency
  • Check for valid player number in IsTypeRevivable (-1 to 16) and SetTypeRevivable (0 to 16)
1.2.2
  • Renamed dissipate configuration variables ("hard-coded" version: made these constants)
  • Replaced revTypes loop with GetTypeId() in several functions
  • Several functions now return boolean for success/failure
  • SetTypeHasDissipate: now checks if unit-type is present in revTypes
1.2.1
  • New global constant: ANY_P (any player = -1)
  • IsTypeRevivable: added ability to check for any player (ANY_P)
  • UnsetTypeRevivable: fixed not being able to unset all players when type not set for all players (i.e. can now be used to unset type when any number of players is set for it)
  • "Hard-coded" version: removed unused local variable
  • Added SetTypeHasDissipate function
1.2
  • Added configuration for effects, sounds and abilities
  • Added GUI configuration
1.1.1
  • Added GetTypeIndex to eliminate double code
  • Renamed some variables
  • Improved readability a bit: ALL_P = bj_MAX_PLAYER_SLOTS & INDEX_P = ALL_P + 1
  • Made opacityIncrement update in ConfigureDissipate()
  • Removed adding of Banish ability leftover from testing
1.1.0
  • Renamed MakeTypeRevivable to SetTypeRevivable
  • Added UnsetTypeRevivable
  • Renamed/redesigned MakeTypeExclusive to AllowAllPlayers
  • Improved unittype/player (-> better (Un)SetTypeRevivable, IsTypeRevivable, etc) storage a lot
  • Replaced TeamColor array with function
1.0.1
  • Renamed MakeUnitRevivable to MakeTypeRevivable
  • IsRevivable -> IsTypeRevivable
  • Added MakeTypeExclusive
  • Some improvements to MakeTypeRevivable
  • Some other improvements


Keywords:
revive, dissipate, unit, revivable, hero
Contents

Revivable Units test (Map)

Reviews
20:23, 22nd Mar 2016 BPower: Fair enough. Approved with a rating of useful. Think about what I said concerning race handle ids. I feel it's a bit limitating that you can only revive one unit of a specific type id, no matter how many units of...

Moderator

M

Moderator

20:23, 22nd Mar 2016
BPower:
Fair enough. Approved with a rating of useful.

Think about what I said concerning race handle ids.

I feel it's a bit limitating that you can only revive one unit of a specific type id, no matter how many units of that type id died.
 
Level 24
Joined
Aug 1, 2013
Messages
4,657
Nice stuff here.
Code is very neat and well readable.

Havent tested it in-game but a few things to improve:

- TriggerAddAction -> TriggerAddCondition
Conditions are faster because actions create a new thread per action, conditions do not really care about them so do not have a few things... for example TriggerSleepAction() wont work in conditions.
However, because you wont be using any of those things, you can just place your actions inside a condition.
Also, place everything that should run on a trigger in one function, so you only have to add one condition to each trigger at max.

- local location dLoc = GetUnitLoc(dyingUnit)
You dont need the location if you use coordinates (aka GetUnitX(), GetUnitY()).
So CreateUnitAtLoc would be CreateUnit.

- Hashtable -> Table or TimerUtils
You use a hashtable but do not use very much of it.
It is recommended to use Table if you want to stick to a hashtable like that (you can make it be optional with static ifs if you dont want to force Table as a requirement).
You do have to use integers like 0, 1, 2 etc instead of 'unit' and 'opac'.
You can make global constants with names like "TABLE_ROW_UNIT" and "TABLE_ROW_OPACITY" and set those to 0 and 1 so you can still know what those rows are for.
An alternative to Table would be TimerUtils and arrays.
You will have to use an allocater to make indices and an array for the units and for the opacity, then you can remove the hashtable from your list and use the one by TimerUtils.
This will also slightly improve timer allocation/deallocation.

- Effects & sound paths -> configurable
This is not really required but it could be usefull to make these configurables... maybe.

- if(revUnits[iSize] == wUnit and revPlayers[iSize] == iPlayer+1) then
You may want to keep track of how many units are used by the players... but its not really necessary.
 
Level 17
Joined
Dec 11, 2014
Messages
2,004
You can't make a single unit revivable with this system. It only works with unit types. Maybe adding this feature would result in a higher rating.

Maybe all the system features (Is unit Revivable? or maybe the dissipate effect) would be better to be configurable for both unit types and units.

I can imagine configuring unit types, and then adding single unit exceptions.
 
Hmm, I'm making this system for my own uses really, don't want to put more effort into it than needed :p
But I encourage anyone to take this code, add features, and upload it to the hive.

Nice stuff here.
Code is very neat and well readable.

Havent tested it in-game but a few things to improve:

- TriggerAddAction -> TriggerAddCondition
Conditions are faster because actions create a new thread per action, conditions do not really care about them so do not have a few things... for example TriggerSleepAction() wont work in conditions.
However, because you wont be using any of those things, you can just place your actions inside a condition.
Also, place everything that should run on a trigger in one function, so you only have to add one condition to each trigger at max.

- local location dLoc = GetUnitLoc(dyingUnit)
You dont need the location if you use coordinates (aka GetUnitX(), GetUnitY()).
So CreateUnitAtLoc would be CreateUnit.

- Hashtable -> Table or TimerUtils
You use a hashtable but do not use very much of it.
It is recommended to use Table if you want to stick to a hashtable like that (you can make it be optional with static ifs if you dont want to force Table as a requirement).
You do have to use integers like 0, 1, 2 etc instead of 'unit' and 'opac'.
You can make global constants with names like "TABLE_ROW_UNIT" and "TABLE_ROW_OPACITY" and set those to 0 and 1 so you can still know what those rows are for.
An alternative to Table would be TimerUtils and arrays.
You will have to use an allocater to make indices and an array for the units and for the opacity, then you can remove the hashtable from your list and use the one by TimerUtils.
This will also slightly improve timer allocation/deallocation.

- Effects & sound paths -> configurable
This is not really required but it could be usefull to make these configurables... maybe.

- if(revUnits[iSize] == wUnit and revPlayers[iSize] == iPlayer+1) then
You may want to keep track of how many units are used by the players... but its not really necessary.

Nice, thanks for the feedback.
I'm not sure how to proceed with the hashtables. I'd prefer not to use any external code if I can avoid it.
I only chose hashtables over global vars because it's easy to attach information to a specific timer that way (thus avoiding collisions when the dissipate effect is created multiple times at once), and get rid of all that information when I'm done with it.
I don't think there's a way to do that without hashtables (other than using Table or TimerUtils)?

Also are these the correct downloads? :p TimerUtils, Table

Edit: on closer inspection, Table could make unittype/players storage much simpler too with 2D arrays... considering it :D
 
Last edited:
Level 24
Joined
Aug 1, 2013
Messages
4,657
We have Table here on the hive as well, remade by Bribe (NewTable) iirc.
I dont really bother about Table because I dont use hashtables at all... at all at all :D
So I dont really know what the difference is between Table and NewTable... you have to search that for yourself.

TimerUtils is correct.

"Hmm, I'm making this system for my own uses really"

There are two kinds of resources...
1, The ones that do what you want.
2, The ones that do what other people want.
... 3, Those who dont do what anyone wants.

Making things for own usage makes things much simpler because you only have to care about the things you care about.
Making things for public usage requires you to search for all related information, use the latest techniques to make it work in the best way and make it as efficient and readable as possible... and then there are the one thing I hate... configurables :D

None is really better than the other... except that 1 and 2 are both better than 3 :D
It is just what you are using/making it for.
If you have your own project or something like that, then there might be some serious systems that are really useless for public usage but are a requirement to make the map work. You may eventually end up publishing them afterwards.
 
Oh yeah, I agree, I have been adding things that I don't really need, i.e. all the configurables (which I don't like either :p). Don't even really need a function to make unit types revivable, as it would be much easier to just do it manually for every unit type I need. But when it comes to adding features, I'll leave that up to other people who want to do that :p

I'm sharing this for two reasons: 1) sharing is caring :D and 2) the feedback you get when you submit something to be used by others is invaluable when you don't really know what you're doing :p

Will have a look at NewTable etc and see what I can use. Mostly the ability to have 2D arrays seems attractive for storing multiple values/players per unit type. Thanks again!

Edit: actually, I'm going to turn revPlayers into a boolean array, and reserve 17 slots per unit. I.e. the index for each player per unit will be unitIndex*17+playerId, where playerId 0-15 is just the playerId and 16 is for "all players". This is waaay easier, can't believe I didn't think of that earlier.

So definitely won't be using Table or anything, still have to take a look at TimerUtils to see if I can be bothered with it :p seeing as the simple hashtable works quite well already

Edit again: updated :p
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
There exist revive systems based on resurrection on an isolated part of the map which keep you from needing to do this remove unit/create unit stuff. If a unit leaves behind no corpse, that is detectable because the resurrection order will return false.

Regardless, what you've done with a pseudo-dissipate effect is cool. I recommend you remake this resource specifically for that.

Sound FX string paths should be configurable. Leave nothing which could be changed by users hardcoded unless there will otherwise be functional flaws.

Eaually, special effect string art should be configurable.

Rawcode integers absolutely should be configurable.

Tip: Make your configurables in GUI like I did with Damage Engine and Spell System. Easier for newer users.
 
Mm, I think being able to use this on any map without having to designate a hidden part of the map to it is an advantage. I like it better this way ^^

Sound FX & Effect configurables - will do (other than those I think everything that can be is already configurable).

Configurables in GUI - do you mean through UDGs?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Mm, I think being able to use this on any map without having to designate a hidden part of the map to it is an advantage. I like it better this way ^^

Actually, I just checked it again, and it revives on the spot. No hidden point on the map required. http://www.hiveworkshop.com/forums/jass-resources-412/snippet-reviveunit-186696/

Sound FX & Effect configurables - will do (other than those I think everything that can be is already configurable).

The rawcode integers must be able to be configured. They should not be hardcoded in case the user has modified those raw abilities and needs to use a copied ability in order to fulfill that role. Unlikely to happen, but the idea is to cover the predictable possibilities.

Configurables in GUI - do you mean through UDGs?

Yes. Jass2/vJass as the base of the system, but with a separate GUI trigger for the configurable things. This way, for people to use your system they need no vJass knowledge.
 
Actually, I just checked it again, and it revives on the spot. No hidden point on the map required.
O rly. Will have a look at that :D

abilities
Oh right, the abilities, mostly the meld abilities, looked over those.


Yes. Jass2/vJass as the base of the system, but with a separate GUI trigger for the configurable things. This way, for people to use your system they need no vJass knowledge.
Alright, will do. Though I'm not sure how I'm gonna do that for adding units, as a function call is necessary for it. But I'll see what I can do :D

Thanks for the feedback.
 
Updated - everything is configurable either through GUI or JASS. Hope this approach is acceptable. Seems the best way to offer both GUI and JASS config in one package.

About the ReviveUnit snippet - I don't see how I can implement that. It resurrects a unit immediately where it dies, whereas in my system you have to revive it in the altar (or another building) to revive it.
So a dummy unit isn't of any use. The reason I need to remove the original dying unit and replace it with a new one is that you can't add the fly ability, change flying height, or change opacity on a dead unit. So I need to create a living one and "simulate" death.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Cool system idea.

Correct me, but what happens if a player loses for example two or more unit of same type ( grunts ).
Can he revive the same amount or just one?

The following are just notes and not required for approval.

As everything is race handle based, you could also use one array for sound / effect per race
instead of a scalar variables per race. Handles ids:
JASS:
// Reference: 1 - Human, 2 - Orc, 3 - Undead, 4 - Nightelf, 5 - Demon, 7 - Other, 11 - Naga

I don't understand why you have to replace dying units with new equal units, then kill those.
Can you explain? I'm curious. :)
JASS:
				set dUnit = CreateUnit(dyingOwner, dyingTypeId, GetUnitX(dyingUnit), GetUnitY(dyingUnit), GetUnitFacing(dyingUnit))
				call RemoveUnit(dyingUnit)

I think that function AllowAllPlayers takes integer wTypeId, boolean allow returns boolean has a too generic function name.

function AddMeldAbil takes integer newAbilMeld returns boolean. This one also.

I think those two functions are not really necessary.
JASS:
		//===========================================================================
		// Set Flying ability
		//===========================================================================
		function SetFlyAbil takes integer newAbilFly returns nothing
			set abilFly = newAbilFly
		endfunction

		//===========================================================================
		// Set Locus ability (unselectable)
		//===========================================================================
		function SetSelectAbil takes integer newAbilSelect returns nothing
			set abilSelect = newAbilSelect
		endfunction

JASS:
		//===========================================================================
		// Configure dissipate effect model
		//===========================================================================
		function ConfigureDissEffect takes string wRace, string dEffect returns boolean			
			if(wRace == "human") then
				set dEffectH = dEffect
			elseif(wRace == "orc") then
				set dEffectO = dEffect
			elseif(wRace == "nightelf") then
				set dEffectNE = dEffect
			elseif(wRace == "undead") then
				set dEffectU = dEffect
			elseif(wRace == "demon") then
				set dEffectD = dEffect
			else
				return false
			endif
			
			return true
		endfunction

		//===========================================================================
		// Configure dissipate sound
		//===========================================================================
		function ConfigureDissSound takes string wRace, sound dSound returns boolean			
			if(wRace == "human") then
				set dSoundH = dSound
			elseif(wRace == "orc") then
				set dSoundO = dSound
			elseif(wRace == "nightelf") then
				set dSoundNE = dSound
			elseif(wRace == "undead") then
				set dSoundU = dSound
			elseif(wRace == "demon") then
				set dSoundD = dSound
			else
				return false
			endif
			
			return true
		endfunction

		//===========================================================================
		// Configure revive effect model
		//===========================================================================
		function ConfigureRevEffect takes string wRace, string rEffect returns boolean			
			if(wRace == "human") then
				set rEffectH = rEffect
			elseif(wRace == "orc") then
				set rEffectO = rEffect
			elseif(wRace == "nightelf") then
				set rEffectNE = rEffect
			elseif(wRace == "undead") then
				set rEffectU = rEffect
			elseif(wRace == "demon") then
				set rEffectD = rEffect
			else
				return false
			endif
			
			return true
		endfunction

		//===========================================================================
		// Configure revive sound
		//===========================================================================
		function ConfigureRevSound takes string wRace, sound rSound returns boolean			
			if(wRace == "human") then
				set rSoundH = rSound
			elseif(wRace == "orc") then
				set rSoundO = rSound
			elseif(wRace == "nightelf") then
				set rSoundNE = rSound
			elseif(wRace == "undead") then
				set rSoundU = rSound
			elseif(wRace == "demon") then
				set rSoundD = rSound
			else
				return false
			endif
			
			return true
		endfunction
^Consider what I said about handle ids. You may change the string argument for race.
 
Last edited:
Cool system idea.
Thank you! :)

Correct me, but what happens if a player loses for example two or more unit of same type ( grunts ).
Can he revive the same amount or just one?
If the owner of the unit has been set to revive that unit-type, only one can be revived. If the owner has not been set to revive, either he can't train the unit-type at all, or unlimited like normal if set through AllowAllPlayers().

As everything is race handle based, you could also use one array for sound / effect per race
instead of a scalar variables per race. Handles ids:
JASS:
// Reference: 1 - Human, 2 - Orc, 3 - Undead, 4 - Nightelf, 5 - Demon, 7 - Other, 11 - Naga
Hmm yeah, using arrays would be a lot better. If I'm understanding you correctly I could replace the if-statements with e.g. dSound[dRace] because e.g. RACE_HUMAN resolves to 1?
Does the race variable type have 11 possible values? Because I thought there were only the ones I used (human/orc/undead/NE/demon).

I don't understand why you have to replace dying units with new equal units, then kill those.
Can you explain? I'm curious. :)
I can't apply vertex colouring or lift the unit with the fly ability on a corpse, so I have to create a new, living unit and play the death animation.
Although thinking about it, I guess I could catch the unit right before it dies? But I'm not sure if that's reliable?

I think that function AllowAllPlayers takes integer wTypeId, boolean allow returns boolean has a too generic function name.

function AddMeldAbil takes integer newAbilMeld returns boolean. This one also.

I think those two function are not really necessary.
Hmm, I will see if I can think of something more descriptive :p About the AddMeldAbil and SetSelectAbil, should I replace them with udg's? Because I was asked to make all abilities configurable.

^Consider what I said about handle ids. You may change the string argument for race.
Yeah, could be a lot shorter with arrays. Same question as above though.



Thanks for your feedback! I'll implement it as much as possible when I have some time.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
Hmm yeah, using arrays would be a lot better. If I'm understanding you correctly I could replace the if-statements with e.g. dSound[dRace] because e.g. RACE_HUMAN resolves to 1?
Yes.
Does the race variable type have 11 possible values? Because I thought there were only the ones I used (human/orc/undead/NE/demon).
Make sure you support the classic races orc/human/undead/nightelf. The others are optional.

I can't apply vertex colouring or lift the unit with the fly ability on a corpse, so I have to create a new, living unit and play the death animation.
Although thinking about it, I guess I could catch the unit right before it dies? But I'm not sure if that's reliable?
Mmh ok. The dummy unit for vertex color and death effect makes totally sense.
I think it's better to hide the original unit instead of removing it upon death event.
 
Thanks for approval! I will definitely implement race handle id based arrays for effects/sounds and their config functions, seems a lot better than what I have now.
I'll see about implementing an extra "stock" array so each unit that dies adds to the amount that can be revived.

Hiding the unit instead of deleting - because it gets erased from memory anyway when it has decayed? Makes sense.

Edit: I'm curious, where can I find a list of all race handle ids? (1-11)? Can't find any documentation on it.
Edit2: alright, this works quite nicely, and it's so much simpler :D
JASS:
				set rRace = GetHandleId(GetUnitRace(rUnit))
					
				if(rEffect[rRace] != null and rEffect[rRace] != "") then
					call DestroyEffect(AddSpecialEffectTarget(rEffect[rRace], rUnit, "origin"))
				endif
				if(rSound[rRace] != null) then
					set rSoundTemp = rSound[rRace]
					call AttachSoundToUnit(rSoundTemp, rUnit)
					call StartSound(rSoundTemp)
					set rSoundTemp = null
				endif
still have to update the configuration stuff, and then do the rest of your feedback :p

Edit: alright, done. Might add the possibility to revive a unit-type for each unit that dies later
 
Last edited:
Top