|
|
#1 |
|
User
Join Date: Oct 2007
Posts: 37
|
A revive method for normal units, uses the Ancestral Spirit ability.
Code:
scope ReviveUnit initializer Init
globals
private constant integer DUMMY_ABILITY_ORDER_ID = 852490 //order id of Ancestral Spirit
private unit DUMMY_UNIT
private constant player DUMMY_UNIT_OWNER = Player(PLAYER_NEUTRAL_PASSIVE)
endglobals
//! textmacro ReviveUnit_CreateObjects takes doExternal, dummyAbilityRaw, dummyUnitRaw
globals
private constant integer DUMMY_ABILITY_ID = '$dummyAbilityRaw$'
private constant integer DUMMY_UNIT_ID = '$dummyUnitRaw$'
endglobals
$doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
//! i function set(field, value)
//! i makechange(current, field, value)
//! i end
//! i function setl(field, level, value)
//! i makechange(current, field, level, value)
//! i end
//! i setobjecttype("abilities")
//! i createobject("Aast", "$dummyAbilityRaw$")
//! i set("aart", "")
//! i set("abpx", 0)
//! i set("abpy", 0)
//! i set("acat", "")
//! i setl("acdn", 1, 0)
//! i set("ahky", "")
//! i setl("amcs", 1, 0)
//! i set("anam", "Revive Unit")
//! i set("arac", "other")
//! i setl("aran", 1, 99999)
//! i set("areq", "")
//! i set("arqa", "")
//! i setl("ast1", 1, 1)
//! i setl("ast2", 1, 1)
//! i setl("atar", 1, "air,dead,ground,invulnerable,player,structure,vulnerable")
//! i set("atat", "")
//! i setl("atp1", 1, "")
//! i setl("aub1", 1, "")
//! i setobjecttype("units")
//! i createobject("uplg", "$dummyUnitRaw$")
//! i set("ua1t", "")
//! i set("ua2t", "")
//! i set("uabi", "Aloc,$dummyAbilityRaw$")
//! i set("uacq", 0)
//! i set("uarm", "")
//! i set("ubld", 0)
//! i set("uble", 0)
//! i set("ucbs", 0)
//! i set("uclr", 0)
//! i set("uclg", 0)
//! i set("uclb", 0)
//! i set("ucol", 0)
//! i set("udro", "\0")
//! i set("udtm", 0)
//! i set("udty", "")
//! i set("udup", 0)
//! i set("uerd", 0)
//! i set("ufle", "\0")
//! i set("uhpm", 0)
//! i set("uico", "")
//! i set("uimz", 0)
//! i set("uine", "\0")
//! i set("ulpz", 0)
//! i set("umdl", "")
//! i set("umvt", "")
//! i set("umxr", 0)
//! i set("umxp", 0)
//! i set("unam", "Revive Unit")
//! i set("upgr", "")
//! i set("upoi", 0)
//! i set("uprw", 0)
//! i set("urac", "other")
//! i set("urtm", 0)
//! i set("urun", 0)
//! i set("usca", 0)
//! i set("uscb", "\0")
//! i set("ushr", "\0")
//! i set("usma", 0)
//! i set("usnd", "")
//! i set("usrg", 0)
//! i set("ussc", 0)
//! i set("utar", "")
//! i set("utc1", 0)
//! i set("utc2", 0)
//! i set("util", "")
//! i set("uwal", 0)
//! i set("uwu1", "\0")
//! i set("uwu2", "\0")
$doExternal$//! endexternalblock
//! endtextmacro
//! runtextmacro ReviveUnit_CreateObjects("", "ARev", "uRev") //change the first parameter to "/" after the objects have been created and map was reloaded.
function ReviveUnit takes unit whichUnit returns boolean
local boolean hidden
local boolean isStructure
local integer playerFood
local boolean result
local integer unitFood
local boolean useFood
local player whichUnitOwner
if (IsUnitType(whichUnit, UNIT_TYPE_DEAD) == false) then
return false
endif
set hidden = IsUnitHidden(whichUnit)
set isStructure = IsUnitType(whichUnit, UNIT_TYPE_STRUCTURE)
set unitFood = GetFoodUsed(GetUnitTypeId(whichUnit))
set whichUnitOwner = GetOwningPlayer(whichUnit)
set playerFood = GetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED)
if (hidden) then
call ShowUnit(whichUnit, true)
endif
call SetUnitOwner(DUMMY_UNIT, whichUnitOwner, false) //Ancestral Spirit revives for the owner of the caster.
call SetUnitUseFood(whichUnit, true) //On revival the units lose some values, among them food, even if it was disabled via SetUnitUseFood beforehand. Interestingly, you can enable food usage in death again, so I use this here.
call SetUnitX(DUMMY_UNIT, GetUnitX(whichUnit)) //to enable instant cast move the dummy to the reviving unit's location
call SetUnitY(DUMMY_UNIT, GetUnitY(whichUnit))
call UnitAddType(whichUnit, UNIT_TYPE_TAUREN) //Only Tauren-classified units are revived by Ancestral Spirit and this I use for targeting. There should not be any other tauren while ReviveUnit executes. I could pick, remove, pick and add again the classification of other units here, but I think that only draws performance and is rare.
call UnitShareVision(whichUnit, whichUnitOwner, true) //Dummy needs sight to cast, dead units actually do not give that but using this function seems to be enough to cast on them, even if they have 0 sight range. I won't restore the old share vision status here as I think it's default to see the own units.
set useFood = (GetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED) != playerFood)
call SetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED, -unitFood) //Ancestral Spirit requires the availability of free food the unit type needs, so I shortly set the used supply of the player to the future costs of the unit, in negative, since the food cap should be at least 0 and the supply limit does grab until there.
set result = IssueImmediateOrderById(DUMMY_UNIT, DUMMY_ABILITY_ORDER_ID)
if (isStructure or hidden) then
call ShowUnit(whichUnit, false)
endif
call SetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED, GetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED) + unitFood + playerFood )
call SetUnitOwner(DUMMY_UNIT, DUMMY_UNIT_OWNER, false) //change dummy unit back to neutral passive to prevent ai to get silly ideas
call SetUnitUseFood(whichUnit, useFood)
call UnitRemoveType(whichUnit, UNIT_TYPE_TAUREN)
set whichUnitOwner = null
if (isStructure and (hidden == false)) then
call ShowUnit(whichUnit, true)
endif
return result
endfunction
public function Init takes nothing returns nothing
set DUMMY_UNIT = CreateUnit(DUMMY_UNIT_OWNER, DUMMY_UNIT_ID, 0., 0., 0.)
endfunction
endscopeSome conditions and considerations: - as commented above, there should not be other taurens - there are some functions that might start events like SetUnitOwner, IssueImmediateOrderById, SetPlayerState --> be careful to not run some events that shouldn't - UnitShareVision status gets set and not reset - the function can be immediately used with the Unit-Death-Event - upkeep will be redisplayed - the spell works even if the object editor states the unit would not be revivalable but you should consider that non-decaying units have a shorter decay duration (only death time I guess), a unit cannot be revived this way if it already decayed, instantly reviving on death event however is also possible if the unit is non-decaying and has a death time of zero Last edited by WaterKnight : 07-26-2010 at 11:30 AM. |
|
|
|
| Sponsored Links - Login to hide this ad! |
|
|
|
|
#2 |
|
oO
Join Date: Jul 2008
Posts: 577
![]() ![]() ![]()
|
Does this work instantly?
And why is ancestral spirit better than ressurection? Last edited by Bobo_The_Kodo : 06-28-2010 at 09:27 PM. |
|
|
|
|
|
#3 |
|
User
Join Date: Oct 2007
Posts: 37
|
It does work instantly. You may kill the unit again right afterwards if you want.
I did not compare Ancestral Spirit to Resurrection but preferred it because I thought it was more secure to aim the target. Resurrection is targetless and revives the highest-leveled units nearby. I could have reduced the area range when dummy unit is directly ported to the target but did not know whether a tangential value of zero would be enough and however, some units could be lying above each other on the same spot. |
|
|
|
|
|
#4 | |
|
Lol I got a custom title!
Join Date: Aug 2004
Posts: 1,231
![]() ![]()
|
Quote:
You could move away any unwanted corpses to a temporary location and then back when ressurection is done. Not sure what quirks Ancestral Spirit has though. Seems like a nice function otherwise, could prove useful, though I have no use for it. |
|
|
|
|
|
|
#5 | |
|
User
Join Date: Oct 2007
Posts: 37
|
Quote:
This would take an unknown amount of iterations. Also it could trigger enter/leave events. I like exotic spells :) |
|
|
|
|
|
|
#6 |
|
obey
|
actually ancentral spirit is aim casted, you can cast it on selected unit, unlike ressurection that revive multiple random units around.
|
|
|
|
|
|
#7 |
|
User
Join Date: Jul 2007
Posts: 215
|
Nice function : D
|
|
|
|
|
|
#8 |
|
oO
Join Date: Jul 2008
Posts: 577
![]() ![]() ![]()
|
Is it possible to make this able to revive buildings?
|
|
|
|
|
|
#9 |
|
User
Join Date: Oct 2007
Posts: 37
|
It is able to revive buildings. Though, I do not know every value that is lost on death and not restored on revival. For example, the ubersplat of the building does not get recreated.
Update: Added invulnerable and vulnerable as targets as I found out that ancestral spirit does not work on invulnerable units on default. |
|
|
|
|
|
#10 |
|
oO
Join Date: Jul 2008
Posts: 577
![]() ![]() ![]()
|
If you hide and show a building it will recreate the ubersplat - you might wanna add that
|
|
|
|
|
|
#11 |
|
User
Join Date: Oct 2007
Posts: 37
|
done, it also now checks if the unit is even dead and works on hidden units
|
|
|
|
|
|
#12 |
|
Procrastination Incarnate
Development Director
|
I would prefer to see this function use the xe dummy instead of creating its own.
__________________ |
|
|
|
|
|
#13 |
|
oO
Join Date: Jul 2008
Posts: 577
![]() ![]() ![]()
|
And you could probably submit it for scripts section after ;)
|
|
|
|
|
|
#14 |
|
obey
|
note:
this will fail if you hit max food, since you cant increase food value anymore to evoid this problem you shoud increase food limit by 1 and if this is not possible decrease current food used by 1. |
|
|
|
|
|
#15 | ||
|
User
Join Date: Oct 2007
Posts: 37
|
Quote:
I've heard of xe cast before but do not use it actually. In my own maps, the function here is alternated anyway, I also use my shared caster I call World Caster. Code:
scope ReviveUnit initializer Init
globals
private constant integer DUMMY_ABILITY_ORDER_ID = 852490 //order id of Ancestral Spirit
private xecast DUMMY_CASTER
endglobals
//! textmacro ReviveUnit_CreateObjects takes doExternal, dummyAbilityRaw
globals
private constant integer DUMMY_ABILITY_ID = '$dummyAbilityRaw$'
endglobals
$doExternal$//! externalblock extension=lua ObjectMerger $FILENAME$
//! i function set(field, value)
//! i makechange(current, field, value)
//! i end
//! i function setl(field, level, value)
//! i makechange(current, field, level, value)
//! i end
//! i setobjecttype("abilities")
//! i createobject("Aast", "$dummyAbilityRaw$")
//! i set("aart", "")
//! i set("abpx", 0)
//! i set("abpy", 0)
//! i set("acat", "")
//! i setl("acdn", 1, 0)
//! i set("ahky", "")
//! i setl("amcs", 1, 0)
//! i set("anam", "Revive Unit")
//! i set("arac", "other")
//! i setl("aran", 1, 99999)
//! i set("areq", "")
//! i set("arqa", "")
//! i setl("ast1", 1, 1)
//! i setl("ast2", 1, 1)
//! i setl("atar", 1, "air,dead,ground,invulnerable,player,structure,vulnerable")
//! i set("atat", "")
//! i setl("atp1", 1, "")
//! i setl("aub1", 1, "")
$doExternal$//! endexternalblock
//! endtextmacro
//! runtextmacro ReviveUnit_CreateObjects("", "ARev") //change the first parameter to "/" after the objects have been created and map was reloaded.
function ReviveUnit takes unit whichUnit returns boolean
local boolean hidden
local boolean isStructure
local integer playerFood
local boolean result
local integer unitFood
local boolean useFood
local player whichUnitOwner
if (IsUnitType(whichUnit, UNIT_TYPE_DEAD) == false) then
return false
endif
set hidden = IsUnitHidden(whichUnit)
set isStructure = IsUnitType(whichUnit, UNIT_TYPE_STRUCTURE)
set unitFood = GetFoodUsed(GetUnitTypeId(whichUnit))
set whichUnitOwner = GetOwningPlayer(whichUnit)
set playerFood = GetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED)
if (hidden) then
call ShowUnit(whichUnit, true)
endif
set DUMMY_CASTER.owningplayer = whichUnitOwner
call SetUnitUseFood(whichUnit, true) //On revival the units lose some values, among them food, even if it was disabled via SetUnitUseFood beforehand. Interestingly, you can enable food usage in death again, so I use this here.
call UnitAddType(whichUnit, UNIT_TYPE_TAUREN) //Only Tauren-classified units are revived by Ancestral Spirit and this I use for targeting. There should not be any other tauren while ReviveUnit executes. I could pick, remove, pick and add again the classification of other units here, but I think that only draws performance and is rare.
call UnitShareVision(whichUnit, whichUnitOwner, true) //Dummy needs sight to cast, dead units actually do not give that but using this function seems to be enough to cast on them, even if they have 0 sight range. I won't restore the old share vision status here as I think it's default to see the own units.
set useFood = (GetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED) != playerFood)
call SetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED, -unitFood) //Ancestral Spirit requires the availability of free food the unit type needs, so I shortly set the used supply of the player to the future costs of the unit, in negative, since the food cap should be at least 0 and the supply limit does grab until there.
call DUMMY_CASTER.castInPoint(GetUnitX(whichUnit), GetUnitY(whichUnit))
set result = (IsUnitType(whichUnit, UNIT_TYPE_DEAD) == false)
if (isStructure or hidden) then
call ShowUnit(whichUnit, false)
endif
call SetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED, GetPlayerState(whichUnitOwner, PLAYER_STATE_RESOURCE_FOOD_USED) + unitFood + playerFood )
call SetUnitUseFood(whichUnit, useFood)
call UnitRemoveType(whichUnit, UNIT_TYPE_TAUREN)
set whichUnitOwner = null
if (isStructure and (hidden == false)) then
call ShowUnit(whichUnit, true)
endif
return result
endfunction
public function Init takes nothing returns nothing
set DUMMY_CASTER = xecast.createBasic(DUMMY_ABILITY_ID, DUMMY_ABILITY_ORDER_ID, null)
endfunction
endscopeSo is this okay? Quote:
That's why I set the current food in the negative area and make it depend on the unit's own supply costs. It works for me. Though, it redisplays upkeep. Another note: The spell works even if the object editor states the unit would not be revivalable but you should consider that non-decaying units have a shorter decay duration (only death time I guess), a unit cannot be revived this way if it already decayed, instantly reviving on death event however is also possible if the unit is non-decaying and has a death time of zero. Last edited by WaterKnight : 07-26-2010 at 11:55 AM. |
||
|
|
|
![]() |
| Thread Tools | Search this Thread |
|
|
|
Donate |