Thread: EventData
View Single Post
Old 10-08-2008, 12:40 AM   #1
grim001
requires vJass
 
grim001's Avatar


Code Moderator
 
Join Date: Nov 2006
Posts: 1,540

Submissions (10)

grim001 is just really nice (277)grim001 is just really nice (277)

Send a message via AIM to grim001
Default EventData

Click image for larger version

Name:	eventtargetlibok3.jpg
Views:	298
Size:	159.8 KB
ID:	38169
EventData was created to simplify the tedious task of using the native event responses related to orders and spells. It allows you to skip all the steps usually involved in finding the target type, coordinates, distance, and angles involved in an order or spell. It also allows you to store information about an order or spell for later use.

Collapse JASS:
library EventData
//===========================================================================
// Information:
//==============
//
//     EventData was created to simplify the tedious task of using the native
// event responses related to orders and spells. It allows you to skip all 
// the steps usually involved in finding the target type, coordinates, dist-
// ance, and angles involved in an order or spell. It also allows you to
// store information about an order or spell for later use.
//
//===========================================================================
// How to use EventData:
//=======================
//
//     Create an EventData struct while in a thread spawned from any order
// or spell related player unit event or specific unit event. (See the bottom
// of the documentation for a list of all compatible events.) Now you can
// call methods on the struct to get data about the spell cast or order.
//
//     You do not have to destroy your EventData structs when you're through
// with them, as they self-destruct after any time has elapsed. However, if
// you want to save the struct for later use, you must prevent the automatic
// destruction by calling .preserve() on the instance.
//
// function UnitCastsSpell takes nothing returns nothing
//     local EventData ed = EventData.create()
//     local unit caster = ed.caster() //Gets the casting unit.
//     local unit utarget
//     local item itarget
//     //local real x = ed.casterX()  //Don't bother to store these into
//     //local real y = ed.casterX()  //local variables. Instead, just
//     //local real tx = ed.targetX() //access the variables directly
//     //local real ty = ed.targetY() //from the EventData struct.
//
//         if SquareRoot(Pow(ed.x - ed.tx, 2.) + Pow(ed.y - ed.ty, 2.)) > 1000. then
//             //Don't bother to do do this kind of math, either...
//         elseif ed.distanceXY() > 500. then
//             //This saves you some typing.
//         endif
//
//         //This spell can target both units and items. To tell which one...
//         if ed.targetIsUnit() then //Perform unit-specific actions.
//             set utarget = ed.targetUnit()
//         elseif ed.targetIsItem() then //Perform item-specific actions.
//             set itarget = ed.targetItem()
//         endif
// endfunction
//
// function UnitRecievesOrder takes nothing returns nothing
//     local EventData ed = EventData.create()
//     local unit ordered = ed.caster() //This is the ordered unit, even though
//                                      //you aren't really a "caster"...
//         call BJDebugMsg(GetUnitName(ordered)+" was ordered to " + ed.orderString())
//         call BJDebugMsg("This order's target type is: " + ed.targetTypeString())
//         call BJDebugMsg("The order was recieved in an " + ed.eventString() + " trigger.")
//         //Shows how you can print some helpful debugging information.
// endfunction
//
//===========================================================================
// EventData API:
//================
//
// EventData.create() -> EventData
//     Returns an instance of the EventTarget struct and caches all of the necessary
//     data about the event. Returns 0 if not created from a compatible event. An
//     error message will be displayed if debug mode is enabled. EventData instances
//     will automatically self-destruct after any time has elapsed, so you do not
//     have to manually call .destroy() on them.
// .preserve()
//     Prevents the EventData instance from automatically being destroyed. Only call
//     this if you need to save an EventData instance for later use.
//
// .caster() -> unit (or .u) 
//     Returns the unit that is casting the spell, or the unit that was ordered.
// .targetUnit() (or .tu) -> unit 
//     Returns the unit target of the spell or order. Returns null if the spell or
//     order did not target a unit.
// .targetDestructable() (or .td) -> destructable 
//     Returns the destructable target of the spell or order. Returns null if the
//     spell or order did not target a destructable.
// .targetItem() (or .ti) -> item 
//     Returns the item target of the spell or order. Returns null if the spell or
//     order did not target an item.
//
// .targetIsUnit() -> boolean 
//     Returns true if the spell or order had a unit target.
// .targetIsDestructable() -> boolean 
//     Returns true if the spell or order had a destructable target.
// .targetIsItem() -> boolean 
//     Returns true if the spell or order had an item target.
// .targetIsPoint() -> boolean 
//     Returns true if the spell or order had a point target.
// .targetIsNone() -> boolean 
//     Returns true if the spell or order had no target.
// .targetTypeString() -> string 
//     Returns the name of the type of target of the spell or order. Useful for
//     debug purposes.
//
// .wasUseItemOrder() (or .wasuseitemorder) -> boolean
//     Returns a boolean indicating whether this was a use item order.
// .usedItemSlot() (or .useditemslot) -> integer 
//     Returns the slot (values 1 to 6) of the used item. Returns 0 if no item
//     was used.
// .usedItem() (or .useditem) -> item 
//     Returns the used item. Returns null if no item was used.
//
// .wasDragItemOrder() (or .wasdragitemorder) -> boolean
//     Returns a boolean indiciating whether this was a drag item order.
// .draggedItem() (or .draggeditem) -> item 
//     Returns the dragged item. Returns null if no item was dragged.
// .draggedToSlot() (or .draggedtoslot) -> integer 
//     Returns the slot the dragged item was dragged to. Returns 0 if no item
//     was dragged.
// .draggedToItem() (or .draggedtoitem) -> item 
//     Returns the item that the dragged item was dragged to. Returns null if
//     no item was dragged, or the item was dragged to an empty inventory slot.
//
// .casterX() (or .x) -> real 
//     Returns the X coordinate of the casting or ordered unit.
// .casterY() (or .y) -> real 
//     Returns the Y coordinate of the casting or ordered unit.
// .casterZ() (or .z) -> real 
//     Returns the Z coordinate of the casting or ordered unit.
// .targetX() (or .tx) -> real 
//     Returns the X coordinate of the target of the spell or order.
// .targetY() (or .ty) -> real 
//     Returns the Y coordinate of the target of the spell or order.
// .targetZ() (or .tz) -> real 
//     Returns the Z coordinate of the target of the spell or order.
//
// .distanceXY() -> real 
//     Returns the XY distance between the casting or ordered unit and the target.
// .distance() -> real 
//     Returns the XYZ distance between the casting or ordered unit and the target.
// .angle() -> real 
//     Returns the angle between the casting or ordered unit and the target.
// .pitch() -> real 
//     Returns the pitch between the casting or ordered unit and the target. Pitch
//     refers to the angle from the XY plane of a line that extends from the ordered
//     unit to the target.
//
// .orderId() -> integer 
//     Returns the order id of the order. Returns 0 if it was a spell cast event.
// .orderString() -> string 
//     Returns the name of the order. Returns "(null)" if it was a spell cast event.
// .eventId() -> integer 
//     Returns the event id of the triggering event.
// .eventString() -> string 
//     Returns the name of the triggering event.
// .print() 
//     Prints all information about the event. Useful for debug purposes.
//  
//===========================================================================
// Compatible Event Types:
//=========================
//
// Order-related PlayerUnitEvents:
// EVENT_PLAYER_UNIT_ISSUED_ORDER, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER,
// EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER
//
// Order-related UnitEvents:
// EVENT_UNIT_ISSUED_ORDER, EVENT_UNIT_ISSUED_POINT_ORDER, EVENT_UNIT_ISSUED_TARGET_ORDER
//
// Spell-related PlayerUnitEvents:
// EVENT_PLAYER_UNIT_SPELL_CHANNEL, EVENT_PLAYER_UNIT_SPELL_CAST, EVENT_PLAYER_UNIT_SPELL_EFFECT
// EVENT_PLAYER_UNIT_SPELL_FINISH, EVENT_PLAYER_UNIT_SPELL_ENDCAST
//
// Spell-related UnitEvents:
// EVENT_UNIT_SPELL_CHANNEL, EVENT_UNIT_SPELL_CAST, EVENT_UNIT_SPELL_EFFECT
// EVENT_UNIT_SPELL_FINISH, EVENT_UNIT_SPELL_ENDCAST
// 
//===========================================================================

struct EventData
    private static constant integer TARGET_TYPE_UNIT = 4
    private static constant integer TARGET_TYPE_DESTRUCTABLE = 3
    private static constant integer TARGET_TYPE_ITEM = 2
    private static constant integer TARGET_TYPE_POINT = 1
    private static constant integer TARGET_TYPE_NONE = 0
    
    private static constant integer EVENT_TYPE_LAMESPELL = 3
    private static constant integer EVENT_TYPE_SPELL = 2
    private static constant integer EVENT_TYPE_ORDER = 1
    private static constant integer EVENT_TYPE_INVALID = 0
    
    private static constant real R2D = 57.2957795

    private static hashtable ht = InitHashtable()
    private static location loc = Location(0., 0.)
    private static integer array eventtype
    private static string array eventstring
    private static string array targetstring
    
    readonly unit u
    readonly unit tu
    readonly destructable td
    readonly item ti
    readonly real x
    readonly real y
    readonly real z
    readonly real tx
    readonly real ty
    readonly real tz
    
    readonly boolean wasuseitemorder = false
    readonly integer useditemslot = 0
    readonly item useditem = null
    
    readonly boolean wasdragitemorder = false
    readonly item draggeditem = null
    readonly integer draggedtoslot = 0
    readonly item draggedtoitem = null
    
    private integer targettype
    private integer orderID
    private integer eventID
    
    //===========================================================================
    // User functions:
    
    method caster takes nothing returns unit
        return u
    endmethod
    
    method targetUnit takes nothing returns unit
        return tu
    endmethod
    method targetDestructable takes nothing returns destructable
        return td
    endmethod
    method targetItem takes nothing returns item
        return ti
    endmethod

    method targetIsUnit takes nothing returns boolean
        return targettype == TARGET_TYPE_UNIT
    endmethod
    method targetIsDestructable takes nothing returns boolean
        return targettype == TARGET_TYPE_DESTRUCTABLE
    endmethod
    method targetIsItem takes nothing returns boolean
        return targettype == TARGET_TYPE_ITEM
    endmethod
    method targetIsPoint takes nothing returns boolean
        return targettype == TARGET_TYPE_POINT
    endmethod
    method targetIsNone takes nothing returns boolean
        return targettype == TARGET_TYPE_NONE
    endmethod
    method targetTypeString takes nothing returns string
        return targetstring[targettype]
    endmethod
    
    method casterX takes nothing returns real
        return x
    endmethod
    method casterY takes nothing returns real
        return y
    endmethod
    method casterZ takes nothing returns real
        return z
    endmethod
    
    method targetX takes nothing returns real
        return tx
    endmethod
    method targetY takes nothing returns real
        return ty
    endmethod
    method targetZ takes nothing returns real
        return tz
    endmethod
    
    method wasUseItemOrder takes nothing returns boolean
        return wasuseitemorder
    endmethod
    method usedItemSlot takes nothing returns integer
        return useditemslot
    endmethod
    method usedItem takes nothing returns item
        return useditem
    endmethod
    
    method wasDragItemOrder takes nothing returns boolean
        return wasdragitemorder
    endmethod
    method draggedItem takes nothing returns item
        return draggeditem
    endmethod
    method draggedToSlot takes nothing returns integer
        return draggedtoslot
    endmethod
    method draggedToItem takes nothing returns item
        return draggedtoitem
    endmethod

    method distanceXY takes nothing returns real
        return SquareRoot((tx - x)*(tx - x) + (ty - y)*(ty - y))
    endmethod
    method distance takes nothing returns real
        return SquareRoot((tx - x)*(tx - x) + (ty - y)*(ty - y) + (tz - z)*(tz - z))
    endmethod
    method angle takes nothing returns real
        return Atan2(ty - y, tx - x)
    endmethod
    method pitch takes nothing returns real
        return Atan((tz - z) / (SquareRoot((tx - x)*(tx - x) + (ty - y)*(ty - y)) + 0.001))
    endmethod
    
    method orderId takes nothing returns integer
        return orderID
    endmethod
    method orderString takes nothing returns string
        return OrderId2String(orderID)
    endmethod
    method eventId takes nothing returns integer
        return eventID
    endmethod
    method eventString takes nothing returns string
        return eventstring[eventID]
    endmethod
    
    method print takes nothing returns nothing
        call BJDebugMsg("Event type: " + eventString())
        call BJDebugMsg("Event unit X/Y/Z: " + R2S(x) + ", " + R2S(y) + ", " + R2S(z))
        call BJDebugMsg("Target type: " + targetTypeString())
        call BJDebugMsg("Target X/Y/Z: " + R2S(tx) + ", " + R2S(ty) + ", " + R2S(tz))
        call BJDebugMsg("DistanceXY: " + R2S(distanceXY()))
        call BJDebugMsg("Distance: " + R2S(distance()))
        call BJDebugMsg("Angle: " + R2S(angle()) + " radians, " + R2S(angle()*R2D) + " degrees")
        call BJDebugMsg("Pitch: " + R2S(pitch()) + " radians, " + R2S(pitch()*R2D) + " degrees")
    endmethod
    
    //===========================================================================
    
    private static timer autodestroytimer = CreateTimer()
    private static EventData array eds
    private static integer ed_n = -1
    private boolean autodestroy = true
    
    private static method doAutoDestroy takes nothing returns nothing
        local integer n = ed_n
            loop
                exitwhen n < 0
                if eds[n].autodestroy then
                    call eds[n].destroy()
                endif
                set n = n - 1
            endloop
        set ed_n = -1
    endmethod
    
    private method autoDestroy takes nothing returns nothing
        set ed_n = ed_n + 1
        set eds[ed_n] = this
        call TimerStart(autodestroytimer, 0., false, function EventData.doAutoDestroy)
    endmethod
    
    //===========================================================================
    
    private static method clone takes EventData ed returns EventData
        local EventData this = allocate()
            set u = ed.u
            set tu = ed.tu
            set td = ed.td
            set ti = ed.ti
            set x = ed.x
            set y = ed.y
            set z = ed.z
            set tx = ed.tx
            set ty = ed.ty
            set tz = ed.tz
            set targettype = ed.targettype
            set orderID = ed.orderID
            set eventID = ed.eventID
            call autoDestroy()
        return ed
    endmethod
    
    static method create takes nothing returns EventData
        local EventData this
        local integer e = GetHandleId(GetTriggerEventId())
            if eventtype[e] == EVENT_TYPE_INVALID then
                call BJDebugMsg("EventData error: EventTarget struct not created within valid event type (" + I2S(e) + ")")
                return 0
            elseif eventtype[e] == EVENT_TYPE_LAMESPELL then
                set this = clone(EventData(LoadInteger(ht, GetHandleId(GetTriggerUnit()), 0)))
                set eventID = e
                return this
            endif
            
            set this = allocate()
            set eventID = e
            set u = GetTriggerUnit()
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            call MoveLocation(loc, x, y)
            set z = GetLocationZ(loc) + GetUnitFlyHeight(u)
            
            if eventtype[e] == EVENT_TYPE_SPELL then
                set orderID = 0
                set tx = GetSpellTargetX()
                set ty = GetSpellTargetY()
            
                if GetSpellTargetUnit() != null then
                    set tu = GetSpellTargetUnit()
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc) + GetUnitFlyHeight(tu)
                    set targettype = TARGET_TYPE_UNIT
                    
                elseif GetSpellTargetDestructable() != null then
                    set td = GetSpellTargetDestructable()
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc)
                    set targettype = TARGET_TYPE_DESTRUCTABLE
                    
                elseif GetSpellTargetItem() != null then
                    set ti = GetSpellTargetItem()
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc)
                    set targettype = TARGET_TYPE_ITEM
                    
                else
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc)
                    if tx != 0. or ty != 0. or tz != 0. then
                        set targettype = TARGET_TYPE_POINT
                    else
                        set targettype = TARGET_TYPE_NONE
                        set tx = x
                        set ty = y
                        set tz = z
                    endif
                    
                endif
                
            else
                set orderID = GetIssuedOrderId()
                
                if orderID >= 852008 and orderID <= 852013 then
                    set wasuseitemorder = true
                    set useditemslot = orderID - 852008 + 1
                    set useditem = UnitItemInSlot(u, useditemslot - 1)
                    
                elseif orderID >= 852002 and orderID <= 852007 then
                    set wasdragitemorder = true
                    set draggeditem = GetOrderTargetItem()
                    set draggedtoslot = orderID - 852002 + 1
                    set draggedtoitem = UnitItemInSlot(u, draggedtoslot - 1)
                endif
                
                set tx = GetOrderPointX()
                set ty = GetOrderPointY()
                
                if GetOrderTargetUnit() != null then
                    set tu = GetOrderTargetUnit()
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc) + GetUnitFlyHeight(tu)
                    set targettype = TARGET_TYPE_UNIT
                    
                elseif GetOrderTargetDestructable() != null then
                    set td = GetOrderTargetDestructable()
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc)
                    set targettype = TARGET_TYPE_DESTRUCTABLE
                    
                elseif GetOrderTargetItem() != null then
                    set ti = GetOrderTargetItem()
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc)
                    set targettype = TARGET_TYPE_ITEM
                    
                else
                    call MoveLocation(loc, tx, ty)
                    set tz = GetLocationZ(loc)
                    if tx != 0. or ty != 0. or tz != 0. then
                        set targettype = TARGET_TYPE_POINT
                    else
                        set targettype = TARGET_TYPE_NONE
                        set tx = x
                        set ty = y
                        set tz = z
                    endif
                    
                endif
                
            endif
            
            call .autoDestroy()
        return this
    endmethod
    
    method preserve takes nothing returns EventData
            set autodestroy = false
        return this
    endmethod
    
    private method onDestroy takes nothing returns nothing
        set u = null
        set tu = null
        set td = null
        set ti = null
        set useditem = null
        set draggeditem = null
        set draggedtoitem = null
    endmethod
    
    //===========================================================================
    
    private static method initEventData takes nothing returns nothing
        set eventtype[38] = EVENT_TYPE_ORDER
        set eventstring[38] = "EVENT_PLAYER_UNIT_ISSUED_ORDER"
        set eventtype[39] = EVENT_TYPE_ORDER
        set eventstring[39] = "EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER"
        set eventtype[40] = EVENT_TYPE_ORDER
        set eventstring[40] = "EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER or EVENT_PLAYER_UNIT_ISSUED_UNIT_ORDER"
        set eventtype[75] = EVENT_TYPE_ORDER
        set eventstring[75] = "EVENT_UNIT_ISSUED_ORDER"
        set eventtype[76] = EVENT_TYPE_ORDER
        set eventstring[76] = "EVENT_UNIT_ISSUED_POINT_ORDER"
        set eventtype[77] = EVENT_TYPE_ORDER
        set eventstring[77] = "EVENT_UNIT_ISSUED_TARGET_ORDER"
        set eventtype[272] = EVENT_TYPE_SPELL
        set eventstring[272] = "EVENT_PLAYER_UNIT_SPELL_CHANNEL"
        set eventtype[273] = EVENT_TYPE_SPELL
        set eventstring[273] = "EVENT_PLAYER_UNIT_SPELL_CAST"
        set eventtype[274] = EVENT_TYPE_SPELL
        set eventstring[274] = "EVENT_PLAYER_UNIT_SPELL_EFFECT"
        set eventtype[275] = EVENT_TYPE_LAMESPELL
        set eventstring[275] = "EVENT_PLAYER_UNIT_SPELL_FINISH"
        set eventtype[276] = EVENT_TYPE_LAMESPELL
        set eventstring[276] = "EVENT_PLAYER_UNIT_ENDCAST"
        set eventtype[289] = EVENT_TYPE_SPELL
        set eventstring[289] = "EVENT_UNIT_SPELL_CHANNEL"
        set eventtype[290] = EVENT_TYPE_SPELL
        set eventstring[290] = "EVENT_UNIT_SPELL_CAST"
        set eventtype[291] = EVENT_TYPE_SPELL
        set eventstring[291] = "EVENT_UNIT_SPELL_EFFECT"
        set eventtype[292] = EVENT_TYPE_LAMESPELL
        set eventstring[292] = "EVENT_UNIT_SPELL_FINISH"
        set eventtype[293] = EVENT_TYPE_LAMESPELL
        set eventstring[293] = "EVENT_UNIT_SPELL_ENDCAST"
        set targetstring[TARGET_TYPE_NONE] = "nothing"
        set targetstring[TARGET_TYPE_POINT] = "a point"
        set targetstring[TARGET_TYPE_ITEM] = "an item"
        set targetstring[TARGET_TYPE_DESTRUCTABLE] = "a destructable"
        set targetstring[TARGET_TYPE_UNIT] = "a unit"
    endmethod
    
    private static method PreserveLameSpell takes nothing returns boolean
            call SaveInteger(ht, GetHandleId(GetTriggerUnit()), 0, .create().preserve())
        return false
    endmethod
    private static method ReleaseLameSpell takes nothing returns boolean
            call EventData(LoadInteger(ht, GetHandleId(GetTriggerUnit()), 0)).autoDestroy()
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        local trigger spelleffect = CreateTrigger()
        local trigger spellendcast = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(spelleffect, EVENT_PLAYER_UNIT_SPELL_EFFECT)
            call TriggerAddCondition(spelleffect, function EventData.PreserveLameSpell)
            call TriggerRegisterAnyUnitEventBJ(spellendcast, EVENT_PLAYER_UNIT_SPELL_ENDCAST)
            call TriggerAddCondition(spellendcast, function EventData.ReleaseLameSpell)
            call initEventData()
    endmethod
    
endstruct

endlibrary

grim001 is offline   Reply With Quote
Sponsored Links - Login to hide this ad!