1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. The long-awaited results for Concept Art Contest #11 have finally been released!
    Dismiss Notice
  3. Join Texturing Contest #30 now in a legendary battle of mythological creatures!
    Dismiss Notice
  4. The 20th iteration of the Terraining Contest is upon us! Join and create exquisite Water Structures for it.
    Dismiss Notice
  5. Hivers united and created a bunch of 2v2 melee maps. Vote for the best in our Melee Mapping Contest #4 - Poll!
    Dismiss Notice
  6. Check out the Staff job openings thread.
    Dismiss Notice

Trigger Viewer

HeroReviveCancelEvent.w3x
Variables
Initialization
Init
HeroReviveCancelEvent
HeroReviveCancelEventGUI
Demo
Demo GUI

		
Name Type Is Array Initial Value
HRCE_Building unit No
HRCE_Hero unit No
HRCE_State real No
Init
  Events
    Map initialization
  Conditions
  Actions
    Player - Set Player 1 (Red) Current gold to 10000
    Player - Set Player 1 (Red) Current lumber to 10000
    Player - Set Player 1 (Red) Current lumber to 10000
    Melee Game - Limit Heroes to 1 per Hero-type (for all players)
    Unit - Create 1 Blood Mage for Player 1 (Red) at (Position of Altar of Kings 0005 <gen>) facing Default building facing degrees
    Unit - Set life of (Last created unit) to 100.00
//TESH.scrollpos=152
//TESH.alwaysfold=0
 library HeroReviveCancelEvent /* v1.1 -- hiveworkshop.com/threads/herorevivecancelevent.293491/#resource-72550
 
     Information
    ¯¯¯¯¯¯¯¯¯¯¯¯

        Provides an event that fires when a player cancels a hero revival at the altar.
        When using this system, you don't need the default event EVENT_PLAYER_HERO_REVIVE_CANCEL anymore.
       
       
     Mechanics
    ¯¯¯¯¯¯¯¯¯¯
   
        (Issue:)
       
        The default problem is that EVENT_PLAYER_HERO_REVIVE_CANCEL will only fire when using
        the "Cancel" spell, but not when directly clicking on the hero icon in training queue.
       
        (Solution:)
       
        When a hero starts reviving process, so enters the queue, we periodicly order the altar to try to 'revive'
        the hero. Normaly this order will return "false", as the hero is already being revived, but once it returns "true"
        we know, that the hero must not be in queue anymore. Then we fire the event.
       
        This method will work for both, when the "Cancel" spell is used, and when the hero icon is clicked in queue.
 */


//  ====API ====
//! novjass

    struct HeroReviveCancelEvent
   
    // register code
   
        static method register takes code c returns nothing
        static method unregister takes code c returns nothing
       
    // Inside registered code, you can access data:
   
       static thistype instance
           readonly unit hero       // hero that was reviving
           readonly unit building   // altar for revival
       

//! endnovjass
//  ===== End API ====

native UnitAlive takes unit u returns boolean
                                                 
    struct HeroReviveCancelEvent
       
        private static constant integer REVIVE_ORDER_ID_OFFSET = 852027
        private static constant integer CANCEL_ORDER_ID        = 851976
        private static constant integer MAX_HERO_AMOUNT        = 4
       
        private static constant real    TIMEOUT                = 0.1
       
        private static hashtable hash    = InitHashtable()
        private static trigger   handler = CreateTrigger()
       
        readonly static thistype instance
        readonly        unit     hero
        readonly        unit     building
       
        private timer clock
        private player owner
        private boolean exists
       
        private method destroy takes nothing returns nothing
            if .exists then
                set .exists = false
               
                call RemoveSavedInteger(hash, GetHandleId(.clock), 0)
                call RemoveSavedInteger(hash, GetHandleId(.hero), 0)
                call DestroyTimer(.clock)
               
                set .clock    = null
                set .hero     = null
                set .building = null
               
                call .deallocate()
            endif
        endmethod
       
        private static method callback takes nothing returns nothing
            local integer food
            local integer gold
            local integer lumber
           
            local thistype this = LoadInteger(hash, GetHandleId(GetExpiredTimer()), 0)
            if not UnitAlive(.building) or UnitAlive(.hero) then
                 call .destroy()
            endif
           
            // resources backup
            set gold   = GetPlayerState(.owner, PLAYER_STATE_RESOURCE_GOLD)
            set lumber = GetPlayerState(.owner, PLAYER_STATE_RESOURCE_LUMBER)
            set food   = GetPlayerState(.owner, PLAYER_STATE_RESOURCE_FOOD_USED)
           
            // give some conditions that will hopefully be always enough to successfuly order the revive order
            call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_GOLD, 1000000)
            call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_LUMBER, 1000000)
            call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_FOOD_USED, 0)
           
            if IssueTargetOrder(.building, "revive", .hero) then
               
                //
                call IssueImmediateOrderById(.building, CANCEL_ORDER_ID)
               
                // retrieve original resources before the handler is fired
                call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_GOLD, gold)
                call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_LUMBER, lumber)
                call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_FOOD_USED, food)
               
                // fire event
                set instance = this
                call TriggerEvaluate(.handler)
                call .destroy()
                return
            endif
           
            // retrieve original resources
            call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_GOLD, gold)
            call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_LUMBER, lumber)
            call SetPlayerState(.owner, PLAYER_STATE_RESOURCE_FOOD_USED, food)
        endmethod

        private static method create takes unit b, unit h returns thistype
            local thistype this = allocate()
           
            set .exists   = true
            set .clock    = CreateTimer()
            set .hero     = h
            set .building = b
            set .owner    = GetOwningPlayer(h)
           
            call TimerStart(.clock, TIMEOUT, true, function thistype.callback)
            call SaveInteger(hash, GetHandleId(.clock), 0, this)
            call SaveInteger(hash, GetHandleId(.hero), 0, this)
           
            return this
        endmethod
       
        // hero gets into revive queue, so now we start periodicaly watching it
        private static method onReviveStart takes nothing returns boolean
            local integer orderId = GetIssuedOrderId()
            if (orderId >= REVIVE_ORDER_ID_OFFSET and orderId <= REVIVE_ORDER_ID_OFFSET + MAX_HERO_AMOUNT) then
                call create(GetOrderedUnit(), GetOrderTargetUnit())
            endif
            return false
        endmethod
       
        // instantly destroy instance when unit finished reviving
        private static method onReviveFinish takes nothing returns boolean
            call thistype(LoadInteger(hash, GetHandleId(GetTriggerUnit()), 0)).destroy()
            return false
        endmethod
       
        private static method onInit takes nothing returns nothing
            local trigger t
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER )
            call TriggerAddCondition(t, Condition(function thistype.onReviveStart))
           
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_REVIVE_FINISH )
            call TriggerAddCondition(t, Condition(function thistype.onReviveFinish))
        endmethod
       
        // for API
       
        public static method register takes code c returns nothing
            local boolexpr bx = Condition(c)
            call SaveTriggerConditionHandle(hash, GetHandleId(bx), 0, TriggerAddCondition(handler, bx))
            set bx = null
        endmethod
       
        public static method unregister takes code c returns nothing
            local boolexpr bx = Condition(c)
            call TriggerRemoveCondition(handler, LoadTriggerConditionHandle(hash, GetHandleId(bx), 0))
            call FlushChildHashtable(hash, GetHandleId(bx))
            call DestroyBoolExpr(bx)
            set bx = null
        endmethod

    endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
 scope HeroReviveCancelEventGUI /* v1.1 -- hiveworkshop.com/threads/herorevivecancelevent.293491/#resource-72550
*/

    struct HeroReviveCancelEventGUI extends array
       
        private static method onHeroReviveCancel takes nothing returns nothing
            local HeroReviveCancelEvent this = HeroReviveCancelEvent.instance
            set udg_HRCE_Building = this.building
            set udg_HRCE_Hero = this.hero
            set udg_HRCE_State = 1.
            set udg_HRCE_State = 0.
        endmethod
       
        private static method onInit takes nothing returns nothing
            call HeroReviveCancelEvent.register(function thistype.onHeroReviveCancel)
        endmethod
   
    endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct Demo extends array

    private static method onReviveCancel takes nothing returns nothing
        local HeroReviveCancelEvent this = HeroReviveCancelEvent.instance
        call BJDebugMsg(GetUnitName(this.building) + " has canceled to revive " + GetUnitName(this.hero) + ".")
    endmethod
   
    private static method onInit takes nothing returns nothing
        call HeroReviveCancelEvent.register(function thistype.onReviveCancel)
    endmethod
   
endstruct
Demo GUI
  Events
    Game - HRCE_State becomes Equal to 1.00
  Conditions
  Actions
    Game - Display to (All players) the text: ((Name of HRCE_Building) + ( has canceled to revive + (Name of HRCE_Hero)))