REQUIREMENTS: JASS NEW GEN
You will need to create a few abilities. Firstly, copy the attack damage bonus ability from items section, make its object ID = 'DM+a', and set the damage bonus to +1. Now copy this item, set the object ID to 'DM+b', and set the damage bonus to +2. For the third time, you will copy the ability again, set the object ID to 'DM+c', and set the damage bonus to +4. I'm hoping that by now you've started to notice a patern, basically keep creating those abilities, progressing in the alphabet, and doubling the damage bonus. So the next few abilities ID's would be DM+d, DM+e, and damages +8, +16. Keep creating those abilities up to damage bonus of 256. This will let you set your units damage to anything from 0 up to 511.
This was the easy object editor part, time for some code.
Firstly, you will need to make a new trigger, after that convert it into text, and remove anything that's in there.
Now we'll type in "library DamageBonus", press enter, and type in "endlibrary."
We're finished with the library! Well not quite, it still needs a couple of things inside of it.
What your trigger should look like right now is:
JASS:
library DamageBonus
endlibrary
Next part to do is create a struct, which is simple. Firstly create the struct, the struct declaration is "struct" followed by a name
(ex. struct DamageBonus), and ended with "endstruct"
Now declare a unit with a name of "obj", and an integer with a name of "dmg" inside of the struct.
Your code should look like this:
JASS:
library DamageBonus
struct DamageBonus
integer dmg
unit obj
endstruct
endlibrary
Basically, now we have something to hold the units damage information in. You'll need to declare two new variables inside of your struct. Both of them are integer, name one pow, and the other cdmg. Make both of those last created variables into static variables. You do this by declaring the word "static" in front of them. Make the cdmg values equal to 'DM+a', and make pow equal to 8.
Right now your code should look like this:
JASS:
library DamageBonus
struct DamageBonus
integer dmg = 0
unit obj = 0
static integer pow = 8
static integer cdmg = 'DM+a'
endstruct
endlibrary
What you want to do right now is make all of those variables private, you do so by placing the keyword "private" in front of them.
After you have made it private, create a static method called create, make it take a unit, and return DamageBonus.
Create a local DamageBonus, create it using allocate method, and let obj variable equal to the unit given, after you have done that, return the DamageBonus struct.
Right now your code should look like this:
JASS:
library DamageBonus
struct DamageBonus
private integer dmg = 0
private unit obj = null
private static integer pow = 8
private static integer cdmg = 'DM+a'
static method create takes unit u returns DamageBonus
local DamageBonus this = DamageBonus.allocate()
set this.obj = u
return this
endmethod
endstruct
endlibrary
What you are going to do now, is creating a few method operators. You create them just like a regular method, but after the method keyword you place the word operator
(ex. method operator damage takes nothing returns integer). You place the symbol "=" after the method name if you are adjusting a value, not receiving it
(ex. method operator damage= takes integer s returns nothing).
Create a get method operator, call it object, and make it return the obj value. Create a duplicate set method, and instead of return the obj value, set obj value to the receiving value. Create two similar methods for dmg variable aswell.
Right now your code should look like this:
JASS:
library DamageBonus
struct DamageBonus
private integer dmg = 0
private unit obj = null
private static integer pow = 8
private static integer cdmg = 'DM+a'
static method create takes unit u returns DamageBonus
local DamageBonus this = DamageBonus.allocate()
set this.obj = u
return this
endmethod
method operator object takes nothing returns unit
return .obj
endmethod
method operator object= takes unit s returns nothing
set .obj = s
endmethod
method operator damage takes nothing returns integer
return .dmg
endmethod
method operator damage= takes integer s returns nothing
set .dmg = s
endmethod
endstruct
endlibrary
We're almost done! All we need now is a method that will actually give the abilities to the units.
Create a method called update_dmg above all the method operator, but below the create method.
Make the last created method have 2 local integers, call one i, and the other num. Set i = .pow, and num = .dmg.
Now create an if statement, make sure that the num value is less than 512. If that's true, than return, and no else statement.
Create a loop, and for the exit statement place i < 0. Inside of the loop check if Pow( 2, i) is less then or equal to num. If so, add an ability to the .obj, for the ability ID use .cdmg + i. After the add function call, set num = num - R2I(Pow(2,i)). Now for the else statement, remove an ability from the object, for the ability id use .cdmg + i. After the if statement, set i to itself minus one. End the loop.
Right now your code should look like this:
JASS:
library DamageBonus
struct DamageBonus
private integer dmg = 0
private unit obj = null
private static integer pow = 8
private static integer cdmg = 'DM+a'
static method create takes unit u returns DamageBonus
local DamageBonus this = DamageBonus.allocate()
set this.obj = u
return this
endmethod
private method update_dmg takes nothing returns nothing
local integer i = .pow
local integer num = .dmg
if num > 511 then
return
endif
loop
exitwhen i < 0
if Pow(2,i) <= num then
call UnitAddAbility( .obj, .cdmg + i )
set num = num - R2I(Pow(2,i))
else
call UnitRemoveAbility( .obj, .cdmg + i )
endif
set i = i - 1
endloop
endmethod
method operator object takes nothing returns unit
return .obj
endmethod
method operator object= takes unit s returns nothing
set .obj = s
endmethod
method operator damage takes nothing returns integer
return .dmg
endmethod
method operator damage= takes integer s returns nothing
set .dmg = s
endmethod
endstruct
endlibrary
Now what you're gonna have to do, is go back to the method operator where you adjusted the damage value, and after the value is adjusted, call .update_dmg().
Only thing left to do, is create an onDestroy method. Inside the method, create a local integer, with the name of i, and set it's value to .pow.
Than create a loop, exitwhen i is less than 0. Inside of the loop remove each of the abilities on the unit. Set i to equal itself minus one. After the loop, set .obj to null.
Now our code should look like this:
JASS:
library DamageBonus
struct DamageBonus
private integer dmg = 0
private unit obj = null
private static integer pow = 8
private static integer cdmg = 'DM+a'
static method create takes unit u returns DamageBonus
local DamageBonus this = DamageBonus.allocate()
set this.obj = u
return this
endmethod
private method update_dmg takes nothing returns nothing
local integer i = .pow
local integer num = .dmg
if num > 511 then
return
endif
loop
exitwhen i < 0
if Pow(2,i) <= num then
call UnitAddAbility( .obj, .cdmg + i )
set num = num - R2I(Pow(2,i))
else
call UnitRemoveAbility( .obj, .cdmg + i )
endif
set i = i - 1
endloop
endmethod
method operator object takes nothing returns unit
return .obj
endmethod
method operator object= takes unit s returns nothing
set .obj = s
endmethod
method operator damage takes nothing returns integer
return .dmg
endmethod
method operator damage= takes integer s returns nothing
set .dmg = s
call .update_dmg()
endmethod
private method onDestroy takes nothing returns nothing
local integer i = .pow
loop
exitwhen i < 0
call UnitRemoveAbility(.obj, .cdmg + i)
set i = i - 1
endloop
set .obj = null
endmethod
endstruct
endlibrary
The system is finished!
Now what we have to do to use it, is create a DamageBonus struct, and set the struct damage to whatever you want. You can even do so in a GUI trigger.
-
Untitled Trigger 001
-
Events
-
Conditions
-
Actions
-
Custom script: local DamageBonus this = DamageBonus.create(some_unit)
-
Custom script: set this.damage=200
Now, there is one issue with this code, it will leak when the units die, so what we will have to do, is attach the structs to the units user data, create a group, and when a unit with the struct attached dies his struct will be destroyed.
Here is the final code with self clean-up type of thing enabled:
JASS:
library DamageBonus initializer init
globals
unit some_unit
endglobals
struct DamageBonus
private integer dmg = 0
private unit obj = null
private static integer pow = 8
private static integer cdmg = 'DM+a'
static group grp = null
static method create takes unit u returns DamageBonus
local DamageBonus this = DamageBonus.allocate()
if IsUnitInGroup(u, .grp) then
debug call BJDebugMsg("Trying to create multiple damage bonuses for unit " + GetUnitName(.obj))
return null
endif
call GroupAddUnit( .grp, u)
set this.obj = u
return this
endmethod
private method update_dmg takes nothing returns nothing
local integer i = .pow
local integer num = .dmg
if num > 511 then
return
endif
loop
exitwhen i < 0
if Pow(2,i) <= num then
call UnitAddAbility( .obj, .cdmg + i )
set num = num - R2I(Pow(2,i))
else
call UnitRemoveAbility( .obj, .cdmg + i )
endif
set i = i - 1
endloop
endmethod
method operator object takes nothing returns unit
return .obj
endmethod
method operator object= takes unit s returns nothing
set .obj = s
endmethod
method operator damage takes nothing returns integer
return .dmg
endmethod
method operator damage= takes integer s returns nothing
set .dmg = s
call .update_dmg()
endmethod
private method onDestroy takes nothing returns nothing
local integer i = .pow
if .obj == null then
debug call BJDebugMsg("Trying to double release a struct attached to unit " + GetUnitName(.obj))
return
endif
loop
exitwhen i < 0
call UnitRemoveAbility(.obj, .cdmg + i)
set i = i - 1
endloop
call GroupRemoveUnit(.grp, .obj)
set .obj = null
endmethod
static method onInit takes nothing returns nothing
set .grp = CreateGroup()
endmethod
endstruct
private function condition takes nothing returns boolean
local DamageBonus d = GetUnitUserData(GetTriggerUnit())
if IsUnitInGroup(d.object, d.grp) then
return true
endif
return false
endfunction
private function action takes nothing returns nothing
local DamageBonus d = GetUnitUserData(GetTriggerUnit())
call d.destroy()
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(t,Condition(function condition))
call TriggerAddAction(t, function action)
endfunction
endlibrary
To use the system above you would have to add one more line to your GUI trigger, here is how it would look.
-
Untitled Trigger 001
-
Events
-
Conditions
-
Actions
-
Custom script: local DamageBonus this = DamageBonus.create(some_unit)
-
Custom script: set this.damage=200
-
Custom script: call SetUnitUserData(some_unit, this)