• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

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.

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,907
Well I do, in the screenshot above, the Damage Interface is present.
Looks like Jasshelper is pointing to the wrong line. I checked the script and I can't find s_Damage_get_source function anywhere in this resource. Disable Bribe's damage engine and every trigger that uses it and tell me if you still have the same error.
 

Wrda

Spell Reviewer
Level 26
Joined
Nov 18, 2012
Messages
1,907
DamageInterface trigger had the struct name "Damage2" while everywhere else was using "Damage", which is the struct name of Bribe's damage engine. I replaced all Chopinski's triggers named "Damage" with "DamageInterface" besides the "Damage2" one. It has no errors now.
 

Attachments

  • NewBonusFix.w3x
    359.7 KB · Views: 11
Level 10
Joined
Dec 16, 2017
Messages
373
What a strange bug, lol
Encountered a bug : When dropping and picking up an item with 3 strength (with 12.50 hp per STR gain - in game constants) - the hero will get permanent additional health.


Also, does this has a tutorial to use in more situations?
Or how to use the cooldown reduction / crowd control ?
 
Last edited:

Uncle

Warcraft Moderator
Level 65
Joined
Aug 10, 2018
Messages
6,703
Encountered a bug : When dropping and picking up an item with 3 strength (with 12.50 hp per STR gain - in game constants) - the hero will get permanent additional health.
Looks like a rounding error, 37.50 rounds up to 38, thus adding more hp. Maybe you could account for it in your own math.
 
Or how to use the cooldown reduction / crowd control ?
you set the values for cooldown reduction and the system updates the cooldown of casted abilities automatic on a SPELL_EFFECT events.
Crowd control mods only works for crowd control applied over this system's functions for this feature.
 
Level 10
Joined
Dec 16, 2017
Messages
373
Yeah, i want to change my crowd control into these triggers, so i am in fully control of the actions, but how do i call the functions ?
This interferes with bribe's knockback system so i removed bribe's one and kept crowd control.
 
Copy the 14 buffs and 15 abilities with the CC prefix and match their raw code below.
you need to copy/create the skills and buffs of crowd control and make sure they have the rawCode expected by the crowd System. or change the constants ids to match the rawCodes in your map:
JASS:
]
 // The raw code of the silence ability
private constant integer SILENCE    = 'U000'
// The raw code of the stun ability
private constant integer STUN       = 'U001'
// The raw code of the attack slow ability
private constant integer ATTACK_SLOW= 'U002'
// The raw code of the movement slow ability
private constant integer MOVEMENT_SLOW      = 'U003'
// The raw code of the banish ability
private constant integer BANISH     = 'U004'
// The raw code of the ensnare ability
private constant integer ENSNARE    = 'U005'
// The raw code of the purge ability
private constant integer PURGE      = 'U006'
// The raw code of the hex ability
private constant integer HEX= 'U007'
// The raw code of the sleep ability
private constant integer SLEEP      = 'U008'
// The raw code of the cyclone ability
private constant integer CYCLONE    = 'U009'
// The raw code of the entangle ability
private constant integer ENTANGLE   = 'U010'
// The raw code of the disarm ability
private constant integer DISARM     = 'U011'
// The raw code of the fear ability
private constant integer FEAR       = 'U012'
// The raw code of the taunt ability
private constant integer TAUNT      = 'U013'
// The raw code of the true sight ability
private constant integer TRUE_SIGHT = 'U014'
// The raw code of the silence buff
private constant integer SILENCE_BUFF       = 'BU00'
// The raw code of the stun buff
private constant integer STUN_BUFF  = 'BU01'
// The raw code of the attack slow buff
private constant integer ATTACK_SLOW_BUFF   = 'BU02'
// The raw code of the movement slow buff
private constant integer MOVEMENT_SLOW_BUFF = 'BU03'
// The raw code of the banish buff
private constant integer BANISH_BUFF= 'BU04'
// The raw code of the ensnare buff
private constant integer ENSNARE_BUFF       = 'BU05'
// The raw code of the purge buff
private constant integer PURGE_BUFF = 'BU06'
// The raw code of the hex buff
private constant integer HEX_BUFF   = 'BU07'
// The raw code of the sleep buff
private constant integer SLEEP_BUFF = 'BU08'
// The raw code of the cyclone buff
private constant integer CYCLONE_BUFF       = 'BU09'
// The raw code of the entangle buff
private constant integer ENTANGLE_BUFF      = 'BU10'
// The raw code of the disarm buff
private constant integer DISARM_BUFF= 'BU11'
// The raw code of the fear buff
private constant integer FEAR_BUFF  = 'BU12'
// The raw code of the taunt buff
private constant integer TAUNT_BUFF = 'BU13'
seems like this are the orders which tell the base abilities. so you can just create them in your map and dont need to swap around.
JASS:
]
set order[CROWD_CONTROL_SILENCE] = "drunkenhaze"
set order[CROWD_CONTROL_STUN] = "thunderbolt"
set order[CROWD_CONTROL_SLOW] = "cripple"
set order[CROWD_CONTROL_SLOW_ATTACK] = "cripple"
set order[CROWD_CONTROL_BANISH] = "banish"
set order[CROWD_CONTROL_ENSNARE] = "ensnare"
set order[CROWD_CONTROL_PURGE] = "purge"
set order[CROWD_CONTROL_HEX] = "hex"
set order[CROWD_CONTROL_SLEEP] = "sleep"
set order[CROWD_CONTROL_CYCLONE] = "cyclone"
set order[CROWD_CONTROL_ENTANGLE] = "entanglingroots"
set order[CROWD_CONTROL_DISARM] = "drunkenhaze"
When you have the abilities
you can in trigger editor use the api functions to apply an cc.
call DisarmUnit(unit target, real duration, string model, string point, boolean stack)
call SilenceUnit(unit target, real duration, string model, string point, boolean stack)

example
call DisarmUnit(udg_Unit, 5, "", "", false)

no idea, why disarm would stack?
 
Last edited:
Level 10
Joined
Dec 16, 2017
Messages
373
Thanks mate, this is very helpful.
Yeah, i've already imported and everything is good, i just wanted to know how can i make use of them, since it has more options like life steals/spell vamp/spell power etc and tenacity which works only with crowd control spells from the system.
 
Top