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

Damage System for Each player

Status
Not open for further replies.
Level 8
Joined
Feb 17, 2007
Messages
368
Can anyone tell me how to create a system that tracks the amount of damage each player attacking a boss does in real time? So when they type a command such as -dmg in the middle of the fight, it shows how much damage they've done so far. Then at the end of the fight, I want the total damage for each player displayed in descending order from highest to lowest.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
You will need a damage-detection system and a variable that keeps track of how much damage each player (so an array of size 12) has dealt to the boss, which would be detected using the damage detection system.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
DBZReborn said:
I know only some vJass.

Oh, you use vJass? Splendid.

DBZReborn said:
Ok well I have the system called Damage in my map now

Okay, is this Damage system used for damage-detection, or what? I can give you a good example but first tell me which damage-detection you use (or what the interface is) so that I can give you a more specific example.

DBZReborn said:
can someone be more specific as to what I exactly have to do?

JASS:
library PlayerDamage requires DamageDetect initializer init

    //##################################################################################
    globals
    
        public      real array          playerDamage
        
    endglobals
    
    //##################################################################################
    public function onDamage takes nothing returns nothing
        local integer id = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        
        set playerDamage[id] = playerDamage[id] + GetEventDamage()
    endfunction
    
    //##################################################################################
    public function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i
        
        //This is where knowing what damage-detection system you use comes into play
        call OnDamageEvent(t) //This is not a specific example
        
        //The rest is pretty standard, though not guaranteed (again, depending on damage-
        //detection protocol)
        call TriggerAddAction(t, function onDamage)
        
        //Ensure that the values in the playerDamage array are initialized to 0 so that
        //there are no problems with addition
        set i = 0
        loop
            exitwhen(i == 16)
            set playerDamage[i] = 0.00
            set i = i+1
        endloop
    endfunction
    
endlibrary

The system that PurgeandFire111 posted is a little heavy for something as simple as a damage counter. If you need the extra features, then by all means use that.
 
Level 8
Joined
Feb 17, 2007
Messages
368
Hey thanks guys for the help! :smile: I am giving you both +rep! This is the Damage System I am using:

JASS:
//  
//      ___   _     __  __   _   ___  ____    _______________________________
//     |   \ /_\   /  |/  | /_\ /  _\|  __|   ||      D E A L   I T ,      ||
//     | |) / _ \ / / | / |/ _ \| |/||  __|   ||    D E T E C T   I T ,    ||
//     |___/_/ \_/_/|__/|_|_/ \_\___/|____|   ||     B L O C K   I T .     ||
//                            By Jesus4Lyf    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//                                                                    v 1.0.5
//      What is Damage?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Damage is a damage dealing, detection and blocking system. It implements
//          all such functionality. It also provides a means to detect what type
//          of damage was dealt, so long as all damage in your map is dealt using
//          this system's deal damage functions (except for basic attacks).
//
//          It is completely recursively defined, meaning if you deal damage on
//          taking damage, the type detection and other features like blocking
//          will not malfunction.
//          
//      How to implement?
//     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//          Create a new trigger object called Damage, go to 'Edit -> Convert to
//          Custom Text', and replace everything that's there with this script.
//
//          At the top of the script, there is a '//! external ObjectMerger' line.
//          Save your map, close your map, reopen your map, and then comment out this
//          line. Damage is now implemented. This line creates a dummy ability used
//          in the system in some circumstances with damage blocking.
//
//      Functions:
//     ¯¯¯¯¯¯¯¯¯¯¯¯
//          function Damage_RegisterEvent takes trigger whichTrigger returns nothing
//              - This registers a special "any unit takes damage" event.
//              - This event supports dynamic trigger use.
//              - Only triggers registered on this event may block damage.
//              - Only fires when the damage dealt is not 0.
//
//          function Damage_RegisterZeroEvent takes trigger whichTrigger returns nothing
//              - The same as Damage_RegisterEvent, but for only zero damage events
//                (which are excluded from Damage_RegisterEvent).
//              - Note that getting the damage type may be unreliable, since spells
//                like faerie fire trigger 0 damage, but it will count as an attack.
//
//          function Damage_GetType takes nothing returns damagetype
//              - This will get the type of damage dealt, like an event response,
//                for when using a unit takes damage event (or the special event above).
//
//          function Damage_IsPhysical takes nothing returns boolean
//          function Damage_IsSpell takes nothing returns boolean
//          function Damage_IsPure takes nothing returns boolean
//              - Wrappers to simply check if Damage_GetType is certain types.
//
//          function Damage_IsAttack takes nothing returns boolean
//              - Checks if the damage is from a physical attack (so you can deal
//                physical damage without it being registered as an actual attack).
//
//          function Damage_Block takes real amount returns nothing
//          function Damage_BlockAll takes nothing returns nothing
//              - For use only with Damage_RegisterEvent.
//              - Blocks 'amount' of the damage dealt.
//              - Multiple blocks at once work correctly.
//              - Blocking more than 100% of the damage will block 100% instead.
//              - Damage_BlockAll blocks 100% of the damage being dealt.
//
//          function Damage_EnableEvent takes boolean enable returns nothing
//              - For disabling and re-enabling the special event.
//              - Use it to deal damage which you do not want to be detected by
//                the special event.
//
//          function UnitDamageTargetEx takes lots of things returns boolean
//              - Replaces UnitDamageTarget in your map, with the same arguments.
//
//          function Damage_Physical takes unit source, unit target, real amount,
//            attacktype whichType, boolean attack, boolean ranged returns boolean
//              - A clean wrapper for physical damage.
//              - 'attack' determines if this is to be treated as a real physical
//                attack or just physical type damage.
//              - 'ranged' determines if this is to be treated as a ranged or melee
//                attack.
//
//          function Damage_Spell takes unit source, unit target, real amount returns boolean
//              - A clean wrapper for spell damage.
//
//          function Damage_Pure takes unit source, unit target, real amount returns boolean
//              - A clean wrapper for pure type damage (universal type, 100% damage).
//          
//      Thanks:
//     ¯¯¯¯¯¯¯¯¯
//          - Romek, for helping me find a better way to think about damage blocking.
//
library Damage uses AIDS, Event
    //============================================================
    //! external ObjectMerger w3a AIlz dprv anam "Life Bonus" ansf "(Damage System)" Ilif 1 500000 aite 0
    globals
        private constant integer LIFE_BONUS_ABIL='dprv'
    endglobals
    
    //============================================================
    globals
        private Event OnDamageEvent
        private Event OnZeroDamageEvent
        private boolean EventEnabled=true
    endglobals
    
    public function RegisterEvent takes trigger whichTrigger returns nothing
        call OnDamageEvent.register(whichTrigger)
    endfunction
    
    public function RegisterZeroEvent takes trigger whichTrigger returns nothing
        call OnZeroDamageEvent.register(whichTrigger)
    endfunction
    
    public function EnableEvent takes boolean enable returns nothing
        set EventEnabled=enable
    endfunction
    
    //============================================================
    globals
        private integer TypeStackLevel=0
        private damagetype array TypeStackValue
        private boolean array TypeStackAttack
        private real array ToBlock
    endglobals
    
    public function GetType takes nothing returns damagetype
        return TypeStackValue[TypeStackLevel]
    endfunction
    
    public function IsAttack takes nothing returns boolean
        return TypeStackAttack[TypeStackLevel]
    endfunction
    
    public function Block takes real amount returns nothing
        set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+amount
    endfunction
    
    public function BlockAll takes nothing returns nothing
        set ToBlock[TypeStackLevel]=ToBlock[TypeStackLevel]+GetEventDamage()
    endfunction
    
    //============================================================
    globals
        private integer BlockNum=0
        private unit array BlockUnit
        private real array BlockUnitLife
        private real array BlockRedamage
        private unit array BlockDamageSource
        
        private timer BlockTimer=CreateTimer()
    endglobals
    
    //============================================================
    globals
        private unit array RemoveBoosted
        private integer RemoveBoostedMax=0
        
        private timer RemoveBoostedTimer=CreateTimer()
    endglobals
    
    globals//locals
        private real BoostedLifeTemp
        private unit BoostedLifeUnit
    endglobals
    private function RemoveBoostedTimerFunc takes nothing returns nothing
        loop
            exitwhen RemoveBoostedMax==0
            set BoostedLifeUnit=RemoveBoosted[RemoveBoostedMax]
            set BoostedLifeTemp=GetWidgetLife(BoostedLifeUnit)
            call UnitRemoveAbility(BoostedLifeUnit,LIFE_BONUS_ABIL)
            if BoostedLifeTemp>0.405 then
                call SetWidgetLife(BoostedLifeUnit,BoostedLifeTemp)
            endif
            set RemoveBoostedMax=RemoveBoostedMax-1
        endloop
    endfunction
    
    //============================================================
    private keyword Detector // Darn, I actually had to do this. XD
    globals//locals
        private unit ForUnit
        private real NextHealth
    endglobals
    private function OnDamageActions takes nothing returns boolean
        if EventEnabled then
            if GetEventDamage()==0. then
                call OnZeroDamageEvent.fire()
            else
                call OnDamageEvent.fire()
            endif
            
            if ToBlock[TypeStackLevel]!=0. then
                //====================================================
                // Blocking
                set ForUnit=GetTriggerUnit()
                
                set NextHealth=GetEventDamage()
                if ToBlock[TypeStackLevel]>=NextHealth then
                    set NextHealth=GetWidgetLife(ForUnit)+NextHealth
                else
                    set NextHealth=GetWidgetLife(ForUnit)+ToBlock[TypeStackLevel]
                endif
                
                call SetWidgetLife(ForUnit,NextHealth)
                if GetWidgetLife(ForUnit)<NextHealth then
                    // NextHealth is over max health.
                    call UnitAddAbility(ForUnit,LIFE_BONUS_ABIL)
                    call SetWidgetLife(ForUnit,NextHealth)
                    
                    set RemoveBoostedMax=RemoveBoostedMax+1
                    set RemoveBoosted[RemoveBoostedMax]=ForUnit
                    call ResumeTimer(RemoveBoostedTimer)
                endif
                //====================================================
                set ToBlock[TypeStackLevel]=0.
            endif
        endif
        return false
    endfunction
    
    //============================================================
    function UnitDamageTargetEx takes unit whichUnit, widget target, real amount, boolean attack, boolean ranged, attacktype attackType, damagetype damageType, weapontype weaponType returns boolean
        local boolean result
        set TypeStackLevel=TypeStackLevel+1
        set TypeStackValue[TypeStackLevel]=damageType
        set TypeStackAttack[TypeStackLevel]=attack
        set result=UnitDamageTarget(whichUnit,target,amount,attack,ranged,attackType,damageType,weaponType)
        set TypeStackLevel=TypeStackLevel-1
        return result
    endfunction
    //! textmacro Damage__DealTypeFunc takes NAME, TYPE
        public function $NAME$ takes unit source, unit target, real amount returns boolean
            return UnitDamageTargetEx(source,target,amount,false,false,ATTACK_TYPE_NORMAL,$TYPE$,WEAPON_TYPE_WHOKNOWS)
        endfunction
        public function Is$NAME$ takes nothing returns boolean
            return GetType()==$TYPE$
        endfunction
    //! endtextmacro
    
    //! runtextmacro Damage__DealTypeFunc("Pure","DAMAGE_TYPE_UNIVERSAL")
    //! runtextmacro Damage__DealTypeFunc("Spell","DAMAGE_TYPE_MAGIC")
    
    // Uses different stuff, but works much the same way.
    public function Physical takes unit source, unit target, real amount, attacktype whichType, boolean attack, boolean ranged returns boolean
        return UnitDamageTargetEx(source,target,amount,attack,ranged,whichType,DAMAGE_TYPE_NORMAL,WEAPON_TYPE_WHOKNOWS)
    endfunction
    public function IsPhysical takes nothing returns boolean
        return GetType()==DAMAGE_TYPE_NORMAL
    endfunction
    
    //============================================================
    private struct Detector extends array // Uses AIDS.
        //! runtextmacro AIDS()
        
        private static conditionfunc ACTIONS_COND
        
        private trigger t
        
        private method AIDS_onCreate takes nothing returns nothing
            set this.t=CreateTrigger()
            call TriggerAddCondition(this.t,thistype.ACTIONS_COND)
            call TriggerRegisterUnitEvent(this.t,this.unit,EVENT_UNIT_DAMAGED)
        endmethod
        
        private method AIDS_onDestroy takes nothing returns nothing
            call DestroyTrigger(this.t)
        endmethod
        
        private static method AIDS_onInit takes nothing returns nothing
            set thistype.ACTIONS_COND=Condition(function OnDamageActions)
        endmethod
    endstruct
    
    //============================================================
    private module InitModule
        private static method onInit takes nothing returns nothing
            local unit abilpreload=CreateUnit(Player(15),'uloc',0,0,0)
            call UnitAddAbility(abilpreload,LIFE_BONUS_ABIL)
            call RemoveUnit(abilpreload)
            set abilpreload=null
            
            set OnDamageEvent=Event.create()
            set OnZeroDamageEvent=Event.create()
            set TypeStackValue[TypeStackLevel]=DAMAGE_TYPE_NORMAL
            set TypeStackAttack[TypeStackLevel]=true
            call TimerStart(RemoveBoostedTimer,0.0,false,function RemoveBoostedTimerFunc)
        endmethod
    endmodule
    private struct InitStruct extends array
        implement InitModule
    endstruct
endlibrary
 
Level 8
Joined
Feb 17, 2007
Messages
368
Ok thanks a lot man! :) Can you or someone else also please tell me how to display the total damage done after the boss fight to all players. I would like for it to be displayed from highest to lowest. So like this:

Damage Done Last Boss Fight:

1. DbzReborn - 5000.103
2. Berb - 1500.501

I dont actually know really how to write vJass code, lol, but I am able to work with it and edit spells and some systems values to the point of my liking. Also I want if you type dmg at any point in time, you can see the amount of dmg done to the current boss; I want it to reset after a boss is killed, then restarted for the next boss. I will +rep anyone who can help me with this. :p
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Indeed, the initializer is supposed to be placed first.

I'll post up some code with a few extra functions for those special things you needed, and fix that initializer bug.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Alright well here's something to keep you busy for now. I have the GetPlayerDamage function which just returns the variable that stores the amount of damage that is dealt. I also included a ResetPlayerDamage function that clears all records of damage.

The big function, PrintDamage will sort the array of player damage into a sorted array and then display it in order of highest to lowest to each player. At the moment I am working on setting up a cross-reference variable so I can record the names of the players associated with each element in the sorted array.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Oops. I swear I posted the code. I don't know what it is you see I forgot to post haha. Sorry when I posted this I was ready to pass the heck out, was so tired. Here's the code:

JASS:
library PlayerDamage initializer init// requires Damage

    //##################################################################################
    globals
    
        public      real array          playerDamage
        public      integer array       playerId
        
    endglobals
    
    //##################################################################################
    // Utility Functions
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //  These are functions that can be used easily to gather special case values or
    //  perform special actions.
    //
    //  function PrintDamage will print a list of player ID's along with each associated
    //  damage-dealt value, all in a sorted order.
    //
    function ResetPlayerDamage takes player p returns nothing
        set playerDamage[GetPlayerId(p)] = 0
    endfunction
    
    function GetPlayerDamage takes player p returns real
        return playerDamage[GetPlayerId(p)]
    endfunction

    function PrintDamage takes real time returns nothing
        local integer i = 0
        local integer j
        local integer h
        
        local real array r
        local real rt
        loop
            exitwhen(i == 16)
            set r[i] = playerDamage[i]
            set i = i + 1
        endloop
        
        set i = 0
        loop
            exitwhen(i == 16)
            set h = i
            set j = i
            loop
                exitwhen(j == 16)
                
                if (h != j) and (r[j] > r[h]) then
                    set h = j
                        
                endif
                set j = j + 1
            endloop            
            set playerId[i] = h
            
            set rt   = r[h]
            set r[h] = r[i]
            set r[i] = rt
            
            set i = i + 1
        endloop
        
        set i = 0
        loop
            exitwhen(i == 16)
            // Array is sorted in order of highest to lowest, so just print.
            call BJDebugMsg(R2S(r[i])+" - "+GetPlayerName(Player(playerId[i])))
            
            set i = i + 1
        endloop
    endfunction
    
    //##################################################################################
    public function onDamage takes nothing returns nothing
        local integer id = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        
        set playerDamage[id] = playerDamage[id] + GetEventDamage()
    endfunction
    
    //##################################################################################
    public function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i
        
        //This is where knowing what damage-detection system you use comes into play
        //call Damage_RegisterEvent(t) //This is not a specific example
        
        //The rest is pretty standard, though not guaranteed (again, depending on damage-
        //detection protocol)
        call TriggerAddAction(t, function onDamage)
        
        //Ensure that the values in the playerDamage array are initialized to 0 so that
        //there are no problems with addition
        set i = 0
        loop
            exitwhen(i == 16)
            set playerDamage[i] = I2R(GetRandomInt(3, 18))
            set i = i + 1
        endloop
        
        call PrintDamage(555)
    endfunction
    
endlibrary

The player name doesn't work yet, but I'll update this code soon enough with a working copy. The damage should still be displayed in proper descending order.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
And here's an update. Player names work now too.

JASS:
library PlayerDamage initializer init// requires Damage

    //##################################################################################
    globals
    
        public      real array          playerDamage
        
    endglobals
    
    //##################################################################################
    // Utility Functions
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //  These are functions that can be used easily to gather special case values or
    //  perform special actions.
    //
    //  function PrintDamage will print a list of player ID's along with each associated
    //  damage-dealt value, all in a sorted order.
    //
    function ResetPlayerDamage takes player p returns nothing
        set playerDamage[GetPlayerId(p)] = 0
    endfunction
    
    function GetPlayerDamage takes player p returns real
        return playerDamage[GetPlayerId(p)]
    endfunction
    
    function PrintDamage takes real time returns nothing
        local integer i = 0
        local integer j
        local integer h
        
        local real rt
        local player pt
        
        local real array r
        local player array p
        loop
            exitwhen(i == 16)
            set r[i]    = playerDamage[i]
            set p[i]    = Player(i)
            set i = i + 1
        endloop
        
        set i = 0
        loop
            exitwhen(i == 16)
            set h = i
            set j = i
            loop
                exitwhen(j == 16)
                if (h != j) and (r[j] > r[h]) then
                    set h = j
                        
                endif
                set j = j + 1
            endloop            
            
            set rt      = r[h]
            set pt      = p[h]
            set p[h]    = p[i]
            set r[h]    = r[i]
            set p[i]    = pt
            set r[i]    = rt
            
            set i = i + 1
        endloop
        
        set i = 0
        loop
            exitwhen(i == 16)
            // Array is sorted in order of highest to lowest, so just print.
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, time,/*
                                        */GetPlayerName(p[i])+" - "+R2S(r[i]))
            set i = i + 1
        endloop
    endfunction
    
    //##################################################################################
    public function onDamage takes nothing returns nothing
        local integer id = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        
        set playerDamage[id] = playerDamage[id] + GetEventDamage()
    endfunction
    
    //##################################################################################
    public function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i
        
        //This is where knowing what damage-detection system you use comes into play
        call Damage_RegisterEvent(t) //This is not a specific example
        
        //The rest is pretty standard, though not guaranteed (again, depending on damage-
        //detection protocol)
        call TriggerAddAction(t, function onDamage)
        
        //Ensure that the values in the playerDamage array are initialized to 0 so that
        //there are no problems with addition
        set i = 0
        loop
            exitwhen(i == 16)
            set playerDamage[i] = I2R(GetRandomInt(3, 18))
            set i = i + 1
        endloop
        
        call PrintDamage(555) // How long the message will be displayed for.
    endfunction
    
endlibrary

Reduced some unnecessary code:

JASS:
library PlayerDamage initializer init// requires Damage

    //##################################################################################
    globals
    
        public      real array          playerDamage
        
    endglobals
    
    //##################################################################################
    // Utility Functions
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //  These are functions that can be used easily to gather special case values or
    //  perform special actions.
    //
    //  function PrintDamage will print a list of player ID's along with each associated
    //  damage-dealt value, all in a sorted order.
    //
    function ResetPlayerDamage takes player p returns nothing
        set playerDamage[GetPlayerId(p)] = 0
    endfunction
    
    function GetPlayerDamage takes player p returns real
        return playerDamage[GetPlayerId(p)]
    endfunction
    
    function PrintDamage takes real time returns nothing
        local integer i = 0
        local integer j
        local integer h
        
        local real rt
        local player pt
        
        local real array r
        local player array p
        loop
            exitwhen(i == 16)
            set r[i]    = playerDamage[i]
            set p[i]    = Player(i)
            set i = i + 1
        endloop
        
        set i = 0
        loop
            exitwhen(i == 16)
            set h = i
            set j = i
            loop
                exitwhen(j == 16)
                if (h != j) and (r[j] > r[h]) then
                    set h = j
                        
                endif
                set j = j + 1
            endloop            
            
            set rt      = r[h]
            set pt      = p[h]
            set p[h]    = p[i]
            set r[h]    = r[i]
            set p[i]    = pt
            set r[i]    = rt
            
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, time,/*
                                        */GetPlayerName(p[i])+" \t "+R2S(r[i]))
            set i = i + 1
        endloop
    endfunction
    
    //##################################################################################
    public function onDamage takes nothing returns nothing
        local integer id = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        
        set playerDamage[id] = playerDamage[id] + GetEventDamage()
    endfunction
    
    //##################################################################################
    public function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i
        
        //This is where knowing what damage-detection system you use comes into play
        //call Damage_RegisterEvent(t) //This is not a specific example
        
        //The rest is pretty standard, though not guaranteed (again, depending on damage-
        //detection protocol)
        call TriggerAddAction(t, function onDamage)
        
        //Ensure that the values in the playerDamage array are initialized to 0 so that
        //there are no problems with addition
        set i = 0
        loop
            exitwhen(i == 16)
            set playerDamage[i] = I2R(GetRandomInt(3, 18))
            set i = i + 1
        endloop
        
        call PrintDamage(555)
    endfunction
    
endlibrary
 
Level 8
Joined
Feb 17, 2007
Messages
368
Alright well I implemented it, but I'm confused as to exactly what is going on. When I first start the map, it shows player damages in descending in the right order, but I only want it to show the damages for players 1-8. Sorry, I should have specified that. :p So just that, and when exactly does the system reset? It should reset immediately at the point the second boss fight starts. I also want the command dmg to bring up the current damage during the boss fight, and after the fight before the second boss fight starts. I've set up strings to attach a player to a color, so I would also like for the players color to show up in the dmg table:

  • Actions
    • Set CounterColor[1] = |CFFFF0303
    • Set CounterColor[2] = |CFF0042FF
    • Set CounterColor[3] = |CFF1CB619
    • Set CounterColor[4] = |CFF540081
    • Set CounterColor[5] = |CFFFFFF01
    • Set CounterColor[6] = |CFFFE8A0E
    • Set CounterColor[7] = |CFF20C000
    • Set CounterColor[8] = |CFFE55BB0
It might be easier for you to just take a look at my map, would you mind? =) Do you have MSN or any instant messenger? If you don't want to do either of these, then take a look at the map Impossible Bosses; that's basically how I want my damage display to be like: http://www.hiveworkshop.com/forums/maps-564/impossible-bosses-betav3m-163910/

Thanks you so much for your patience and understanding! You have been very helpful. =) I just really want to get the basic code setup so I can initialize it for every boss.

EDIT: I'm trying to get it to work right now.
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
At the bottom of the init trigger you'll see:

JASS:
        call PrintDamage(555)

Just remove that to stop displaying them at the beginning.

JASS:
            set playerDamage[i] = I2R(GetRandomInt(3, 18))

Also, you may want to get rid of them being randomized at the beginning. This was strictly for testing (and to show you it worked).

DBZReborn said:
for players 1-8.

Just change every time I use the number "16" with "8". You can also make a constant at the top and use that value so you don't have to change it all manually (there are only a couple times it is used, though).

DBZReborn said:
So just that, and when exactly does the system reset?

It can be reset by calling ResetPlayerDamage. This takes a specific player so you'll have to loop through all the players and apply the action for all of them.

RBZReborn said:
It should reset immediately at the point the second boss fight starts.

There is no event for "Boss Fight Start" so you're going to have to handle that one on your own. Or give me the map and have me add it, but it's easier for everyone if you try to do it first.

DBZReborn said:
I also want the command dmg to bring up the current damage during the boss fight, and after the fight before the second boss fight starts. I've set up strings to attach a player to a color, so I would also like for the players color to show up in the dmg table:

Okay, I'll update the code to use your color-code variables (I guess I'll add a function for clearing the entire contents of the damage table, and fix your 8-player deal).

For your command, just detect whenever a player types "-dmg" or whatever the command is. Then you can use the GetPlayerDamage function that I included to acquire the value from the table.

DBZReborn said:
It might be easier for you to just take a look at my map, would you mind? =) Do you have MSN or any instant messenger? If you don't want to do either of these, then take a look at the map Impossible Bosses; that's basically how I want my damage display to be like: Impossible Bosses BetaV3M

I have lots to do, and lots of people to help; please try this on your own first.

DBZReborn said:
EDIT: I'm trying to get it to work right now.

Just read this now. I appreciate it.

I'll post the updated code, too, it'll just take a second.

JASS:
library PlayerDamage initializer init// requires Damage

    //##################################################################################
    globals
    
        public      real array          playerDamage

        public      constant integer    PLAYER_COUNT      = 8
        
    endglobals
    
    //##################################################################################
    // Utility Functions
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //  These are functions that can be used easily to gather special case values or
    //  perform special actions.
    //
    //  function PrintDamage will print a list of player ID's along with each associated
    //  damage-dealt value, all in a sorted order.
    //
    function ResetPlayerDamage takes player p returns nothing
        set playerDamage[GetPlayerId(p)] = 0
    endfunction
    function ResetAllDamage takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen(i == PLAYER_COUNT)
            set playerDamage[i] = 0
            set i = i + 1
        endloop
    endfunction
    
    function GetPlayerDamage takes player p returns real
        return playerDamage[GetPlayerId(p)]
    endfunction
    
    function PrintDamage takes real time returns nothing
        local integer i = 0
        local integer j
        local integer h
        local string  s
        
        local real rt
        local player pt
        
        local real array r
        local player array p
        loop
            exitwhen(i == PLAYER_COUNT)
            set r[i]    = playerDamage[i]
            set p[i]    = Player(i)
            set i = i + 1
        endloop
        
        set i = 0
        loop
            exitwhen(i == PLAYER_COUNT)
            set h = i
            set j = i
            loop
                exitwhen(j == PLAYER_COUNT)
                if (h != j) and (r[j] > r[h]) then
                    set h = j
                        
                endif
                set j = j + 1
            endloop            
            
            set rt      = r[h]
            set pt      = p[h]
            set p[h]    = p[i]
            set r[h]    = r[i]
            set p[i]    = pt
            set r[i]    = rt
            
            set s = udg_CounterColor[p[i]-1]+GetPlayerName(p[i])+":    "+R2S(r[i])
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, time, s)
            set i = i + 1
        endloop
    endfunction
    
    //##################################################################################
    public function onDamage takes nothing returns nothing
        local integer id = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        
        set playerDamage[id] = playerDamage[id] + GetEventDamage()
    endfunction
    
    //##################################################################################
    public function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i
        
        //This is where knowing what damage-detection system you use comes into play
        //call Damage_RegisterEvent(t) //This is not a specific example
        
        //The rest is pretty standard, though not guaranteed (again, depending on damage-
        //detection protocol)
        call TriggerAddAction(t, function onDamage)
        
        //Ensure that the values in the playerDamage array are initialized to 0 so that
        //there are no problems with addition
        set i = 0
        loop
            exitwhen(i == PLAYER_COUNT)
            set playerDamage[i] = I2R(GetRandomInt(3, 18))
            set i = i + 1
        endloop
    endfunction
    
endlibrary

This should work.
 
Level 8
Joined
Feb 17, 2007
Messages
368
Thank you so much! Everything is working perfectly except for this line:
JASS:
            set s=udg_CounterColor[p[i] - 1] + GetPlayerName(p[i]) + ":    " + R2S(r[i])

It gives me two errors: Bad types for Binary Operator. Cannot convert real to integer.

EDIT: 1 other teeny little thing, there is a space before the name of the 1st player. I'm sure I can figure out how to fix this eventually though, you don't have to fix it. :p
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
If you remove the udg_CounterColor[p[i]-1] it works, so it's got something to do with your variable. It's a string, right?

Oh, you know what. It could be the -1. Try using +1 instead.
 
Level 8
Joined
Feb 17, 2007
Messages
368
Yeah its a string array of 8, for each player:



I tried the +1 but it gives me the same error; XD Here is the error:



I even tried changing it to this:

JASS:
set s = udg_CounterColor[GetPlayerId(p[i]-1)]+GetPlayerName(p[i])+":    "+R2S(r[i])

But then it says: Cannot convert real to player.

Btw I had to turn on the
JASS:
call Damage_RegisterEvent(t)
otherwise it wouldn't register the damage.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Sorry, I could only provide some really quick ideas as I was going out. I'm back now, I'll reply soon.

Oh, hold on. You're right, in some sense. I forgot that I made p[] a player variable. This went through a lot of trials using sorts and the variables were constantly shifted. You will need to use GetPlayerId as you said.

DBZReborn said:
Btw I had to turn on the .... otherwise it wouldn't register the damage.

Oh, sorry; I swear I uncommented that line.

DBZReborn said:
But then it says: Cannot convert real to player.

That's really strange. I can't see anything off-hand. I'll look into it.

Odd, you say it gives you an error but when I tried everything out it worked fine. This is the code:

JASS:
globals
    string array udg_CounterColor
endglobals

library Damage
    public function RegisterEvent takes trigger t returns nothing
    endfunction
endlibrary

library PlayerDamage initializer init requires Damage

    //##################################################################################
    globals
    
        public      real array          playerDamage

        public      constant integer    PLAYER_COUNT      = 8
        
    endglobals
    
    //##################################################################################
    // Utility Functions
    // ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    //  These are functions that can be used easily to gather special case values or
    //  perform special actions.
    //
    //  function PrintDamage will print a list of player ID's along with each associated
    //  damage-dealt value, all in a sorted order.
    //
    function ResetPlayerDamage takes player p returns nothing
        set playerDamage[GetPlayerId(p)] = 0
    endfunction
    function ResetAllDamage takes nothing returns nothing
        local integer i = 0
        loop
            exitwhen(i == PLAYER_COUNT)
            set playerDamage[i] = 0
            set i = i + 1
        endloop
    endfunction
    
    function GetPlayerDamage takes player p returns real
        return playerDamage[GetPlayerId(p)]
    endfunction
    
    function PrintDamage takes real time returns nothing
        local integer i = 0
        local integer j
        local integer h
        local string  s
        
        local real rt
        local player pt
        
        local real array r
        local player array p
        loop
            exitwhen(i == PLAYER_COUNT)
            set r[i]    = playerDamage[i]
            set p[i]    = Player(i)
            set i = i + 1
        endloop
        
        set i = 0
        loop
            exitwhen(i == PLAYER_COUNT)
            set h = i
            set j = i
            loop
                exitwhen(j == PLAYER_COUNT)
                if (h != j) and (r[j] > r[h]) then
                    set h = j
                        
                endif
                set j = j + 1
            endloop            
            
            set rt      = r[h]
            set pt      = p[h]
            set p[h]    = p[i]
            set r[h]    = r[i]
            set p[i]    = pt
            set r[i]    = rt
            
            set s = udg_CounterColor[GetPlayerId(p[i])+1]+GetPlayerName(p[i])+":    "+R2S(r[i])
            call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, time, s)
            set i = i + 1
        endloop
    endfunction
    
    //##################################################################################
    public function onDamage takes nothing returns nothing
        local integer id = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        
        set playerDamage[id] = playerDamage[id] + GetEventDamage()
    endfunction
    
    //##################################################################################
    public function init takes nothing returns nothing
        local trigger t = CreateTrigger()
        local integer i
        
        //This is where knowing what damage-detection system you use comes into play
        call Damage_RegisterEvent(t) //This is not a specific example
        
        //The rest is pretty standard, though not guaranteed (again, depending on damage-
        //detection protocol)
        call TriggerAddAction(t, function onDamage)
        
        //Ensure that the values in the playerDamage array are initialized to 0 so that
        //there are no problems with addition
        set i = 0
        loop
            exitwhen(i == PLAYER_COUNT)
            set playerDamage[i] = I2R(GetRandomInt(3, 18))
            set i = i + 1
        endloop
    endfunction
    
endlibrary

Does this compile properly for you? The Damage library and the global string array udg_CounterColor[] are declared so that I could use the same names. You can remove that part and it should not hinder the functionality in any way.

Let's see here, this is what you have:

JASS:
set s = udg_CounterColor[GetPlayerId(p[i]-1)]+GetPlayerName(p[i])+":    "+R2S(r[i])

And this is what I have:

JASS:
set s = udg_CounterColor[GetPlayerId(p[i])+1]+GetPlayerName(p[i])+":    "+R2S(r[i])

They're identical. Can you post the trigger in which you define the udg_CounterColor array?
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Wow I must be high or something. I didn't even notice this:

JASS:
p[i]-1

Earlier I was subtracting 1 from the player, which doesn't make any sense. The +1 should have been outside of the GetPlayerId parameters.
 
Level 8
Joined
Feb 17, 2007
Messages
368
Ok so, I have a new problem! The amount of damage is not registering correctly. For example, if I set my hero to have an attack damage of 25000, and my boss has 30000hp, the max damage it should read is 30000. However, it reads 50000 damage because it takes 2 hits to kill the boss with 25000 damage. Any ideas as to how to fix this?
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Oh, I see. Yea, I've got an idea. I have to go to work soon though so I can't do anything at the moment. If you want to try it yourself all you need to do is check to see (in the onDamage function) if the damage is greater than the life (using GetWidgetLife) then use the unit's life to add to the damage-table instead.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Alright, I'm back from work now. I'll do it.

This is the new onDamage function. Nothing else was changed.

JASS:
    //##################################################################################
    public function onDamage takes nothing returns nothing
        local integer id = GetPlayerId(GetOwningPlayer(GetEventDamageSource()))
        
        if GetEventDamage() > GetWidgetLife(GetTriggerUnit()) then
            set playerDamage[id] = playerDamage[id] + GetWidgetLife(GetTriggerUnit())
            //if the dealt damage exceeds the unit's life then the "real" amount of
            //damage would be the unit's current life, because that's how much damage
            //is required to kill it.
        else
            set playerDamage[id] = playerDamage[id] + GetEventDamage()
            //in any other situation we can just add the damage of the event to the
            //counter as "full-damage" was dealt.
        endif
    endfunction
 
Status
Not open for further replies.
Top