wc3campaigns
WC3C Homepage - www.wc3c.netUser Control Panel (Requires Log-In)Engage in discussions with other users and join contests in the WC3C forums!Read one of our many tutorials, ranging in difficulty from beginner to advanced!Show off your artistic talents in the WC3C Gallery!Download quality models, textures, spells (vJASS/JASS), systems, and scripts!Download maps that have passed through our rigorous approval process!

Go Back   Wc3C.net > Warcraft III Modding > Developer's Corner > Triggers & Scripts
User Name
Password
Register Rules Get Hosted! Chat Pastebin FAQ and Rules Members List Calendar



Reply
 
Thread Tools Search this Thread
Old 06-28-2010, 10:44 AM   #1
WaterKnight
User
 
Join Date: Oct 2007
Posts: 35

WaterKnight has little to show at this moment (4)

Default [vJass] ReviveUnit

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
endscope

Some 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.
WaterKnight is offline   Reply With Quote
Sponsored Links - Login to hide this ad!
Old 06-28-2010, 09:26 PM   #2
Bobo_The_Kodo
oO
 
Bobo_The_Kodo's Avatar
 
Join Date: Jul 2008
Posts: 579

Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)

Default

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.
Bobo_The_Kodo is offline   Reply With Quote
Old 06-28-2010, 11:04 PM   #3
WaterKnight
User
 
Join Date: Oct 2007
Posts: 35

WaterKnight has little to show at this moment (4)

Default

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.
WaterKnight is offline   Reply With Quote
Old 06-29-2010, 02:34 AM   #4
Thunder_Eye
Lol I got a custom title!
 
Thunder_Eye's Avatar
 
Join Date: Aug 2004
Posts: 1,231

Thunder_Eye has a spectacular aura about (88)Thunder_Eye has a spectacular aura about (88)Thunder_Eye has a spectacular aura about (88)

Default

Quote:
Originally Posted by WaterKnight
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.

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.
__________________
Thunder_Eye is offline   Reply With Quote
Old 06-29-2010, 01:02 PM   #5
WaterKnight
User
 
Join Date: Oct 2007
Posts: 35

WaterKnight has little to show at this moment (4)

Default

Quote:
Originally Posted by Thunder_Eye
You could move away any unwanted corpses to a temporary location and then back when ressurection is done.

This would take an unknown amount of iterations. Also it could trigger enter/leave events. I like exotic spells :)
WaterKnight is offline   Reply With Quote
Old 07-08-2010, 04:01 PM   #6
DioD
obey
 
DioD's Avatar
 
Join Date: Feb 2006
Posts: 1,532

Submissions (4)

DioD is a jewel in the rough (220)DioD is a jewel in the rough (220)DioD is a jewel in the rough (220)DioD is a jewel in the rough (220)

Send a message via ICQ to DioD
Default

actually ancentral spirit is aim casted, you can cast it on selected unit, unlike ressurection that revive multiple random units around.
DioD is offline   Reply With Quote
Old 07-11-2010, 02:25 AM   #7
Nestharus
User
 
Join Date: Jul 2007
Posts: 218

Nestharus has little to show at this moment (6)

Default

Nice function : D
Nestharus is offline   Reply With Quote
Old 07-24-2010, 06:05 PM   #8
Bobo_The_Kodo
oO
 
Bobo_The_Kodo's Avatar
 
Join Date: Jul 2008
Posts: 579

Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)

Default

Is it possible to make this able to revive buildings?
Bobo_The_Kodo is offline   Reply With Quote
Old 07-24-2010, 09:57 PM   #9
WaterKnight
User
 
Join Date: Oct 2007
Posts: 35

WaterKnight has little to show at this moment (4)

Default

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.
WaterKnight is offline   Reply With Quote
Old 07-25-2010, 12:54 AM   #10
Bobo_The_Kodo
oO
 
Bobo_The_Kodo's Avatar
 
Join Date: Jul 2008
Posts: 579

Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)

Default

If you hide and show a building it will recreate the ubersplat - you might wanna add that
Bobo_The_Kodo is offline   Reply With Quote
Old 07-25-2010, 09:14 AM   #11
WaterKnight
User
 
Join Date: Oct 2007
Posts: 35

WaterKnight has little to show at this moment (4)

Default

done, it also now checks if the unit is even dead and works on hidden units
WaterKnight is offline   Reply With Quote
Old 07-25-2010, 03:00 PM   #12
Anitarf
Procrastination Incarnate


Development Director
 
Join Date: Feb 2004
Posts: 8,028

Submissions (19)

Anitarf has a brilliant future (883)Anitarf has a brilliant future (883)Anitarf has a brilliant future (883)Anitarf has a brilliant future (883)Anitarf has a brilliant future (883)Anitarf has a brilliant future (883)Anitarf has a brilliant future (883)Anitarf has a brilliant future (883)

2008 Spell olympics - Fire - SilverApproved Map: Old School Alliance TacticsHero Contest #2 - 3rd PlaceSpell making session 2 winner

Default

I would prefer to see this function use the xe dummy instead of creating its own.
__________________
Anitarf is offline   Reply With Quote
Old 07-25-2010, 10:10 PM   #13
Bobo_The_Kodo
oO
 
Bobo_The_Kodo's Avatar
 
Join Date: Jul 2008
Posts: 579

Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)Bobo_The_Kodo has a spectacular aura about (109)

Default

And you could probably submit it for scripts section after ;)
Bobo_The_Kodo is offline   Reply With Quote
Old 07-25-2010, 11:04 PM   #14
DioD
obey
 
DioD's Avatar
 
Join Date: Feb 2006
Posts: 1,532

Submissions (4)

DioD is a jewel in the rough (220)DioD is a jewel in the rough (220)DioD is a jewel in the rough (220)DioD is a jewel in the rough (220)

Send a message via ICQ to DioD
Default

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.
DioD is offline   Reply With Quote
Old 07-26-2010, 11:29 AM   #15
WaterKnight
User
 
Join Date: Oct 2007
Posts: 35

WaterKnight has little to show at this moment (4)

Default

Quote:
Originally Posted by Anitarf
I would prefer to see this function use the xe dummy instead of creating its own.

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
endscope

So is this okay?

Quote:
Originally Posted by DioD
this will fail if you hit max food, since you cant increase food value anymore

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.
WaterKnight is offline   Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off


All times are GMT. The time now is 04:59 AM.


Donate

Affiliates
The Hubb http://bylur.com - Warcraft, StarCraft, Diablo and DotA Blog & Forums The JASS Vault Clan WEnW Campaign Creations Clan CBS GamesModding Flixreel Videos

Powered by vBulletin (Copyright ©2000 - 2014, Jelsoft Enterprises Ltd).
Hosted by www.OICcam.com
IT Support and Services provided by Executive IT Services