• 🏆 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!

how to set up this Jass Streak System v5.0.0.0

Status
Not open for further replies.
Level 8
Joined
Aug 8, 2011
Messages
297
Original Post: http://www.hiveworkshop.com/forums/spells-569/advanced-streak-system-v5-0-0-0-a-203324/index7.html

What triggers shall i import to my map ? atm i have imported them all but "Demo Map" also the disabled once.


I THINK ITS WORKING, BUT IT KEEPS WRITING "null" as a message on left side! how to remove that ?

EDIT: It made an fatal error when i killed a second hero :/. still need help to implent this jass triggers. i got the newest gen etc, and i already have an jass implented in my map.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Did you read the system requirements?
JASS:
/*
*       - A Damage Detection System.
*         Supports:
*               - DamageEvent   By Nestharus        (hiveworkshop.com/forums/jass-resources-412/snippet-damageevent-186829/)
*               - Damage        By Jesus4Lyf        (thehelper.net/forums/showthread.php/131287-Damage)
*
*       - A Unit Indexer.
*         Supports:
*               - UnitIndexer   By Nestharus        (hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/)
*               - AIDS          By Jesus4Lyf        (thehelper.net/forums/showthread.php/130752-Advanced-Indexing-Data-Storage)
*
*       - A Sound System.
*         Supports:
*               - SoundTools    By Magtheridon96    (hiveworkshop.com/forums/jass-resources-412/system-soundtools-207308/)
*               - SoundUtils    By Rising_Dusk      (wc3c.net/showthread.php?t=107433)
*
*       - An Event Handler.
*         Supports:
*               - Event         By Nestharus        (hiveworkshop.com/forums/jass-resources-412/snippet-event-186555/)
*               - Event         By Jesus4Lyf        (thehelper.net/forums/showthread.php/126846-Event)
*
*       - Table By Bribe
*           - hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
*       - TimerUtils By Vexorian
*           - wc3c.net/showthread.php?t=101322
*/
 
Level 8
Joined
Aug 8, 2011
Messages
297
JASS:
/******
*




*
*   Configurable Functions:
*   -----------------------
*
*       - function GetBounty           takes integer killerPlayerId, integer dyingPlayerId, unit killingUnit, unit dyingUnit                                                 returns integer
*       - function GetLostGold         takes integer killerPlayerId, integer dyingPlayerId, unit killingUnit, unit dyingUnit, integer killingBounty                          returns integer
*       - function GetAssistGold       takes integer killerPlayerId, integer dyingPlayerId, unit killingUnit, unit dyingUnit, integer killingBounty, integer numberAssisters returns integer
*
*       - function KillingPlayerFilter takes integer playerId                                                                                                                returns boolean
*       - function AssistPlayerFilter  takes integer playerId                                                                                                                returns boolean
*       - function DyingPlayerFilter   takes integer playerId                                                                                                                returns boolean
*
*       - function GetFirstbloodString takes string killingName                                                                                                              returns string
*       - function GetKillString       takes string killingName, string dyingName, string bounty                                                                             returns string
*       - function GetEndString        takes string killingName, string dyingName, string streak, string bounty                                                              returns string
*
*       - function GetSuicideString    takes integer killingPlayerId, string killingName                                                                                     returns string
*       - function GetDenialString     takes integer killingPlayerId, string killingName, integer dyingPlayerId, string dyingName                                            returns string
*
*   Event Responses:
*   ----------------
*
*       - StreakSystem.getKillingUnitId()
*       - StreakSystem.getKillingUnit()
*       - StreakSystem.getDyingUnitId()
*       - StreakSystem.getDyingUnit()
*       - StreakSystem.getKillingPlayerId()
*       - StreakSystem.getKillingPlayer()
*       - StreakSystem.getDyingPlayerId()
*       - StreakSystem.getDyingPlayer()
*           - For: FIRSTBLOOD, STREAK, END_STREAK, MULTIKILL, COMBO_BREAKER, SUICIDE, DENIAL
*           - These can be used inside END_MULTIKILL if DEATH_END_MULTI is set to true. They will only
*             return valid data if a unit dies and loses a multikill.
*           - Warning: Calling StreakSystem.getKillingPlayer() or StreakSystem.getDyingPlayer() inside
*             a function registered to END_MULTIKILL will crash the game if the multikill simply faded.
*             Use the Id counterparts instead.
*
*       - StreakSystem.getEndedMultikill()
*       - StreakSystem.getMultikillLoserId()
*       - StreakSystem.getMultikillLoser()
*           - For: END_MULTIKILL
*
*       - StreakSystem.getAchievedStreak()
*           - For: STREAK
*       - StreakSystem.getEndedStreak()
*           - For: END_STREAK
*       - StreakSystem.getAchievedMultikill()
*           - For: MULTIKILL
*       - StreakSystem.getComboBroken()
*           - For: COMBO_BREAKER
*
*   API:
*   ----
*
*       - struct StreakSystem extends array
*
*           - static boolean enabled
*               - Tells whether the system is enabled or not.
*           - static boolean firstblood
*               - Tells whether firstblood was taken or not.
*
*           - static Event FIRSTBLOOD
*               - This event fires when a hero takes firstblood
*           - static Event STREAK
*               - This event fires when a hero is on a streak
*           - static Event MULTIKILL
*               - This event fires when a hero gets a multikill
*           - static Event END_STREAK
*               - This event fires when a streak is ended
*           - static Event END_MULTIKILL
*               - This event fires when a multikill is no longer valid
*           - static Event COMBO_BREAKER
*               - This event fires when a hero gets a combo-breaker
*           - static Event SUICIDE
*               - This event fires when a hero kills himself
*           - static Event DENIAL
*               - This event fires when a hero kills his own ally
*
*           - static method newStreak takes string streakName, string streakDisplay, string soundPath, integer duration returns nothing
*           - static method newMultikill takes string text, string soundPath, integer duration returns nothing
*               - These two functions create a streak-type and a multikill-type. The duration is in milliseconds.
*               - Since it is not very clear what the arguments should be, here is an example:
*                   - call StreakSystem.newStreak("killing spree", "is on a killing spree!", "war3mapImported\\KillingSpree.mp3", 2489)
*                   - call StreakSystem.newMultikill("is on a Rampage!!!", "war3mapImported\\Rampage.wav", 1991)
*               - As you can see, the function newStreak takes the name of the streak, then the form of the 
*                 streak message, then the path of the streak sound and finally, the duration of the streak 
*                 sound in milliseconds. The newMultikill function takes the form of the multikill message,
*                 then the path of the multikill sound and finally, the duration of that sound in milliseconds.
*
*           - static method setFirstBloodSound takes string path, integer duration returns nothing
*           - static method setComboBreakerSound takes string path, integer duration returns nothing
*               - These two functions are used to configure the sounds that are played when a player gets 
*                 firstblood/a combo-breaker.
*
*           - static method getKillingUnitId takes nothing returns UnitIndex
*           - static method getKillingUnit takes nothing returns unit
*           - static method getDyingUnitId takes nothing returns UnitIndex
*           - static method getDyingUnit takes nothing returns unit
*           - static method getKillingPlayerId takes nothing returns integer
*           - static method getKillingPlayer takes nothing returns player
*           - static method getDyingPlayerId takes nothing returns integer
*           - static method getDyingPlayer takes nothing returns player
*               - These functions retrieve the killing players and units and the 
*                 dying units and players for event responses.
*
*           - static method getAchievedStreak takes nothing returns integer
*           - static method getEndedStreak takes nothing returns integer
*           - static method getAchievedMultikill takes nothing returns integer
*           - static method getEndedMultikill takes nothing returns integer
*           - static method getMultikillLoserId takes nothing returns integer
*           - static method getMultikillLoser takes nothing returns player
*           - static method getComboBroken takes nothing returns integer
*               - These functions retrieve the streak and multikill data for
*                 for event responses.
*            
*           - static method getKills takes player whichPlayer returns integer
*           - static method getDeaths takes player whichPlayer returns integer
*           - static method getDenies takes player whichPlayer returns integer
*           - static method getSuicides takes player whichPlayer returns integer
*           - static method getAssists takes player whichPlayer returns integer
*           - static method getStreaks takes player whichPlayer returns integer
*           - static method getMultikills takes player whichPlayer returns integer
*           - static method getCombobreakers takes player whichPlayer returns integer
*           - static method getMultikillsOfType takes player whichPlayer returns integer
*           - static method getStreaksOfType takes player whichPlayer returns integer
*               - These functions are used to get the total stats of a player.
*
*           - static method getKillsById takes integer playerId returns integer
*           - static method getDeathsById takes integer playerId returns integer
*           - static method getDeniesById takes integer playerId returns integer
*           - static method getSuicidesById takes integer playerId returns integer
*           - static method getAssistsById takes integer playerId returns integer
*           - static method getStreaksById takes integer playerId returns integer
*           - static method getMultikillsById takes integer playerId returns integer
*           - static method getCombobreakersById takes integer playerId returns integer
*           - static method getMultikillsOfTypeById takes integer playerId returns integer
*           - static method getStreaksOfTypeById takes integer playerId returns integer
*               - These functions are used to get the total stats of a player given his Id.
*
*           - static method getCurrentStreak takes player p returns integer
*           - static method getCurrentMultikill takes player p returns integer
*               - These functions are used to get the current streak of a player
*                 or his current multikills.
*
*           - static method getCurrentStreakById takes integer playerId returns integer
*           - static method getCurrentMultikillById takes integer playerId returns integer
*               - These functions are used to get the current streak of a player
*                 or his current multikills given his Id.
*
*           - static method resetStreak takes integer playerId returns nothing
*           - static method resetStreaks takes nothing returns nothing
*               - These functions are used to either reset the streak of one or all players.
*
*           - static method resetAssist takes integer unitId returns nothing
*           - static method resetAssists takes nothing returns nothing
*               - These functions are used to either reset the streak associated with one or all units.
*
*           - static method operator goldGain takes nothing returns boolean
*           - static method operator goldGain= takes boolean b returns nothing
*           - static method operator goldLoss takes nothing returns boolean
*           - static method operator goldLoss= takes boolean b returns nothing
*               - Management of KillingPlayer-Goldgain and DyingPlayer-Goldloss.
*
*           - static method operator bountyBase takes nothing returns integer
*           - static method operator bountyBase= takes integer i returns nothing
*           - static method operator bountyIncrement takes nothing returns integer
*           - static method operator bountyIncrement= takes integer i returns nothing
*               - Management of Bounty Formula.
*
*******************************************************************/
library ASS requires optional DamageEvent, optional Damage, optional UnitIndexer, optional AIDS, optional SoundTools, optional SoundUtils, Table, optional RegisterPlayerUnitEvent, TimerUtils, Event

    /*
    *   Configuration
    */
    globals
        /*
        *   Whether you have Event by Nestharus or Jesus4Lyf is unknown to me.
        *   Hence, I put up this boolean for configuration. If you are using
        *   Damage and thus AIDS and Event by Jesus4Lyf, then set this to false.
        */
        private constant boolean EVENT_BY_NESTHARUS = true
    endglobals
    
    /*
    *   System Configuration
    */
    globals
        // Max interval between Multikills (seconds)
        private constant    real            MULTI_TIME              = 10
        // Multikill Update Interval (seconds)
        private constant    real            MULTI_UPDATE            = 1
        // Are sounds 3D?
        private constant    boolean         S3D                     = false
        // Firstblood bonus
        private constant    integer         FIRST_GOLD              = 200
        // Duration of the text messages
        private constant    real            TEXT_DURATION           = 8.00
        // Interval between streak and multikill sounds
        private constant    real            INTERVAL                = 0.50
        // Assist Decay time (seconds)
        private constant    real            ASSIST_DECAY            = 45
        // Assist Update Interval (seconds)
        private constant    real            ASSIST_UPDATE           = 1
        // Can the heroes of leavers get streaks?
        private constant    boolean         LEAVER_HEROES           = false
        // Leavers can assist?
        private constant    boolean         LEAVER_CAN_ASSIST       = false
        // Initial Gold base
        private             integer         baseGold                = 210
        // Gold increment according to formulas
        private             integer         goldIncrement           = 10
        // Do you lose gold when you die?
        private             boolean         loseGold                = true
        // Do you gain gold when you kill?
        private             boolean         gainGold                = true
        // Do you want floating texts?
        private constant    boolean         TEXTTAGS                = true
        // Texttag configuration: Age
        private constant    real            TEXTTAG_AGE             = 2.
        // Texttag configuration: Fade-point
        private constant    real            TEXTTAG_FADE            = 1.5
        // Texttag configuration: Size
        private constant    real            TEXTTAG_SIZE            = 0.024
        // Texttag configuration: Velocity X
        private constant    real            TEXTTAG_X               = 0.
        // Texttag configuration: Velocity Y
        private constant    real            TEXTTAG_Y               = 0.0355
        // Give gold to assisters?
        private constant    boolean         ASSIST_GOLD             = true
        // Does Suicide end a streak?
        private constant    boolean         SUICIDE_ENDS            = false
        // When you deny a hero, do you get a kill?
        private constant    boolean         DENIES_COUNT_KILLS      = false
        // When you get denied, do you get a death?
        private constant    boolean         DENIES_COUNT_DEATHS     = false
        // Does suicide count as a death?
        private constant    boolean         SUICIDE_DEATH           = true
        // Does a Death end a multikill?
        private constant    boolean         DEATH_END_MULTI         = true
        // Do you want to have the Combo-breaker message and sound feature?
        private constant    boolean         COMBO_BREAKER           = true
        // Minimum Streak to end to get a Combo-breaker
        private constant    integer         COMBO_BREAKER_MIN       = 3
        // Should the suicide event fire before the end streak event? Or after?
        // This is only important if SUICIDE_ENDS is set to true.
        private constant    boolean         SUICIDE_FIRE_FIRST      = true
    endglobals
    
    private keyword Streak
    
    private function GetBounty takes integer killingId, integer dyingId, unit killingUnit, unit dyingUnit returns integer
        return baseGold + goldIncrement * Streak[dyingId] + goldIncrement * Streak[killingId]
    endfunction
    
    private function GetLostGold takes integer killingId, integer dyingId, unit killingUnit, unit dyingUnit, integer gold returns integer
        return gold / 3
    endfunction
    
    private function GetAssistGold takes integer killingId, integer dyingId, unit killingUnit, unit dyingUnit, integer gold, integer numberAssisters returns integer
        return gold / numberAssisters
    endfunction
    
    private function KillingPlayerFilter takes integer playerId returns boolean
        return playerId < 12
    endfunction
    
    private function AssistPlayerFilter takes integer playerId returns boolean
        return playerId < 12
    endfunction
    
    private function DyingPlayerFilter takes integer playerId returns boolean
        return playerId < 12
    endfunction
    
    private function StreakPlayerFilter takes integer playerId returns boolean
        return playerId < 12
    endfunction
    
    private function MultikillPlayerFilter takes integer playerId returns boolean
        return playerId < 12
    endfunction
    
    private function CombobreakerPlayerFilter takes integer playerId returns boolean
        return playerId < 12
    endfunction
    
    private function GetFirstbloodString takes string killingName returns string
        return killingName + " just drew |cffff0000firstblood|r!"
    endfunction
    
    private function GetKillString takes string killingName, string dyingName, string bounty returns string
        return killingName + " pwned " + dyingName + "'s head for |cffffcc00" + bounty + "|r gold."
    endfunction
    
    private function GetEndString takes string killingName, string dyingName, string streak, string bounty returns string
        return dyingName + streak + " streak has been ended by " + killingName + " for |cffffcc00" + bounty + "|r gold."
    endfunction
    
    private function GetSuicideString takes string dyingName returns string
        return dyingName + "|r has killed himself!"
    endfunction
    
    private function GetDenialString takes string killingName, string dyingName returns string
        return killingName + "|r has denied his ally " + dyingName + "|r!"
    endfunction
    
    private module Init
        private static method onInit takes nothing returns nothing
            /*
            *   Player color strings configuration.
            */
            set thistype.colors[0]  = "|cffff0303"
            set thistype.colors[1]  = "|cff0042ff"
            set thistype.colors[2]  = "|cff1ce6b9"
            set thistype.colors[3]  = "|cff540081"
            set thistype.colors[4]  = "|cfffffc01"
            set thistype.colors[5]  = "|cfffeba0e"
            set thistype.colors[6]  = "|cff20c000"
            set thistype.colors[7]  = "|cffe55bb0"
            set thistype.colors[8]  = "|cff959697"
            set thistype.colors[9]  = "|cff7ebff1"
            set thistype.colors[10] = "|cff106246"
            set thistype.colors[11] = "|cff4e2a04"
        endmethod
    endmodule
    
    /*
    *   Configuration Ends Here
    */
    
    static if not LEAVER_HEROES then
        private struct PlayerActive extends array
            private static boolean array playerOff
            static method operator [] takes integer i returns boolean
                return not playerOff[i]
            endmethod
            private static method run takes nothing returns boolean
                set playerOff[GetPlayerId(GetTriggerPlayer())] = true
                return false
            endmethod
            private static method onInit takes nothing returns nothing
                local trigger t = CreateTrigger()
                local integer i = 15
                loop
                    call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_LEAVE)
                    exitwhen i == 0
                    set i = i - 1
                endloop
                call TriggerAddCondition(t, Condition(function thistype.run))
            endmethod
        endstruct
    endif
    
    private module InitEventHandler
        private static method onInit takes nothing returns nothing
            set FIRSTBLOOD = Event.create()
            set STREAK = Event.create()
            set MULTIKILL = Event.create()
            set END_STREAK = Event.create()
            set END_MULTIKILL = Event.create()
            set COMBO_BREAKER = Event.create()
            set SUICIDE = Event.create()
            set DENIAL = Event.create()
        endmethod
    endmodule
    
    private struct EventHandler extends array
        readonly static Event FIRSTBLOOD
        readonly static Event STREAK
        readonly static Event MULTIKILL
        readonly static Event END_STREAK
        readonly static Event END_MULTIKILL
        readonly static Event COMBO_BREAKER
        readonly static Event SUICIDE
        readonly static Event DENIAL
        
        static integer killingUnitId = 0
        static integer dyingUnitId = 0
        static integer killingPlayerId = 0
        static integer dyingPlayerId = 0
        static integer streakAchieved = 0
        static integer streakEnded = 0
        static integer multikillAchieved = 0
        static integer multikillEnded = 0
        static integer multikillLoserId = 0
        static integer comboBroken = 0
        static unit dyingUnit = null
        static unit killingUnit = null
        
        implement InitEventHandler
    endstruct
    
    private struct Multikill extends array
        private static integer array value
        private static real array counters
        
        method operator multikill takes nothing returns integer
            return value[this]
        endmethod
        
        method operator multikill= takes integer i returns nothing
            set value[this] = i
        endmethod
        
        method operator counter takes nothing returns real
            return counters[this]
        endmethod
        
        method operator counter= takes real r returns nothing
            set counters[this] = r
        endmethod
        
        static method reset takes integer this returns nothing
            set value[this] = 0
            set counters[this] = 0
        endmethod
        
        static method resetAll takes nothing returns nothing
            local integer i = 15
            loop
                call reset(i)
                exitwhen i == 0
                set i = i - 1
            endloop
        endmethod
        
        private static method updateMulti takes nothing returns nothing
            local integer index = 15
            loop
                set counters[index] = counters[index] - MULTI_UPDATE
                
                if counters[index] <= 0 then
                    /*
                    *   Cache Event Response Data and Fire Event.
                    */
                    set EventHandler.multikillLoserId = index
                    set EventHandler.multikillEnded = value[index]
                    set value[index] = 0
                    
                    set EventHandler.killingUnitId = 0
                    set EventHandler.dyingUnitId = 0
                    set EventHandler.killingUnit = null
                    set EventHandler.dyingUnit = null
                    set EventHandler.killingPlayerId = -1
                    set EventHandler.dyingPlayerId = -1
                    
                    call EventHandler.END_MULTIKILL.fire()
                endif
                
                exitwhen index == 0
                set index = index - 1
            endloop
        endmethod
        
        private static method onInit takes nothing returns nothing
            call TimerStart(CreateTimer(), MULTI_UPDATE, true, function thistype.updateMulti)
        endmethod
    endstruct
    
    private struct Streak extends array
        private static integer array value
        
        static method operator [] takes integer i returns integer
            return value[i]
        endmethod
        
        static method operator []= takes integer i, integer v returns nothing
            set value[i] = v
        endmethod
        
        static method reset takes integer i returns nothing
            set value[i] = 0
        endmethod
        
        static method resetAll takes nothing returns nothing
            local integer i = 15
            loop
                call reset(i)
                exitwhen i == 0
                set i = i - 1
            endloop
        endmethod
    endstruct
    
    private function Exit takes nothing returns nothing
        loop
            call ExecuteFunc(Exit.name)
        endloop
    endfunction
    
    private struct Assist extends array
        private static Table array counters
        private static Table array assisting
        
        private static integer array count
        private static integer array next
        private static integer array prev
        private static boolean array inList
        private static boolean array allocated
        
        static method operator [] takes integer i returns thistype
            return i
        endmethod
        
        method operator [] takes integer i returns boolean
            return assisting[this].boolean[i]
        endmethod
        
        method operator []= takes integer i, boolean b returns nothing
            set assisting[this].boolean[i] = b
        endmethod
        
        method operator counter takes nothing returns integer
            return counters[this]
        endmethod
        
        method operator counter= takes integer i returns nothing
            set counters[this] = i
        endmethod
        
        method operator number takes nothing returns integer
            return count[this]
        endmethod
        
        method operator number= takes integer i returns nothing
            set count[this] = i
        endmethod
        
        static method reset takes integer unitId returns nothing
            /*
            *   Set the number of assisting players to 0,
            *   and flush all the data in the tables.
            */
            set count[unitId] = 0
            call assisting[unitId].flush()
            call counters[unitId].flush()
        endmethod
        
        static method resetAll takes nothing returns nothing
            local integer this = next[0]
            loop
                exitwhen this == 0
                call reset(this)
                set this = next[this]
            endloop
        endmethod
        
        static if not LIBRARY_UnitIndexer and not LIBRARY_AIDS then
            private static unit crashThread
            private static integer crashThreadInt
        endif
        
        private static method getIndexed takes nothing returns unit
            static if LIBRARY_UnitIndexer then
                return GetIndexedUnit()
            elseif LIBRARY_AIDS then
                return AIDS_GetEnteringIndexUnit()
            else
                return crashThread
            endif
        endmethod
        
        private static method getIndexedId takes nothing returns integer
            static if LIBRARY_UnitIndexer then
                return GetIndexedUnitId()
            elseif LIBRARY_AIDS then
                return AIDS_GetIndexOfEnteringUnitAllocated()
            else
                return crashThreadInt
            endif
        endmethod
        
        private static method getDeindexed takes nothing returns unit
            static if LIBRARY_UnitIndexer then
                return GetIndexedUnit()
            elseif LIBRARY_AIDS then
                return GetIndexUnit(AIDS_GetDecayingIndex())
            else
                return crashThread
            endif
        endmethod
        
        private static method getDeindexedId takes nothing returns integer
            static if LIBRARY_UnitIndexer then
                return GetIndexedUnitId()
            elseif LIBRARY_AIDS then
                return AIDS_GetDecayingIndex()
            else
                return crashThreadInt
            endif
        endmethod
        
        private static method index takes nothing returns boolean
            if IsUnitType(getIndexed(), UNIT_TYPE_HERO) then
                /*
                *   Make sure tables are initialized
                */
                if counters[getIndexedId()] == 0 then
                    set counters[getIndexedId()] = Table.create()
                    set assisting[getIndexedId()] = Table.create()
                endif
                set allocated[getIndexedId()] = true
            endif
            return false
        endmethod
        
        private static method deindex takes nothing returns boolean
            if IsUnitType(getDeindexed(), UNIT_TYPE_HERO) then
                /*
                *   Reset data
                */
                set count[getDeindexedId()] = 0
                call counters[getDeindexedId()].flush()
                call assisting[getDeindexedId()].flush()
                set allocated[getDeindexedId()] = false
            endif
            return false
        endmethod
        
        private static integer damageTargetId = 0
        private static integer damageSourceId = 0
        private static unit damageTarget = null
        
        private static method filter takes player p, integer id returns boolean
            static if LEAVER_CAN_ASSIST then
                return allocated[damageTargetId] and AssistPlayerFilter(id) and damageSourceId != 0 and (not assisting[damageTargetId].boolean[id]) and IsUnitEnemy(damageTarget, p) and damageSourceId != damageTargetId
            else
                return allocated[damageTargetId] and AssistPlayerFilter(id) and damageSourceId != 0 and (not assisting[damageTargetId].boolean[id]) and IsUnitEnemy(damageTarget, p) and damageSourceId != damageTargetId and PlayerActive[id]
            endif
        endmethod
        
        private static method onDamage takes nothing returns boolean
            local integer id
            local player p
            
            /*
            *   Data configuration based on system implemented.
            */
            static if LIBRARY_DamageEvent then
                set p = GetOwningPlayer(DamageEvent.source)
                set id = GetPlayerId(p)
                set damageTarget = DamageEvent.target
                set damageTargetId = DamageEvent.targetId
                set damageSourceId = DamageEvent.sourceId
            elseif LIBRARY_Damage then
                set p = GetOwningPlayer(GetEventDamageSource())
                set id = GetPlayerId(p)
                set damageTarget = GetTriggerUnit()
                set damageTargetId = GetUnitId(damageTarget)
                set damageSourceId = GetUnitId(GetEventDamageSource())
            endif
            
            if filter(p, id) then
                
                /*
                *   If the target is not in the list, we add him.
                */
                if not inList[damageTargetId] then
                    set inList[damageTargetId] = true
                    set next[damageTargetId] = 0
                    set prev[damageTargetId] = prev[0]
                    set next[prev[0]] = damageTargetId
                    set prev[0] = damageTargetId
                endif
                
                /*
                *   Mark player as assisting, increase assister count and reset assist counter
                */
                set assisting[damageTargetId].boolean[id] = true
                set count[damageTargetId] = count[damageTargetId] + 1
                set counters[damageTargetId].real[id] = ASSIST_DECAY
            endif
            
            set p = null
            return false
        endmethod
        
        private static method updateAssist takes nothing returns nothing
            local integer assist = next[0]
            local integer index = 15
            local real n = 0
            loop
                exitwhen assist == 0
                loop
                    if assisting[assist].boolean[index] then
                        set n = counters[assist].real[index] - ASSIST_UPDATE
                        set counters[assist].real[index] = n
                        
                        if n <= 0 then
                            /*
                            *   Mark the player as not assisting, decrease
                            *   the assisting player count, and check if we
                            *   can remove the target from the assists list
                            */
                            set assisting[assist].boolean[index] = false
                            set count[assist] = count[assist] - 1
                            if count[assist] == 0 then
                                set prev[next[assist]] = prev[assist]
                                set next[prev[assist]] = next[assist]
                                set inList[assist] = false
                            endif
                        endif
                    endif
                    
                    exitwhen index == 0
                    set index = index - 1
                endloop
                set index = 15
                set assist = next[assist]
            endloop
        endmethod
        
        private static method onInit takes nothing returns nothing
            static if LIBRARY_Damage then
                local trigger t = CreateTrigger()
            endif
            static if LIBRARY_UnitIndexer then
                call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
                call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
            elseif LIBRARY_AIDS then
                call AIDS_RegisterOnEnterAllocated(Condition(function thistype.index))
                call AIDS_RegisterOnDeallocate(Condition(function thistype.deindex))
            else
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "ERROR: NO UNIT INDEXING SYSTEM FOUND.")
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "SHUTING DOWN IN: 5")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "4")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "3")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "2")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "1")
                call TriggerSleepAction(1)
                call Exit()
            endif
            
            static if LIBRARY_DamageEvent then
                call DamageEvent.ANY.register(Condition(function thistype.onDamage), 0)
            elseif LIBRARY_Damage then
                call Damage_RegisterEvent(t)
                call TriggerAddCondition(t, Condition(function thistype.onDamage))
                set t = null
            else
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "ERROR: NO DAMAGE DETECTING SYSTEM FOUND.")
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "SHUTING DOWN IN: 5")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "4")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "3")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "2")
                call TriggerSleepAction(1)
                call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "1")
                call TriggerSleepAction(1)
                call Exit()
            endif
            
            call TimerStart(CreateTimer(), ASSIST_UPDATE, true, function thistype.updateAssist)
        endmethod
    endstruct
    
    private struct MessageHandler extends array
        private static string queue = ""
        
        static method print takes string s returns nothing
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, TEXT_DURATION, s)
        endmethod
        
        static method enqueue takes string s returns nothing
            set queue = queue + s + "\n"
        endmethod
        
        static method printQueue takes nothing returns nothing
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, TEXT_DURATION, queue)
        endmethod
        
        static method clearQueue takes nothing returns nothing
            set queue = ""
        endmethod
    endstruct
    
    private struct TextTagHandler extends array
        private static method createText takes player p, real cameraCenter, string s returns nothing
            local texttag tag = CreateTextTag()
            call SetTextTagText(tag, s, TEXTTAG_SIZE)
            call SetTextTagPos(tag, GetCameraEyePositionX(), GetCameraEyePositionY() + cameraCenter, 16.0)
            call SetTextTagVelocity(tag, TEXTTAG_X, TEXTTAG_Y)
            call SetTextTagVisibility(tag, GetLocalPlayer() == p)
            call SetTextTagFadepoint(tag, TEXTTAG_FADE)
            call SetTextTagLifespan(tag, TEXTTAG_AGE)
            call SetTextTagPermanent(tag, false)
            set tag = null
        endmethod
        
        static method plus takes player p, real cameraCenter, string s returns nothing
            call createText(p, cameraCenter, "|cffffcc00+" + s)
        endmethod
        
        static method minus takes player p, real cameraCenter, string s returns nothing
            call createText(p, cameraCenter, "|cffff0000-" + s)
        endmethod
    endstruct
    
    private struct PlayerStatHandler extends array
        static integer array kills
        static integer array deaths
        static integer array assists
        static integer array denies
        static integer array suicides
        
        static integer array streaks
        static integer array multikills
        static integer array combobreakers
        
        static Table array streakTypes
        static Table array multikillTypes
        
        private static method onInit takes nothing returns nothing
            local integer i = 15
            loop
                set streakTypes[i] = Table.create()
                set multikillTypes[i] = Table.create()
                exitwhen i == 0
                set i = i - 1
            endloop
        endmethod
    endstruct
    
    struct StreakSystem extends array
        private static integer maxStreak = 0
        private static integer minStreak = 1
        private static integer maxMultikill = 1
        
        static if LIBRARY_SoundTools then
            private static Sound firstSound
            private static Sound comboBreaker
            
            private static Sound array sounds
            private static Sound array multiSound
        elseif LIBRARY_SoundUtils then
            private static integer firstSound
            private static integer comboBreaker
            
            private static integer array sounds
            private static integer array multiSound
        endif
        
        private static string array strings
        private static string array multiString
        private static string array endString
        private static string array colors
        
        static boolean firstblood = false
        static boolean enabled = true
        
        private static key cacheKey
        private static Table cache = cacheKey
        
        /*
        *   Event Response Get Functions
        */
        static method getKillingUnitId takes nothing returns integer
            return EventHandler.killingUnitId
        endmethod
        static method getKillingUnit takes nothing returns unit
            return EventHandler.killingUnit
        endmethod
        static method getDyingUnitId takes nothing returns integer
            return EventHandler.dyingUnitId
        endmethod
        static method getDyingUnit takes nothing returns unit
            return EventHandler.dyingUnit
        endmethod
        static method getKillingPlayerId takes nothing returns integer
            return EventHandler.killingPlayerId
        endmethod
        static method getKillingPlayer takes nothing returns player
            return Player(EventHandler.killingPlayerId)
        endmethod
        static method getDyingPlayerId takes nothing returns integer
            return EventHandler.dyingPlayerId
        endmethod
        static method getDyingPlayer takes nothing returns player
            return Player(EventHandler.dyingPlayerId)
        endmethod
        static method getAchievedStreak takes nothing returns integer
            return EventHandler.streakAchieved
        endmethod
        static method getEndedStreak takes nothing returns integer
            return EventHandler.streakEnded
        endmethod
        static method getAchievedMultikill takes nothing returns integer
            return EventHandler.multikillAchieved
        endmethod
        static method getEndedMultikill takes nothing returns integer
            return EventHandler.multikillEnded
        endmethod
        static method getMultikillLoserId takes nothing returns integer
            return EventHandler.multikillLoserId
        endmethod
        static method getMultikillLoser takes nothing returns player
            return Player(EventHandler.multikillLoserId)
        endmethod
        static method getComboBroken takes nothing returns integer
            return EventHandler.comboBroken
        endmethod
        
        /*
        *   Event registration functions
        */
        static if EVENT_BY_NESTHARUS then
            static method registerFirstbloodEvent takes code c returns nothing
                call EventHandler.FIRSTBLOOD.register(Filter(c))
                return
            endmethod
            static method registerStreakEvent takes code c returns nothing
                call EventHandler.STREAK.register(Filter(c))
                return
            endmethod
            static method registerMultikillEvent takes code c returns nothing
                call EventHandler.MULTIKILL.register(Filter(c))
                return
            endmethod
            static method registerStreakEndEvent takes code c returns nothing
                call EventHandler.END_STREAK.register(Filter(c))
                return
            endmethod
            static method registerMultikillEndEvent takes code c returns nothing
                call EventHandler.END_MULTIKILL.register(Filter(c))
                return
            endmethod
            static method registerCombobreakerEvent takes code c returns nothing
                call EventHandler.COMBO_BREAKER.register(Filter(c))
                return
            endmethod
            static method registerSuicideEvent takes code c returns nothing
                call EventHandler.SUICIDE.register(Filter(c))
                return
            endmethod
            static method registerDenialEvent takes code c returns nothing
                call EventHandler.DENIAL.register(Filter(c))
                return
            endmethod
        else
            static method registerFirstbloodEvent takes trigger t returns nothing
                call EventHandler.FIRSTBLOOD.register(t)
            endmethod
            static method registerStreakEvent takes trigger t returns nothing
                call EventHandler.STREAK.register(t)
            endmethod
            static method registerMultikillEvent takes trigger t returns nothing
                call EventHandler.MULTIKILL.register(t)
            endmethod
            static method registerStreakEndEvent takes trigger t returns nothing
                call EventHandler.END_STREAK.register(t)
            endmethod
            static method registerMultikillEndEvent takes trigger t returns nothing
                call EventHandler.END_MULTIKILL.register(t)
            endmethod
            static method registerCombobreakerEvent takes trigger t returns nothing
                call EventHandler.COMBO_BREAKER.register(t)
            endmethod
            static method registerSuicideEvent takes trigger t returns nothing
                call EventHandler.SUICIDE.register(t)
            endmethod
            static method registerDenialEvent takes trigger t returns nothing
                call EventHandler.DENIAL.register(t)
            endmethod
        endif
        
        /*
        *   API Get Total Stat Functions
        */
        static method getKills takes player p returns integer
            return PlayerStatHandler.kills[GetPlayerId(p)]
        endmethod
        static method getDeaths takes player p returns integer
            return PlayerStatHandler.deaths[GetPlayerId(p)]
        endmethod
        static method getDenies takes player p returns integer
            return PlayerStatHandler.denies[GetPlayerId(p)]
        endmethod
        static method getSuicides takes player p returns integer
            return PlayerStatHandler.suicides[GetPlayerId(p)]
        endmethod
        static method getAssists takes player p returns integer
            return PlayerStatHandler.assists[GetPlayerId(p)]
        endmethod
        static method getStreaks takes player p returns integer
            return PlayerStatHandler.streaks[GetPlayerId(p)]
        endmethod
        static method getMultikills takes player p returns integer
            return PlayerStatHandler.multikills[GetPlayerId(p)]
        endmethod
        static method getCombobreakers takes player p returns integer
            return PlayerStatHandler.combobreakers[GetPlayerId(p)]
        endmethod
        static method getStreaksOfType takes player p, integer typ returns integer
            return PlayerStatHandler.streakTypes[GetPlayerId(p)][typ]
        endmethod
        static method getMultikillsOfType takes player p, integer typ returns integer
            return PlayerStatHandler.multikillTypes[GetPlayerId(p)][typ]
        endmethod
        
        static method getCurrentStreak takes player p returns integer
            return Streak[GetPlayerId(p)]
        endmethod
        static method getCurrentMultikill takes player p returns integer
            return Multikill(GetPlayerId(p)).multikill
        endmethod
        
        /*
        *   API Get Total Stat ById Functions
        */
        static method getKillsById takes integer id returns integer
            return PlayerStatHandler.kills[id]
        endmethod
        static method getDeathsById takes integer id returns integer
            return PlayerStatHandler.deaths[id]
        endmethod
        static method getDeniesById takes integer id returns integer
            return PlayerStatHandler.denies[id]
        endmethod
        static method getSuicidesById takes integer id returns integer
            return PlayerStatHandler.suicides[id]
        endmethod
        static method getAssistsById takes integer id returns integer
            return PlayerStatHandler.assists[id]
        endmethod
        static method getStreaksById takes integer id returns integer
            return PlayerStatHandler.streaks[id]
        endmethod
        static method getMultikillsById takes integer id returns integer
            return PlayerStatHandler.multikills[id]
        endmethod
        static method getCombobreakersById takes integer id returns integer
            return PlayerStatHandler.combobreakers[id]
        endmethod
        static method getStreaksOfTypeById takes integer id, integer typ returns integer
            return PlayerStatHandler.streakTypes[id][typ]
        endmethod
        static method getMultikillsOfTypeById takes integer id, integer typ returns integer
            return PlayerStatHandler.multikillTypes[id][typ]
        endmethod
        
        static method getCurrentStreakById takes integer id returns integer
            return Streak[id]
        endmethod
        static method getCurrentMultikillById takes integer id returns integer
            return Multikill(id).multikill
        endmethod
        
        /*
        *   Streak and Multikill Create Functions
        */
        static method newStreak takes string streakName, string streakDisplay, string soundPath, integer duration returns nothing
            set maxStreak = maxStreak + 1
            
            /*
            *   Passing empty strings will do nothing but increase the minimum streak.
            */
            if streakName != "" then
                set strings[maxStreak] = " " + streakDisplay
                set endString[maxStreak] = "'s " + streakName
                static if LIBRARY_SoundTools then
                    set sounds[maxStreak] = NewSound(soundPath, duration, false, S3D)
                elseif LIBRARY_SoundUtils then
                    set sounds[maxStreak] = DefineSound(soundPath, duration, false, S3D)
                endif
            else
                set minStreak = minStreak + 1
            endif
        endmethod
        
        static method newMultikill takes string text, string soundPath, integer duration returns nothing
            set maxMultikill = maxMultikill + 1
            set multiString[maxMultikill] = " " + text
            static if LIBRARY_SoundTools then
                set multiSound[maxMultikill] = NewSound(soundPath, duration, false, S3D)
            elseif LIBRARY_SoundUtils then
                set multiSound[maxMultikill] = DefineSound(soundPath, duration, false, S3D)
            endif
        endmethod
        
        static method setFirstBloodSound takes string path, integer duration returns nothing
            static if LIBRARY_SoundTools then
                set firstSound = NewSound(path, duration, false, S3D)
            elseif LIBRARY_SoundUtils then
                set firstSound = DefineSound(path, duration, false, S3D)
            endif
        endmethod
        
        static method setComboBreakerSound takes string path, integer duration returns nothing
            static if LIBRARY_SoundTools then
                set comboBreaker = NewSound(path, duration, false, S3D)
            elseif LIBRARY_SoundUtils then
                set comboBreaker = DefineSound(path, duration, false, S3D)
            endif
        endmethod
        
        /*
        *   Gold Gain/Loss Control
        */
        static method operator goldGain takes nothing returns boolean
            return gainGold
        endmethod
        static method operator goldGain= takes boolean b returns nothing
            set gainGold = b
        endmethod
        static method operator goldLoss takes nothing returns boolean
            return loseGold
        endmethod
        static method operator goldLoss= takes boolean b returns nothing
            set loseGold = b
        endmethod
        
        /*
        *   Bounty Formula Control
        */
        static method operator bountyBase takes nothing returns integer
            return baseGold
        endmethod
        static method operator bountyBase= takes integer v returns nothing
            set baseGold = v
        endmethod
        static method operator bountyIncrement takes nothing returns integer
            return goldIncrement
        endmethod
        static method operator bountyIncrement= takes integer v returns nothing
            set goldIncrement = v
        endmethod
        
        /*
        *   Streak Functions
        */
        static method resetStreak takes integer playerId returns nothing
            call Streak.reset(playerId)
        endmethod
        static method resetAllStreaks takes nothing returns nothing
            call Streak.resetAll()
        endmethod
        
        /*
        *   Multikill Functions
        */
        static method resetMultikill takes integer playerId returns nothing
            call Multikill.reset(playerId)
        endmethod
        static method resetAllMultikills takes nothing returns nothing
            call Multikill.resetAll()
        endmethod
        
        /*
        *   Assist Functions
        */
        static method resetAssist takes integer unitId returns nothing
            call Assist.reset(unitId)
        endmethod
        static method resetAllAssists takes nothing returns nothing
            call Assist.resetAll()
        endmethod
        
        /*
        *   Simple wrapper for gold gaining.
        */
        private static method addGold takes player p, integer amount returns nothing
            call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) + amount)
        endmethod
        
        private static method doMulti takes nothing returns nothing
            local timer tmr = GetExpiredTimer()
            local integer handleId = GetHandleId(tmr)
            local integer multi = GetTimerData(tmr)
            
            /*
            *   Make sure the multikill is greater than 1 and still valid
            */
            if cache.real[handleId] > 0 and multi > 1 then
            
                /*
                *   Checking if the multikill is greater than the maximum multikill,
                *   then displaying the correct message and playing the correct sound
                */
                if multi > maxMultikill then
                    call MessageHandler.print(cache.string[handleId] + multiString[maxMultikill])
                    call RunSound(multiSound[maxMultikill])
                else
                    call MessageHandler.print(cache.string[handleId] + multiString[multi])
                    call RunSound(multiSound[multi])
                endif
            endif
            
            call ReleaseTimer(tmr)
            set tmr = null
        endmethod
        
        private static method onDeath takes nothing returns nothing
            /*
            *   These variables are for storing basic data like the killing unit,
            *   the dying unit, the killing player, etc...
            */
            local unit dyingUnit
            local unit killingUnit
            local player dyingPlayer
            local player killingPlayer
            local integer dyingId
            local integer killingId
            
            /*
            *   Local variables that will be needed later.
            */
            local integer index = 0
            local integer bounty
            local integer unitIdDying
            local integer unitIdKilling
            local integer timerId
            local string assistString = ""
            local string killingName
            local string dyingName
            local player tempPlayer
            local timer delayTimer
            
            /*
            *   These locals will only be declared if TEXTTAGS is set to true.
            */
            static if TEXTTAGS then
                local integer assistGold
                local integer lostGold
                local texttag tag
                local real cameraCenter
            endif
            
            /*
            *   Make sure the dying unit is a hero and the system is enabled
            */
            if enabled and IsUnitType(GetTriggerUnit(), UNIT_TYPE_HERO) then
            
                set dyingUnit = GetTriggerUnit()
                set killingUnit = GetKillingUnit()
                set dyingPlayer = GetTriggerPlayer()
                set killingPlayer = GetOwningPlayer(killingUnit)
                set killingId = GetPlayerId(killingPlayer)
                set dyingId = GetPlayerId(dyingPlayer)
                
                if KillingPlayerFilter(killingId) and DyingPlayerFilter(dyingId) and killingUnit != null and killingPlayer != null then
                    static if LEAVER_STREAK then
                        /*
                        *   Check if the player has left.
                        */
                        if not PlayerActive[killingId] then
                            set dyingUnit = null
                            set killingUnit = null
                            set dyingPlayer = null
                            set killingPlayer = null
                            return
                        endif
                    endif
                    
                    /*
                    *   Check if the killing player and the dying player are allies.
                    */
                    if IsPlayerAlly(killingPlayer, dyingPlayer) then
                        
                        call resetAssist(GetUnitUserData(dyingUnit))
                        
                        if killingPlayer != dyingPlayer then
                            /*
                            *   Total Stat Incrementation
                            */
                            set PlayerStatHandler.denies[killingId] = PlayerStatHandler.denies[killingId] + 1
                            static if DENIES_COUNT_DEATHS then
                                set PlayerStatHandler.deaths[dyingId] = PlayerStatHandler.deaths[dyingId] + 1
                            endif
                            static if DENIES_COUNT_KILLS then
                                set PlayerStatHandler.kills[killingId] = PlayerStatHandler.kills[killingId] + 1
                            endif
                            
                            /*
                            *   We print the allied-player-denial message.
                            */
                            call MessageHandler.print(GetDenialString(colors[killingId] + GetPlayerName(killingPlayer), colors[dyingId] + GetPlayerName(dyingPlayer)))
                            
                            /*
                            *   We store the event data responses and fire the event.
                            */
                            set EventHandler.killingUnitId = GetUnitUserData(killingUnit)
                            set EventHandler.killingUnit = killingUnit
                            set EventHandler.killingPlayerId = killingId
                            set EventHandler.dyingUnitId = GetUnitUserData(dyingUnit)
                            set EventHandler.dyingUnit = dyingUnit
                            set EventHandler.dyingPlayerId = dyingId
                            call EventHandler.DENIAL.fire()
                        else
                            /*
                            *   Total Stat Incrementations
                            */
                            set PlayerStatHandler.suicides[killingId] = PlayerStatHandler.suicides[killingId] + 1
                            static if SUICIDE_DEATH then
                                set PlayerStatHandler.deaths[dyingId] = PlayerStatHandler.deaths[dyingId] + 1
                            endif
                            
                            /*
                            *   We print the suicide message.
                            */
                            call MessageHandler.print(GetSuicideString(colors[killingId] + GetPlayerName(dyingPlayer)))
                            
                            /*
                            *   We store the event data responses.
                            */
                            set EventHandler.killingUnitId = GetUnitUserData(killingUnit)
                            set EventHandler.killingUnit = killingUnit
                            set EventHandler.killingPlayerId = killingId
                            set EventHandler.dyingUnitId = EventHandler.killingUnitId
                            set EventHandler.dyingUnit = EventHandler.killingUnit
                            set EventHandler.dyingPlayerId = killingId
                            
                            static if SUICIDE_ENDS then
                                /*
                                *   Cache event data and reset streak
                                */
                                set EventHandler.streakEnded = currentStreak[killingId]
                                set Streak[killingId] = 0
                            endif
                            
                            /*
                            *   Fire suicide and streak-end 
                            */
                            static if SUICIDE_FIRE_FIRST then
                                call EventHandler.SUICIDE.fire()
                                static if SUICIDE_ENDS then
                                    call EventHandler.END_STREAK.fire()
                                endif
                            else
                                static if SUICIDE_ENDS then
                                    call EventHandler.END_STREAK.fire()
                                endif
                                call EventHandler.SUICIDE.fire()
                            endif
                        endif
                        
                        /*
                        *   Null all the locals and return.
                        */
                        set dyingUnit = null
                        set killingUnit = null
                        set dyingPlayer = null
                        set killingPlayer = null
                        return
                    endif
                    
                    /*
                    *   Increase kills of killing player and deaths of dying player
                    */
                    set PlayerStatHandler.kills[killingId] = PlayerStatHandler.kills[killingId] + 1
                    set PlayerStatHandler.deaths[dyingId] = PlayerStatHandler.deaths[dyingId] + 1
                    
                    /*
                    *   Increase streak of killing player and reset multikill counter
                    */
                    set Streak[killingId] = Streak[killingId] + 1
                    set Multikill(killingId).counter = MULTI_TIME
                    
                    set unitIdDying = GetUnitUserData(dyingUnit)
                    set unitIdKilling = GetUnitUserData(killingUnit)
                    
                    /*
                    *   Event response data
                    */
                    set EventHandler.killingUnitId = unitIdKilling
                    set EventHandler.dyingUnitId = unitIdDying
                    set EventHandler.killingUnit = killingUnit
                    set EventHandler.dyingUnit = dyingUnit
                    set EventHandler.killingPlayerId = killingId
                    set EventHandler.dyingPlayerId = dyingId
                    
                    static if DEATH_END_MULTI then
                        /*
                        *   Cache event data, reset multikills of dying player and fire event
                        */
                        set EventHandler.multikillEnded = Multikill(dyingId).multikill
                        set EventHandler.multikillLoserId = dyingId
                        
                        set Multikill(dyingId).multikill = 0
                        set Multikill(dyingId).counter = 0
                        
                        call EventHandler.END_MULTIKILL.fire()
                    endif
                    
                    /*
                    *   The bounty of the killing player.
                    */
                    set bounty = GetBounty(killingId, dyingId, killingUnit, dyingUnit)
                    
                    /*
                    *   Get the colored names of the killing player and dying player.
                    */
                    set killingName = colors[killingId] + GetPlayerName(killingPlayer) + "|r"
                    set dyingName = colors[dyingId] + GetPlayerName(dyingPlayer) + "|r"
                    
                    static if TEXTTAGS then
                        set assistGold = 0
                        set lostGold = 0
                        /*
                        *   We are dividing the camera distance by 2 to be used while placing the texttag
                        *   at the center of the screen for the player. This will equate half the length of
                        *   your field of view. Interesting, ey?
                        */
                        set cameraCenter = GetCameraField(CAMERA_FIELD_TARGET_DISTANCE) / 2
                    endif
                    
                    /*
                    *   If the number of assisters is one, it means that only the killing player fought the unit.
                    *   If the number of assisters is greater than one, there is at least one assister, so:
                    */
                    if Assist[unitIdDying].number > 1 then
                    
                        set assistString = " Assists: "
                        
                        /*
                        *   We loop through all the players
                        */
                        loop
                            set tempPlayer = Player(index)
                            
                            /*
                            *   Check if the player is an enemy to the dying player and if he assisted in the kill.
                            */
                            if Assist[unitIdDying][index] and index != killingId and index != dyingId and PlayerActive[index] then
                                
                                /*
                                *   Add player name to assist string and increase total assists
                                */
                                set assistString = assistString + colors[index] + GetPlayerName(tempPlayer) + "|r/"
                                set PlayerStatHandler.assists[index] = PlayerStatHandler.assists[index] + 1
                                
                                static if ASSIST_GOLD then
                                    static if TEXTTAGS then
                                        /*
                                        *   Give assisting player gold and create texttag
                                        */
                                        set assistGold = GetAssistGold(killingId, dyingId, killingUnit, dyingUnit, bounty, Assist[unitIdDying].number)
                                        call addGold(tempPlayer, assistGold)
                                        call TextTagHandler.plus(tempPlayer, cameraCenter, I2S(assistGold))
                                    else
                                        /*
                                        *   Give assisting player gold
                                        */
                                        call addGold(tempPlayer, GetAssistGold(killingId, dyingId, killingUnit, dyingUnit, bounty, Assist[unitIdDying].number))
                                    endif
                                endif
                            endif
                            
                            exitwhen index == 15
                            set index = index + 1
                        endloop
                        
                        /*
                        *   Adjust assist string.
                        */
                        set assistString = SubString(assistString, 0, StringLength(assistString) - 1)
                    endif
                    
                    call Assist.reset(unitIdDying)
                    
                    /*
                    *   If bounty-gain is enabled, give gold to the 
                    *   player and create a texttag if that feature
                    *   is selected.
                    */
                    if gainGold then
                        call addGold(killingPlayer, bounty)
                        static if TEXTTAGS then
                            call TextTagHandler.plus(killingPlayer, cameraCenter, I2S(bounty))
                        endif
                    endif
                    
                    /*
                    *   If gold-loss is enabled, we remove gold from the player
                    *   and create a texttag if the feature is selected.
                    */
                    if loseGold then
                        static if TEXTTAGS then
                            set lostGold = GetLostGold(killingId, dyingId, killingUnit, dyingUnit, bounty)
                            call addGold(dyingPlayer, -lostGold)
                            call TextTagHandler.minus(dyingPlayer, cameraCenter, I2S(lostGold))
                        else
                            call addGold(dyingPlayer, -(GetLostGold(killingId, dyingId, killingUnit, dyingUnit, bounty)))
                        endif
                    endif
                    
                    if firstblood then
                        
                        /*
                        *   Evaluate dying player streak
                        */
                        if Streak[dyingId] >= minStreak and Streak[dyingId] <= maxStreak then
                            call MessageHandler.enqueue(GetEndString(killingName, dyingName, endString[Streak[dyingId]], I2S(bounty)) + assistString)
                            set EventHandler.streakEnded = Streak[dyingId]
                            call EventHandler.END_STREAK.fire()
                            
                            /*
                            *   Combobreaker evaluation
                            */
                            if Streak[dyingId] >= COMBO_BREAKER_MIN then
                                set PlayerStatHandler.combobreakers[killingId] = PlayerStatHandler.combobreakers[killingId] + 1
                                call RunSound(comboBreaker)
                                set EventHandler.comboBroken = Streak[dyingId]
                                call EventHandler.COMBO_BREAKER.fire()
                            endif
                        elseif Streak[dyingId] > maxStreak then
                            /*
                            *   Display End Streak Message and fire event
                            */
                            call MessageHandler.enqueue(GetEndString(killingName, dyingName, endString[maxStreak], I2S(bounty)) + assistString)
                            set EventHandler.streakEnded = maxStreak
                            call EventHandler.END_STREAK.fire()
                            
                            /*
                            *   Run combo breaker sound, increase total combo breakers and fire event
                            */
                            set PlayerStatHandler.combobreakers[killingId] = PlayerStatHandler.combobreakers[killingId] + 1
                            call RunSound(comboBreaker)
                            set EventHandler.comboBroken = Streak[dyingId]
                            call EventHandler.COMBO_BREAKER.fire()
                        else
                            /*
                            *   Display Ordinary Kill Message
                            */
                            call MessageHandler.enqueue(GetKillString(killingName, dyingName, I2S(bounty)) + assistString)
                        endif
                        
                        /*
                        *   Evaluate killing player streak
                        */
                        if Streak[killingId] >= minStreak and Streak[killingId] <= maxStreak then
                            call MessageHandler.enqueue(killingName + strings[Streak[killingId]])
                            call RunSound(sounds[Streak[killingId]])
                            
                            /*
                            *   Smart Algorithm for streak/streak-type tracking
                            */
                            if Streak[killingId] == minStreak then
                                set PlayerStatHandler.streaks[killingId] = PlayerStatHandler.streaks[killingId] + 1
                            else
                                set PlayerStatHandler.streakTypes[killingId][Streak[killingId] - 1] = PlayerStatHandler.streakTypes[killingId][Streak[killingId] - 1] - 1
                            endif
                            
                            /*
                            *   Increase the number of streak types for player and fire event
                            */
                            set PlayerStatHandler.streakTypes[killingId][Streak[killingId]] = PlayerStatHandler.streakTypes[killingId][Streak[killingId]] + 1
                            set EventHandler.streakAchieved = Streak[killingId]
                            call EventHandler.STREAK.fire()
                        elseif Streak[killingId] > maxStreak then
                        
                            /*
                            *   We display the streak message of the maximum streak value because 
                            *   the streak of the killing player is too large and we play the streak sound.
                            */
                            call MessageHandler.enqueue(killingName + strings[maxStreak])
                            call RunSound(sounds[maxStreak])
                            
                            /*
                            *   Store the achieved streak and fire the Streak event
                            */
                            set EventHandler.streakAchieved = maxStreak
                            call EventHandler.STREAK.fire()
                        endif
                    else
                        /*
                        *   Register firstblood as taken, display messages, give gold, play sound and fire event
                        */
                        set firstblood = true
                        
                        call MessageHandler.enqueue(GetKillString(killingName, dyingName, I2S(bounty)) + assistString)
                        call MessageHandler.enqueue(GetFirstbloodString(killingName))
                        
                        call RunSound(firstSound)
                        call addGold(killingPlayer, FIRST_GOLD)
                        call EventHandler.FIRSTBLOOD.fire()
                        
                        static if TEXTTAGS then
                            call TextTagHandler.plus(killingPlayer, cameraCenter - 35., I2S(FIRST_GOLD))
                        endif
                    endif
                    
                    /*
                    *   Increase current multikills by 1 and reset dying player streak
                    */
                    set Multikill[killingId].multikill = Multikill[killingId].multikill + 1
                    set Streak[dyingId] = 0
                    
                    /*
                    *   Evaluation of killing player multikills
                    */
                    if Multikill[killingId].multikill > 1 then
                        /*
                        *   Create a timer and store multikill data in it to display
                        *   multikill message after a delay
                        */
                        set delayTimer = NewTimerEx(Multikill[killingId].multikill)
                        set timerId = GetHandleId(delayTimer)
                        set cache.real[timerId] = Multikill[killingId].counter
                        set cache.string[timerId] = killingName
                        call TimerStart(delayTimer, INTERVAL, false, function thistype.doMulti)
                        
                        /*
                        *   Smart Algorithm for multikill/multikill-type detection
                        */
                        if Multikill[killingId].multikill == 2 then
                            set PlayerStatHandler.multikills[killingId] = PlayerStatHandler.multikills[killingId] + 1
                        elseif Multikill[killingId].multikill <= maxMultikill then
                            set PlayerStatHandler.multikillTypes[killingId][Multikill[killingId].multikill - 1] = PlayerStatHandler.multikillTypes[killingId][Multikill[killingId].multikill - 1] - 1
                        endif
                        
                        /*
                        *   Increase number of multikill types and fire event
                        */
                        set PlayerStatHandler.multikillTypes[killingId][Multikill[killingId].multikill] = PlayerStatHandler.multikillTypes[killingId][Multikill[killingId].multikill] + 1
                        set EventHandler.multikillAchieved = Multikill[killingId].multikill
                        call EventHandler.MULTIKILL.fire()
                    endif
                    
                    set tempPlayer = null
                    set delayTimer = null
                endif
            endif
            
            /*
            *   Print all enqueued strings and clear queue
            */
            call MessageHandler.printQueue()
            call MessageHandler.clearQueue()
            
            set dyingUnit = null
            set killingUnit = null
            set dyingPlayer = null
            set killingPlayer = null
        endmethod
        
        implement Init
        
        private static method onInit takes nothing returns nothing
            static if LIBRARY_RegisterPlayerUnitEvent then
                call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.onDeath)
            else
                local trigger t = CreateTrigger()
                local code c = function thistype.onDeath
                call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
                call TriggerAddCondition(t, Condition(c))
                set t = null
            endif
        endmethod
    endstruct
    
endlibrary

and here is my map, if someone needs it for finding the error:
 

Attachments

  • Dota Next Generation NG 6.98.w3x
    2.1 MB · Views: 55
Last edited:
Status
Not open for further replies.
Top