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

New Bonus [vJASS][LUA]

Intro
Hello, this is my first submission in the spell section, so apologies in advance for any mistake. I present to you the New Bonus System. Since Object Merger stopped working and we still have no ways to edit the bonus values of a unit natively, I decided to create this light weight system to manage that and give everyone a simpler way to work with bonus values than the Bonus Mod.
How it works?
By using the new Object API introduced to Warcraft, we can now modify an unit ability field value, so when giving an unit a bonus, we add a specific ability to that unit that gives such bonus, if it do not have it already, and change that ability field bonus value to the desired value. Retrieving the amount is also trivial, by just reading that field value.

How to Import?
Importing New Bonus is really simple. Just copy the 9 abilities with the prefix "NewBonus" from the Object Editor into your map [Raw Codes Z001 to Z009 in demo map] and match their new raw code to the bonus types in the global block of the library. You can also define their raw code when pasting to be Z001 to Z009, that's why I created them with this raw codes. Then create a trigger called NewBonus, convert it to custom text, delete all text in it and paste the Library code there. That's it, you are done!
Requirements
NewBonus requires patch 1.31+ and RegisterPlayerUnitEvent Library. NewBonus Extended also Requires DamageInterface, CooldownReduction and Tenacity libraries.

vJASS:
function GetUnitBonus takes unit u, integer bonus_type returns real
    -> Returns the specified bonus amount for the unit
    -> Example: set amount = GetUnitBonus(GetTriggerUnit(), BONUS_AGILITY)

function SetUnitBonus takes unit u, integer bonus_type, real amount returns real
    -> Set the specified bonus type to amount for the unit
    -> Example: call SetUnitBonus(GetTriggerUnit(), BONUS_DAMAGE, 100)

function RemoveUnitBonus takes unit u, integer bonus_type returns nothing
    -> Removes the Specified bonus type from unit
    -> Example: call RemoveUnitBonus(GetTriggerUnit(), BONUS_AGILITY)

function AddUnitBonus takes unit u, integer bonus_type, real amount returns real
    -> Add the specified amount for the specified bonus tyte for unit
    -> Example: call AddUnitBonus(GetTriggerUnit(), BONUS_DAMAGE, 100)

function AddUnitBonusTimed takes unit u, integer bonus_type, real amount, real duration returns nothing
    -> Add the specified amount for the specified bonus type for unit for a duration
    -> Example: call AddUnitBonusTimed(GetTriggerUnit(), BONUS_ARMOR, 13, 10.5)

function LinkBonusToBuff takes unit u, integer bonus_type, real amount, integer buffId returns nothing
    -> Links the bonus amount specified to a buff or ability. As long as the unit has the buff or
    -> the ability represented by the parameter buffId the bonus is not removed.
    -> Example: call LinkBonusToBuff(GetTriggerUnit(), BONUS_ARMOR, 10, 'B000')

function LinkBonusToItem takes unit u, integer bonus_type, real amount, item i returns nothing
    -> Links the bonus amount specified to an item. As long as the unit has that item the bonus is not removed.
    -> Note that it will work for items with the same id, because it takes as parameter the item object.
    -> Example: call LinkBonusToItem(GetManipulatingUnit(), BONUS_ARMOR, 10, GetManipulatedItem())

function UnitCopyBonuses takes unit source, unit target returns nothing
    -> Copy the source unit bonuses using the Add functionality to the target unit
    -> Example: call UnitCopyBonuses(GetTriggerUnit(), GetSummonedUnit())

function UnitMirrorBonuses takes unit source, unit target returns nothing
    -> Copy the source unit bonuses using the Set functionality to the target unit
    -> Example: call UnitMirrorBonuses(GetTriggerUnit(), GetSummonedUnit())

function RegisterBonusEvent takes code c returns nothing
    -> Register code to run when any unit bonus is modified
    -> Example: RegisterBonusEvent(function YourFunction)

function RegisterBonusTypeEvent takes integer bonus, code c returns nothing
    -> Register code to run when a specific unit bonus is modified
    -> Example: RegisterBonusTypeEvent(BONUS_DAMAGE, function YourFunction)

function GetBonusUnit takes nothing returns unit
    -> Call this function to get the bonus event unit

function GetBonusType takes nothing returns integer
    -> Call this function to get the bonus event type

function SetBonusType takes integer bonus returns nothing
    -> Call this function to set the bonus event type

function GetBonusAmount takes nothing returns real
    -> Call this function to get the bonus event amount

function SetBonusAmount takes real amount returns nothing
    -> Call this function to set the bonus event amount
Lua:
function GetUnitBonus(unit, type)
    -> Returns the specified bonus amount for the unit
    -> Example: set amount = GetUnitBonus(GetTriggerUnit(), BONUS_AGILITY)

function SetUnitBonus(unit, type, value)
    -> Set the specified bonus type to amount for the unit
    -> Example: call SetUnitBonus(GetTriggerUnit(), BONUS_DAMAGE, 100)

function RemoveUnitBonus(unit, type)
    -> Removes the Specified bonus type from unit
    -> Example: call RemoveUnitBonus(GetTriggerUnit(), BONUS_AGILITY)

function AddUnitBonus(unit, type, value)
    -> Add the specified amount for the specified bonus tyte for unit
    -> Example: call AddUnitBonus(GetTriggerUnit(), BONUS_DAMAGE, 100)

function AddUnitBonusTimed(unit, type, amount, duration)
    -> Add the specified amount for the specified bonus type for unit for a duration
    -> Example: call AddUnitBonusTimed(GetTriggerUnit(), BONUS_ARMOR, 13, 10.5)

function LinkBonusToBuff(unit, type, amount, buff)
    -> Links the bonus amount specified to a buff or ability. As long as the unit has the buff or
    -> the ability represented by the parameter buffId the bonus is not removed.
    -> Example: call LinkBonusToBuff(GetTriggerUnit(), BONUS_ARMOR, 10, 'B000')

function LinkBonusToItem(unit, type, amount, item)
    -> Links the bonus amount specified to an item. As long as the unit has that item the bonus is not removed.
    -> Note that it will work for items with the same id, because it takes as parameter the item object.
    -> Example: call LinkBonusToItem(GetManipulatingUnit(), BONUS_ARMOR, 10, GetManipulatedItem())

function UnitCopyBonuses(source, target)
    -> Copy the source unit bonuses using the Add functionality to the target unit
    -> Example: call UnitCopyBonuses(GetTriggerUnit(), GetSummonedUnit())

function UnitMirrorBonuses(source, target)
    -> Copy the source unit bonuses using the Set functionality to the target unit
    -> Example: call UnitMirrorBonuses(GetTriggerUnit(), GetSummonedUnit())

function RegisterBonusEvent(code)
    -> Register code to run when any unit bonus is modified
    -> Example: RegisterBonusEvent(function() YourFunctionc end)

function RegisterBonusTypeEvent(type, code)
    -> Register code to run when a specific unit bonus is modified
    -> Example: RegisterBonusTypeEvent(BONUS_DAMAGE, function() YourFunction end)

function GetBonusUnit()
    -> Call this function to get the bonus event unit

function GetBonusType()
    -> Call this function to get the bonus event type

function SetBonusType(type)
    -> Call this function to set the bonus event type

function GetBonusAmount()
    -> Call this function to get the bonus event amount

function SetBonusAmount(real)
    -> Call this function to set the bonus event amount
  • BONUS_DAMAGE
  • BONUS_ARMOR
  • BONUS_AGILITY
  • BONUS_STRENGTH
  • BONUS_INTELLIGENCE
  • BONUS_HEALTH
  • BONUS_MANA
  • BONUS_MOVEMENT_SPEED
  • BONUS_SIGHT_RANGE
  • Real Value Bonusses
  • BONUS_HEALTH_REGEN
  • BONUS_MANA_REGEN
  • BONUS_ATTACK_SPEED
  • BONUS_MAGIC_RESISTANCE
  • BONUS_EVASION_CHANCE
  • BONUS_CRITICAL_CHANCE
  • BONUS_CRITICAL_DAMAGE
  • BONUS_LIFE_STEAL
  • BONUS_DAMAGE
  • BONUS_ARMOR
  • BONUS_AGILITY
  • BONUS_STRENGTH
  • BONUS_INTELLIGENCE
  • BONUS_HEALTH
  • BONUS_MANA
  • BONUS_MOVEMENT_SPEED
  • BONUS_SIGHT_RANGE
  • Real Value Bonusses
  • BONUS_HEALTH_REGEN
  • BONUS_MANA_REGEN
  • BONUS_ATTACK_SPEED
  • BONUS_MAGIC_RESISTANCE
  • BONUS_EVASION_CHANCE
  • BONUS_MISS_CHANCE
  • BONUS_CRITICAL_CHANCE
  • BONUS_CRITICAL_DAMAGE
  • BONUS_SPELL_POWER_FLAT
  • BONUS_SPELL_POWER_PERCENT
  • BONUS_LIFE_STEAL
  • BONUS_SPELL_VAMP
  • BONUS_COOLDOWN_REDUCTION
  • BONUS_COOLDOWN_REDUCTION_FLAT
  • BONUS_COOLDOWN_OFFSET
  • BONUS_TENACITY
  • BONUS_TENACITY_FLAT
  • BONUS_TENACITY_OFFSET

(v1.0)
  • Submission
(v1.1)
  • Updated the code to use BlzSetUnitMaxHP() and BlzSetUnitMaxMana() in order to make Bonus_Health and Bonus_Mana work properly.
(v1.2)
  • Implemented the ability to link a bonus amount to a buff or ability as per requested by @The_Silent . Refactored the code and added a new example of this new functionality in the test map.
(v1.3)
  • FIxed a bug on AddUnitBonusExTimed()
(v1.4)
  • Normalized the AMOUNT input parameter to Integer instead of real to fix a type conversion problem when converting real to integer for abilities which field value is a integer value.
(v1.5)
  • Updated the system to respect integer fields bounds when adding to existing bonus (max 2147483647 and min -2147483648).
  • It's still the users job to pass the correct amount, the system will only handle addtions and subtractions that overflow/underflow.
(v1.6)
  • Split NewBonus into 2 libraries
    • NewBonus contains the core system to set / remove / add bonus types
    • NewBonusUtils contains extra functionalities such as timed and linked bonuses
  • Redesigned timed and linked bonuses to improve performance.
  • New utility functions AddUnitBonusTimed(), LinkBonusToBuff(), LinkBonusToItem()
  • Renamed Constans to upper case to be more visible.
  • Updated test map: included examples for the 3 new utility functions.
(v1.7)
  • Fixed a bug when Adding Health/Mana bonus not keeping the unit Health/Mana Percentage
  • Added the funcitons: They manipuilate real bonuses values correctly.
    • GetUnitBonusReal()
    • SetUnitBonusReal()
    • RemoveUnitBonusReal()
    • AddUnitBonusReal()
  • Refactored the LinkBonusToItem() to use the On Drop event instead of a periodic timer to check the link
  • Included an Expanded version of NewBonus and NewBonusUtils that take advangtage of the Damage Inteface System and Cooldown Reduction System
  • Renamed 4 bonus types for better readability.
  • Removed the "Ex" from the end of the API functions
(v1.8)
  • 2 new bonus types:
    • Sight Range
    • Magic Resistence (real)
  • 2 new functionalities in the NewBonusUtils (See API for usage): Thx to SinisterLuffy for the idea
    • function UnitCopyBonuses takes unit source, unit target returns nothing
    • function UnitMirrorBonuses takes unit source, unit target returns nothing
(v1.9)
  • Correction of a minor spelling error.
(v2.0)
  • Fixed a minor syntax error for the non extended Utils library
(v2.1)
  • System ported to LUA
  • 4 new bonus types for the non-Extended version of the system
    • Evasion Chance
    • Critical Strike Chance
    • Critical Strike Damage
    • Life Steal
(v2.2)
  • Removed the functions GetUnitBonusReal, SetUnitBonusReal, AddUnitBonusReal and RemoveUnitBonusReal
  • Now the functions GetUnitBonus, SetUnitBonus, AddUnitBonus and RemoveUnitBonus handles both real and integer bonus types correctly
  • Fix a minor bug in the NewBonusUtils Library
(v2.3)
  • Support for Bonus Events!!
  • Merged the normal and extended version into one library. (You can control which version is enabled by setting the new EXTENDED constant in the global section)
  • Code Cleaning and formatting.
(v2.4)
  • Fixed a bug in bonus event evaluation
  • 3 new bonus types included from the new Tenacity system
    • BONUS_TENACITY,
    • BONUS_TENACITY_FLAT
    • BONUS_TENACITY_OFFSET


For a quick import of the abilities use the editor Object Data.
For those with problems to open the map because of Reforged 1.32 patch, please see this
Contents

NewBonus (Map)

New Bonus (Map)

Reviews
MyPad
Considering the test map alone, I would approve this system. However, certain things addressed in the Code section of the review would need to be resolved before approval. Hence, this has been moved to Awaiting Update.
Level 12
Joined
May 16, 2020
Messages
660
Hi Chopinski, not sure if it's a bug or an error on my side, but the BONUS_SIGHT_RANGE does not reverse with "call RemoveUnitBonus".

See the second trigger. There it should restore the original sight radius, but it doesn't happen:

  • Dark Ascension
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dark Ascension
    • Actions
      • Set VariableSet DarkAscension_Caster = (Triggering unit)
      • Set VariableSet DarkAscension_DamageBonus = (50 x (Level of Dark Ascension for DarkAscension_Caster))
      • Set VariableSet DarkAscension_PlayerGroup = (All enemies of (Owner of DarkAscension_Caster).)
      • Custom script: set udg_DarkAscension_GroupEnemies = CreateGroup()
      • -------- ADD DAMAGE --------
      • Custom script: call SetUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
      • -------- DENY VISION --------
      • Player Group - Make DarkAscension_PlayerGroup treat DarkAscension_PlayerGroup as an Ally
      • -------- REDUCE VISION --------
      • Player Group - Pick every player in DarkAscension_PlayerGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_GroupEnemies = (Units owned by (Picked player).)
          • Unit Group - Pick every unit in DarkAscension_GroupEnemies and do (Actions)
            • Loop - Actions
              • Set VariableSet DarkAscension_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DarkAscension_TempUnit is alive) Equal to True
                  • (DarkAscension_TempUnit is A structure) Equal to False
                • Then - Actions
                  • Set VariableSet DarkAscension_SightReduction = -250
                  • Custom script: call SetUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction)
                • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Dark Ascension Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Dark Ascension Timer <gen>
          • Countdown Timer - Start DarkAscension_Timer as a One-shot timer that will expire in 10.00 seconds
        • Else - Actions

  • Dark Ascension Timer
    • Events
      • Time - DarkAscension_Timer expires
    • Conditions
    • Actions
      • -------- RESET DAMAGE --------
      • Custom script: call RemoveUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE)
      • -------- RESTORE VISION --------
      • Player Group - Make DarkAscension_PlayerGroup treat DarkAscension_PlayerGroup as an Ally with shared vision
      • Unit Group - Pick every unit in DarkAscension_GroupEnemies and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_TempUnit = (Picked unit)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
      • -------- --------
      • Custom script: call DestroyGroup (udg_DarkAscension_GroupEnemies)
      • Countdown Timer - Pause DarkAscension_Timer
      • Game - Display to (All players) the text: Dark Ascension OFF
      • Trigger - Turn off (This trigger)
 
Level 20
Joined
May 16, 2012
Messages
635
Hi Chopinski, not sure if it's a bug or an error on my side, but the BONUS_SIGHT_RANGE does not reverse with "call RemoveUnitBonus".

See the second trigger. There it should restore the original sight radius, but it doesn't happen:

  • Dark Ascension
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dark Ascension
    • Actions
      • Set VariableSet DarkAscension_Caster = (Triggering unit)
      • Set VariableSet DarkAscension_DamageBonus = (50 x (Level of Dark Ascension for DarkAscension_Caster))
      • Set VariableSet DarkAscension_PlayerGroup = (All enemies of (Owner of DarkAscension_Caster).)
      • Custom script: set udg_DarkAscension_GroupEnemies = CreateGroup()
      • -------- ADD DAMAGE --------
      • Custom script: call SetUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
      • -------- DENY VISION --------
      • Player Group - Make DarkAscension_PlayerGroup treat DarkAscension_PlayerGroup as an Ally
      • -------- REDUCE VISION --------
      • Player Group - Pick every player in DarkAscension_PlayerGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_GroupEnemies = (Units owned by (Picked player).)
          • Unit Group - Pick every unit in DarkAscension_GroupEnemies and do (Actions)
            • Loop - Actions
              • Set VariableSet DarkAscension_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DarkAscension_TempUnit is alive) Equal to True
                  • (DarkAscension_TempUnit is A structure) Equal to False
                • Then - Actions
                  • Set VariableSet DarkAscension_SightReduction = -250
                  • Custom script: call SetUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction)
                • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Dark Ascension Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Dark Ascension Timer <gen>
          • Countdown Timer - Start DarkAscension_Timer as a One-shot timer that will expire in 10.00 seconds
        • Else - Actions

  • Dark Ascension Timer
    • Events
      • Time - DarkAscension_Timer expires
    • Conditions
    • Actions
      • -------- RESET DAMAGE --------
      • Custom script: call RemoveUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE)
      • -------- RESTORE VISION --------
      • Player Group - Make DarkAscension_PlayerGroup treat DarkAscension_PlayerGroup as an Ally with shared vision
      • Unit Group - Pick every unit in DarkAscension_GroupEnemies and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_TempUnit = (Picked unit)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
      • -------- --------
      • Custom script: call DestroyGroup (udg_DarkAscension_GroupEnemies)
      • Countdown Timer - Pause DarkAscension_Timer
      • Game - Display to (All players) the text: Dark Ascension OFF
      • Trigger - Turn off (This trigger)

i'll take a look at it, thx.
 
Level 20
Joined
May 16, 2012
Messages
635
Hi Chopinski, not sure if it's a bug or an error on my side, but the BONUS_SIGHT_RANGE does not reverse with "call RemoveUnitBonus".

See the second trigger. There it should restore the original sight radius, but it doesn't happen:

  • Dark Ascension
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dark Ascension
    • Actions
      • Set VariableSet DarkAscension_Caster = (Triggering unit)
      • Set VariableSet DarkAscension_DamageBonus = (50 x (Level of Dark Ascension for DarkAscension_Caster))
      • Set VariableSet DarkAscension_PlayerGroup = (All enemies of (Owner of DarkAscension_Caster).)
      • Custom script: set udg_DarkAscension_GroupEnemies = CreateGroup()
      • -------- ADD DAMAGE --------
      • Custom script: call SetUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
      • -------- DENY VISION --------
      • Player Group - Make DarkAscension_PlayerGroup treat DarkAscension_PlayerGroup as an Ally
      • -------- REDUCE VISION --------
      • Player Group - Pick every player in DarkAscension_PlayerGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_GroupEnemies = (Units owned by (Picked player).)
          • Unit Group - Pick every unit in DarkAscension_GroupEnemies and do (Actions)
            • Loop - Actions
              • Set VariableSet DarkAscension_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DarkAscension_TempUnit is alive) Equal to True
                  • (DarkAscension_TempUnit is A structure) Equal to False
                • Then - Actions
                  • Set VariableSet DarkAscension_SightReduction = -250
                  • Custom script: call SetUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction)
                • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Dark Ascension Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Dark Ascension Timer <gen>
          • Countdown Timer - Start DarkAscension_Timer as a One-shot timer that will expire in 10.00 seconds
        • Else - Actions

  • Dark Ascension Timer
    • Events
      • Time - DarkAscension_Timer expires
    • Conditions
    • Actions
      • -------- RESET DAMAGE --------
      • Custom script: call RemoveUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE)
      • -------- RESTORE VISION --------
      • Player Group - Make DarkAscension_PlayerGroup treat DarkAscension_PlayerGroup as an Ally with shared vision
      • Unit Group - Pick every unit in DarkAscension_GroupEnemies and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_TempUnit = (Picked unit)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
      • -------- --------
      • Custom script: call DestroyGroup (udg_DarkAscension_GroupEnemies)
      • Countdown Timer - Pause DarkAscension_Timer
      • Game - Display to (All players) the text: Dark Ascension OFF
      • Trigger - Turn off (This trigger)

@Ugabunda I've tested what you reported and there's nothing wrong with the system, so it must be something on your trigger. I noticed that you are using the SetUnitBonus() function, which overwrites previous amounts with the new one, you might want to use AddUnitBonus() for that matter maybe. You can test the Sight Range bonus on the test map, it takes a 1 or 2 to update but it works as intended. Check if the unit getting it's bonus reduced is the correct one as well.
 
Level 12
Joined
May 16, 2020
Messages
660
Mmm was just able to test it. A few things:
  1. You were right, for some reason not the right units were selected to remove the sight bonus. However:
  2. When I select the right units, the bonus removal still does not work. I'm using now:
  • call AddUnitBonus(udg...
and then

  • call RemoveUnitBonus(udg...
FYI: In your test map the Sight Range bonus does not work either (+100 does nothing, and removing does nothing)

***

Edit: I also tested it with damage, and there the bonus damage gets removed correctly. So I really think it's only Sight Range:

  • Dark Ascension
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dark Ascension
    • Actions
      • Game - Display to (All players) the text: Dark Ascension ON
      • Set VariableSet DarkAscension_Caster = (Triggering unit)
      • Set VariableSet DarkAscension_DamageBonus = (50 x (Level of Dark Ascension for DarkAscension_Caster))
      • Set VariableSet DarkAscension_GroupPlayer = (All enemies of (Owner of DarkAscension_Caster).)
      • Set VariableSet DarkAscension_SightReduction = -350
      • Custom script: set udg_DarkAscension_GroupTemp = CreateGroup()
      • -------- ADD DAMAGE --------
      • Custom script: call SetUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
      • -------- DENY VISION --------
      • Player Group - Make DarkAscension_GroupPlayer treat DarkAscension_GroupPlayer as an Ally
      • -------- REDUCE VISION --------
      • Player Group - Pick every player in DarkAscension_GroupPlayer and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_GroupTemp = (Units owned by (Picked player).)
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in DarkAscension_GroupTemp and do (Actions)
            • Loop - Actions
              • Set VariableSet DarkAscension_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DarkAscension_TempUnit is alive) Equal to True
                  • (DarkAscension_TempUnit is A structure) Equal to False
                • Then - Actions
                  • Custom script: call AddUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction)
                  • Custom script: call AddUnitBonus(udg_DarkAscension_TempUnit, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
                  • Unit Group - Add DarkAscension_TempUnit to DarkAscension_GroupVision
                • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Dark Ascension Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Dark Ascension Timer <gen>
          • Countdown Timer - Start DarkAscension_Timer as a One-shot timer that will expire in 10.00 seconds
        • Else - Actions

  • Dark Ascension Timer
    • Events
      • Time - DarkAscension_Timer expires
    • Conditions
    • Actions
      • -------- RESET DAMAGE --------
      • Custom script: call RemoveUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE)
      • -------- RESTORE SHARED VISION --------
      • Player Group - Make DarkAscension_GroupPlayer treat DarkAscension_GroupPlayer as an Ally with shared vision
      • Custom script: call DestroyForce (udg_DarkAscension_GroupPlayer)
      • -------- RESTORE VISION RANGE --------
      • Unit Group - Pick every unit in DarkAscension_GroupVision and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_TempUnit = (Picked unit)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_DAMAGE)
      • Custom script: call DestroyGroup (udg_DarkAscension_GroupVision)
      • -------- --------
      • Countdown Timer - Pause DarkAscension_Timer
      • Game - Display to (All players) the text: Dark Ascension OFF
      • Trigger - Turn off (This trigger)
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
Mmm was just able to test it. A few things:
  1. You were right, for some reason not the right units were selected to remove the sight bonus. However:
  2. When I select the right units, the bonus removal still does not work. I'm using now:
  • call AddUnitBonus(udg...
and then

  • call RemoveUnitBonus(udg...
FYI: In your test map the Sight Range bonus does not work either (+100 does nothing, and removing does nothing)

It does work, i will send a GIF showing it working once i have a little more time. Sight Range takes 1 or 2 seconds to take effect and it works in tiles apparently, so if you bonus is to small it might not produce a visible change.
 
Level 12
Joined
May 16, 2020
Messages
660
It does work, i will send a GIF showing it working once i have a little more time. Sight Range takes 1 or 2 seconds to take effect and it works in tiles apparently, so if you bonus is to small it might not produce a visible change.

Just edited my previous comment. So damage is added and removed correctly. But not Sight Range. And yes, the "removal" takes 2 seconds to take full effect. But the "restoration" does not happen at all (I chose -350 Sight Range).
 

NightKnight

Hosted Project RUID
Level 14
Joined
Sep 3, 2014
Messages
222
Hey man! Epic work in this great system! I got a request tho. So in my map, I want to make a crafting system, which will produce the same item-type but with different qualities, so different stats. I wondered if you could make possible that i link stats to a specific item, not item-type, and link it to the item not the unit, so as to work automatically when changing the unit carrying it
 
Level 20
Joined
May 16, 2012
Messages
635
Hey man! Epic work in this great system! I got a request tho. So in my map, I want to make a crafting system, which will produce the same item-type but with different qualities, so different stats. I wondered if you could make possible that i link stats to a specific item, not item-type, and link it to the item not the unit, so as to work automatically when changing the unit carrying it

LinkBonusToItem already uses an item object as a parameter, so what you want to do is already possible with just that, you just need to use conditions when your unit acquire an item to figure out what bonus it will get. The system requires no change for you to be able to do that.
 
Level 12
Joined
May 16, 2020
Messages
660
Hi Chopinski, you were right about the sight range. In your test map it does work. I didn't realize the change because 100 is too small of a change. But if I go down to -1400 and "null" the bonus, sight is restored indeed.

But in my map I'm still unable to restore sight for some reason, even though I pick the same units and use:
  • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
Can you please check the trigger? I really don't know what else could be wrong...
  • Dark Ascension
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dark Ascension
    • Actions
      • Game - Display to (All players) the text: Dark Ascension ON
      • Set VariableSet DarkAscension_Caster = (Triggering unit)
      • Set VariableSet DarkAscension_DamageBonus = (50 x (Level of Dark Ascension for DarkAscension_Caster))
      • Set VariableSet DarkAscension_GroupPlayer = (All enemies of (Owner of DarkAscension_Caster).)
      • Set VariableSet DarkAscension_SightReduction = -350
      • Custom script: set udg_DarkAscension_GroupTemp = CreateGroup()
      • -------- ADD DAMAGE --------
      • Custom script: call SetUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
      • -------- DENY VISION --------
      • Player Group - Make DarkAscension_GroupPlayer treat DarkAscension_GroupPlayer as an Ally
      • -------- REDUCE VISION --------
      • Player Group - Pick every player in DarkAscension_GroupPlayer and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_GroupTemp = (Units owned by (Picked player).)
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in DarkAscension_GroupTemp and do (Actions)
            • Loop - Actions
              • Set VariableSet DarkAscension_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DarkAscension_TempUnit is alive) Equal to True
                  • (DarkAscension_TempUnit is A structure) Equal to False
                  • (Owner of DarkAscension_TempUnit) Not equal to Neutral Hostile
                • Then - Actions
                  • Custom script: call AddUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction)
                  • Custom script: call AddUnitBonus(udg_DarkAscension_TempUnit, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
                  • Unit Group - Add DarkAscension_TempUnit to DarkAscension_GroupVision
                • Else - Actions
      • Game - Display to (All players) the text: (String((Number of units in DarkAscension_GroupVision)))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Dark Ascension Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Dark Ascension Timer <gen>
          • Countdown Timer - Start DarkAscension_Timer as a One-shot timer that will expire in 10.00 seconds
        • Else - Actions
  • Dark Ascension Timer
    • Events
      • Time - DarkAscension_Timer expires
    • Conditions
    • Actions
      • -------- RESET DAMAGE --------
      • Custom script: call RemoveUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE)
      • -------- RESTORE SHARED VISION --------
      • Player Group - Make DarkAscension_GroupPlayer treat DarkAscension_GroupPlayer as an Ally with shared vision
      • Custom script: call DestroyForce (udg_DarkAscension_GroupPlayer)
      • -------- RESTORE VISION RANGE --------
      • Game - Display to (All players) the text: (String((Number of units in DarkAscension_GroupVision)))
      • Unit Group - Pick every unit in DarkAscension_GroupVision and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_TempUnit = (Picked unit)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_DAMAGE)
      • Custom script: call DestroyGroup (udg_DarkAscension_GroupVision)
      • -------- --------
      • Countdown Timer - Pause DarkAscension_Timer
      • Game - Display to (All players) the text: Dark Ascension OFF
      • Trigger - Turn off (This trigger)
 
Level 20
Joined
May 16, 2012
Messages
635
Hi Chopinski, you were right about the sight range. In your test map it does work. I didn't realize the change because 100 is too small of a change. But if I go down to -1400 and "null" the bonus, sight is restored indeed.

But in my map I'm still unable to restore sight for some reason, even though I pick the same units and use:
  • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
Can you please check the trigger? I really don't know what else could be wrong...
  • Dark Ascension
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dark Ascension
    • Actions
      • Game - Display to (All players) the text: Dark Ascension ON
      • Set VariableSet DarkAscension_Caster = (Triggering unit)
      • Set VariableSet DarkAscension_DamageBonus = (50 x (Level of Dark Ascension for DarkAscension_Caster))
      • Set VariableSet DarkAscension_GroupPlayer = (All enemies of (Owner of DarkAscension_Caster).)
      • Set VariableSet DarkAscension_SightReduction = -350
      • Custom script: set udg_DarkAscension_GroupTemp = CreateGroup()
      • -------- ADD DAMAGE --------
      • Custom script: call SetUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
      • -------- DENY VISION --------
      • Player Group - Make DarkAscension_GroupPlayer treat DarkAscension_GroupPlayer as an Ally
      • -------- REDUCE VISION --------
      • Player Group - Pick every player in DarkAscension_GroupPlayer and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_GroupTemp = (Units owned by (Picked player).)
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in DarkAscension_GroupTemp and do (Actions)
            • Loop - Actions
              • Set VariableSet DarkAscension_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DarkAscension_TempUnit is alive) Equal to True
                  • (DarkAscension_TempUnit is A structure) Equal to False
                  • (Owner of DarkAscension_TempUnit) Not equal to Neutral Hostile
                • Then - Actions
                  • Custom script: call AddUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction)
                  • Custom script: call AddUnitBonus(udg_DarkAscension_TempUnit, BONUS_DAMAGE, udg_DarkAscension_DamageBonus)
                  • Unit Group - Add DarkAscension_TempUnit to DarkAscension_GroupVision
                • Else - Actions
      • Game - Display to (All players) the text: (String((Number of units in DarkAscension_GroupVision)))
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Dark Ascension Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Dark Ascension Timer <gen>
          • Countdown Timer - Start DarkAscension_Timer as a One-shot timer that will expire in 10.00 seconds
        • Else - Actions
  • Dark Ascension Timer
    • Events
      • Time - DarkAscension_Timer expires
    • Conditions
    • Actions
      • -------- RESET DAMAGE --------
      • Custom script: call RemoveUnitBonus(udg_DarkAscension_Caster, BONUS_DAMAGE)
      • -------- RESTORE SHARED VISION --------
      • Player Group - Make DarkAscension_GroupPlayer treat DarkAscension_GroupPlayer as an Ally with shared vision
      • Custom script: call DestroyForce (udg_DarkAscension_GroupPlayer)
      • -------- RESTORE VISION RANGE --------
      • Game - Display to (All players) the text: (String((Number of units in DarkAscension_GroupVision)))
      • Unit Group - Pick every unit in DarkAscension_GroupVision and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_TempUnit = (Picked unit)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
          • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_DAMAGE)
      • Custom script: call DestroyGroup (udg_DarkAscension_GroupVision)
      • -------- --------
      • Countdown Timer - Pause DarkAscension_Timer
      • Game - Display to (All players) the text: Dark Ascension OFF
      • Trigger - Turn off (This trigger)

I haven't read it yet, but tell me what you want your ability to do. Post it's description.
 
Level 12
Joined
May 16, 2020
Messages
660
Sure, this is what it should do:
  • The ability is based on Moonstone ability to summon an artificial night
  • Upon cast, the caster gets 50*ability level bonus damage for the duration of the ability
  • Upon cast, all enemy units lose the shared vision gained from allies (= you can only see your own units) and have reduced sight radius of -350 for the duration of the ability
 
Level 20
Joined
May 16, 2012
Messages
635
Sure, this is what it should do:
  • The ability is based on Moonstone ability to summon an artificial night
  • Upon cast, the caster gets 50*ability level bonus damage for the duration of the ability
  • Upon cast, all enemy units lose the shared vision gained from allies (= you can only see your own units) and have reduced sight radius of -350 for the duration of the ability

Ok, Do you wish for the debuff to be dispellable?
 
Level 12
Joined
May 16, 2020
Messages
660
Ok, Do you wish for the debuff to be dispellable?

For the caster? no, should not be dispellable. If somehow possible, he should only retain the bonus damage as long as the the artificial night remains though.

For the units affected by vision impairment I wouldn't add a debuff. Probably adds too much lag when >100 units get added a debuff at the same time...
 
Level 20
Joined
May 16, 2012
Messages
635
For the caster? no, should not be dispellable. If somehow possible, he should only retain the bonus damage as long as the the artificial night remains though.

For the units affected by vision impairment I wouldn't add a debuff. Probably adds too much lag when >100 units get added a debuff at the same time...

That depends on how you do it, but yeah, since you are using GUI. You should try to learn JASS, it would make your modding life so much easier. Later i will try to solve it, im at work right now.
 
Level 12
Joined
May 16, 2020
Messages
660
Hey Chopinski, I experimented some more, but this function doesn't seem to work for Sight_Range (it does work for damage though):
  • Custom script: call RemoveUnitBonus(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE)
But I saw that I can use a "timed" version of Sight Range:
  • Custom script: call AddUnitBonusTimed(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction, udg_DarkAscension_Duration)
With this it works! And I have a version of the spell which works now (not MUI, but it's functional):

  • Dark Ascension Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet DarkAscension_Player[1] = Player 1 (Red)
      • Set VariableSet DarkAscension_Player[2] = Player 2 (Blue)
      • Set VariableSet DarkAscension_Player[3] = Player 3 (Teal)
      • Set VariableSet DarkAscension_Player[4] = Player 4 (Purple)
      • Set VariableSet DarkAscension_Player[5] = Player 5 (Yellow)
      • Set VariableSet DarkAscension_Player[6] = Player 6 (Orange)
      • Set VariableSet DarkAscension_Player[7] = Player 7 (Green)
      • Set VariableSet DarkAscension_Player[8] = Player 8 (Pink)
      • Set VariableSet DarkAscension_Player[9] = Player 9 (Gray)
      • Set VariableSet DarkAscension_Player[10] = Player 10 (Light Blue)
      • Set VariableSet DarkAscension_Player[11] = Player 11 (Dark Green)
      • Set VariableSet DarkAscension_Player[12] = Player 12 (Brown)
      • Set VariableSet DarkAscension_Duration = 30.00
      • Set VariableSet DarkAscension_SightReduction = -350
  • Dark Ascension
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Dark Ascension
    • Actions
      • Set VariableSet DarkAscension_Caster = (Triggering unit)
      • Set VariableSet DarkAscension_DamageBonus = (50 x (Level of Dark Ascension for DarkAscension_Caster))
      • Set VariableSet DarkAscension_GroupPlayer = (All players matching ((((Matching player) is an enemy of (Owner of DarkAscension_Caster).) Equal to True) and ((Matching player) Not equal to Player 13 (Maroon))).)
      • Custom script: set udg_DarkAscension_GroupTemp = CreateGroup()
      • -------- ADD DAMAGE --------
      • Custom script: call AddUnitBonusTimed(udg_DarkAscension_Caster, BONUS_DAMAGE, udg_DarkAscension_DamageBonus, udg_DarkAscension_Duration)
      • -------- DENY VISION --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DarkAscension_Caster belongs to an ally of Player 1 (Red).) Equal to True
        • Then - Actions
          • For each (Integer DarkAscension_Integer1) from 7 to 12, do (Actions)
            • Loop - Actions
              • For each (Integer DarkAscension_Integer2) from 7 to 12, do (Actions)
                • Loop - Actions
                  • Player - For DarkAscension_Player[DarkAscension_Integer1], turn Shared vision Off toward DarkAscension_Player[DarkAscension_Integer2]
        • Else - Actions
          • For each (Integer DarkAscension_Integer1) from 1 to 6, do (Actions)
            • Loop - Actions
              • For each (Integer DarkAscension_Integer2) from 1 to 6, do (Actions)
                • Loop - Actions
                  • Player - For DarkAscension_Player[DarkAscension_Integer1], turn Shared vision Off toward DarkAscension_Player[DarkAscension_Integer2]
      • -------- REDUCE VISION --------
      • Player Group - Pick every player in DarkAscension_GroupPlayer and do (Actions)
        • Loop - Actions
          • Set VariableSet DarkAscension_GroupTemp = (Units owned by (Picked player).)
          • Custom script: set bj_wantDestroyGroup = true
          • Unit Group - Pick every unit in DarkAscension_GroupTemp and do (Actions)
            • Loop - Actions
              • Set VariableSet DarkAscension_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DarkAscension_TempUnit is alive) Equal to True
                  • (DarkAscension_TempUnit is A structure) Equal to False
                  • (Owner of DarkAscension_TempUnit) Not equal to Player 1 (Red)
                  • (Owner of DarkAscension_TempUnit) Not equal to Player 7 (Green)
                • Then - Actions
                  • Custom script: call AddUnitBonusTimed(udg_DarkAscension_TempUnit, BONUS_SIGHT_RANGE, udg_DarkAscension_SightReduction, udg_DarkAscension_Duration)
                • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Dark Ascension Timer <gen> is on) Equal to False
        • Then - Actions
          • Trigger - Turn on Dark Ascension Timer <gen>
          • Countdown Timer - Start DarkAscension_Timer as a One-shot timer that will expire in DarkAscension_Duration seconds
        • Else - Actions
  • Dark Ascension Timer
    • Events
      • Time - DarkAscension_Timer expires
    • Conditions
    • Actions
      • -------- RESTORE SHARED VISION --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (DarkAscension_Caster belongs to an ally of Player 1 (Red).) Equal to True
        • Then - Actions
          • For each (Integer DarkAscension_Integer1) from 7 to 12, do (Actions)
            • Loop - Actions
              • For each (Integer DarkAscension_Integer2) from 7 to 12, do (Actions)
                • Loop - Actions
                  • Player - For DarkAscension_Player[DarkAscension_Integer1], turn Shared vision Off toward DarkAscension_Player[DarkAscension_Integer2]
        • Else - Actions
          • For each (Integer DarkAscension_Integer1) from 1 to 6, do (Actions)
            • Loop - Actions
              • For each (Integer DarkAscension_Integer2) from 1 to 6, do (Actions)
                • Loop - Actions
                  • Player - For DarkAscension_Player[DarkAscension_Integer1], turn Shared vision On toward DarkAscension_Player[DarkAscension_Integer2]
      • Custom script: call DestroyForce (udg_DarkAscension_GroupPlayer)
      • -------- --------
      • Countdown Timer - Pause DarkAscension_Timer
      • Trigger - Turn off (This trigger)

What I'm failing to understand is why the "call RemoveUnitBonus" works for damage, but not for Sight_Range?

Edit: Regarding JASS, I'm trying to pick up some code here and there. But I still fail to understand how people can possibly know all the text by heart. For some things I simply don't know where to even start.
 

Uncle

Warcraft Moderator
Level 63
Joined
Aug 10, 2018
Messages
6,455
@Ugabunda
Writing code in wc3 is not much different than creating triggers in GUI, things are named accordingly and you have tools that mimic GUI's "Search For Text" feature.

Plus you wouldn't write your JASS in the World Editor, you would use some other tool like Visual Studio Code, which will have intellisense support and will be an overall MUCH better experience.

Intellisense is what relieves you of having to memorize everything. So for example, when you type the word "Create" a dropdown menu appears with every single function related to creating something. CreateUnit, CreateItem, CreateGroup, CreateDestructable, etc... and after selecting a function you will have instructions as to what to type next to get the function to work. See my attached picture "example".

It's honestly much easier and 100x faster than GUI once you get the hang of it.

With all that being said, I feel obligated to recommend learning Lua over JASS, because it's just nicer in every way. The only reason JASS is worth using as far as I'm aware is because it's been around all this time and has many systems that take advantage of it (including this great one). But if all of these systems would be converted to Lua I wouldn't really see an argument that could be made to use JASS ever again. The only reason this is even a problem in the first place is because the Editor only supports one language at a time, JASS or Lua. Maps use JASS by default (you're using it in your map right now) so it's hard for people to make the conversion over to Lua. So I guess what I'm saying is... learn Jass, THEN Lua.
 

Attachments

  • example.png
    example.png
    42.2 KB · Views: 105
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
@Ugabunda I've recreated your ability based on your description. Haven't tested with the Set and Remove functionalities from new bonus, but they should work since both use the same base code as the Add. I've noticed that you were using the Set and Remove in a bad manner, maybe because you didn't understand than fully yet. The SetUnitBonus() will overwrite any previous bonus amount that the unit have for a given bonus type and RemoveUnitBonus simply calls the SetUnitBonus function but just using 0 as a parameter. The AddUnitBonus() will consider any previous Set/Add bonus that the unit have and add (or subtract if its negative) to it, so this should be the best function to use. Most of the time (if not all of it) you will want to use AddUnitBonus instead of Set and Remove to avoid making mistakes like that, at least until you fully understand what the system is doing.

Here are the triggers. AddUnitBonusTimed() is MUI by itself but the auxiliary variables that i used to make this might be overwritten with multiple casts, but i'm sure you can make it fully MUI by yourself.

  • Darkness
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Darkness
    • Actions
      • -------- Set Up --------
      • Set VariableSet Caster = (Triggering unit)
      • Set VariableSet Bonus = (50 x (Level of Darkness for Caster))
      • Set VariableSet Duration = (Ability: (Unit: Caster's Ability with Ability Code: Darkness )'s Real Level Field Duration - Normal ('adur'), of Level: ((Level of Darkness for Caster) - 1))
      • Set VariableSet Sight = -450
      • -------- Damage --------
      • Custom script: call AddUnitBonusTimed(udg_Caster, BONUS_DAMAGE, udg_Bonus, udg_Duration)
      • -------- Remove Allied Vision and Sight Range --------
      • For each (Integer A) from 1 to 24, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Player((Integer A))) is an enemy of (Owner of Caster).) Equal to True
            • Then - Actions
              • Set VariableSet Group = (Units owned by (Player((Integer A))).)
              • Unit Group - Pick every unit in Group and do (Actions)
                • Loop - Actions
                  • Set VariableSet Unit = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Unit is alive) Equal to True
                      • (Unit is A structure) Equal to False
                    • Then - Actions
                      • Custom script: call AddUnitBonusTimed(udg_Unit, BONUS_SIGHT_RANGE, udg_Sight, udg_Duration)
                    • Else - Actions
              • Custom script: call DestroyGroup(udg_Group)
            • Else - Actions
          • For each (Integer B) from 1 to 24, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Player((Integer A))) Not equal to (Player((Integer B)))
                  • ((Player((Integer A))) is an enemy of (Owner of Caster).) Equal to True
                • Then - Actions
                  • Player - For (Player((Integer A))), turn Shared vision Off toward (Player((Integer B)))
                • Else - Actions
      • -------- Reset Timer --------
      • Countdown Timer - Start Timer as a One-shot timer that will expire in Duration seconds
  • Reset
    • Events
      • Time - Timer expires
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 24, do (Actions)
        • Loop - Actions
          • For each (Integer B) from 1 to 24, do (Actions)
            • Loop - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Player((Integer A))) Not equal to (Player((Integer B)))
                  • ((Player((Integer A))) is an enemy of (Owner of Caster).) Equal to True
                • Then - Actions
                  • Player - For (Player((Integer A))), turn Shared vision On toward (Player((Integer B)))
                • Else - Actions

I also uploaded a test map so you ca see it working. To test it in game simply select the paladin unit and see the magic happening.
 

Attachments

  • SightRange.w3x
    93.4 KB · Views: 76
Level 12
Joined
May 16, 2020
Messages
660
Many thanks @Uncle and @chopinski !

This Intellisense explains a lot. I recently get more and more annoyed with GUI because it is so slow when creating triggers which should be easy (selecting 100x the same functions, creating ugly global variables, needing to click 10 times to add a small change in a variable...). So yeah, I'm soon at the breaking point of overcoming my laziness with checking out JASS more seriously.
 
Level 5
Joined
Dec 25, 2014
Messages
111
So.. i found a weird bug interaction with this system.
I wanna increase the armor of a unit that increase by some percentage of mana if they have a spesific buff by using the system api and another one that increase them by some percentage of strength using warcraft api. Like this :

Mana to Armor
  • Mana to Armor
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Set ArmorManaTempGroup = (Units in (Playable map area) matching ((Evaluate Condition <gen> conditions) Equal to True))
      • Unit Group - Pick every unit in ArmorManaTempGroup and do (Actions)
        • Loop - Actions
          • Set ArmorManaUnit = (Picked unit)
          • Set ArmorManaRealMana = (0.02 x (Max mana of ArmorManaUnit))
          • Custom script: call SetUnitBonus(udg_ArmorManaUnit, BONUS_ARMOR, R2I(udg_ArmorManaRealMana))
      • Custom script: call DestroyGroup(udg_ArmorManaTempGroup)

Str to armor
  • Strength to Armor
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Set ArmorSTRTempGroup = (Units in (Playable map area) matching (((Matching unit) is A Hero) Equal to True))
      • Unit Group - Pick every unit in ArmorSTRTempGroup and do (Actions)
        • Loop - Actions
          • Set ArmorSTRReal = (0.30 x (Real((Strength of (Picked unit) (Include bonuses)))))
          • Unit - Set Armor of (Picked unit) to ArmorSTRReal
      • Custom script: call DestroyGroup(udg_ArmorSTRTempGroup)

Each of them are working fine.
Except if you turn on both of them.
My unit's armor got decreased instead by the total amount of it gets from mana to armor value.
I really confused now. What am i do wrong here?
Here also the test map
 

Attachments

  • StatsCustomizer.w3x
    33.5 KB · Views: 66
Level 20
Joined
May 16, 2012
Messages
635
So.. i found a weird bug interaction with this system.
I wanna increase the armor of a unit that increase by some percentage of mana if they have a spesific buff by using the system api and another one that increase them by some percentage of strength using warcraft api. Like this :

Mana to Armor
  • Mana to Armor
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Set ArmorManaTempGroup = (Units in (Playable map area) matching ((Evaluate Condition <gen> conditions) Equal to True))
      • Unit Group - Pick every unit in ArmorManaTempGroup and do (Actions)
        • Loop - Actions
          • Set ArmorManaUnit = (Picked unit)
          • Set ArmorManaRealMana = (0.02 x (Max mana of ArmorManaUnit))
          • Custom script: call SetUnitBonus(udg_ArmorManaUnit, BONUS_ARMOR, R2I(udg_ArmorManaRealMana))
      • Custom script: call DestroyGroup(udg_ArmorManaTempGroup)

Str to armor
  • Strength to Armor
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Set ArmorSTRTempGroup = (Units in (Playable map area) matching (((Matching unit) is A Hero) Equal to True))
      • Unit Group - Pick every unit in ArmorSTRTempGroup and do (Actions)
        • Loop - Actions
          • Set ArmorSTRReal = (0.30 x (Real((Strength of (Picked unit) (Include bonuses)))))
          • Unit - Set Armor of (Picked unit) to ArmorSTRReal
      • Custom script: call DestroyGroup(udg_ArmorSTRTempGroup)

Each of them are working fine.
Except if you turn on both of them.
My unit's armor got decreased instead by the total amount of it gets from mana to armor value.
I really confused now. What am i do wrong here?
Here also the test map

It's not a bug. Your problem has nothing to do with the system but with how the SetArmor blizzard function works. That function takes in consideration the bonus (green value) armor amount, so when you set the armor amount of a unit that has a bonus value it compensates the White value to match the total amount, that's why you see a negative value when you learn your ability. To make it work how you want you have to make a few changes that you can see below. Basically you have to add to the amount that will be passed to the blizzard function the bonus amount that was set by this system. It's a weird behavior but that's how it works, that function does not take in consideration the white value only. I also fused the 2 triggers into one, so it's a bit more efficient and easier to read. Also on a side note I recommend you use the AddUnitBonusTimed function from my system instead of the SetUnitBonus. SetUnitBonus will overwrite any value previously set, so if at some point in some other trigger you change the unit armor the Set function will make that change almost impossible to recover.

  • Armor
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Group = (Units in (Playable map area) matching (((Matching unit) is A Hero) Equal to True))
      • Unit Group - Pick every unit in Group and do (Actions)
        • Loop - Actions
          • Set VariableSet Unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit has buff Brilliance Aura) Equal to True
            • Then - Actions
              • Set VariableSet ManaArmor = (0.02 x (Max mana of Unit))
              • Set VariableSet Armor = ((0.30 x (Real((Strength of Unit (Include bonuses))))) + ManaArmor)
              • Unit - Set Armor of Unit to Armor
              • Custom script: call AddUnitBonusTimed(udg_Unit, BONUS_ARMOR, udg_ManaArmor, 0.501)
            • Else - Actions
              • Set VariableSet Armor = (0.30 x (Real((Strength of Unit (Include bonuses)))))
              • Unit - Set Armor of Unit to Armor
      • Custom script: call DestroyGroup(udg_Group)
 

Attachments

  • StatsCustomizer.w3x
    32.8 KB · Views: 70
Level 5
Joined
Dec 25, 2014
Messages
111
It's not a bug. Your problem has nothing to do with the system but with how the SetArmor blizzard function works. That function takes in consideration the bonus (green value) armor amount, so when you set the armor amount of a unit that has a bonus value it compensates the White value to match the total amount, that's why you see a negative value when you learn your ability. To make it work how you want you have to make a few changes that you can see below. Basically you have to add to the amount that will be passed to the blizzard function the bonus amount that was set by this system. It's a weird behavior but that's how it works, that function does not take in consideration the white value only. I also fused the 2 triggers into one, so it's a bit more efficient and easier to read. Also on a side note I recommend you use the AddUnitBonusTimed function from my system instead of the SetUnitBonus. SetUnitBonus will overwrite any value previously set, so if at some point in some other trigger you change the unit armor the Set function will make that change almost impossible to recover.

  • Armor
    • Events
      • Time - Every 0.50 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Group = (Units in (Playable map area) matching (((Matching unit) is A Hero) Equal to True))
      • Unit Group - Pick every unit in Group and do (Actions)
        • Loop - Actions
          • Set VariableSet Unit = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit has buff Brilliance Aura) Equal to True
            • Then - Actions
              • Set VariableSet ManaArmor = (0.02 x (Max mana of Unit))
              • Set VariableSet Armor = ((0.30 x (Real((Strength of Unit (Include bonuses))))) + ManaArmor)
              • Unit - Set Armor of Unit to Armor
              • Custom script: call AddUnitBonusTimed(udg_Unit, BONUS_ARMOR, udg_ManaArmor, 0.501)
            • Else - Actions
              • Set VariableSet Armor = (0.30 x (Real((Strength of Unit (Include bonuses)))))
              • Unit - Set Armor of Unit to Armor
      • Custom script: call DestroyGroup(udg_Group)

Ah now i see how it is.
That is also applied to the other stats to, isn't it?

Anyway thanks for the explaination.
 
Just FYI: You can edit the demon hunter's evasion ability's evasion chance with blzsetabilityreallevelfield thus you don't need to use damage interface to make evasion. Also implementing evasion this way prevents secondary effects from occurring when an attack misses where as damage engine or damage interface your unit will still get stunned from bash for example even if the damage is changed to 0.

edit: Could we have a demon hunter evasion based evasion chance bonus in the next new bonus release please?
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
Just FYI: You can edit the demon hunter's evasion ability's evasion chance with blzsetabilityreallevelfield thus you don't need to use damage interface to make evasion. Also implementing evasion this way prevents secondary effects from occurring when an attack misses where as damage engine or damage interface your unit will still get stunned from bash for example even if the damage is changed to 0.

edit: Could we have a demon hunter evasion based evasion chance bonus in the next new bonus release please?

Yeah, I know all that. I wanted to specifically integrate both of my systems with NewBonus because I create Maps myself and with that I would be able to have more control over events. I can include a version that do not use the other system and with more bonusses types in the future, but right now I'm very busy with work and college. When I got a little more time, I'll go back to it.
 
Level 7
Joined
Oct 11, 2008
Messages
304
Your Extended version is not using 3 globals you declared (probably because of the non-extended version)


JASS:
        private constant integer CRITICAL_STRIKE_ABILITY  = 'Z00C'
        private constant integer EVASION_ABILITY          = 'Z00D'
        private constant integer LIFE_STEAL_ABILITY       = 'Z00E'
 
Level 20
Joined
May 16, 2012
Messages
635
Your Extended version is not using 3 globals you declared (probably because of the non-extended version)


JASS:
        private constant integer CRITICAL_STRIKE_ABILITY  = 'Z00C'
        private constant integer EVASION_ABILITY          = 'Z00D'
        private constant integer LIFE_STEAL_ABILITY       = 'Z00E'
Yeah, it's because I CTRL + C, CTRL +V the configuration block block and only changed the types for the extended version. It's there but does nothing. Not worth the effort of reposting a new version since it's inoffensive.
 
Level 20
Joined
May 16, 2012
Messages
635
OK, but can the ability manipulated in a way which calculates multiplicatively, and not additively?

Or maybe have a setting where you can choose how the stats should behave when adding up? (this would be useful for items specifically)
You can create your own way of manipulating this bonus specifically, but that's a job for a separate system.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
Alright, thanks. Just some pointers: I guess this is the area which I have to adjust, right? (current_amount + amount):

JASS:
static method AddUnitBonus takes unit u, integer bonus_type, integer amount returns integer
                local integer current_amount = GetUnitBonus(u, bonus_type)


                // Added in version 1.5 to avoid overflow/underflow of the field value
                if amount > 0 and current_amount > 2147483647 - amount then //Overflow
                    set amount = 2147483647 - current_amount
                elseif amount < 0 and current_amount < -2147483648 - amount then //Underflow
                    set amount = -2147483648 - current_amount
                endif
    
                call SetUnitBonus(u, bonus_type, (current_amount + amount))
 
Level 20
Joined
May 16, 2012
Messages
635
Alright, thanks. Just some pointers: I guess this is the area which I have to adjust, right? (current_amount + amount):

JASS:
static method AddUnitBonus takes unit u, integer bonus_type, integer amount returns integer
                local integer current_amount = GetUnitBonus(u, bonus_type)


                // Added in version 1.5 to avoid overflow/underflow of the field value
                if amount > 0 and current_amount > 2147483647 - amount then //Overflow
                    set amount = 2147483647 - current_amount
                elseif amount < 0 and current_amount < -2147483648 - amount then //Underflow
                    set amount = -2147483648 - current_amount
                endif
   
                call SetUnitBonus(u, bonus_type, (current_amount + amount))
There's more to it than that. Take a look at my Cooldown Reduction system. It does basically what you want but for cooldown reduction. I don't recommend messing with the system code, you can create some unwanted behavior for other stuff. You will also need to know jass a little bit.
 
Level 12
Joined
May 16, 2020
Messages
660
I'm having a problem with "GetUnitBonus". I can correctly grab the current BONUS_DAMAGE of a hero, but not BONUS_ATTACK_SPEED.

In the trigger below, the "Omnislash_AttackSpeed" (a Real variable) is always -1.000 in-game, even though I pick up several items which increase BONUS_ATTACK_SPEED.

  • Omnislash
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Omnislash
    • Actions
      • Set VariableSet Omnislash_Index = (Omnislash_Index + 1)
      • Set VariableSet Omnislash_Caster[Omnislash_Index] = (Triggering unit)
      • Set VariableSet Omnislash_Target = (Target unit of ability being cast)
      • Set VariableSet Omnislash_Counter[Omnislash_Index] = 0
      • Set VariableSet Omnislash_CounterMax[Omnislash_Index] = (55 + (5 x (Level of Omnislash for Omnislash_Caster[Omnislash_Index])))
      • Set VariableSet Omnislash_CounterReal[Omnislash_Index] = 0.00
      • -------- --------
      • Custom script: set udg_Omnislash_AttackSpeed = GetUnitBonus(udg_Omnislash_Caster[udg_Omnislash_Index], BONUS_ATTACK_SPEED)
      • Game - Display to (All players) the text: (String(Omnislash_AttackSpeed))
      • -------- --------
      • Set VariableSet Omnislash_CounterRealMax[Omnislash_Index] = ((((Unit: (Triggering unit)'s Weapon Real Field: Attack Base Cooldown ('ua1c') at Index:0) x 100.00) / (100.00 + (Real((Unit: (Triggering unit)'s Integer Field: Agility (with Bonus) ('uagb')))))) / 1.50)
      • Game - Display to (All players) the text: (String(Omnislash_CounterRealMax[Omnislash_Index]))
      • Set VariableSet Omnislash_DamageBonus[Omnislash_Index] = (15 + (15 x (Level of Omnislash for Omnislash_Caster[Omnislash_Index])))
      • Set VariableSet Omnislash_Boolean[Omnislash_Index] = True
      • Special Effect - Create a special effect attached to the weapon of Omnislash_Caster[Omnislash_Index] using Abilities\Weapons\PhoenixMissile\Phoenix_Missile.mdl
      • Set VariableSet Omnislash_SFX[Omnislash_Index] = (Last created special effect)
      • -------- --------
      • Unit - Pause Omnislash_Caster[Omnislash_Index]
      • Unit - Make Omnislash_Caster[Omnislash_Index] Invulnerable
      • Animation - Change Omnislash_Caster[Omnislash_Index]'s vertex coloring to (40.00%, 40.00%, 40.00%) with 40.00% transparency
      • Animation - Change Omnislash_Caster[Omnislash_Index]'s animation speed to 200.00% of its original speed
      • -------- --------
      • Set VariableSet Omnislash_Point[1] = (Position of Omnislash_Target)
      • Set VariableSet Omnislash_Point[2] = (Omnislash_Point[1] offset by 50.00 towards (Random angle) degrees.)
      • Unit - Move Omnislash_Caster[Omnislash_Index] instantly to Omnislash_Point[2]
      • Unit - Make Omnislash_Caster[Omnislash_Index] face Omnislash_Point[1] over 0.00 seconds
      • -------- --------
      • Custom script: set udg_Omnislash_AttackDamage = GetUnitBonus(udg_Omnislash_Caster[udg_Omnislash_Index], BONUS_DAMAGE)
      • Game - Display to (All players) the text: (String(Omnislash_AttackDamage))
      • Set VariableSet Omnislash_Damage = (((Base Damage of Omnislash_Caster[Omnislash_Index] for weapon index 0) + (Omnislash_AttackDamage + Omnislash_DamageBonus[Omnislash_Index])) + (Random integer number between (Dice Number of Omnislash_Caster[Omnislash_Index] for weapon index 0) and (Dice Sides
      • Unit - Cause Omnislash_Caster[Omnislash_Index] to damage Omnislash_Target, dealing (Real(Omnislash_Damage)) damage of attack type Hero and damage type Normal
      • -------- --------
      • Animation - Play Omnislash_Caster[Omnislash_Index]'s attack animation
      • Special Effect - Create a special effect attached to the origin of Omnislash_Caster[Omnislash_Index] using Abilities\Spells\NightElf\Blink\BlinkCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- --------
      • Custom script: call RemoveLocation(udg_Omnislash_Point[1])
      • Custom script: call RemoveLocation(udg_Omnislash_Point[2])
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Omnislash_Index Equal to 1
        • Then - Actions
          • Countdown Timer - Start Omnislash_Timer as a Repeating timer that will expire in 0.05 seconds
          • Trigger - Turn on Omnislash Loop <gen>
        • Else - Actions

The items which I pick up also use your system, and correctly increase attack speed (I test this by attacking a dummy, and the hero does attack faster). For example, the following item:

  • elseif GetItemTypeId(i) == 'asbl' then
    • call LinkBonusToItem(u, BONUS_ARMOR, 10, i)
    • call LinkBonusToItem(u, BONUS_ATTACK_SPEED, 0.3, i)

Am I doing something wrong?



Edit (separate question):
In the NewBonusUtils is a timer, which runs at 0.03125 per second.
I assume that's the timer which is used when I call "AddUnitBonusTimed".
However, for my map, 0.25 per second is good enough.

Can I safely increase it, without destroying anything in the background?
 
Last edited:
Level 20
Joined
May 16, 2012
Messages
635
I'm having a problem with "GetUnitBonus". I can correctly grab the current BONUS_DAMAGE of a hero, but not BONUS_ATTACK_SPEED.

In the trigger below, the "Omnislash_AttackSpeed" (a Real variable) is always -1.000 in-game, even though I pick up several items which increase BONUS_ATTACK_SPEED.

  • Omnislash
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Omnislash
    • Actions
      • Set VariableSet Omnislash_Index = (Omnislash_Index + 1)
      • Set VariableSet Omnislash_Caster[Omnislash_Index] = (Triggering unit)
      • Set VariableSet Omnislash_Target = (Target unit of ability being cast)
      • Set VariableSet Omnislash_Counter[Omnislash_Index] = 0
      • Set VariableSet Omnislash_CounterMax[Omnislash_Index] = (55 + (5 x (Level of Omnislash for Omnislash_Caster[Omnislash_Index])))
      • Set VariableSet Omnislash_CounterReal[Omnislash_Index] = 0.00
      • -------- --------
      • Custom script: set udg_Omnislash_AttackSpeed = GetUnitBonus(udg_Omnislash_Caster[udg_Omnislash_Index], BONUS_ATTACK_SPEED)
      • Game - Display to (All players) the text: (String(Omnislash_AttackSpeed))
      • -------- --------
      • Set VariableSet Omnislash_CounterRealMax[Omnislash_Index] = ((((Unit: (Triggering unit)'s Weapon Real Field: Attack Base Cooldown ('ua1c') at Index:0) x 100.00) / (100.00 + (Real((Unit: (Triggering unit)'s Integer Field: Agility (with Bonus) ('uagb')))))) / 1.50)
      • Game - Display to (All players) the text: (String(Omnislash_CounterRealMax[Omnislash_Index]))
      • Set VariableSet Omnislash_DamageBonus[Omnislash_Index] = (15 + (15 x (Level of Omnislash for Omnislash_Caster[Omnislash_Index])))
      • Set VariableSet Omnislash_Boolean[Omnislash_Index] = True
      • Special Effect - Create a special effect attached to the weapon of Omnislash_Caster[Omnislash_Index] using Abilities\Weapons\PhoenixMissile\Phoenix_Missile.mdl
      • Set VariableSet Omnislash_SFX[Omnislash_Index] = (Last created special effect)
      • -------- --------
      • Unit - Pause Omnislash_Caster[Omnislash_Index]
      • Unit - Make Omnislash_Caster[Omnislash_Index] Invulnerable
      • Animation - Change Omnislash_Caster[Omnislash_Index]'s vertex coloring to (40.00%, 40.00%, 40.00%) with 40.00% transparency
      • Animation - Change Omnislash_Caster[Omnislash_Index]'s animation speed to 200.00% of its original speed
      • -------- --------
      • Set VariableSet Omnislash_Point[1] = (Position of Omnislash_Target)
      • Set VariableSet Omnislash_Point[2] = (Omnislash_Point[1] offset by 50.00 towards (Random angle) degrees.)
      • Unit - Move Omnislash_Caster[Omnislash_Index] instantly to Omnislash_Point[2]
      • Unit - Make Omnislash_Caster[Omnislash_Index] face Omnislash_Point[1] over 0.00 seconds
      • -------- --------
      • Custom script: set udg_Omnislash_AttackDamage = GetUnitBonus(udg_Omnislash_Caster[udg_Omnislash_Index], BONUS_DAMAGE)
      • Game - Display to (All players) the text: (String(Omnislash_AttackDamage))
      • Set VariableSet Omnislash_Damage = (((Base Damage of Omnislash_Caster[Omnislash_Index] for weapon index 0) + (Omnislash_AttackDamage + Omnislash_DamageBonus[Omnislash_Index])) + (Random integer number between (Dice Number of Omnislash_Caster[Omnislash_Index] for weapon index 0) and (Dice Sides
      • Unit - Cause Omnislash_Caster[Omnislash_Index] to damage Omnislash_Target, dealing (Real(Omnislash_Damage)) damage of attack type Hero and damage type Normal
      • -------- --------
      • Animation - Play Omnislash_Caster[Omnislash_Index]'s attack animation
      • Special Effect - Create a special effect attached to the origin of Omnislash_Caster[Omnislash_Index] using Abilities\Spells\NightElf\Blink\BlinkCaster.mdl
      • Special Effect - Destroy (Last created special effect)
      • -------- --------
      • Custom script: call RemoveLocation(udg_Omnislash_Point[1])
      • Custom script: call RemoveLocation(udg_Omnislash_Point[2])
      • -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Omnislash_Index Equal to 1
        • Then - Actions
          • Countdown Timer - Start Omnislash_Timer as a Repeating timer that will expire in 0.05 seconds
          • Trigger - Turn on Omnislash Loop <gen>
        • Else - Actions

The items which I pick up also use your system, and correctly increase attack speed (I test this by attacking a dummy, and the hero does attack faster). For example, the following item:

  • elseif GetItemTypeId(i) == 'asbl' then
    • call LinkBonusToItem(u, BONUS_ARMOR, 10, i)
    • call LinkBonusToItem(u, BONUS_ATTACK_SPEED, 0.3, i)

Am I doing something wrong?



Edit (separate question):
In the NewBonusUtils is a timer, which runs at 0.03125 per second.
I assume that's the timer which is used when I call "AddUnitBonusTimed".
However, for my map, 0.25 per second is good enough.

Can I safely increase it, without destroying anything in the background?
GetUnitBonus returns -1 when an invalid bonus type is passed to the function, so check if you are writing the bonus type correctly. Check if the abilities match with the codes in the configuration. Check if you are passing the correct unit as well. I tested in the test map and the system manage to get the bonus attack speed fine so you either doing something wrong or you imported something incorrectly. I tested it in the latest version of the system in both vJASS and Lua.

You can change the timer timeout but make sure to change in all occurrences, although I recommend not to. That timeout is standard and will not cause any performance loss for you even when having thousands of instances so I see no point in doing it.
 
Level 12
Joined
May 16, 2020
Messages
660
Thank you. Ah man, was a pretty easy fix: I just needed to add "GetUnitBonusReal".

Regarding the timer: I always read though that you should be mindful about using 0.03 sec triggers.
Is that just for old PCs that had troubles processing so many instances of events, and nowadays that's no longer an issue if you say that "you can have thousands of instances"?
 
Level 20
Joined
May 16, 2012
Messages
635
Thank you. Ah man, was a pretty easy fix: I just needed to add "GetUnitBonusReal".
Oh, you are using an older version of the system. In the latest version those functions with the Real in the end where removed and you can use one function for both real and integer bonus types.

Regarding the timer: I always read though that you should be mindful about using 0.03 sec triggers.
Is that just for old PCs that had troubles processing so many instances of events, and nowadays that's no longer an issue if you say that "you can have thousands of instances"?
You should be mindful when you are doing a lot of things every 0.03 seconds, but in this case it's just checking for an ability level and that is pretty fast even in JASS.
 
Level 12
Joined
May 16, 2020
Messages
660
Oh, you are using an older version of the system. In the latest version those functions with the Real in the end where removed and you can use one function for both real and integer bonus types.

I just wanted to update to the new version (NewBonus, NOT extended), and I think there is a bug with BONUS_DAMAGE.

If my variable is a "Real" type I can get the DAMAGE_BONUS:
  • Custom script: set udg_Attack = GetUnitBonus(GetTriggerUnit(), BONUS_DAMAGE)

1624479191242.png


However, if I change the variable type to "Integer", I get an error:
  • Custom script: set udg_Attack = GetUnitBonus(GetTriggerUnit(), BONUS_DAMAGE)

1624479264392.png


Error message:

1624479286075.png


Edit: Same for Strength, Intelligence, Agility etc.
Or are we meant to always use "Real" variables, regardless if it's Magic resistance (previously Real) or Damage (previously Integer)?
 
Last edited:
Top