• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Kill Streak / Player Kills Counting System v 1.1.0

  • Like
Reactions: Wrda
This system is for counting kills / deaths from units. These can be counted in multiple ways and displayed very differently with ease.

This system has many uses along with a Kill streak system. The ability to boost damage / anything when a unit gets certain amount of kills, player kills, player non hero kills, player total kills, kill streak system with a timeout. Allows different timeout for non hero and hero unit kills, allows you to have separate filters for non hero based and hero based kills ( on what counts for there kills.) Ability to display values to multiboard in efficient vJass while using GUI variables.

There are several units on the map ( spread out)
You can see hero gets kills / non hero kills / other player gets kills / and so on.
Same with deaths
You can play around with the functions to filter out unit from counting for kills by hero or non hero units in GUI. Just take a look at the GUI Setup triggers.

Notes: If this gets approved i also plan on making a few other add ons for this to make it easy for anyone with a custom multiboard in there game to use this.
If anyone has any suggestions for add ons or for improving / bugs in this please let me know. Thanks

To test it i have put units on the map kill a few and let player two in upper right (heroes) and upper left ( non heroes) kill your peasants. Then go down and kill some accolytes with your heroes / non hero units.

  • KillCounterVariables
    • Events
    • Conditions
    • Actions
      • Set RCSGameTime = RCSGameTime
      • Set RCSGameTimeAccuracy = 0.00
      • Set RCSGameTimer = RCSGameTimer
      • Set RCSKillDeathCounterPlayer[0] = 0
      • Set RCSHashtable = (Last created hashtable)
      • Set RCSKillsUnitGroup = RCSKillsUnitGroup
  • RCSKillCounterSetup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- Notes: Each custom function below can use the RCSDeadUnit for the dead unit. The RCSKillerUnit for the killing unit. --------
      • -------- Notes: Unless marked in the comments on what you can use. --------
      • -------- --------
      • -------- If you want no kills to be counted for that player or for the individual unit go to the thing labeled Everything for Player Kills or Everything for Individual Kills --------
      • -------- and remove the ITE. It will then not allow anything to be counted. --------
      • -------- --------
      • -------- If you do not want a specific portion of the system to run like counting non hero player kills then remove the ITE. --------
      • -------- --------
      • -------- If you want to be able to stop a portion of the system like the non hero player kills put a boolean in the ITE. Then change that boolean to true --------
      • -------- when you want that portion to run and false when you do not want it to run. --------
      • -------- You can also use integers or reals or any other boolean comparison to stop the counting of player kills or individual kills. --------
      • -------- --------
      • -------- This boolean tells the system if you want to have the kills for the individual kills section to reset after a certain time. --------
      • Set RCSGameTimerBoolean = True
      • -------- --------
      • -------- This boolean tells the system if you want the individual kills for the non hero units to reset at the time limit. --------
      • -------- The boolean RCSGameTimerBoolean must be true or this does not matter. --------
      • Set RCSIndividualKillsBoolean[1] = True
      • -------- --------
      • -------- This boolean tells the system if you want the individual kills for the hero units to reset at the time limit. --------
      • -------- The boolean RCSGameTimerBoolean must be true or this does not matter. --------
      • Set RCSIndividualKillsBoolean[2] = True
      • -------- --------
      • -------- This lets you set the timeout time for when the kills counter gets reset for non hero units. --------
      • Set RCSGameTimeReset[1] = 2.00
      • -------- --------
      • -------- This lets you set the timeout time for when the kills counter gets reset for hero units. --------
      • Set RCSGameTimeReset[2] = 2.00
      • -------- --------
      • -------- This lets you set the game time accuracy. This is the counter used for the time between kills in the individual kills counter. --------
      • -------- For example this gives a delay of 0.03125 for the unit to kill another unit. --------
      • -------- Example: Game starts. Unit A kills a unit. Unit A kills a new unit. If time elapsed is more than 2 seconds it will reset and that kill will be kill one. --------
      • -------- If that first unit killed was right before the timer went off at 0.03124 that unit will actually have 2.00001 seconds before his counter is reset. --------
      • -------- But if that unit killed the other unit right after the timer went off at 0.00001 That unit will have 2.03124 seconds till his kills get reset. --------
      • -------- lowering the timer is possible but may start to cause lag. So be careful how much you change it by. It should be able to go very low without a problem but just in case. --------
      • -------- --------
      • Custom script: set udg_RCSGameTimeAccuracy = 0.03125
      • -------- --------
      • Custom script: endfunction
      • -------- --------
      • -------- In these multiboard functions. This is where you add actions for adding player kills to a multiboard. Use the variable RCSInteger for kills / deaths depending on the function --------
      • -------- Use the variable RCSPlayerInteger to get the killing player for the player kills functions. And for the player whose the dying player for the death functions. --------
      • -------- They are returned as GUI player numbers. Player 1 red = 1 --------
      • -------- --------
      • -------- MULTIBOARD DEATHS --------
      • -------- This is where you register The players Non Hero Deaths to a Multiboard. --------
      • -------- --------
      • Custom script: function RCSNonHeroDeathsCounterActions takes nothing returns nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RCSPlayerInteger Less than 4
        • Then - Actions
          • Multiboard - Set the text for myMultiboard item in column MbIntegerColumnArray[RCSPlayerInteger], row MbIntegerRowArray[(((RCSPlayerInteger - 1) x 6) + 4)] to (String(RCSInteger))
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- This is where you register The players Hero Deaths to a Multiboard. --------
      • -------- --------
      • Custom script: function RCSHeroDeathsCounterActions takes nothing returns nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RCSPlayerInteger Less than 4
        • Then - Actions
          • Multiboard - Set the text for myMultiboard item in column MbIntegerColumnArray[RCSPlayerInteger], row MbIntegerRowArray[(((RCSPlayerInteger - 1) x 6) + 5)] to (String(RCSInteger))
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- This is where you register The players Total Deaths to a Multiboard. --------
      • -------- --------
      • Custom script: function RCSTotalDeathsCounterActions takes nothing returns nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RCSPlayerInteger Less than 4
        • Then - Actions
          • Multiboard - Set the text for myMultiboard item in column MbIntegerColumnArray[RCSPlayerInteger], row MbIntegerRowArray[(((RCSPlayerInteger - 1) x 6) + 6)] to (String(RCSInteger))
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- MULTIBOARD KILLS --------
      • -------- This is where you register The players Non Hero Kills to a Multiboard. --------
      • -------- --------
      • Custom script: function RCSNonHeroKillsCounterActions takes nothing returns nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RCSPlayerInteger Less than 4
        • Then - Actions
          • Multiboard - Set the text for myMultiboard item in column MbIntegerColumnArray[RCSPlayerInteger], row MbIntegerRowArray[(((RCSPlayerInteger - 1) x 6) + 1)] to (String(RCSInteger))
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- This is where you register The players Hero Kills to a Multiboard. --------
      • -------- --------
      • Custom script: function RCSHeroKillsCounterActions takes nothing returns nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RCSPlayerInteger Less than 4
        • Then - Actions
          • Multiboard - Set the text for myMultiboard item in column MbIntegerColumnArray[RCSPlayerInteger], row MbIntegerRowArray[(((RCSPlayerInteger - 1) x 6) + 2)] to (String(RCSInteger))
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- This is where you register The players Total Kills to a Multiboard. --------
      • -------- --------
      • Custom script: function RCSTotalKillsCounterActions takes nothing returns nothing
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RCSPlayerInteger Less than 4
        • Then - Actions
          • Multiboard - Set the text for myMultiboard item in column MbIntegerColumnArray[RCSPlayerInteger], row MbIntegerRowArray[(((RCSPlayerInteger - 1) x 6) + 3)] to (String(RCSInteger))
        • Else - Actions
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- This function filters out units that you want to not count toward kills for non-hero / hero / total kills. --------
      • -------- If you add a unit to this it will not count for kills for any of the kill counters. --------
      • -------- --------
      • -------- EVERYTHING FOR PLAYER DEATHS --------
      • Custom script: function RCSEveryDeathsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Player number of (Owner of RCSDeadUnit)) Not equal to (Player number of (Owner of RCSKillerUnit))
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for units that get counted in the non-hero kills portion. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- NON-HERO PLAYER DEATHS --------
      • Custom script: function RCSNonHeroDeathsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for units that get counted in the hero kills portion. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- HERO PLAYER DEATHS --------
      • Custom script: function RCSHeroDeathsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for all units that get counted in the all kills portion. Note: this can be used to count units count / not counted above. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- TOTAL PLAYER DEATHS --------
      • Custom script: function RCSTotalDeathsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of RCSDeadUnit) Not equal to Knight
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- This function filters out units that you want to not count toward kills for non-hero / hero / total kills. --------
      • -------- If you add a unit to this it will not count for kills for any of the kill counters. --------
      • -------- --------
      • -------- EVERYTHING FOR PLAYER KILLS --------
      • Custom script: function RCSEveryKillsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Player number of (Owner of RCSDeadUnit)) Not equal to (Player number of (Owner of RCSKillerUnit))
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for units that get counted in the non-hero kills portion. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- NON-HERO PLAYER KILLS --------
      • Custom script: function RCSNonHeroKillsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for units that get counted in the hero kills portion. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- HERO PLAYER KILLS --------
      • Custom script: function RCSHeroKillsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for all units that get counted in the all kills portion. Note: this can be used to count units count / not counted above. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- TOTAL PLAYER KILLS --------
      • Custom script: function RCSTotalKillsCounterFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of RCSDeadUnit) Not equal to Knight
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- This function filters out units that you want to not count toward kills for non-hero / hero / total kills. Also allows you to filter out certain players. --------
      • -------- Example: Below in the condition i stop players from counting kills of their own units --------
      • -------- If you add a unit to this it will not count for kills for any of the individual kill counters. --------
      • -------- --------
      • -------- EVERYTHING FOR INDIVIDUAL KILLS --------
      • Custom script: function RCSEveryKillsIndividualFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of RCSDeadUnit) Equal to Footman
          • (Owner of RCSDeadUnit) Not equal to (Owner of RCSKillerUnit)
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for units that get counted in the non-hero kills portion. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- NON-HERO KILLS INDIVIDUAL --------
      • Custom script: function RCSNonHeroKillsIndividualFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of RCSDeadUnit) Equal to Footman
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for units that get counted in the hero kills portion. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- HERO KILLS INDIVIDUAL --------
      • Custom script: function RCSHeroKillsIndividualFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of RCSDeadUnit) Equal to Peasant
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- --------
      • -------- The below function is the filter for all units that get counted in the all kills portion. Note: this can be used to count units count / not counted above. --------
      • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
      • -------- --------
      • -------- TOTAL KILLS INDIVIDUAL --------
      • Custom script: function RCSTotalKillsIndividualFilter takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of RCSDeadUnit) Equal to Knight
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- This function below tells the system whether or not to remove all info from that unit in the hashtable. --------
      • -------- If all conditions in the ITE are true it will reset the dead units kills in the hashtable. --------
      • -------- This function should also be use to check for upgrades for that unit like every 5 kill streak that unit gains a bonus. It should be applied here with the RCSKillerUnit --------
      • -------- Note: If you want those streak bonuses to be more efficient every so many times you should check to see if they should be removed. --------
      • -------- Example: Every so many seconds use a timer and put this in it to regularly check each units kills. Custom script: call RCSForceIndividualKills() --------
      • -------- --------
      • Custom script: function RCSKillsResetKills takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of RCSDeadUnit) Equal to Peasant
        • Then - Actions
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
      • Custom script: endfunction
      • -------- --------
      • -------- This function should also be use to check for upgrades for that unit like every 5 kill streak that unit gains a bonus. It should be applied here with the RCSKillerUnit --------
      • -------- Note: If you want those streak bonuses to be more efficient every so many times you should check to see if they should be removed. --------
      • -------- Example: Every so many seconds use a timer and put this in it to regularly check each units kills. Custom script: call RCSForceIndividualKills() --------
      • -------- This will only return the units with kills of 0. So like below i check if unit has zero kills. Then i check if unit has the ability. Then if that unit does i remove the ability. --------
      • -------- I checked the ability to see if the unit has the ability above 0. If it does then i set it to 0. --------
      • -------- For this you can only use. RCSKillerUnit and RCSKillsInteger. Do Not use RCSDeadUnit --------
      • -------- --------
      • Custom script: function RCSKillStreakCheckKills takes nothing returns boolean
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • RCSInteger Equal to 0
          • (Level of Acid Bomb for RCSKillerUnit) Greater than 0
        • Then - Actions
          • Unit - Remove Acid Bomb from RCSKillerUnit
          • Custom script: return true
        • Else - Actions
      • Custom script: return false
JASS:
    //      Kill Streak / Player Kills Counting System
    //      version 1.1.0 by deathismyfriend
    
    //     Function List
    //
    //
    //  This function pauses the game timer. 
    //  This is the timer that tells when to reset the individual kills of that unit.
    //  function RCSPauseGameTimer takes nothing returns nothing
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: call RCSPauseGameTimer()
    //
    //
    //  This function starts the timer if you have paused it. ( It is on to start the game)
    //  This is the timer that tells when to reset the individual kills of that unit.
    //  function RCSStartGameTimer takes nothing returns nothing
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: call RCSStartGameTimer()
    //
    //
    //  This function allows users to retrieve the individual kills from that unit. 
    //  function RCSGetIndivKillsFromUnit takes unit u returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: call RCSGetIndivKillsFromUnit( udg_tempUnit)
    //
    //
    //  This function allows users to retrieve the total individual kills from that unit.
    //  The total kills are the kills that unit got from the start of the game.
    //  function RCSGetIndivTotalKillsFromUnit takes unit u returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: call RCSGetIndivTotalKillsFromUnit( udg_tempUnit)
    //
    //
    //  This function checks each unit to see if that unit has gotten a kill 
    //      within the desired time limit set by the user.
    //  This function takes each unit and checks against the limit.
    //  Since the normal method of my system only checks the time limit when that unit kills a new unit.
    //  This function corrects that inaccuracy.  This should be called everytime that you want to get 
    //      the kills for that unit for a purpose like a damage boost or something else like that.
    //  function RCSForceIndividualKills takes nothing returns nothing
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: call RCSForceIndividualKills()
    //
    //
    //  This function checks each unit to see if that unit has gotten a kill 
    //  function RCSGetPlayerTotalKills takes player p returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: set udg_tempInteger = RCSGetPlayerTotalKills( udg_tempPlayer)
    //
    //
    //  function RCSGetPlayerNonHeroKills takes player p returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: set udg_tempInteger = RCSGetPlayerNonHeroKills( udg_tempPlayer)
    //
    //
    //  function RCSGetPlayerHeroKills takes player p returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: set udg_tempInteger = RCSGetPlayerHeroKills( udg_tempPlayer)
    //
    //
    //  function RCSGetPlayerTotalDeaths takes player p returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: set udg_tempInteger = RCSGetPlayerTotalDeaths( udg_tempPlayer)
    //
    //
    //  function RCSGetPlayerNonHeroDeaths takes player p returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: set udg_tempInteger = RCSGetPlayerNonHeroDeaths( udg_tempPlayer)
    //
    //
    //  function RCSGetPlayerHeroDeaths takes player p returns integer
    //  To use this use the custom script below. ( You can Copy and Paste it.)
    //  Custom script: set udg_tempInteger = RCSGetPlayerHeroDeaths( udg_tempPlayer)
    //
    //
    
    
    function RCSGetPlayerTotalKills takes player p returns integer
        return udg_RCSKillDeathCounterPlayer[ GetPlayerId( p)]
    endfunction
    
    function RCSGetPlayerNonHeroKills takes player p returns integer
        return udg_RCSKillDeathCounterPlayer[ GetPlayerId( p) + 16]
    endfunction
    
    function RCSGetPlayerHeroKills takes player p returns integer
        return udg_RCSKillDeathCounterPlayer[ GetPlayerId( p) + 32]
    endfunction
    
    function RCSGetPlayerTotalDeaths takes player p returns integer
        return udg_RCSKillDeathCounterPlayer[ GetPlayerId( p)+ 48]
    endfunction
    
    function RCSGetPlayerNonHeroDeaths takes player p returns integer
        return udg_RCSKillDeathCounterPlayer[ GetPlayerId( p) + 64]
    endfunction
    
    function RCSGetPlayerHeroDeaths takes player p returns integer
        return udg_RCSKillDeathCounterPlayer[ GetPlayerId( p) + 80]
    endfunction
    
    function RCSGetIndivKillsFromUnit takes unit u returns integer
        local boolean b = IsUnitType( u, UNIT_TYPE_HERO)
        local real time = udg_RCSGameTime + udg_RCSGameTimeAccuracy
        local integer id = GetHandleId( u)
        
        if not b and RCSNonHeroKillsIndividualFilter() then
            if udg_RCSGameTimeReset[1] > ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                return LoadInteger( udg_RCSHashtable, id, 1)
            else
                call SaveInteger( udg_RCSHashtable, id, 1, 0)
                return 0
            endif
        elseif b and RCSHeroKillsIndividualFilter() then
            if udg_RCSGameTimeReset[2] > ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                return LoadInteger( udg_RCSHashtable, id, 1)
            else
                call SaveInteger( udg_RCSHashtable, id, 1, 0)
                return 0
            endif
        endif
        return 0
    endfunction
    
    function RCSGetIndivTotalKillsFromUnit takes unit u returns integer
        return LoadInteger( udg_RCSHashtable, GetHandleId(u), 3)
    endfunction
    
    function RCSForceGroupEnumIndKills takes nothing returns nothing
        local unit u = GetEnumUnit()
        local integer id = GetHandleId(u)
        local boolean b = IsUnitType( u, UNIT_TYPE_HERO)
        if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then // This filter out the non hero kills
            if udg_RCSGameTimeReset[1] < ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                call SaveInteger( udg_RCSHashtable, id, 1, 0)
                set udg_RCSKillerUnit = u
                set udg_RCSInteger = 0
                call RCSKillStreakCheckKills()
                set udg_RCSKillerUnit = null
            endif
        elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then // This filter out the hero kills
            if udg_RCSGameTimeReset[1] < ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                call SaveInteger( udg_RCSHashtable, id, 2, 0)
                set udg_RCSKillerUnit = u
                set udg_RCSInteger = 0
                call RCSKillStreakCheckKills()
                set udg_RCSKillerUnit = null
            endif
        endif
        set u = null
    endfunction
    
    function RCSForceIndividualKills takes nothing returns nothing
        call ForGroup( udg_RCSKillsUnitGroup, function RCSForceGroupEnumIndKills)
    endfunction
    
    function RCSRegisterIndividualKills takes unit dead, unit killer, integer id, integer childKey returns integer
        local integer i = LoadInteger( udg_RCSHashtable, id, childKey)
        set i = i + 1
        call SaveInteger( udg_RCSHashtable, id, childKey, i)
        if RCSKillsResetKills() then
            call FlushChildHashtable( udg_RCSHashtable, id)
            if not IsUnitInGroup( killer, udg_RCSKillsUnitGroup) then
                call GroupRemoveUnit( udg_RCSKillsUnitGroup, dead)
            endif
        endif
        return i
    endfunction

    function RCSResetIndividualKills takes unit dead, unit killer, integer id, integer childKey, integer kills returns nothing
        call SaveInteger( udg_RCSHashtable, id, childKey, kills)
        if RCSKillsResetKills() then
            call FlushChildHashtable( udg_RCSHashtable, id)
            if not IsUnitInGroup( killer, udg_RCSKillsUnitGroup) then
                call GroupRemoveUnit( udg_RCSKillsUnitGroup, dead)
            endif
        endif
    endfunction
    
    function RCSKillCounterActions takes nothing returns boolean
        local unit dead = GetTriggerUnit()
        local unit killer = GetKillingUnit()
        local integer pId = GetPlayerId( GetOwningPlayer( killer))
        local boolean b = IsUnitType( killer, UNIT_TYPE_HERO)
        local integer id
        local integer i
        local integer pId2 = GetPlayerId( GetOwningPlayer( dead))
        local real time
        set udg_RCSDeadUnit = dead
        set udg_RCSKillerUnit = killer
        
        if RCSEveryKillsIndividualFilter() then // This counts individual kills.
            if not IsUnitInGroup( killer, udg_RCSKillsUnitGroup) then
                call GroupAddUnit( udg_RCSKillsUnitGroup, killer)
            endif
            set time = udg_RCSGameTime + udg_RCSGameTimeAccuracy
            set id = GetHandleId( killer)
            // This checks the timeout for that unit.
            if udg_RCSGameTimerBoolean  then
                if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then // This filter out the non hero kills
                    if udg_RCSGameTimeReset[1] > ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                        call RCSRegisterIndividualKills( dead, killer, id, 1)
                    else
                        call RCSResetIndividualKills( dead, killer, id, 1, 1)
                    endif
                    call SaveReal( udg_RCSHashtable, id, 0, time)
                elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then // This filter out the hero kills
                    if udg_RCSGameTimeReset[1] > ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                        call RCSRegisterIndividualKills( dead, killer, id, 2)
                    else
                        call RCSResetIndividualKills( dead, killer, id, 2, 1)
                    endif
                    call SaveReal( udg_RCSHashtable, id, 0, time)
                endif
                if udg_RCSIndividualKillsBoolean[3] and RCSTotalKillsIndividualFilter() then // This filter out the total kills
                    call RCSRegisterIndividualKills( dead, killer, id, 3)
                endif
            else
                if RCSNonHeroKillsIndividualFilter() and not b then // This filter out the non hero kills
                    call RCSRegisterIndividualKills( dead, killer, id, 1)
                elseif RCSHeroKillsIndividualFilter() and b then // This filter out the hero kills
                    call RCSRegisterIndividualKills( dead, killer, id, 2)
                endif
                if RCSTotalKillsIndividualFilter() then // This filter out the total kills
                    call RCSRegisterIndividualKills( dead, killer, id, 3)
                endif
            endif
        endif
        
        set udg_RCSPlayerInteger = pId + 1
        if RCSEveryKillsCounterFilter() then  // This filter out the kills that are the same for all kills.
            if RCSNonHeroKillsCounterFilter() and not b then // This filter out the non hero kills
                // Increase for non-hero units.
                set i = pId + 16
                set udg_RCSKillDeathCounterPlayer[ i] = udg_RCSKillDeathCounterPlayer[ i] + 1
                set udg_RCSInteger = udg_RCSKillDeathCounterPlayer[ i]
                call RCSNonHeroKillsCounterActions()
            elseif RCSHeroKillsCounterFilter() and b then // This filter out the hero kills
                // Increase for hero units.
                set i = pId + 32
                set udg_RCSKillDeathCounterPlayer[ i] = udg_RCSKillDeathCounterPlayer[ i] + 1
                set udg_RCSInteger = udg_RCSKillDeathCounterPlayer[ i]
                call RCSHeroKillsCounterActions()
            endif
            if RCSTotalKillsCounterFilter() then // This filter out the total kills
                // Increase for all units.
                set udg_RCSKillDeathCounterPlayer[ pId] = udg_RCSKillDeathCounterPlayer[ pId] + 1
                set udg_RCSInteger = udg_RCSKillDeathCounterPlayer[ pId]
                call RCSTotalKillsCounterActions()
            endif
        endif
        
        set b = IsUnitType( dead, UNIT_TYPE_HERO)
        set udg_RCSPlayerInteger = pId2 + 1
        if RCSEveryDeathsCounterFilter() then  // This filter out the kills that are the same for all kills.
            if RCSNonHeroDeathsCounterFilter() and not b then // This filter out the non hero kills
                // Increase for non-hero units.
                set i = pId2 + 64
                set udg_RCSKillDeathCounterPlayer[ i] = udg_RCSKillDeathCounterPlayer[ i] + 1
                set udg_RCSInteger = udg_RCSKillDeathCounterPlayer[ i]
                call RCSNonHeroDeathsCounterActions()
            elseif RCSHeroDeathsCounterFilter() and b then // This filter out the hero kills
                // Increase for hero units.
                set i = pId2 + 80
                set udg_RCSKillDeathCounterPlayer[ i] = udg_RCSKillDeathCounterPlayer[ i] + 1
                set udg_RCSInteger = udg_RCSKillDeathCounterPlayer[ i]
                call RCSHeroDeathsCounterActions()
            endif
            if RCSTotalDeathsCounterFilter() then // This filter out the total kills
                // Increase for all units.
                set i = pId2 + 48
                set udg_RCSKillDeathCounterPlayer[ i] = udg_RCSKillDeathCounterPlayer[ i] + 1
                set udg_RCSInteger = udg_RCSKillDeathCounterPlayer[ i]
                call RCSTotalDeathsCounterActions()
            endif
        endif
        
        set dead = null
        set killer = null
        set udg_RCSDeadUnit = null
        set udg_RCSKillerUnit = null
        return false
    endfunction
    
    function RCSGameTimerEventEnd takes nothing returns nothing
        set udg_RCSGameTime = udg_RCSGameTime + udg_RCSGameTimeAccuracy
    endfunction
    
    function RCSPauseGameTimer takes nothing returns nothing
        call PauseTimer( udg_RCSGameTimer)
    endfunction
    
    function RCSStartGameTimer takes nothing returns nothing
        call TimerStart( udg_RCSGameTimer, udg_RCSGameTimeAccuracy, true, function RCSGameTimerEventEnd)
    endfunction
    
    function RCSGameTimerSetup takes nothing returns nothing
        local timer t = GetExpiredTimer()
        call TimerStart( udg_RCSGameTimer, udg_RCSGameTimeAccuracy, true, function RCSGameTimerEventEnd)
        set udg_RCSKillsUnitGroup = CreateGroup()
        call DestroyTimer(t)
        set t = null
    endfunction

    //===========================================================================
    function InitTrig_RCSKillCounterCode takes nothing returns nothing
        local trigger t = CreateTrigger()
        if udg_RCSHashtable == null then
            set udg_RCSHashtable = InitHashtable()
        endif
        call TimerStart( CreateTimer(), 0.01, false, function RCSGameTimerSetup)
        call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_DEATH)
        call TriggerAddCondition( t, Condition( function RCSKillCounterActions))
        set t = null
    endfunction


version 1.1.0
Removed multiboard functionality as it was hard to use for most GUIers.
Added the ability to get hero / non hero / total player deaths.
Added some functions to get player kills / deaths.​
version 1.0.4
Fixed mistake with showing the kills of unregistered players to the MB.​
version 1.0.2
Fixed a small bug.​
version 1.0.1
updated description.​
version 1.0.0
first version released.​


Thanks IcemanBo for the bug reports.

Keywords:
kills, kill, kill counting, kills counting system, kill counting system, system, counting system, kill streak, kill streak system, individual kills, i
Contents

Just another Warcraft III map (Map)

Reviews
17:39, 8th Mar 2014 PurgeandFire: Review: http://www.hiveworkshop.com/forums/2496930-post27.html

Moderator

M

Moderator

17:39, 8th Mar 2014
PurgeandFire: Review:
http://www.hiveworkshop.com/forums/2496930-post27.html
 
Takes wayyyy to many space.
You already have "Kills Counter" in the multiboard title.
Change the title to "Player Kills" and rechange the column names to:
Hero, Unit, Total :)

Will do. I always said i suck at naming things.

Any other suggestions are appreciated.

Edit: Much better naming with that lol. Thanks for the suggestion.
 
This seems lite-weight. Are you sure there's nothing configurable by the user however? c;

What do you mean by that ?

Also i don't look for other systems on here. My system is not simply a streak system.

Edit: Yours is also vJass mine is for GUIers / Jassers

The customizing is fully in GUI. With only a few needed custom functions which are in the jass script.
 
Last edited:

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
beside, you are moderator, you should know that..

Moderators are clearly infallible Gods, ey?

I'm a user.
With privileges and responsibilities.

I was posting that system to show him the amount of configuration this kind of system could use because I missed the GUI trigger.

Teach me more about your ideal Modus Operandi please~

edit
I'm not trying to attack anyone, I'm just not very pleasant this time of year and I'm going through pure bullshit IRL, so apologies to you if you felt that.
 
edit
I'm not trying to attack anyone, I'm just not very pleasant this time of year and I'm going through pure bullshit IRL, so apologies to you if you felt that.

Don't worry mag i know you weren't. I was just lost on why you posted a link to your system.

If you missed the GUI trigger it is a simple mistake no big deal.
 
Hello, I had one bug when testing it.

When I killed the knight(player2) my kill was not count.
I tryed it more often, with always same result.

Could not test with my own conditions, because I don't use JNGP.

You don't need JNGP for this.

Also if you look in the setup trigger it shows that when you kill the knight it will not count.

  • (Unit-type of RCSDeadUnit) Not equal to Knight
 
ok then.. I havent read it all.

I do need JNGP, if I want change/save it. Error appears, and WE deactivates most of the trigger.

Ill have to check that out thanks for the update.

Edit: I forgot to remove the unneeded libraries. ( i use a template map for all my systems so i don't have to add everything i need all the time. )

Will update in 2 seconds.

Edit 2: Updated the dl map
 

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
this is not GUI friendly, you kill GUI users by that setup trigger instead (hard to understand)

then, I wonder why you need to use that local timer
JASS:
    function RCSGameTimerSetup takes nothing returns nothing
        local timer t = GetExpiredTimer()
        call TimerStart( udg_RCSGameTimer, udg_RCSGameTimeAccuracy, true, function RCSGameTimerEventEnd)
        set udg_RCSKillsUnitGroup = CreateGroup()
        call DestroyTimer(t)
        set t = null
    endfunction
for what?

also I highly recommend you to shorten thos variables and functions names. It's really hard to review it bcs of those shity names..
 
this is not GUI friendly, you kill GUI users by that setup trigger instead (hard to understand)

then, I wonder why you need to use that local timer
JASS:
    function RCSGameTimerSetup takes nothing returns nothing
        local timer t = GetExpiredTimer()
        call TimerStart( udg_RCSGameTimer, udg_RCSGameTimeAccuracy, true, function RCSGameTimerEventEnd)
        set udg_RCSKillsUnitGroup = CreateGroup()
        call DestroyTimer(t)
        set t = null
    endfunction
for what?

also I highly recommend you to shorten thos variables and functions names. It's really hard to review it bcs of those shity names..

How is this not GUI friendly ? Everything they need to know is in GUI.
The local timer is to clean up the timer that expired. Otherwise it would leak a timer.
The variables are longer to not interfere with other systems. That is part of coding in GUI.
 

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
I'm Jasser, and I still can't understand, as example, this part
  • -------- This is where you register The players Non Hero Deaths to a Multiboard. --------
  • -------- --------
  • Custom script: function RCSNonHeroDeathsCounterActions takes nothing returns nothing
  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
  • If - Conditions
  • RCSPlayerInteger Less than 4
  • Then - Actions
  • Multiboard - Set the text for myMultiboard item in column MbIntegerColumnArray[RCSPlayerInteger], row MbIntegerRowArray[(((RCSPlayerInteger - 1) x 6) + 4)] to (String(RCSInteger))
  • Else - Actions
  • Custom script: endfunction
  • -------- --------
still I recommend you to shorten thos variable and function names.. :)

thnks for the info!
 
Review:
  • Most of your comments say:
    • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
    But most of the conditions don't have anything in them. The one that does filter out a unit just filters out a knight. It is not a big deal, but IMO you should change the comments to prevent confusion (you probably just updated the trigger and forgot to update the comments).
    .
  • In RCSGameTimerSetup, you can just directly use:
    call DestroyTimer(GetExpiredTimer())
    Rather than declaring a local, destroying it, and then nulling the local.
    .
  • In RCSRegisterIndividualKills, you can just directly declare the local as such:
    JASS:
    local integer i = LoadInteger( udg_RCSHashtable, id, childKey) + 1
    Rather than declaring it, and then incrementing it by 1 in the next line.
    .
  • There is a lot of repeated code. Take for example, RCSForceGroupEnumIndKills:
    Original:
    JASS:
        function RCSForceGroupEnumIndKills takes nothing returns nothing
            local unit u = GetEnumUnit()
            local integer id = GetHandleId(u)
            local boolean b = IsUnitType( u, UNIT_TYPE_HERO)
            if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then // This filter out the non hero kills
                if udg_RCSGameTimeReset[1] < ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                    call SaveInteger( udg_RCSHashtable, id, 1, 0)
                    set udg_RCSKillerUnit = u
                    set udg_RCSInteger = 0
                    call RCSKillStreakCheckKills()
                    set udg_RCSKillerUnit = null
                endif
            elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then // This filter out the hero kills
                if udg_RCSGameTimeReset[1] < ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                    call SaveInteger( udg_RCSHashtable, id, 2, 0)
                    set udg_RCSKillerUnit = u
                    set udg_RCSInteger = 0
                    call RCSKillStreakCheckKills()
                    set udg_RCSKillerUnit = null
                endif
            endif
            set u = null
        endfunction

    How can we improve this? Notice that the two if blocks do essentially the same
    thing, except that one uses a different key. As such, here is one possible implementation:
    JASS:
        function RCSForceGroupEnumIndKills takes nothing returns nothing 
            local unit    u  = GetEnumUnit()
            local integer id = GetHandleId(u)
            local boolean b  = IsUnitType(u, UNIT_TYPE_HERO)
            local integer hkey
    
            if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then
                set hkey = 1
            elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then
                set hkey = 2
            else
                set u = null
                return
            endif
    
            if udg_RCSGameTimeReset[1] < (udg_RCSGameTime - LoadReal(udg_RCSHashtable, id, 0)) then
                call SaveInteger(udg_RCSHashtable, id, hkey, 0)
                set udg_RCSKillerUnit = u
                set udg_RCSInteger    = 0
                call RCSKillStreakCheckKills()
                set udg_RCSKillerUnit = null
                set u = null
            endif
        endfunction
    That looks pretty neat. And it makes the differences between the two if-conditions more visible. In the original, you'll think that the if-conditions evaluate to two completely different things. However, in the example above, you'll know that only the keys change.

    You can also delegate them to a function, which may be neater:
    JASS:
        // Try to come up with a better name than I did :P
        function RCSForceGroupEnumIndKillsEvaluate takes unit enum, integer id, integer hkey returns nothing
            if udg_RCSGameTimeReset[1] < (udg_RCSGameTime - LoadReal(udg_RCSHashtable, id, 0)) then
                call SaveInteger(udg_RCSHashtable, id, hkey, 0)
                set udg_RCSKillerUnit = enum
                set udg_RCSInteger    = 0
                call RCSKillStreakCheckKills()
                set udg_RCSKillerUnit = null
            endif
        endfunction
    
        function RCSForceGroupEnumIndKills takes nothing returns nothing 
            local unit    u  = GetEnumUnit()
            local integer id = GetHandleId(u)
            local boolean b  = IsUnitType(u, UNIT_TYPE_HERO)
    
            if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then
                call RCSForGroupEnumIndKillsEvaluate(u, id, 1)
            elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then
                call RCSForGroupEnumIndKillsEvaluate(u, id, 2)
            endif
    
            set u = null
        endfunction
    Of course, this has no real efficiency boost, but rather a fundamental logic/readability boost. That is important, too. Remember the DRY principle.

    .
  • ^A similar dilemma as the above note with RCSGetIndivKillsFromUnit. Also, you can remove the return 0 within the if-blocks since it'll return 0 outside the block.
    .
  • (Optional) The test map could be better. You should include some general information and a way to respawn units (especially for a kill system--once you kill all the units on the map, you can't test it anymore). But this is just a recommendation, not a requirement.

tl;dr Eh, I'm going to go ahead and approve this. It works just fine and has some nice customizability. The code is pretty difficult to read and has a few problems mentioned above. The test map could be better. I haven't really considered alternate implementations, but your code itself is fine. Most of my notes are just incredibly minor, and I know this has been sitting unreviewed for a while, so I apologize for that.

Approved.
 
Review:
  • Most of your comments say:
    • -------- Filter out all units in the ITE that you do not want to count the kills for. In the example peasants will not be counted for kills. --------
    But most of the conditions don't have anything in them. The one that does filter out a unit just filters out a knight. It is not a big deal, but IMO you should change the comments to prevent confusion (you probably just updated the trigger and forgot to update the comments).
    .
  • In RCSGameTimerSetup, you can just directly use:
    call DestroyTimer(GetExpiredTimer())
    Rather than declaring a local, destroying it, and then nulling the local.
    .
  • In RCSRegisterIndividualKills, you can just directly declare the local as such:
    JASS:
    local integer i = LoadInteger( udg_RCSHashtable, id, childKey) + 1
    Rather than declaring it, and then incrementing it by 1 in the next line.
    .
  • There is a lot of repeated code. Take for example, RCSForceGroupEnumIndKills:
    Original:
    JASS:
        function RCSForceGroupEnumIndKills takes nothing returns nothing
            local unit u = GetEnumUnit()
            local integer id = GetHandleId(u)
            local boolean b = IsUnitType( u, UNIT_TYPE_HERO)
            if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then // This filter out the non hero kills
                if udg_RCSGameTimeReset[1] < ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                    call SaveInteger( udg_RCSHashtable, id, 1, 0)
                    set udg_RCSKillerUnit = u
                    set udg_RCSInteger = 0
                    call RCSKillStreakCheckKills()
                    set udg_RCSKillerUnit = null
                endif
            elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then // This filter out the hero kills
                if udg_RCSGameTimeReset[1] < ( udg_RCSGameTime - LoadReal( udg_RCSHashtable, id, 0)) then
                    call SaveInteger( udg_RCSHashtable, id, 2, 0)
                    set udg_RCSKillerUnit = u
                    set udg_RCSInteger = 0
                    call RCSKillStreakCheckKills()
                    set udg_RCSKillerUnit = null
                endif
            endif
            set u = null
        endfunction

    How can we improve this? Notice that the two if blocks do essentially the same
    thing, except that one uses a different key. As such, here is one possible implementation:
    JASS:
        function RCSForceGroupEnumIndKills takes nothing returns nothing 
            local unit    u  = GetEnumUnit()
            local integer id = GetHandleId(u)
            local boolean b  = IsUnitType(u, UNIT_TYPE_HERO)
            local integer hkey
    
            if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then
                set hkey = 1
            elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then
                set hkey = 2
            else
                set u = null
                return
            endif
    
            if udg_RCSGameTimeReset[1] < (udg_RCSGameTime - LoadReal(udg_RCSHashtable, id, 0)) then
                call SaveInteger(udg_RCSHashtable, id, hkey, 0)
                set udg_RCSKillerUnit = u
                set udg_RCSInteger    = 0
                call RCSKillStreakCheckKills()
                set udg_RCSKillerUnit = null
                set u = null
            endif
        endfunction
    That looks pretty neat. And it makes the differences between the two if-conditions more visible. In the original, you'll think that the if-conditions evaluate to two completely different things. However, in the example above, you'll know that only the keys change.

    You can also delegate them to a function, which may be neater:
    JASS:
        // Try to come up with a better name than I did :P
        function RCSForceGroupEnumIndKillsEvaluate takes unit enum, integer id, integer hkey returns nothing
            if udg_RCSGameTimeReset[1] < (udg_RCSGameTime - LoadReal(udg_RCSHashtable, id, 0)) then
                call SaveInteger(udg_RCSHashtable, id, hkey, 0)
                set udg_RCSKillerUnit = enum
                set udg_RCSInteger    = 0
                call RCSKillStreakCheckKills()
                set udg_RCSKillerUnit = null
            endif
        endfunction
    
        function RCSForceGroupEnumIndKills takes nothing returns nothing 
            local unit    u  = GetEnumUnit()
            local integer id = GetHandleId(u)
            local boolean b  = IsUnitType(u, UNIT_TYPE_HERO)
    
            if not b and udg_RCSIndividualKillsBoolean[1] and RCSNonHeroKillsIndividualFilter() then
                call RCSForGroupEnumIndKillsEvaluate(u, id, 1)
            elseif b and udg_RCSIndividualKillsBoolean[2] and RCSHeroKillsIndividualFilter() then
                call RCSForGroupEnumIndKillsEvaluate(u, id, 2)
            endif
    
            set u = null
        endfunction
    Of course, this has no real efficiency boost, but rather a fundamental logic/readability boost. That is important, too. Remember the DRY principle.

    .
  • ^A similar dilemma as the above note with RCSGetIndivKillsFromUnit. Also, you can remove the return 0 within the if-blocks since it'll return 0 outside the block.
    .
  • (Optional) The test map could be better. You should include some general information and a way to respawn units (especially for a kill system--once you kill all the units on the map, you can't test it anymore). But this is just a recommendation, not a requirement.

tl;dr Eh, I'm going to go ahead and approve this. It works just fine and has some nice customizability. The code is pretty difficult to read and has a few problems mentioned above. The test map could be better. I haven't really considered alternate implementations, but your code itself is fine. Most of my notes are just incredibly minor, and I know this has been sitting unreviewed for a while, so I apologize for that.

Approved.

I'll try to update when I can as the fixes you mentioned should be done.
Thanks for the approval and the comments.
I think I was drunk when I coded this so I'm surprised it didn't need more fixing.

@ BunnyAng
If you need help implementing it just ask.
 
Top