Nestharus
o-o
- Reaction score
- 84
Known Issues
Lua Installation Scripts
Initialization Script
LUA_GET_VAR_OBJECT
This script can be used to create new bonuses, just be sure to add them to this script rather than generating them solo, or your map will only have that single generated bonus.
System Code
Does not work properly with unit upgrades that change health/mana max. Your units will die when working with negative bonuses if their health/mana was modified by an upgrade. In fact, it's best to just do all upgrades through Bonus as there may be other bugs that I have not yet discovered.
Lua Installation Scripts
JASS:
//! externalblock extension=lua FileExporter $FILENAME$
//! runtextmacro LUA_FILE_HEADER()
//BonusAbility v1.0.0.1
//BonusJASS v1.0.0.0
//! i writelua("BonusAbility", [======[
//////////////////////////////////////////////////////////////////
//code
//! i abilities = {}
//! i
//! i Ability = {} --[[
//! i -------------------------------------------------------------------------------------------------------
//! i *
//! i * Fields
//! i * ---------------------------------------------------------------------------------------------------
//! i * * -> maxpower | maximum power of ability (in base 2)
//! i * * -> isperc | is percent
//! i * * -> abilityid | id of ability object
//! i * * -> field | id of ability field that gives data bonus
//! i * * -> name | name to assign to ability object
//! i * * -> ranged | the ability has a definite range
//! i * ---------------------------------------------------------------------------------------------------
//! i *
//! i * Functions
//! i * ---------------------------------------------------------------------------------------------------
//! i * * -> function Ability.new(perc, abilityid, bonusfield, name, ranged, enabled) returns ability
//! i * ---------------------------------------------------------------------------------------------------
//! i *
//! i ------------------------------------------------------------------------------------------------------- ]]
//! i local function genobjects(self)
//! i local function getmultiplier(power)
//! i --[[get multiplier value]]
//! i local multiplier
//! i
//! i multiplier = 1
//! i
//! i if (self.isperc) then
//! i multiplier = .01
//! i end
//! i
//! i --[[get multiplier sign]]
//! i if (self.ranged) then
//! i if (power == self.maxpower) then
//! i multiplier = -multiplier
//! i end
//! i elseif (power == 0) then
//! i multiplier = 0
//! i elseif (power ~= self.maxpower + 1) then
//! i multiplier = -multiplier
//! i end
//! i
//! i return multiplier
//! i end
//! i
//! i ----------------------------------------------------------------------------
//! i -- CODE
//! i ----------------------------------------------------------------------------
//! i --[[generate objects]]
//! i if (self.ranged) then
//! i for power = 0, self.maxpower, 1 do
//! i --[[create object]]
//! i self.objects[power]=getvarobject(self.abilityid, "abilities","BONUS_" .. self.name .. "_" .. tostring(power), false)
//! i self.abilities[power] = createobject(self.abilityid, self.objects[power])
//! i
//! i --[[set object name]]
//! i makechange(self.abilities[power], "anam", "BONUS_" .. self.name .. "_" .. tostring(power))
//! i
//! i --[[set object bonus]]
//! i makechange(current, self.field, 1, getmultiplier(power)*2^power)
//! i end
//! i else
//! i --[[create object]]
//! i self.objects[0] = getvarobject(self.abilityid, "abilities", "BONUS_" .. self.name, false)
//! i self.abilities[0] = createobject(self.abilityid, self.objects[0])
//! i makechange(self.abilities[0], "anam", "BONUS_" .. self.name .. "_" .. tostring(power))
//! i
//! i --[[Level 1: 0]]
//! i --[[Level Mid: Negative Power - 1]]
//! i --[[Level Max: Positive Power - 1]]
//! i makechange(current, "alev", self.maxpower + 2)
//! i
//! i --[[set object bonus]]
//! i for power = 0, self.maxpower + 2, 1 do
//! i makechange(current, self.field, power + 1, getmultiplier(power)*2^(power - 1))
//! i end
//! i end
//! i ----------------------------------------------------------------------------
//! i end
//! i
//! i function Ability.new(perc, abilityid, bonusfield, name, ranged, enabled, maxpower) --[[
//! i -------------------------------------------------------------------------------------------------------
//! i * -> perc | is ability value percent?
//! i * -> abilityid | base ability id
//! i * -> bonusfield | field with value of ability
//! i * -> name | name of ability
//! i * -> ranged | does ability have defined range
//! i * -> enabled | is ability enabled
//! i * -> maxpower | maximum power
//! i ------------------------------------------------------------------------------------------------------- ]]
//! i local self = nil
//! i
//! i if (enabled) then
//! i self = {}
//! i
//! i --[[init fields]]
//! i self.objects = {} --> stores generated ability ids
//! i self.abilities = {} --> stores generated ability objects
//! i self.maxpower = maxpower --> stores max power of 2 ability value can be
//! i self.isperc = perc --> does ability use a percent value?
//! i self.abilityid = abilityid --> base ability id
//! i self.field = bonusfield --> object field that modifies bonus value
//! i self.name = name --> ability name
//! i self.ranged = ranged --> ability has definite range
//! i
//! i --[[generate objects]]
//! i genobjects(self)
//! i end
//! i
//! i table.insert(abilities,self)
//! i abilities = Ability.getvalid(abilities) --> filter out invalid abilities
//! i abilities.containslimited = Ability.limitedenabled(abilities) --> determine if any abilities are limited
//! i abilities.containsunlimited = Ability.unlimitedenabled(abilities) --> determines if any abilites are unlimited
//! i
//! i return self
//! i end
//! i
//! i function Ability.getvalid(abilities)
//! i local abilitylist = {}
//! i for id, ability in ipairs(abilities) do
//! i if (ability~=nil) then
//! i table.insert(abilitylist, ability)
//! i end
//! i end
//! i return abilitylist
//! i end
//! i
//! i function Ability.limitedenabled(abilities)
//! i for id, ability in ipairs(abilities) do
//! i if (ability.limited) then
//! i return true
//! i end
//! i end
//! i return false
//! i end
//! i function Ability.unlimitedenabled(abilities)
//! i for id, ability in ipairs(abilities) do
//! i if (ability.limited) then
//! i return true
//! i end
//! i end
//! i return false
//! i end
//end code
//////////////////////////////////////////////////////////////////
//! i ]======])
//! i writelua("BonusJASS", [======[
//////////////////////////////////////////////////////////////////
//code
//! i BonusJASS = { }
//! i
//! i local POWER_MAX = "pm" --> max power
//! i local POWER_SET = "ps" --> power set (2^0 to 2^POWER_MAX)
//! i local OBJECT_ID = "bo" --> object ids
//! i local IS_RANGED = "ir" --> is ranged
//! i local BINARY_POWER = "bp" --> power of 2
//! i local CURRENT_BONUS = "cb" --> current bonus of unit
//! i
//! i local function getabilityids(abilities)
//! i local constants = ""
//! i local prefix
//! i local cur = 0
//! i
//! i for id, ability in ipairs(abilities) do
//! i constants = constants .. "constant integer BONUS_" .. ability.name .. "=" .. tostring(cur) .. "\n"
//! i cur = cur + ability.maxpower + 1
//! i if (not ability.ranged) then
//! i cur = cur + 1
//! i end
//! i end
//! i
//! i return constants
//! i end
//! i
//! i local function getisranged(abilities)
//! i local isranged = ""
//! i local cur = 0
//! i
//! i for id, ability in ipairs(abilities) do
//! i if (ability.ranged) then
//! i isranged = isranged .. "set " .. IS_RANGED .. "[" .. tostring(cur) .. "]=true\n"
//! i else
//! i isranged = isranged .. "set " .. IS_RANGED .. "[" .. tostring(cur) .. "]=false\n"
//! i cur = cur + 1
//! i end
//! i cur = cur + ability.maxpower + 1
//! i end
//! i
//! i return isranged
//! i end
//! i
//! i local function getpowermax(abilities)
//! i local powermax = ""
//! i local cur = 0
//! i
//! i for id, ability in ipairs(abilities) do
//! i powermax = powermax .. "set " .. POWER_MAX .. "[" .. tostring(cur) .. "]=" .. tostring(ability.maxpower) .. "\n"
//! i cur = cur + ability.maxpower + 1
//! i if (not ability.ranged) then
//! i cur = cur + 1
//! i end
//! i end
//! i
//! i return powermax
//! i end
//! i
//! i local function getpowerset(abilities)
//! i local powerset = ""
//! i local index = 0
//! i for id, ability in ipairs(abilities) do
//! i if (ability.ranged) then
//! i for power = 0, ability.maxpower - 1, 1 do
//! i powerset = powerset .. "set " .. POWER_SET .. "[" .. tostring(index) .. "]=" .. tostring((2^power)) .. "\n"
//! i powerset = powerset .. "set " .. BINARY_POWER .. "[" .. tostring(index) .. "]=" .. tostring(power) .. "\n"
//! i index = index + 1
//! i end
//! i else
//! i powerset = powerset .. "set " .. POWER_SET .. "[" .. tostring(index) .. "]=" .. tostring(0) .. "\n"
//! i index = index + 1
//! i for power = 0, ability.maxpower - 1, 1 do
//! i powerset = powerset .. "set " .. POWER_SET .. "[" .. tostring(index) .. "]=" .. tostring((2^power)) .. "\n"
//! i powerset = powerset .. "set " .. BINARY_POWER .. "[" .. tostring(index) .. "]=" .. tostring(power) .. "\n"
//! i index = index + 1
//! i end
//! i end
//! i powerset = powerset .. "set " .. POWER_SET .. "[" .. tostring(index) .. "]=" .. tostring(-(2^ability.maxpower)) .. "\n"
//! i powerset = powerset .. "set " .. BINARY_POWER .. "[" .. tostring(index) .. "]=" .. tostring(-ability.maxpower) .. "\n"
//! i index = index + 1
//! i end
//! i return powerset
//! i end
//! i
//! i local function getobjectids(abilities)
//! i local powerset = ""
//! i local index = 0
//! i for id, ability in ipairs(abilities) do
//! i if (ability.ranged) then
//! i for power = 0, ability.maxpower, 1 do
//! i powerset = powerset .. "set " .. OBJECT_ID .. "[" .. tostring(index) .. "]='" .. ability.objects[power] .. "'\/\/" .. tostring(power) .. "\n"
//! i index = index + 1
//! i end
//! i else
//! i powerset = powerset .. "set " .. OBJECT_ID .. "[" .. tostring(index) .. "]='" .. ability.objects[0] .. "'\n"
//! i index = index + 2 + ability.maxpower
//! i end
//! i end
//! i return powerset
//! i end
//! i
//! i local function getpreload(abilities)
//! i local preload=""
//! i for id, ability in ipairs(abilities) do
//! i if (ability.ranged) then
//! i for power = 0, ability.maxpower, 1 do
//! i preload = preload .. "call UnitAddAbility(u,'" .. ability.objects[power] .. "')\n"
//! i end
//! i else
//! i preload = preload .. "call UnitAddAbility(u,'" .. ability.objects[0] .. "')\n"
//! i end
//! i end
//! i return preload
//! i end
//! i
//! i function BonusJASS.get(abilities)
//! i local beginglobals = "globals\n"
//! i local powermax = "private integer array " .. POWER_MAX .. "\n"
//! i local powerset = "private integer array " .. POWER_SET .. "\n"
//! i local binarypower = "private integer array " .. BINARY_POWER .. "\n"
//! i local objectid = "private integer array " .. OBJECT_ID .. "\n"
//! i local isranged = "private boolean array " .. IS_RANGED .. "\n"
//! i local currentbonus = "private Table array " .. CURRENT_BONUS .. "\n"
//! i local abilityids = getabilityids(abilities)
//! i local endglobals = "endglobals\n"
//! i
//! i local begininit = "private module I\nprivate static method onInit takes nothing returns nothing\n"
//! i local preloadif = "static if PRELOAD then\n"
//! i local preloadend = "endif\n"
//! i local preload = "local unit u\nset UnitIndexer.enabled=false\nset u = CreateUnit(Player(14),'hpea',0,0,0)\n" .. getpreload(abilities) .. "call RemoveUnit(u)\nset u = null\nset UnitIndexer.enabled=true\n"
//! i local index = "call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)\n"
//! i local deindex = "call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)\n"
//! i local objectids = getobjectids(abilities) --> actual object ids of abilities for UnitAddAbility
//! i local powermaxes = getpowermax(abilities) --> max power (from config)
//! i local powersets = getpowerset(abilities) --> power set: 1, 2, 4, 8, -16 etc
//! i local israngeds = getisranged(abilities) --> is ability ranged or not
//! i local endinit = "endmethod\nendmodule\n"
//! i
//! i local beginstruct = "private struct O extends array\n"
//! i local beginindex = "private static method index takes nothing returns boolean\n"
//! i local indexcode =
//! i [[set cb[GetIndexedUnitId()] = Table.create()]] .. "\n"
//! i local endindex = "return false\nendmethod\n"
//! i local begindeindex = "private static method deindex takes nothing returns boolean\n"
//! i local deindexcode =
//! i [[call cb[GetIndexedUnitId()].destroy()]] .. "\n"
//! i local enddeindex = "return false\nendmethod\n"
//! i local endstruct = "implement I\nendstruct\n"
//! i
//! i local jass = ""
//! i
//! i jass = jass .. [[//! textmacro BONUS_SCRIPT]] .. "\n"
//! i jass = jass .. beginglobals
//! i jass = jass .. powermax
//! i jass = jass .. powerset
//! i jass = jass .. binarypower
//! i jass = jass .. objectid
//! i jass = jass .. isranged
//! i jass = jass .. currentbonus
//! i jass = jass .. abilityids
//! i jass = jass .. endglobals
//! i
//! i jass = jass .. begininit
//! i jass = jass .. preloadif
//! i jass = jass .. preload
//! i jass = jass .. preloadend
//! i jass = jass .. index
//! i jass = jass .. deindex
//! i jass = jass .. objectids
//! i jass = jass .. powermaxes
//! i jass = jass .. powersets
//! i jass = jass .. israngeds
//! i jass = jass .. endinit
//! i
//! i jass = jass .. beginstruct
//! i jass = jass .. beginindex
//! i jass = jass .. indexcode
//! i jass = jass .. endindex
//! i jass = jass .. begindeindex
//! i jass = jass .. deindexcode
//! i jass = jass .. enddeindex
//! i jass = jass .. endstruct
//! i jass = jass .. [[//! endtextmacro]] .. "\n"
//! i
//! i return jass
//! i end
//end code
//////////////////////////////////////////////////////////////////
//! i ]======])
//! endexternalblock
Initialization Script
LUA_GET_VAR_OBJECT
This script can be used to create new bonuses, just be sure to add them to this script rather than generating them solo, or your map will only have that single generated bonus.
JASS:
/****************************************************************************************
* *
* Ranged Bonus Power *
* *
* Power determines how big a bonus range can go. For example, a power of 15 would be *
* -(2^16) to 2^(16)-1 or -65536 to 65535. *
* *
*****************************************************************************************
* *
* Unlimited Bonus Power *
* *
* Power for unlimited bonuses increases speed of add/remove for larger values *
* and makes larger values easier to get to. For example, 50,000,000 is much *
* faster adding units of 1,048,576 than adding units of 16. In units of 16, *
* 50,000,000 might as well be impossible to get to. *
* *
*****************************************************************************************
* *
* ENABLED *
* *
* Should the bonus be implemented into the system? By disabling a bonus, it will not *
* be in the system at all. Abilities and constants won't be made. *
* *
****************************************************************************************/
//! textmacro BONUS_CREATE_BONUSES
/********************
* *
* ability data *
* *
********************/
// perc abil field name ranged enabled max power
//! i Ability.new(false, "AId1", "Idef", "ARMOR", true, true, 12) --> armor
//! i Ability.new(false, "AItg", "Iatt", "DAMAGE", true, true, 15) --> damage
//! i Ability.new(false, "AIa1", "Iagi", "AGILITY", true, true, 13) --> agility
//! i Ability.new(false, "AIs1", "Istr", "STRENGTH", true, true, 13) --> strength
//! i Ability.new(false, "AIi1", "Iint", "INTELLIGENCE", true, true, 13) --> intelligence
//! i Ability.new(false, "AIlf", "Ilif", "LIFE", false, true, 17) --> life
//! i Ability.new(false, "Arel", "Ihpr", "LIFE_REGEN", true, true, 15) --> life regen
//! i Ability.new(false, "AImb", "Iman", "MANA", false, true, 17) --> mana
//! i Ability.new(true, "AIrm", "Imrp", "MANA_REGEN", true, true, 8) --> mana regen, 8 max
//! i Ability.new(false, "AIsi", "Isib", "SIGHT", true, true, 10) --> sight, 10 max
//! i Ability.new(true, "AIsx", "Isx1", "ATTACK_SPEED", true, true, 8) --> attack speed, 8 max
//! endtextmacro
/********************
* *
* code *
* *
********************/
//! externalblock extension=lua ObjectMerger $FILENAME$
//! runtextmacro LUA_FILE_HEADER()
//! i dofile("GetVarObject")
//! i dofile("BonusAbility")
//! i dofile("BonusJASS")
//! runtextmacro BONUS_CREATE_BONUSES()
//! i local jass = BonusJASS.get(abilities)
//! i writejass("BONUS",jass)
//! i updateobjects()
//! endexternalblock
System Code
JASS:
library Bonus /* v2.0.0.2
*************************************************************************************
*
* Adds bonuses to units. In the ini area, these bonuses can be enabled and disabled.
* Ranges of bonus values can also be modified.
*
* Bonuses
* - Armor any unit non percent bonus
* - Damage units with attack only non percent bonus
* - Agility hero only non percent bonus
* - Strength hero only non percent bonus
* - Intelligence hero only non percent bonus
* - Life any unit non percent bonus
* - Life Regeneration any unit non percent bonus
* - Mana any unit non percent bonus
* - Mana Regeneration units with mana only percent bonus
* - Sight Range any unit non percent bonus
* - Attack Speed units with attack only percent bonus
*
*************************************************************************************
*
* */uses/*
* */ UnitIndexer /* hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
* */ Table /* hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
************************************************************************************
* SETTINGS
*/
globals
/*************************************************************************************
*
* PRELOAD
*
* Preloads all bonus abilities. This will add a hefty load time to the map but will
* prevent lag in game.
*
*************************************************************************************/
private constant boolean PRELOAD = false
endglobals
/*
*************************************************************************************
*
* Bonuses
*
* constant integer BONUS_ARMOR
* constant integer BONUS_DAMAGE
* constant integer BONUS_AGILITY
* constant integer BONUS_STRENGTH
* constant integer BONUS_INTELLIGENCE
* constant integer BONUS_LIFE
* constant integer BONUS_LIFE_REGEN
* constant integer BONUS_MANA
* constant integer BONUS_MANA_REGEN
* constant integer BONUS_ATTACK_SPEED
* constant integer BONUS_SIGHT
*
* Functions
*
* function GetUnitBonus takes unit whichUnit, integer whichBonus returns integer
* function SetUnitBonus takes unit whichUnit, integer whichBonus, integer value returns nothing
* function AddUnitBonus takes unit whichUnit, integer whichBonus, integer value returns nothing
*
************************************************************************************/
//! runtextmacro BONUS_SCRIPT()
function SetUnitBonus takes unit u, integer b, integer v returns nothing
local boolean n
local integer a
local integer p
local integer on
local integer i
local integer nch
local integer nb
debug if (not IsUnitIndexed(u)) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "UNIT BONUS ERROR: INVALID UNIT")
debug return
debug endif
debug if (0==pm<b>) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "UNIT BONUS ERROR: INVALID BONUS TYPE")
debug return
debug endif
set i=GetUnitUserData(u)
if (v != cb<i><b>) then
set nch=0
if (ir<b>) then
set n=0>v
set cb<i><b>=v
set p=b+pm<b>-1
set on=p+1
call UnitRemoveAbility(u,bo[on])
if (n) then
set v=v-ps[on]
endif
loop
if (0>v-ps[p]) then
call UnitRemoveAbility(u,bo[p])
else
call UnitAddAbility(u,bo[p])
call UnitMakeAbilityPermanent(u,true,bo[p])
set v=v-ps[p]
endif
exitwhen p==b
set p=p-1
endloop
if (n) then
call UnitAddAbility(u,bo[on])
call UnitMakeAbilityPermanent(u,true,bo[on])
endif
else
set nb=v
set v=v-cb<i><b>
set cb<i><b>=nb
set a=bo<b>
set on=b+pm<b>+1
loop
loop
exitwhen 0<v
set v=v-ps[on]
set nch=nch+1
endloop
set p=b+pm<b>
loop
if (0<=v-ps[p]) then
set v=v-ps[p]
call UnitAddAbility(u,a)
call SetUnitAbilityLevel(u,a,bp[p]+2)
call UnitRemoveAbility(u,a)
else
set p=p-1
exitwhen p==b
endif
endloop
exitwhen 0==v
endloop
loop
exitwhen 0==nch
set nch=nch-1
call UnitAddAbility(u,a)
call SetUnitAbilityLevel(u,a,(-bp[on])+2)
call UnitRemoveAbility(u,a)
endloop
endif
endif
endfunction
function GetUnitBonus takes unit u, integer b returns integer
return cb[GetUnitUserData(u)]<b>
endfunction
function AddUnitBonus takes unit u, integer b, integer v returns nothing
call SetUnitBonus(u,b,GetUnitBonus(u,b)+v)
endfunction
endlibrary
</b></b></b></b></b></i></b></i></b></b></i></b></b></i></b>