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

Blood rage problems

Status
Not open for further replies.
Level 10
Joined
Jun 6, 2007
Messages
392
Hello! I have 2 problems concerning my blood rage ability, description and triggers can be found here.

1. Sometimes when the computer learns the ability, the bars aren't created. This doesn't happen when a player controlled hero learns blood rage. The issue can be seen in this replay.

2. After some time, the game begins to get lag spikes. This only happens when there are computer controlled heroes with blood rage.

I've been trying to solve these issues without any luck. Any help appreciated.
 
Level 10
Joined
Jun 6, 2007
Messages
392
In that case, here's the description:
Description:
Allows the hero to gain rage points when dealing damage or when nearby unit dies. Rage points will be used to reduce damage taken by the hero. If hero has enough rage points, he will also gain additional bonuses.

Level 1 - Level 1 bonus (+10 damage) enabled at 250 rage points.
Level 2 - Level 2 bonus (+3 hp regen) enabled at 500 rage points.
Level 3 - Level 3 bonus (+50% attack rate) enabled at 750 rage points.

and trigger:
JASS:
//###########################################################################################################
//# Blood Rage                                                                                              #
//# Created by Erkki2                                                                                       #
//# Required libraries:                                                                                     #
//#     Unit Indexer by Bribe                                                                               #
//#     Damage Engine by Bribe                                                                              #
//#                                                                                                         #
//# Import instructions:                                                                                    #
//#     1. Copy the cheat death ability to your map and create an ability for Blood Rage                    #
//#     2. Check "automatically create unknown variables while pasting trigger data" in map preferences     #
//#     3. Copy this trigger and required libraries to your map                                             #
//#     4. Set DamageBlockingAbility in Damage Engine trigger to the ability copied at 1                    #
//#     5. Set configurables in this trigger                                                                #
//#     6. To modify rage from in your own triggers, call addRage(unit, amount)                             #
//###########################################################################################################

scope BloodRage

//  #################
//  # CONFIGURABLES #
//  #################
     globals
         
         //Raw code of the spell ability
         private constant integer ABIL_CODE = 'A000'
               
         //Iteration interval
         private constant real TIMEOUT = 0.03125
         
         //How high above unit the bar is
         private constant real BAR_HEIGHT = 150.0
         
         //Maximum amount of rage
         private constant real MAX_RAGE = 1000.0
         
         //How many characters ("|") the bar has
         private constant integer BAR_WIDTH = 150
         
         //Setting this to smaller value will move the bar left, and higher value to tight
         private constant real LETTER_WIDTH = 0.4
         
         //Height of the bar
         private constant real BAR_FONT_SIZE = 0.015
         
         //Colour settings for the bar
         private constant integer BAR_RED = 255
         private constant integer BAR_GREEN = 0
         private constant integer BAR_BLUE = 0
         private constant integer BAR_ALPHA = 255
         private constant integer BAR_BACKGROUND_RED = 102
         private constant integer BAR_BACKGROUND_GREEN = 0
         private constant integer BAR_BACKGROUND_BLUE = 0
         private constant integer BAR_BACKGROUND_ALPHA = 255
         
         //Unit will gain (X * damage dealt) rage points when dealing damage
         private constant real ATTACK_RAGE_FACTOR = 0.3
         
         //Unit will gain X rage when an allied unit dies nearby
         private constant real ALLY_DEATH_RAGE_AMOUNT = 50
         
         //Unit will gain X rage when an enemy unit dies nearby
         private constant real ENEMY_DEATH_RAGE_AMOUNT = 30
         
         //Unit will gain rage points when a unit dies within this area
         private constant real RAGE_GAIN_AREA = 800
         
         //The speed at which rage depletes
         private constant real DEGENERATION_PER_SECOND = 30
         
         //If the unit has not gained rage in x seconds, it will begin to degenerate
         private constant real DEGENERATION_DELAY = 10.0
         
         //Damage blocked by rage
         private constant real DAMAGE_REDUCTION_FACTOR = 0.5
         
         //Rage lost per point of blocked damage
         private constant real RAGE_DRAIN_FACTOR = 1

     endglobals
     
     //Rage points required to gain level "level"
     private function levelRageAmount takes integer level returns real
         return level*250.0
     endfunction
     
     //Rage bonus ability for level "level"
     private function rageAbility takes integer level returns integer
         if level == 1 then
             return 'A002'
         elseif level == 2 then
             return 'A003'
         elseif level == 3 then
             return 'A004'
         endif
         return 0
     endfunction
     
     //Level of rage bonus ability for level "level".
     private function rageBonusLevel takes integer level returns integer
         return 1
     endfunction

     //Rage doesn't deregenerate if current rage is below this amount
     private function degenerationTreshold takes unit u returns real
         return 100.0*GetUnitAbilityLevel(u, ABIL_CODE)
     endfunction
     
//  ############################################################
//  # CONFIGURABLES END, Don't touch anything after this line. #
//  ############################################################

     private struct Spell
     
         private thistype next
         private thistype prev
         private static timer iterator = CreateTimer()
         private static integer count = 0
         
         private unit u
         private texttag rageBarTotal
         private texttag rageBarCurrent
         private real currentRage
         private integer rageLevel
         private real degenDelay
         
         private method destroy takes nothing returns nothing
             call this.deallocate()
             set this.next.prev = this.prev
             set this.prev.next = this.next
             call DestroyTextTag(this.rageBarCurrent)
             call DestroyTextTag(this.rageBarTotal)
             set this.rageBarCurrent = null
             set this.rageBarTotal = null
             set this.u = null
             set count = count - 1
         endmethod
         
         private static method periodic takes nothing returns nothing
             local thistype this = thistype(0).next
             local real x
             local real y
             local string text
             local integer i
             local integer treshold
             
             loop
                 exitwhen this == 0
                 
                 //Set bar position to unit's position.
                 //Move bar to left so that its center is at the unit.
                 set x = GetUnitX(this.u) - BAR_WIDTH*LETTER_WIDTH
                 set y = GetUnitY(this.u)
                 
                 call SetTextTagPos(this.rageBarTotal, x, y, BAR_HEIGHT)
                 call SetTextTagPos(this.rageBarCurrent, x, y, BAR_HEIGHT)

                 //Set bar to match unit's current rage amount
                 set text = ""
                 set i = 0
                 set treshold = R2I(this.currentRage/MAX_RAGE*I2R(BAR_WIDTH))
                 loop
                     exitwhen i >= treshold
                     set text = text + "|"
                     set i = i + 1
                 endloop
             
                 call SetTextTagText(this.rageBarCurrent, text, BAR_FONT_SIZE)
                 
                 //If unit is dead, hide the bar, and if unit is alive, show the bar
                 call SetTextTagVisibility(rageBarTotal, GetUnitState(this.u, UNIT_STATE_LIFE) > 0)
                 call SetTextTagVisibility(rageBarCurrent, GetUnitState(this.u, UNIT_STATE_LIFE) > 0)
                 
                 //If unit's rage level changes, add/remove bonuses accordingly
                 loop
                     if this.currentRage >= levelRageAmount(this.rageLevel + 1) /*
 */                  and GetUnitAbilityLevel(this.u, ABIL_CODE) > this.rageLevel then
                         call UnitAddAbility(this.u, rageAbility(this.rageLevel + 1))
                         call SetUnitAbilityLevel(this.u, rageAbility(this.rageLevel + 1), rageBonusLevel(this.rageLevel))
                         set this.rageLevel = this.rageLevel + 1
                     elseif this.currentRage < levelRageAmount(this.rageLevel) then
                         call UnitRemoveAbility(this.u, rageAbility(this.rageLevel))
                         set this.rageLevel = this.rageLevel - 1
                     else
                         exitwhen true
                     endif
                 endloop
                 
                 //This unit hasn't gained rage in DEGENERATION_DELAY seconds
                 if this.degenDelay < TIMEOUT then
                     //Degenerate unit's rage
                     if this.currentRage - DEGENERATION_PER_SECOND > degenerationTreshold(this.u) then
                         set this.currentRage = this.currentRage - DEGENERATION_PER_SECOND*TIMEOUT
                     endif
                 else
                     set this.degenDelay = this.degenDelay - TIMEOUT
                 endif
                 
                 set this = this.next
             
             endloop
         
             //if there are no spell instances running, pause the timer
             if count == 0 then
                 call PauseTimer(iterator)
             endif
             
         endmethod

         //Registers a unit to have blood rage
         private static method registerUnit takes unit u returns nothing
             local thistype this
             local string text
             local integer i

             set this = thistype.allocate()
             set this.next = 0
             set this.prev = thistype(0).prev
             set thistype(0).prev.next = this
             set thistype(0).prev = this
             set count = count + 1
                 
             if count == 1 then
                 call TimerStart(iterator, TIMEOUT, true, function thistype.periodic)
             endif
             
             set this.u = u
             set this.currentRage = 0
             set this.rageLevel = 0
             set this.degenDelay = DEGENERATION_DELAY
             
             set text = ""
             set i = 0
             
             loop
                 exitwhen i >= BAR_WIDTH
                 set text = text + "|"
                 set i = i + 1
             endloop
             
             set this.rageBarCurrent = CreateTextTag()
             call SetTextTagText(this.rageBarCurrent, "", BAR_FONT_SIZE)
             call SetTextTagPos(this.rageBarCurrent, GetUnitX(this.u), GetUnitY(this.u), BAR_HEIGHT)
             call SetTextTagColor(this.rageBarCurrent, BAR_RED, BAR_GREEN, BAR_BLUE, BAR_ALPHA)
             
             set this.rageBarTotal = CreateTextTag()
             call SetTextTagText(this.rageBarTotal, text, BAR_FONT_SIZE)
             call SetTextTagPos(this.rageBarTotal, GetUnitX(this.u), GetUnitY(this.u), BAR_HEIGHT)
             call SetTextTagColor(this.rageBarTotal, BAR_BACKGROUND_RED, BAR_BACKGROUND_GREEN, BAR_BACKGROUND_BLUE, BAR_BACKGROUND_ALPHA)
         endmethod
         
         //Registers units that are indexed
         private static method registerUnitsIndexed takes nothing returns boolean
             if GetUnitAbilityLevel(udg_UDexUnits[udg_UDex], ABIL_CODE) > 0 then
                 call thistype.registerUnit(udg_UDexUnits[udg_UDex])
             endif
             return false
         endmethod
         
         //Registers a hero that learns blood rage
         private static method registerLearningHero takes nothing returns boolean            
             if GetUnitAbilityLevel(GetTriggerUnit(), ABIL_CODE) == 1 and (GetLearnedSkill() == ABIL_CODE) then
                 call thistype.registerUnit(GetTriggerUnit())
             endif
             return false
         endmethod
         
         //Unregisters a unit from blood rage
         private static method deindexUnit takes nothing returns boolean
             local thistype this = thistype(0).next
             loop
                 exitwhen this == 0
                 if GetUnitUserData(this.u) == 0 then
                     call this.destroy()
                     return false
                 endif
                 set this = this.next
             endloop
             return false
         endmethod
         
         //Changes unit's current rage by amount
         private method modifyRage takes real amount returns nothing
             if this.currentRage + amount <= 0 then
                 set this.currentRage = 0
             elseif currentRage + amount >= MAX_RAGE then
                 set this.currentRage = MAX_RAGE
             else
                 set this.currentRage = this.currentRage + amount
                 if amount > 0 then
                     set this.degenDelay = DEGENERATION_DELAY
                 endif
             endif
         endmethod
         
         //This function allows modifying rage from outside this trigger
         static method addRage takes unit u, real amount returns nothing
             local thistype this = thistype(0).next
             loop
                 exitwhen this == 0
                 if u == this.u then
                     call this.modifyRage(amount)
                     return
                 endif
                 set this = this.next
             endloop
         endmethod
         
         //Adds rage when unit deals damage
         private static method addRageAttack takes nothing returns boolean
             local thistype this = thistype(0).next
             if not (GetUnitAbilityLevel(udg_DamageEventSource, ABIL_CODE) == 0) then
                 loop
                     exitwhen this == 0
                     if udg_DamageEventSource == this.u then
                         call this.modifyRage(udg_DamageEventAmount*ATTACK_RAGE_FACTOR)
                         return false
                     endif
                     set this = this.next
                 endloop
             endif
             return false
         endmethod
         
         //Adds rage when a unit dies nearby
         private static method addRageDeath takes nothing returns boolean
             local real dx
             local real dy
             local unit dying = GetTriggerUnit()
             local thistype this = thistype(0).next
             if GetUnitAbilityLevel(dying, 'Aloc') == 0 then
                 loop
                     exitwhen this == 0
                     set dx = GetUnitX(this.u) - GetUnitX(dying)
                     set dy = GetUnitY(this.u) - GetUnitY(dying)
                     if SquareRoot(dx*dx + dy*dy) <= RAGE_GAIN_AREA then
                         if IsUnitAlly(dying, GetOwningPlayer(this.u)) then
                             call this.modifyRage(ALLY_DEATH_RAGE_AMOUNT)
                         else
                             call this.modifyRage(ENEMY_DEATH_RAGE_AMOUNT)
                         endif
                     endif
                     set this = this.next
                 endloop
             endif
             return false
         endmethod
     
         //Reduces damage taken by units that have blood rage
         private static method reduceDamage takes nothing returns boolean
             local thistype this = thistype(0).next
             local real reduction
             if not (GetUnitAbilityLevel(udg_DamageEventTarget, ABIL_CODE) == 0) then
                 loop
                     exitwhen this == 0
                     if udg_DamageEventTarget == this.u then
                         if this.currentRage > udg_DamageEventAmount*DAMAGE_REDUCTION_FACTOR*RAGE_DRAIN_FACTOR then
                             set reduction = udg_DamageEventAmount*DAMAGE_REDUCTION_FACTOR
                         else
                             set reduction = this.currentRage/RAGE_DRAIN_FACTOR
                         endif
                             set this.currentRage = this.currentRage - reduction*RAGE_DRAIN_FACTOR
                             set udg_DamageEventAmount = udg_DamageEventAmount - reduction
                         return false
                     endif
                     set this = this.next
                 endloop
             endif
             return false
         endmethod
     
         private static method onInit takes nothing returns nothing
             local trigger t = CreateTrigger()
             local trigger t2 = CreateTrigger()
             local trigger t3 = CreateTrigger()
             local trigger t4 = CreateTrigger()
             local trigger t5 = CreateTrigger()
             local trigger t6 = CreateTrigger()
             local integer i = 0
             
             call TriggerRegisterVariableEvent( t, "udg_UnitIndexEvent", EQUAL, 1.00 )
             call TriggerAddCondition(t, Condition(function thistype.registerUnitsIndexed))
             call TriggerAddCondition(t2, Condition(function thistype.registerLearningHero))
             call TriggerAddCondition(t3, Condition(function thistype.deindexUnit))
             call TriggerRegisterVariableEvent( t4, "udg_UnitIndexEvent", EQUAL, 2.00 )
             call TriggerRegisterVariableEvent( t4, "udg_DamageEvent", EQUAL, 1.00 )
             call TriggerAddCondition(t4, Condition(function thistype.addRageAttack))
             call TriggerAddCondition(t5, Condition(function thistype.addRageDeath))
             call TriggerRegisterVariableEvent( t6, "udg_DamageModifierEvent", EQUAL, 1.00 )
             call TriggerAddCondition(t6, Condition(function thistype.reduceDamage))
             
             loop
                 exitwhen i == 16
                 
                 call TriggerRegisterPlayerUnitEvent(t2, Player(i),  EVENT_PLAYER_HERO_SKILL, null)
                 call TriggerRegisterPlayerUnitEvent(t5, Player(i),  EVENT_PLAYER_UNIT_DEATH, null)
             
                 set i = i + 1
             endloop
             
         endmethod
         
     endstruct
     
     //This function can be used to modify rage from outside this trigger
     function addRage takes unit u, real amount returns nothing
         call Spell.addRage(u, amount)
     endfunction

endscope
 
Status
Not open for further replies.
Top