Name | Type | is_array | initial_value |
//TESH.scrollpos=19
//TESH.alwaysfold=0
/****************************************************************************************
* *
* 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, false, 13) --> agility
//! i Ability.new(false, "AIs1", "Istr", "STRENGTH", true, false, 13) --> strength
//! i Ability.new(false, "AIi1", "Iint", "INTELLIGENCE", true, false, 13) --> intelligence
//! i Ability.new(false, "AIlf", "Ilif", "LIFE", false, true, 21) --> life
//! i Ability.new(false, "Arel", "Ihpr", "LIFE_REGEN", true, true, 15) --> life regen
//! i Ability.new(false, "AImb", "Iman", "MANA", false, true, 8) --> mana
//! i Ability.new(true, "AIrm", "Imrp", "MANA_REGEN", true, true, 8) --> mana regen, 8 max
//! i Ability.new(false, "AIsi", "Isib", "SIGHT", true, false, 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
//TESH.scrollpos=0
//TESH.alwaysfold=0
//Writes map header to map (run once, but multiple times won't hurt)
//------------------------------------------------------------------------
//function initmap()
//comment after initialization
/*
//! externalblock extension=lua FileExporter $FILENAME$
//! runtextmacro LUA_FILE_HEADER()
//! i initmap()
//! endexternalblock
*/
//uncomment after initialization
//! import "luajass.WmW_Masters.j"
//------------------------------------------------------------------------
//import and run lua script to current script (all do same thing)
//------------------------
//function dofile(name)
//function require(name)
//function loadfile(name)
//lua scripts are shared across all maps
//jass scripts are local to a map
//returns code inside of file
//------------------------
//function readlua(name)
//function readjass(name)
//writes code to file
//------------------------
//function writelua(name, code)
//function writejass(name, code)
//deletes file
//------------------------
//function deletelua(name)
//function deletejass(name)
//! textmacro LUA_FILE_HEADER
//! i do
//replace "FILE_NAME" with the name of the map
//must be valid directory name
//! i local FILENAME = "WmW_Masters"
//! i function getfilename()
//! i return FILENAME
//! i end
//Initialization
///////////////////////////////////////////////////////////////////////
//! i local PATH_LUA_p = "grimext\\luadir"
//! i local PATH_JASS_p = PATH_LUA_p .. "\\" .. FILENAME .. "_dir"
//! i local PATH_LUA = PATH_LUA_p .. "\\"
//! i local PATH_JASS = PATH_JASS_p .. "\\"
//! i local JASS_HUB = "jass\\luajass." .. FILENAME .. ".j"
//! i function initmap()
//! i os.execute("if not exist " .. PATH_LUA .. " (mkdir " .. PATH_LUA .. ")")
//! i os.execute("if not exist " .. PATH_JASS .. " (mkdir " .. PATH_JASS .. ")")
//! i local file = io.open(JASS_HUB, "r")
//! i if (file == nil) then
//! i file = io.open(JASS_HUB, "w")
//! i file:write("")
//! i file:close()
//! i else
//! i file:close()
//! i end
//! i os.execute("if not exist grimext\\luadir\\" .. FILENAME .. "_dir (mkdir grimext\\luadir\\" .. FILENAME .. "_dir)")
//! i end
///////////////////////////////////////////////////////////////////////
//! i local olddofile = dofile
//! i local oldrequire = require
//! i local oldloadfile = loadfile
//! i function dofile(name)
//! i oldrequire("luadir\\" .. name)
//! i end
//! i function require(name)
//! i dofile(name)
//! i end
//! i function loadfile(name)
//! i dofile(name)
//! i end
//! i local function getluapath(name)
//! i return (PATH_LUA .. name .. ".lua")
//! i end
//! i local function getjasspath(name)
//! i return (PATH_JASS .. name .. ".luajass.j")
//! i end
//! i local function getjassimport(name)
//! i return ("\/\/! import \"..\\" .. getjasspath(name) .. "\"")
//! i end
//! i local function del(name)
//! i os.remove(name)
//! i end
//! i local function read(path)
//! i local file = io.open(path, "r")
//! i code = nil
//! i if (file ~= nil) then
//! i code = file:read("*all")
//! i file:close()
//! i end
//! i return code
//! i end
//! i local function write(path, code)
//! i file = io.open(path, "w")
//! i file:write(code)
//! i file:close()
//! i end
//! i local function import(name)
//! i local code = read(JASS_HUB)
//! i local line = getjassimport(name) .. "\n"
//! i local s,k = code:find(line)
//! i if (s == nil) then
//! i write(JASS_HUB, code .. line)
//! i end
//! i end
//! i function readlua(name)
//! i return read(getluapath(name))
//! i end
//! i function writelua(name, code)
//! i write(getluapath(name), code)
//! i end
//! i function readjass(name)
//! i return read(getjasspath(name))
//! i end
//! i function writejass(name, code)
//! i write(getjasspath(name), code)
//! i import(name)
//! i end
//! i function deletelua(name)
//! i del(getluapath(name))
//! i end
//! i function deletejass(name)
//! i del(getjasspath(name))
//! i local line = getjassimport(name) .. "\n"
//! i local code = read(JASS_HUB)
//! i local s,k = code:find(line)
//! i if (s ~= nil) then
//! i write(JASS_HUB, code:sub(1,s-1) .. code:sub(k+1))
//! i end
//! i end
//! i end
//! endtextmacro
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Credits to Tarrasque for Brutal Lord Model
Credits to CRAZYRUSSIAN for BTNcrCarA3 and BTNcrCarA4 Icons
Credits to HappyTauren for Skeleton Fire Warior Mage, BTNPowerLich
Credits to Dionesiist for Infernal Knight and Hellgaoler model
Credits to Frankster for Archangel model
Credits to Elenai for Resurrect icon
Credits to donut3.5 for Wraith Lord model and icon
Credits to Sellenisko for InquisitorMalendis model
Fingolfin for Helghast model
oh_snap for Helghast icon
Captain_Rufar for science icon
The_Silent for sentry tower model
Big Dub for BTNOrbVar4
kola for BTNQuestScroll
-Grendel for Assailant Spire
Pyramidhe@d for Amethyst Tower
*/
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Costs /* v1.0.0.2
*************************************************************************************
*
* */uses/*
* */ optional GetUnitCost /*
* */ optional GetItemCost /*
* */ Table /* hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
* */ WorldBounds /* hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
* */ optional UnitIndexer /* hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
*
************************************************************************************
*
* SETTINGS
*/
globals
constant integer UNITS_GET_COST = 'n002'
endglobals
/*
*
************************************************************************************/
globals
private player p=Player(14) //player to get gold/lumber costs
private unit u=null //sells/upgrades
endglobals
//! runtextmacro optional UNIT_COST()
//! runtextmacro optional ITEM_COST()
private module Init
private static method onInit takes nothing returns nothing
//! runtextmacro optional UNIT_COST_2()
set UnitIndexer.enabled=false
set u = CreateUnit(p,UNITS_GET_COST,WorldBounds.maxX,WorldBounds.maxY,0)
set UnitIndexer.enabled=true
//move seller to top right corner of map
//must be offset by 1 square 64x64 square in order to work
call SetUnitX(u,WorldBounds.maxX-64)
call SetUnitY(u,WorldBounds.maxY-64)
//! runtextmacro optional UNIT_COST_3()
//! runtextmacro optional ITEM_COST_2()
endmethod
endmodule
private struct Inits extends array
implement Init
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library GetUnitCost /* v1.0.1.0
*************************************************************************************
*
* */uses/*
* */ UnitIndexer /* hiveworkshop.com/forums/jass-functions-413/system-unit-indexer-172090/
* */ RegisterPlayerUnitEvent /* hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
*
************************************************************************************
*
* Functions
*
* function GetUnitTypeIdGoldCost takes integer unitTypeId returns integer
* function GetUnitTypeIdWoodCost takes integer unitTypeId returns integer
*
* NATIVES WORK WITH NON-HERO UNITS ONLY
*/
native GetUnitGoldCost takes integer unitid returns integer
native GetUnitWoodCost takes integer unitid returns integer
/*
* function GetUnitTotalGoldCost takes unit whichUnit returns integer
* - Gets total unit gold cost including prior upgrades
* function GetUnitTotalWoodCost takes unit whichUnit returns integer
* - Gets total unit wood cost including prior upgrades
*
************************************************************************************/
//! textmacro UNIT_COST
globals
private Table g = 0 //unit type id gold cost table
private Table l = 0 //unit type id lumber cost table
private integer array gu //unit gold cost array (indexed)
private integer array lu //unit lumber cost array (indexed)
private integer array ug //upgrade gold
private integer array ul //upgrade lumber
endglobals
//unit cost (sell)
private function O takes nothing returns boolean
call RemoveUnit(GetSoldUnit())
return false
endfunction
private function LogUnit takes integer id returns nothing
//store previous gold, lumber, and food
local integer k=GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)
local integer w=GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)
local integer h=GetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_USED)
local integer m=GetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_CAP)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,1000000)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER,1000000)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_USED,0)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_CAP,100000)
//build unit
set UnitIndexer.enabled=false
call AddUnitToStock(u,id,1,1)
call IssueNeutralImmediateOrderById(p,u,id)
call RemoveUnitFromStock(u,id)
set UnitIndexer.enabled = true
//retrieve gold and lumber cost
set g[id]=1000000-GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)
set l[id]=1000000-GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)
//set player gold back to what it was
call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,k)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER,w)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_USED,h)
call SetPlayerState(p,PLAYER_STATE_RESOURCE_FOOD_CAP,m)
endfunction
function GetUnitTypeIdGoldCost takes integer id returns integer
debug if (null!=UnitId2String(id)) then
if (not g.has(id)) then
if (IsHeroUnitId(id)) then
call LogUnit(id)
else
set g[id]=GetUnitGoldCost(id)
set l[id]=GetUnitWoodCost(id)
endif
endif
return g[id]
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"COSTS ERROR: INVALID UNIT TYPE ID")
debug endif
debug return 0
endfunction
function GetUnitTypeIdWoodCost takes integer id returns integer
debug if (null!=UnitId2String(id)) then
if (not g.has(id)) then
if (IsHeroUnitId(id)) then
call LogUnit(id)
else
set g[id]=GetUnitGoldCost(id)
set l[id]=GetUnitWoodCost(id)
endif
endif
return l[id]
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"COSTS ERROR: INVALID UNIT TYPE ID")
debug endif
debug return 0
endfunction
function GetUnitTotalGoldCost takes unit t returns integer
debug if (null!=t) then
if (0==GetUnitUserData(t)) then
return GetUnitTypeIdGoldCost(GetUnitTypeId(t))
endif
return gu[GetUnitUserData(t)]
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"COSTS ERROR: INVALID UNIT")
debug endif
debug return 0
endfunction
function GetUnitTotalWoodCost takes unit t returns integer
debug if (null!=t) then
if (0==GetUnitUserData(t)) then
return GetUnitTypeIdWoodCost(GetUnitTypeId(t))
endif
return lu[GetUnitUserData(t)]
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"COSTS ERROR: INVALID UNIT")
debug endif
debug return 0
endfunction
//on unit index
private function I takes nothing returns boolean
local integer i=GetUnitTypeId(GetIndexedUnit())
local integer k=GetIndexedUnitId()
//store gold/lumber cost for unit
set gu[k]=GetUnitTypeIdGoldCost(i)
set lu[k]=l[i]
return false
endfunction
//on unit deindex
private function D takes nothing returns boolean
local integer k=GetIndexedUnitId()
//reset gold/lumber cost for unit
set gu[k]=0
set lu[k]=0
return false
endfunction
//on unit upgrade start
private function US takes nothing returns boolean
local integer k=GetUnitUserData(GetTriggerUnit())
local integer i=GetUnitTypeId(GetTriggerUnit())
//if the unit is indexed, store upgrade gold/lumber cost
if (0!=k) then
set ug[k]=GetUnitTypeIdGoldCost(i)
set ul[k]=l[i]
set gu[k]=ug[k]+gu[k]
set lu[k]=ul[k]+lu[k]
endif
return false
endfunction
//on unit upgrade cancel
private function UC takes nothing returns boolean
local integer k=GetUnitUserData(GetTriggerUnit())
//if unit is indexed, add upgrade cost to cost
if (0!=k) then
set gu[k]=gu[k]-ug[k]
set lu[k]=lu[k]-ul[k]
endif
return false
endfunction
//! endtextmacro
//! textmacro UNIT_COST_2
local trigger t=CreateTrigger() //sell unit
//! endtextmacro
//! textmacro UNIT_COST_3
set g=Table.create() //gold table
set l=Table.create() //lumber table
//register unit indexing for setting/resetting gold/lumber costs for units
call RegisterUnitIndexEvent(Condition(function I),UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function D),UnitIndexer.DEINDEX)
//this is done for removing units that are sold for getting their costs
call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_SELL)
call TriggerAddCondition(t,Condition(function O))
//this is done for updating unit gold/lumber costs on upgrade
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_START, Condition(function US))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_CANCEL, Condition(function UC))
//! endtextmacro
endlibrary
//TESH.scrollpos=169
//TESH.alwaysfold=0
library Table // made by Bribe, special thanks to Nestharus, version 3.0.0.0
/*
API
------------
struct Table
| static method create takes nothing returns Table
| create a new Table
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush all stored values inside of it
|
| method remove takes integer key returns nothing
| remove the value at index "key"
|
| method operator []= takes integer key, $TYPE$ value returns nothing
| assign "value" to index "key"
|
| method operator [] takes integer key returns $TYPE$
| load the value at index "key"
|
| method has takes integer key returns boolean
| whether or not the key was assigned
|
----------------
struct TableArray
| static method operator [] takes integer array_size returns TableArray
| create a new array of Tables of size "array_size"
|
| method destroy takes nothing returns nothing
| destroy it
|
| method flush takes nothing returns nothing
| flush and destroy it
|
| method operator size takes nothing returns integer
| returns the size of the TableArray
|
| method operator [] takes integer key returns Table
| returns a Table accessible exclusively to index "key"
*/
globals
private hashtable ht = InitHashtable() //The last hashtable you need
private integer more = 2 //Index generation for Tables (above 2)
private integer less = 0 //Index generation for TableArrays (below 0)
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return 1
endmethod
static method operator list takes nothing returns Table
return 2
endmethod
endstruct
private struct handles extends array
method has takes integer key returns boolean
return HaveSavedHandle(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedHandle(ht, this, key)
endmethod
endstruct
private struct agents extends array
method operator []= takes integer key, agent value returns nothing
call SaveAgentHandle(ht, this, key, value)
endmethod
endstruct
//! textmacro NEW_ARRAY_BASIC takes SUPER, FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$(ht, this, key, value)
endmethod
method has takes integer key returns boolean
return HaveSaved$SUPER$(ht, this, key)
endmethod
method remove takes integer key returns nothing
call RemoveSaved$SUPER$(ht, this, key)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//! textmacro NEW_ARRAY takes FUNC, TYPE
private struct $TYPE$s extends array
method operator [] takes integer key returns $TYPE$
return Load$FUNC$Handle(ht, this, key)
endmethod
method operator []= takes integer key, $TYPE$ value returns nothing
call Save$FUNC$Handle(ht, this, key, value)
endmethod
endstruct
private module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
//! runtextmacro NEW_ARRAY("Player", "player")
//! runtextmacro NEW_ARRAY("Widget", "widget")
//! runtextmacro NEW_ARRAY("Destructable", "destructable")
//! runtextmacro NEW_ARRAY("Item", "item")
//! runtextmacro NEW_ARRAY("Unit", "unit")
//! runtextmacro NEW_ARRAY("Ability", "ability")
//! runtextmacro NEW_ARRAY("Timer", "timer")
//! runtextmacro NEW_ARRAY("Trigger", "trigger")
//! runtextmacro NEW_ARRAY("TriggerCondition", "triggercondition")
//! runtextmacro NEW_ARRAY("TriggerAction", "triggeraction")
//! runtextmacro NEW_ARRAY("TriggerEvent", "event")
//! runtextmacro NEW_ARRAY("Force", "force")
//! runtextmacro NEW_ARRAY("Group", "group")
//! runtextmacro NEW_ARRAY("Location", "location")
//! runtextmacro NEW_ARRAY("Rect", "rect")
//! runtextmacro NEW_ARRAY("BooleanExpr", "boolexpr")
//! runtextmacro NEW_ARRAY("Sound", "sound")
//! runtextmacro NEW_ARRAY("Effect", "effect")
//! runtextmacro NEW_ARRAY("UnitPool", "unitpool")
//! runtextmacro NEW_ARRAY("ItemPool", "itempool")
//! runtextmacro NEW_ARRAY("Quest", "quest")
//! runtextmacro NEW_ARRAY("QuestItem", "questitem")
//! runtextmacro NEW_ARRAY("DefeatCondition", "defeatcondition")
//! runtextmacro NEW_ARRAY("TimerDialog", "timerdialog")
//! runtextmacro NEW_ARRAY("Leaderboard", "leaderboard")
//! runtextmacro NEW_ARRAY("Multiboard", "multiboard")
//! runtextmacro NEW_ARRAY("MultiboardItem", "multiboarditem")
//! runtextmacro NEW_ARRAY("Trackable", "trackable")
//! runtextmacro NEW_ARRAY("Dialog", "dialog")
//! runtextmacro NEW_ARRAY("Button", "button")
//! runtextmacro NEW_ARRAY("TextTag", "texttag")
//! runtextmacro NEW_ARRAY("Lightning", "lightning")
//! runtextmacro NEW_ARRAY("Image", "image")
//! runtextmacro NEW_ARRAY("Ubersplat", "ubersplat")
//! runtextmacro NEW_ARRAY("Region", "region")
//! runtextmacro NEW_ARRAY("FogState", "fogstate")
//! runtextmacro NEW_ARRAY("FogModifier", "fogmodifier")
//! runtextmacro NEW_ARRAY("Hashtable", "hashtable")
struct Table extends array
// Implement modules for intuitive type-syntax
implement realm
implement booleanm
implement stringm
implement playerm
implement widgetm
implement destructablem
implement itemm
implement unitm
implement abilitym
implement timerm
implement triggerm
implement triggerconditionm
implement triggeractionm
implement eventm
implement forcem
implement groupm
implement locationm
implement rectm
implement boolexprm
implement soundm
implement effectm
implement unitpoolm
implement itempoolm
implement questm
implement questitemm
implement defeatconditionm
implement timerdialogm
implement leaderboardm
implement multiboardm
implement multiboarditemm
implement trackablem
implement dialogm
implement buttonm
implement texttagm
implement lightningm
implement imagem
implement ubersplatm
implement regionm
implement fogstatem
implement fogmodifierm
implement hashtablem
method operator handle takes nothing returns handles
return this
endmethod
method operator agent takes nothing returns agents
return this
endmethod
// set this = a[GetSpellAbilityId()]
method operator [] takes integer key returns Table
return LoadInteger(ht, this, key)
endmethod
// set a[389034] = 8192
method operator []= takes integer key, Table a returns nothing
call SaveInteger(ht, this, key, a)
endmethod
// set b = a.has(2493223)
method has takes integer key returns boolean
return HaveSavedInteger(ht, this, key)
endmethod
// call a.remove(294080)
method remove takes integer key returns nothing
call RemoveSavedInteger(ht, this, key)
endmethod
// Remove all data from a Table instance
method flush takes nothing returns nothing
call FlushChildHashtable(ht, this)
endmethod
// local Table a = Table.create()
static method create takes nothing returns Table
local Table this = dex.list[0]
if this == 0 then
set more = more + 1
set this = more
else
set dex.list[0] = dex.list[this]
call dex.list.remove(this)
endif
debug set dex.list[this] = -1
return this
endmethod
// Removes all data from a Table instance and recycles its index.
//
// call a.destroy()
//
method destroy takes nothing returns nothing
debug if dex.list[this] != -1 then
debug call BJDebugMsg("Table Error: Tried to double-free instance: " + I2S(this))
debug return
debug endif
call this.flush()
set dex.list[this] = dex.list[0]
set dex.list[0] = this
endmethod
endstruct
struct TableArray extends array
//Returns a new TableArray to do your bidding. Simply use:
//
// local TableArray ta = TableArray[array_size]
//
static method operator [] takes integer array_size returns TableArray
local Table a = dex.size[array_size] //Get the unique recycle list for this array size
local TableArray this = a[0] //The last-destroyed TableArray that had this array size
debug if array_size <= 0 then
debug call BJDebugMsg("TypeError: Invalid specified TableArray size: " + I2S(array_size))
debug return 0
debug endif
if this == 0 then
set less = less - array_size
set this = less
else
set a[0] = a[this] //Set the last destroyed to the last-last destroyed
call a.remove(this) //Clear hash memory
endif
set dex.size[this] = array_size //This remembers the array size
return this
endmethod
//Returns the size of the TableArray
method operator size takes nothing returns integer
return dex.size[this]
endmethod
//da[integer a].unit[integer b] = unit u
//da[integer a][integer c] = integer d
//
//Inline-friendly when not running in debug mode
//
method operator [] takes integer key returns Table
static if DEBUG_MODE then
local integer i = this.size
if i == 0 then
call BJDebugMsg("IndexError: Tried to get key from invalid TableArray instance: " + I2S(this))
return 0
elseif key < 0 or key >= i then
call BJDebugMsg("IndexError: Tried to get key [" + I2S(key) + "] from outside TableArray bounds: " + I2S(i))
return 0
endif
endif
return this + key
endmethod
//Destroys a TableArray without flushing it; assumed you'd call .flush()
//if you want it flushed too. This is public so that if you are flushing
//instances the whole time you don't waste efficiency when disposing the
//TableArray.
//
method destroy takes nothing returns nothing
local Table a = dex.size[this.size]
debug if this.size <= 0 then
debug call BJDebugMsg("TypeError: Tried to destroy an invalid TableArray: " + I2S(this))
debug return
debug endif
if a == 0 then
//Create an array to index recycled instances with their array size
set a = Table.create()
set dex.size[this.size] = a
endif
call dex.size.remove(this) //Clear the array size from hash memory
set a[this] = a[0]
set a[0] = this
endmethod
//All you need to know about this one is that it won't hit the op limit.
private static method clean takes Table a, integer end returns nothing
local integer i = a + 5000
if i < end then
call clean.evaluate(i, end)
set end = i
endif
loop
call a.flush()
set a = a + 1
exitwhen a == end
endloop
endmethod
//Flushes the TableArray and also destroys it. Doesn't get any more
//similar to the FlushParentHashtable native than this.
//
method flush takes nothing returns nothing
local integer end = this.size + this
debug if this == end then
debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
debug return
debug endif
call clean.evaluate(this, end)
call this.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Event /* v2.0.0.1
************************************************************************************
*
* Functions
*
* function CreateEvent takes nothing returns integer
* function TriggerRegisterEvent takes trigger t, integer ev returns nothing
*
************************************************************************************
*
* struct Event extends array
*
* static method create takes nothing returns thistype
* method registerTrigger takes trigger t returns nothing
* method register takes boolexpr c returns nothing
* method fire takes nothing returns nothing
*
************************************************************************************/
globals
private real q=0
endglobals
struct Event extends array
private static integer w=0
private static trigger array e
static method create takes nothing returns thistype
set w=w+1
set e[w]=CreateTrigger()
return w
endmethod
method registerTrigger takes trigger t returns nothing
call TriggerRegisterVariableEvent(t,SCOPE_PRIVATE+"q",EQUAL,this)
endmethod
method register takes boolexpr c returns nothing
call TriggerAddCondition(e[this],c)
endmethod
method fire takes nothing returns nothing
set q=0
set q=this
call TriggerEvaluate(e[this])
endmethod
endstruct
function CreateEvent takes nothing returns Event
return Event.create()
endfunction
function TriggerRegisterEvent takes trigger t,Event ev returns nothing
call ev.registerTrigger(t)
endfunction
function RegisterEvent takes boolexpr c,Event ev returns nothing
call ev.register(c)
endfunction
function FireEvent takes Event ev returns nothing
call ev.fire()
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitIndexer /* v4.0.2.5
*************************************************************************************
*
* Assigns unique indexes to units via unit user data.
*
*************************************************************************************
*
* */uses/*
* */ WorldBounds /* hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
* */ Event /* hiveworkshop.com/forums/submissions-414/snippet-event-186555/
*
************************************************************************************
*
* Functions
*
* function RegisterUnitIndexEvent takes boolexpr codeToRegister, Event unitIndexEvent returns nothing
* function TriggerRegisterUnitIndexEvent takes trigger triggerToRegister, Event unitIndexEvent returns nothing
*
* function GetUnitById takes integer index returns unit
* - Returns unit given a unit index
* function GetUnitId takes unit u returns integer
* - Returns unit index given a unit
*
* function IsUnitIndexed takes unit u returns boolean
* function IsUnitDeindexing takes unit u returns boolean
*
* function GetIndexedUnitId takes nothing returns integer
* function GetIndexedUnit takes nothing returns unit
*
************************************************************************************
*
* module UnitIndexStruct
*
* - A pseudo module interface that runs a set of methods if they exist and provides
* - a few fields and operators. Runs on static ifs to minimize code.
*
* static method operator [] takes unit u returns thistype
* - Return GetUnitUserData(u)
*
* readonly unit unit
* - The indexed unit of the struct
* readonly boolean allocated
* - Is unit allocated for the struct
*
* Interface:
*
* - These methods don't have to exist. If they don't exist, the code
* - that calls them won't even be in the module.
*
* private method index takes nothing returns nothing
* - called when a unit is indexed and passes the filter.
* -
* - thistype this: Unit's index
* private method deindex takes nothing returns nothing
* - called when a unit is deindexed and is allocated for struct
* -
* - thistype this: Unit's index
* private static method filter takes unit unitToIndex returns boolean
* - Determines whether or not to allocate struct for unit
* -
* - unit unitToIndex: Unit being filtered
*
************************************************************************************
*
* struct UnitIndexer extends array
*
* - Controls the unit indexer system.
*
* static constant Event UnitIndexer.INDEX
* static constant Event UnitIndexer.DEINDEX
* - Don't register functions and triggers directly to the events. Register them via
* - RegisterUnitIndexEvent and TriggerRegisterUnitIndexEvent.
*
* static boolean enabled
* - Enables and disables unit indexing. Useful for filtering out dummy units.
*
************************************************************************************
*
* struct UnitIndex extends array
*
* - Constrols specific unit indexes.
*
* method lock takes nothing returns nothing
* - Locks an index. When an index is locked, it will not be recycled
* - when the unit is deindexed until all locks are removed. Deindex
* - events still fire at the appropriate times, the index just doesn't
* - get thrown into the recycler.
* method unlock takes nothing returns nothing
* - Unlocks an index.
*
************************************************************************************/
globals
private trigger q=CreateTrigger()
private trigger l=CreateTrigger()
private unit array e
private integer r=0
private integer y=0
private integer o=0
private boolean a=false
private integer array n
private integer array p
private integer array lc
endglobals
function GetIndexedUnitId takes nothing returns integer
return o
endfunction
function GetIndexedUnit takes nothing returns unit
return e[o]
endfunction
//! runtextmacro optional UNIT_LIST_LIB()
private struct PreLoader extends array
public static method run takes nothing returns nothing
call DestroyTimer(GetExpiredTimer())
set a=true
endmethod
public static method eval takes trigger t returns nothing
local integer f=n[0]
local integer d=o
loop
exitwhen 0==f
if (IsTriggerEnabled(t)) then
set o=f
if (TriggerEvaluate(t)) then
call TriggerExecute(t)
endif
else
exitwhen true
endif
set f=n[f]
endloop
set o=d
endmethod
public static method evalb takes boolexpr c returns nothing
local trigger t=CreateTrigger()
local thistype f=n[0]
local integer d=o
call TriggerAddCondition(t,c)
loop
exitwhen 0==f
set o=f
call TriggerEvaluate(t)
set f=n[f]
endloop
call DestroyTrigger(t)
set t=null
set o=d
endmethod
endstruct
//! runtextmacro optional UNIT_EVENT_MACRO()
private module UnitIndexerInit
private static method onInit takes nothing returns nothing
local integer i=15
local boolexpr bc=Condition(function thistype.onLeave)
local boolexpr bc2=Condition(function thistype.onEnter)
local group g=CreateGroup()
local player p
set INDEX=CreateEvent()
set DEINDEX=CreateEvent()
call TriggerRegisterEnterRegion(q,WorldBounds.worldRegion,bc2)
loop
set p=Player(i)
call TriggerRegisterPlayerUnitEvent(l,p,EVENT_PLAYER_UNIT_ISSUED_ORDER,bc)
call SetPlayerAbilityAvailable(p,ABILITIES_UNIT_INDEXER,false)
call GroupEnumUnitsOfPlayer(g,p,bc2)
exitwhen 0==i
set i=i-1
endloop
call DestroyGroup(g)
set bc=null
set g=null
set bc2=null
set p=null
call TimerStart(CreateTimer(),0,false,function PreLoader.run)
endmethod
endmodule
struct UnitIndex extends array
method lock takes nothing returns nothing
debug if (null!=e[this]) then
set lc[this]=lc[this]+1
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"UNIT INDEXER ERROR: ATTEMPT TO LOCK NULL INDEX")
debug endif
endmethod
method unlock takes nothing returns nothing
debug if (0<lc[this]) then
set lc[this]=lc[this]-1
if (0==lc[this] and null==e[this]) then
set n[this]=y
set y=this
endif
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"UNIT INDEXER ERROR: ATTEMPT TO UNLOCK UNLOCKED INDEX")
debug endif
endmethod
endstruct
struct UnitIndexer extends array
readonly static Event INDEX
readonly static Event DEINDEX
static method operator enabled= takes boolean b returns nothing
if (b) then
call EnableTrigger(l)
call EnableTrigger(q)
else
call DisableTrigger(l)
call DisableTrigger(q)
endif
endmethod
static method operator enabled takes nothing returns boolean
return IsTriggerEnabled(l)
endmethod
private static method onEnter takes nothing returns boolean
local unit Q=GetFilterUnit()
local integer i
local integer d=o
if (Q!=e[GetUnitUserData(Q)]) then
if (0==y) then
set r=r+1
set i=r
else
set i=y
set y=n[y]
endif
call UnitAddAbility(Q,ABILITIES_UNIT_INDEXER)
call UnitMakeAbilityPermanent(Q,true,ABILITIES_UNIT_INDEXER)
call SetUnitUserData(Q,i)
set e[i]=Q
static if not LIBRARY_UnitList then
if (not a)then
set p[i]=p[0]
set n[p[0]]=i
set n[i]=0
set p[0]=i
endif
else
set p[i]=p[0]
set n[p[0]]=i
set n[i]=0
set p[0]=i
call GroupAddUnit(g,e[i])
endif
set o=i
call FireEvent(INDEX)
set o=d
endif
set Q=null
return false
endmethod
private static method onLeave takes nothing returns boolean
static if LIBRARY_UnitEvent then
implement optional UnitEventModule
else
local unit u=GetFilterUnit()
local integer i=GetUnitUserData(u)
local integer d=o
if (0==GetUnitAbilityLevel(u,ABILITIES_UNIT_INDEXER) and u==e[i]) then
static if not LIBRARY_UnitList then
if (not a)then
set n[p[i]]=n[i]
set p[n[i]]=p[i]
endif
else
set n[p[i]]=n[i]
set p[n[i]]=p[i]
call GroupRemoveUnit(g,e[i])
endif
set o=i
call FireEvent(DEINDEX)
set o=d
if (0==lc[i]) then
set n[i]=y
set y=i
endif
set e[i]=null
endif
set u=null
endif
return false
endmethod
implement UnitIndexerInit
endstruct
//! runtextmacro optional UNIT_EVENT_MACRO_2()
function RegisterUnitIndexEvent takes boolexpr c,integer ev returns nothing
call RegisterEvent(c, ev)
if (not a and ev==UnitIndexer.INDEX and 0!=n[0]) then
call PreLoader.evalb(c)
endif
endfunction
function TriggerRegisterUnitIndexEvent takes trigger t,integer ev returns nothing
call TriggerRegisterEvent(t,ev)
if (not a and ev == UnitIndexer.INDEX and 0!=n[0]) then
call PreLoader.eval(t)
endif
endfunction
function GetUnitById takes integer W returns unit
return e[W]
endfunction
function GetUnitId takes unit u returns integer
return GetUnitUserData(u)
endfunction
function IsUnitIndexed takes unit u returns boolean
return u==e[GetUnitUserData(u)]
endfunction
function IsUnitDeindexing takes unit u returns boolean
return IsUnitIndexed(u) and 0==GetUnitAbilityLevel(u,ABILITIES_UNIT_INDEXER)
endfunction
module UnitIndexStruct
static method operator [] takes unit u returns thistype
return GetUnitUserData(u)
endmethod
method operator unit takes nothing returns unit
return e[this]
endmethod
static if thistype.filter.exists then
static if thistype.index.exists then
static if thistype.deindex.exists then
readonly boolean allocated
else
method operator allocated takes nothing returns boolean
return filter(e[this])
endmethod
endif
else
method operator allocated takes nothing returns boolean
return filter(e[this])
endmethod
endif
elseif (thistype.index.exists) then
static if thistype.deindex.exists then
readonly boolean allocated
else
method operator allocated takes nothing returns boolean
return this==GetUnitUserData(e[this])
endmethod
endif
else
method operator allocated takes nothing returns boolean
return this==GetUnitUserData(e[this])
endmethod
endif
static if thistype.index.exists then
private static method onIndexEvent takes nothing returns boolean
static if thistype.filter.exists then
if (filter(e[o])) then
static if thistype.deindex.exists then
set thistype(o).allocated=true
endif
call thistype(o).index()
endif
else
static if thistype.deindex.exists then
set thistype(o).allocated=true
endif
call thistype(o).index()
endif
return false
endmethod
endif
static if thistype.deindex.exists then
private static method onDeindexEvent takes nothing returns boolean
static if thistype.filter.exists then
static if thistype.index.exists then
if (thistype(o).allocated) then
set thistype(o).allocated=false
call thistype(o).deindex()
endif
else
if (filter(e[o])) then
call thistype(o).deindex()
endif
endif
else
static if thistype.index.exists then
set thistype(o).allocated=false
endif
call thistype(o).deindex()
endif
return false
endmethod
endif
static if thistype.index.exists then
static if thistype.deindex.exists then
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.onIndexEvent),UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.onDeindexEvent),UnitIndexer.DEINDEX)
endmethod
else
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.onIndexEvent),UnitIndexer.INDEX)
endmethod
endif
elseif thistype.deindex.exists then
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.onDeindexEvent),UnitIndexer.DEINDEX)
endmethod
endif
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library WorldBounds /* v2.0.0.0
************************************************************************************
*
* struct WorldBounds extends array
* readonly static integer maxX
* readonly static integer maxY
* readonly static integer minX
* readonly static integer minY
* readonly static integer centerX
* readonly static integer centerY
* readonly static rect world
* readonly static region worldRegion
*
************************************************************************************/
private module WorldBoundInit
private static method onInit takes nothing returns nothing
set world=GetWorldBounds()
set maxX=R2I(GetRectMaxX(world))
set maxY=R2I(GetRectMaxY(world))
set minX=R2I(GetRectMinX(world))
set minY=R2I(GetRectMinY(world))
set centerX=R2I((maxX+minX)/2)
set centerY=R2I((minY+maxY)/2)
set worldRegion=CreateRegion()
call RegionAddRect(worldRegion,world)
endmethod
endmodule
struct WorldBounds extends array
readonly static integer maxX
readonly static integer maxY
readonly static integer minX
readonly static integer minY
readonly static integer centerX
readonly static integer centerY
readonly static rect world
readonly static region worldRegion
implement WorldBoundInit
endstruct
endlibrary
//TESH.scrollpos=29
//TESH.alwaysfold=0
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.0.0.0
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must
* return false. They can return nothing as well. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* returns
* nothing
*
* - Registers code that will execute when an event fires.
*
* - function RegisterPlayerUnitEventForPlayer
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* player whichPlayer : The player you would like to register the event for
* returns
* nothing
*
* - Registers code that will execute when an event fires for a certain player.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, boolexpr c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t[i] == null then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t[i], c)
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, boolexpr c, player pl returns nothing
local integer i = 260 + 16 * GetHandleId(p) + GetPlayerId(pl)
if t[i] == null then
set t[i] = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
endif
call TriggerAddCondition(t[i], c)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Multiboard /* v2.0.0.0
*************************************************************************************
*
* Multiboard Struct API that actually works and is actually easy to use.
*
*************************************************************************************
*
* */uses/*
*
* */ Table /* hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
*
************************************************************************************
*
* struct Multiboard
*
* string title
* boolean display
* boolean minimize
* boolean suppress
*
* real width= (set only)
* string icon= (set only)
* string text= (set only)
*
* readonly MultiboardRow row
* readonly MultiboardColumn column
*
* this[row][column] -> MultiboardItem
*
* static method create takes integer rowCount, integer columnCount returns Multiboard
* method destroy takes nothing returns nothing
*
* method clear takes nothing returns nothing
*
* method setTitleColor takes integer red, integer green, integer blue, integer alpha returns nothing
* method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
* method setStyle takes boolean showValues, boolean showIcons returns nothing
*
************************************************************************************
*
* struct MultiboardRow extends array
* struct MultiboardColumn extends array
*
* integer count
* - row.count
*
* string text
* string icon=
* real width=
* - row[0].width
*
* method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
* method setStyle takes boolean showValue, boolean showIcon returns nothing
* - row[0].setStyle
*
************************************************************************************
*
* struct MultiboardItem extends array
*
* string text= (set only)
* string icon= (set only)
* real width= (set only)
*
* method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
* method setStyle takes boolean showValue, boolean showIcon returns nothing
*
************************************************************************************/
globals
private Table table
private Table table2
private integer array r
private integer ic = 0
private multiboard array boardp
private integer array rc
private integer array cc
private boolean array suppressed
endglobals
private module Init
private static method onInit takes nothing returns nothing
set table = Table.create()
set table2 = Table.create()
endmethod
endmodule
struct MultiboardItem extends array
method operator text= takes string value returns nothing
call MultiboardSetItemValue(table.multiboarditem[this], value)
endmethod
method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
call MultiboardSetItemValueColor(table.multiboarditem[this], red, green, blue, alpha)
endmethod
method setStyle takes boolean showValue, boolean showIcon returns nothing
call MultiboardSetItemStyle(table.multiboarditem[this], showValue, showIcon)
endmethod
method operator icon= takes string str returns nothing
call MultiboardSetItemIcon(table.multiboarditem[this], str)
endmethod
method operator width= takes real percent returns nothing
call MultiboardSetItemWidth(table.multiboarditem[this], percent)
endmethod
implement Init
endstruct
//! textmacro MULTIBOARD_LOOPER takes ROW, TABLE, CODE
local multiboarditem mb
loop
exitwhen 0 == c
set mb = $TABLE$.multiboarditem[this]
call $CODE$
set this = this + 1
set c = c - 1
endloop
set mb = null
//! endtextmacro
private keyword Multiboard2D
private keyword getItems
private keyword clearItems
struct Multiboard extends array
method getItems takes nothing returns nothing
local integer row = rc[this]
local integer column
local multiboarditem mb
loop
set column = cc[this]
loop
set mb = MultiboardGetItem(boardp[this], row, column)
set table.multiboarditem[(this*500+row)*500+column] = mb
set table2.multiboarditem[(this*500+column)*500+row] = mb
exitwhen 0 == column
set column = column - 1
endloop
exitwhen 0 == row
set row = row - 1
endloop
set mb = null
endmethod
method clearItems takes nothing returns nothing
local integer row = rc[this]
local integer column
loop
set column = cc[this]
loop
call MultiboardReleaseItem(table.multiboarditem[(this*500+row)*500+column])
call table.handle.remove((this*500+row)*500+column)
call table2.handle.remove((this*500+column)*500+row)
exitwhen 0 == column
set column = column - 1
endloop
exitwhen 0 == row
set row = row - 1
endloop
endmethod
static method create takes integer rowCount, integer columnCount returns thistype
local thistype this = r[0]
if (0 == this) then
set this = ic + 1
set ic = this
else
set suppressed[this] = false
set r[0] = r[this]
endif
set boardp[this] = CreateMultiboard()
call MultiboardSetColumnCount(boardp[this], columnCount)
call MultiboardSetRowCount(boardp[this], rowCount)
set rc[this] = rowCount
set cc[this] = columnCount
call getItems()
return this
endmethod
method destroy takes nothing returns nothing
set r[this] = r[0]
set r[0] = this
call clearItems()
call DestroyMultiboard(boardp[this])
set boardp[this] = null
endmethod
method clear takes nothing returns nothing
call MultiboardClear(boardp[this])
endmethod
method operator display takes nothing returns boolean
return IsMultiboardDisplayed(boardp[this])
endmethod
method operator display= takes boolean b returns nothing
call MultiboardDisplay(boardp[this], b)
endmethod
method operator minimize takes nothing returns boolean
return IsMultiboardMinimized(boardp[this])
endmethod
method operator minimize= takes boolean b returns nothing
call MultiboardMinimize(boardp[this], b)
endmethod
method operator title takes nothing returns string
return MultiboardGetTitleText(boardp[this])
endmethod
method operator title= takes string txt returns nothing
call MultiboardSetTitleText(boardp[this], txt)
endmethod
method setTitleColor takes integer red, integer green, integer blue, integer alpha returns nothing
call MultiboardSetTitleTextColor(boardp[this], red, green, blue, alpha)
endmethod
method operator suppress takes nothing returns boolean
return suppressed[this]
endmethod
method operator suppress= takes boolean b returns nothing
set suppressed[this] = b
call MultiboardSuppressDisplay(b)
endmethod
method operator width= takes real percent returns nothing
call MultiboardSetItemsWidth(boardp[this], percent)
endmethod
method operator row takes nothing returns MultiboardRow
return this
endmethod
method operator column takes nothing returns MultiboardColumn
return this
endmethod
method operator [] takes integer row returns Multiboard2D
return this*500+row
endmethod
method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
call MultiboardSetItemsValueColor(boardp[this], red, green, blue, alpha)
endmethod
method setStyle takes boolean showValues, boolean showIcons returns nothing
call MultiboardSetItemsStyle(boardp[this], showValues, showIcons)
endmethod
method operator icon= takes string txt returns nothing
call MultiboardSetItemsIcon(boardp[this], txt)
endmethod
method operator text= takes string txt returns nothing
call MultiboardSetItemsValue(boardp[this], txt)
endmethod
endstruct
private struct MultiboardSet extends array
method text takes string v, integer c, Table t returns nothing
//! runtextmacro MULTIBOARD_LOOPER("c", "t", "MultiboardSetItemValue(mb, v)")
endmethod
method color takes integer red, integer green, integer blue, integer alpha, integer c, Table t returns nothing
//! runtextmacro MULTIBOARD_LOOPER("c", "t", "MultiboardSetItemValueColor(mb, red, green, blue, alpha)")
endmethod
method style takes boolean v, boolean i, integer c, Table t returns nothing
//! runtextmacro MULTIBOARD_LOOPER("c", "t", "MultiboardSetItemStyle(mb, v, i)")
endmethod
method icon takes string s, integer c, Table t returns nothing
//! runtextmacro MULTIBOARD_LOOPER("c", "t", "MultiboardSetItemIcon(mb, s)")
endmethod
method width takes real p, integer c, Table t returns nothing
//! runtextmacro MULTIBOARD_LOOPER("c", "t", "MultiboardSetItemWidth(mb, p)")
endmethod
endstruct
struct MultiboardColumn extends array
method operator count takes nothing returns integer
return MultiboardGetColumnCount(boardp[this])
endmethod
method operator count= takes integer columns returns nothing
call Multiboard(this).clearItems()
call MultiboardSetColumnCount(boardp[this], columns)
set cc[this] = columns
call Multiboard(this).getItems()
endmethod
method operator text= takes string value returns nothing
call MultiboardSet(this).text(value, rc[this/250000], table2)
endmethod
method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
call MultiboardSet(this).color(red, green, blue, alpha, rc[this/250000], table2)
endmethod
method setStyle takes boolean showValue, boolean showIcon returns nothing
call MultiboardSet(this).style(showValue, showIcon, rc[this/250000], table2)
endmethod
method operator icon= takes string str returns nothing
call MultiboardSet(this).icon(str, rc[this/250000], table2)
endmethod
method operator width= takes real percent returns nothing
call MultiboardSet(this).width(percent, rc[this/250000], table2)
endmethod
method operator [] takes integer column returns thistype
return (this*500+column)*500
endmethod
endstruct
struct MultiboardRow extends array
method operator count takes nothing returns integer
return MultiboardGetRowCount(boardp[this])
endmethod
method operator count= takes integer rows returns nothing
call Multiboard(this).clearItems()
call MultiboardSetRowCount(boardp[this], rows)
set rc[this] = rows
call Multiboard(this).getItems()
endmethod
method operator text= takes string value returns nothing
call MultiboardSet(this).text(value, cc[this/250000], table)
endmethod
method setColor takes integer red, integer green, integer blue, integer alpha returns nothing
call MultiboardSet(this).color(red, green, blue, alpha, cc[this/250000], table)
endmethod
method setStyle takes boolean showValue, boolean showIcon returns nothing
call MultiboardSet(this).style(showValue, showIcon, cc[this/250000], table)
endmethod
method operator icon= takes string str returns nothing
call MultiboardSet(this).icon(str, cc[this/250000], table)
endmethod
method operator width= takes real percent returns nothing
call MultiboardSet(this).width(percent,cc[this/250000], table)
endmethod
method operator [] takes integer row returns thistype
return (this*500+row)*500
endmethod
endstruct
private struct Multiboard2D extends array
method operator [] takes integer column returns MultiboardItem
return this*500+column
endmethod
endstruct
endlibrary
//TESH.scrollpos=8
//TESH.alwaysfold=0
library PlayerColorUtils uses Table
// PlayerColor Utils by The_Witcher
//
// Just a bunch of functions for easier player <-> color string handling
//
// Feel free to use!
//
// Functions:
// function GetPlayerColorStringById takes integer i returns string
globals
private string array colors
private Table ids
endglobals
// Get the color string for a specific player
function GetPlayerColorStringById takes integer i returns string
return colors[i]
endfunction
function GetPlayerIdByColor takes string color returns integer
if (ids.has(StringHash(color))) then
return ids[StringHash(color)]
endif
return -1
endfunction
private module Init
private static method onInit takes nothing returns nothing
set ids = Table.create()
set colors[0] = "|cffFF0202"
set colors[1] = "|cff0041FF"
set colors[2] = "|cff1BE5B8"
set colors[3] = "|cff530080"
set colors[4] = "|cffFFFC00"
set colors[5] = "|cffFE890D"
set colors[6] = "|cff1FBF00"
set colors[7] = "|cffE45AAF"
set colors[8] = "|cff949596"
set colors[9] = "|cff7DBEF1"
set colors[10] = "|cff0F6145"
set colors[11] = "|cff4D2903"
set ids[StringHash("red")] = 0
set ids[StringHash("blue")] = 1
set ids[StringHash("teal")] = 2
set ids[StringHash("purple")] = 3
set ids[StringHash("yellow")] = 4
set ids[StringHash("orange")] = 5
set ids[StringHash("green")] = 6
set ids[StringHash("pink")] = 7
set ids[StringHash("grey")] = 8
set ids[StringHash("gray")] = 8
set ids[StringHash("light blue")] = 9
set ids[StringHash("lb")] = 9
set ids[StringHash("dark green")] = 10
set ids[StringHash("dg")] = 10
set ids[StringHash("brown")] = 11
endmethod
endmodule
private struct init extends array
implement Init
endstruct
endlibrary
//TESH.scrollpos=6
//TESH.alwaysfold=0
library PlayerAlliance /* v1.0.0.0
*************************************************************************************
*
* Simple player alliances
*
*******************************************************************
*
* Alliance Flags
*
* constant integer ALLIANCE_UNALLIED
* constant integer ALLIANCE_UNALLIED_VISION
* constant integer ALLIANCE_NEUTRAL
* constant integer ALLIANCE_NEUTRAL_VISION
* constant integer ALLIANCE_ALLIED
* constant integer ALLIANCE_VISION
* constant integer ALLIANCE_ALLIED_UNITS
* constant integer ALLIANCE_ALLIED_ADVUNITS
*
* function Ally takes player player1, player player2, integer allianceFlag returns nothing
* - Allies two players given alliance flag
*
************************************************************************************/
globals
/*************************************************************************************
*
* Alliance Flags
*
*************************************************************************************/
constant integer ALLIANCE_UNALLIED = 0
//ally = false
//vision = false
//control = false
//full control = false
//passive = false
constant integer ALLIANCE_UNALLIED_VISION = 1
//ally = false
//vision = true
//control = false
//full control = false
//passive = false
constant integer ALLIANCE_NEUTRAL = 2
//ally = false
//vision = false
//control = false
//full control = false
//passive = true
constant integer ALLIANCE_NEUTRAL_VISION = 3
//ally = false
//vision = true
//control = false
//full control = false
//passive = true
constant integer ALLIANCE_ALLIED = 4
//ally = true
//vision = false
//control = false
//full control = false
//passive = false
constant integer ALLIANCE_VISION = 5
//ally = true
//vision = true
//control = false
//full control = false
//passive false
constant integer ALLIANCE_ALLIED_UNITS = 6
//ally = true
//vision = true
//control = true
//full control = false
//passive = false
constant integer ALLIANCE_ALLIED_ADVUNITS = 7
//ally = true
//vision = true
//control = true
//full control = true
//passive = false
endglobals
/*************************************************************************************
*
* Ally
*
* Allies two players given an alliance flag. Will ally both source player and target player.
*
* player p1: The source player of alliance
* player p2: The target player of alliance
*
* returns: nothing
*
*************************************************************************************/
function Ally takes player p1, player p2, integer flag returns nothing
debug if (p1 != null and p2 != null and p1 != p2 and flag >= 0 and flag <= 7) then
//first see if the alliance type was an actual alliance or not
if (flag < ALLIANCE_ALLIED) then
//if it wasn't, unset alliance flags
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_REQUEST, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_RESPONSE, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_XP, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_SPELLS, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_REQUEST, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_RESPONSE, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_XP, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_SPELLS, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
//if enemy
if (flag <= ALLIANCE_UNALLIED_VISION) then
//unset passive flag
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, false)
//check for vision
if (flag == ALLIANCE_UNALLIED_VISION) then
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, true)
else
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, false)
endif
//if neutral
else
//set passive flag
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, true)
//check for vision
if (flag == ALLIANCE_NEUTRAL_VISION) then
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, true)
else
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, false)
endif
endif
else
//make allied
call SetPlayerAlliance(p1, p2, ALLIANCE_PASSIVE, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_REQUEST, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_HELP_RESPONSE, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_XP, true)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_SPELLS, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_PASSIVE, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_REQUEST, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_HELP_RESPONSE, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_XP, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_SPELLS, true)
//check for vision
if (flag >= ALLIANCE_VISION) then
//add vision
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, true)
//check for shared control
if (flag >= ALLIANCE_ALLIED_UNITS) then
//add shared control
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_CONTROL, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_CONTROL, true)
//check for advanced control
if (flag == ALLIANCE_ALLIED_ADVUNITS) then
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_ADVANCED_CONTROL, true)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_ADVANCED_CONTROL, true)
else
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
endif
else
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
endif
else
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_VISION, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_VISION, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_CONTROL, false)
call SetPlayerAlliance(p1, p2, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
call SetPlayerAlliance(p2, p1, ALLIANCE_SHARED_ADVANCED_CONTROL, false)
endif
endif
debug else
debug if (p1 == null) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "PLAYER ALLIANCE ERROR: NULL PLAYER 1 ")
debug endif
debug if (p2 == null) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "PLAYER ALLIANCE ERROR: NULL PLAYER 2 ")
debug endif
debug if (p1 == p2) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "PLAYER ALLIANCE ERROR: PLAYER 1 == PLAYER 2 ")
debug endif
debug if (flag < 0 or flag > 7) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "PLAYER ALLIANCE ERROR: INVALID ALLIANCE FLAG")
debug endif
debug endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library RemoveString
//removes all traces of a string from another string
//0 means remove all
//call RemoveString("123123","12",0,0) -> 33
//call RemoveString("123-123","-",0,0) -> 123123
//maxRemove is useful for removing an instance of a string once
//call RemoveString("-load mau3-load -ffff","-load ",1,0) -> "mau3-load -ffff"
function RemoveString takes string s, string str, integer maxRemove, integer start returns string
local integer p = StringLength(str)
local integer i = StringLength(s)
local integer m = start
if (0<i) then
if (0==maxRemove) then
set maxRemove=-1
endif
loop
exitwhen m==i or 0==maxRemove
if (str==SubString(s,m,m+p)) then
set maxRemove = maxRemove - 1
set s=SubString(s,0,m)+SubString(s,m+p,StringLength(s))
set i=i-1
else
set m=m+1
endif
endloop
endif
return s
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library FindString
function FindString takes string str, string strToFind, integer start returns integer
local integer i=start
local integer l=StringLength(str)
local integer l2=StringLength(strToFind)
loop
exitwhen i>l-l2
if (SubString(str,i,i+l2)==strToFind) then
return i
endif
set i=i+1
endloop
return -1
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library RandomNumber
globals
private integer seconds = 0
private timer t
endglobals
function UpdateSeed takes nothing returns nothing
call SetRandomSeed(R2I((seconds+TimerGetElapsed(t))*1000)+GetRandomInt(-2147483648, 2147483647))
endfunction
private module Init
private static method inc takes nothing returns nothing
set seconds = seconds + 1
endmethod
private static method onInit takes nothing returns nothing
set t = CreateTimer()
call TimerStart(t, 1, true, function thistype.inc)
endmethod
endmodule
private struct Inits extends array
implement Init
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Tile /* v1.0.0.0
*************************************************************************************
*
* Makes it easier to work with Warcraft 3 space on the map. The smallest unit for Warcraft 3 is
* a 32x32 tile. Will put all x, y components in units of 32 and work with relative magnitudes.
*
************************************************************************************
*
* */uses/*
*
* */ WorldBounds /* hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
*
************************************************************************************
*
* function NormalizeXY takes real c returns integer
* - Puts coordinate into units of 32
*
* function NormalizeRelativeX takes real c returns integer
* function NormalizeRelativeY takes real c returns integer
* - Puts coordinate into units of 32 relative to minimum map coordinates
*
* function GetMaxRelativeX takes nothing returns integer
* function GetMaxRelativeY takes nothing returns integer
* - Gets max coordinates relative to min coordinates in units of 32
*
************************************************************************************/
globals
private integer maxXr
private integer maxYr
endglobals
function NormalizeXY takes real c returns integer
if (0 < c) then
return R2I(c + 16)/32*32
endif
return R2I(c - 16)/32*32
endfunction
function NormalizeRelativeX takes real c returns integer
return R2I(c - WorldBounds.minX + 16)/32
endfunction
function NormalizeRelativeY takes real c returns integer
return R2I(c - WorldBounds.minY + 16)/32
endfunction
function GetMaxRelativeX takes nothing returns integer
return maxXr
endfunction
function GetMaxRelativeY takes nothing returns integer
return maxYr
endfunction
private module Init
private static method onInit takes nothing returns nothing
set maxXr = WorldBounds.maxX/32 - WorldBounds.minX/32
set maxYr = WorldBounds.maxY/32 - WorldBounds.minY/32
endmethod
endmodule
private struct Inits extends array
implement Init
endstruct
module Tile
static method operator [] takes real x returns thistype
return NormalizeRelativeX(x)
endmethod
method operator [] takes real y returns thistype
return this*(maxYr + 1)+NormalizeRelativeY(y)
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Tt /* v1.1.0.1
*************************************************************************************
*
* Timer Tools, or Tt for short, provides two types of timers.
*
* Timer tools timers use a special merging algorithm. When two timers merge, they
* both expiring on the same timer. If two timers expire close to the same time, they
* merge. The first tick accuracy is based on the size of the timer's timeout. The larger
* the timeout, the more inaccurate the first tick can be. The tick only becomes inaccurate
* if it merges with another timer.
*
* Timer timeouts are changed to a very slightly degree so that timers have a higher chance
* of merging. For example, 1.001 and 1 would have absolutely no chance of merging because
* they both have different timeouts. Timer Tools timers attempt to remedy this situation
* by making the timeout a little inaccurate (still highly accurate). This means that if
* 2 timers have timeouts that are very close to each other, like 1.001 and 1, they'd both
* have a timeout of 1 and have a chance to merge. 1.001 would also be able to merge with
* other future 1 second timeout timers if any are added. The timeout inaccuracy is based
* on the size of the timeout. For example, 1.1's actual timeout would be
* 1.09999 (just about 1.1) while 3600's timeout would be 3555.56, or about 44.44 seconds off.
* Keep in mind that 3600 seconds is 1 full hour, so 44.44 seconds relative to that entire hour
* really isn't that much. It's accuracy is 98.7654% at that point. The accuracy setting
* can be modified. Increasing it to a value like 10000000 will pretty much remove all inaccuracy.
* 3600 with 10000000 accuracy turns into 3599.712.
*
************************************************************************************
*
* */uses/*
*
* */ Table /* hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
*
************************************************************************************
*
* SETTINGS
*/
globals
/*************************************************************************************
*
* RELATIVE_MERGE
*
* Effects the accuracy of first tick. The smaller the merge value, the less chance two
* timers have of sharing the same first tick, which leads to worse performance.
* However, a larger merge value decreases the accuracy of the first tick.
*
* Formula: Log(RELATIVE_MERGE/timeout)/100*timeout
* Log(64000/3600)/100*3600=44.995589035797596625536391805959 seconds max off
*
*************************************************************************************/
private constant real RELATIVE_MERGE=64000
/*************************************************************************************
*
* CONSTANT_MERGE
*
* Effects the accuracy of the first tick. This is a constant merge. It just adds
* this value to the relative merge.
*
* The max 3600's first tick can be off is 44.995589035797596625536391805959+.03
* or 45.295589035797596625536391805959 seconds.
*
*************************************************************************************/
private constant real CONSTANT_MERGE=.3
/*************************************************************************************
*
* RELATIVE_ACCURACY
*
* Effects the timeout of a timer. A larger number will give a more accurate timeout.
* This allows two timers of relatively close timeouts to have a chance to merge and
* lowers the total number of timeouts within the system. More timeouts means less
* performance.
*
* Formula: RELATIVE_ACCURACY/Round(RELATIVE_ACCURACY/timeout)
* 64000/Round(64000/3600)=3555.5555555555555555555555555556
*
* 3600's timeout will be 3555.5555555555555555555555555556 instead of 3600
*
*************************************************************************************/
private constant real RELATIVE_ACCURACY=64000
/*************************************************************************************
*
* CONSTANT_ACCURACY
*
* This essentially just removes small decimals. An accuracy of 800 would allow for
* decimals in units of .00125. Removing small decimals helps increase the performance
* of very small timeouts by a drastic amount.
*
* Formula: Round(timeout*CONSTANT_ACCURACY)/CONSTANT_ACCURACY
* Round(3555.5555555555555555555555555556*800)/800=3555.555
*
* If a timeout is less than the minimum possible timeout, then it is changed to the
* minimum possible timeout.
*
*************************************************************************************/
private constant real CONSTANT_ACCURACY=800
endglobals
/*
************************************************************************************
*
* Constant Timer Queue Module
* - Constant timeouts
* Constant Merged Timer Module
* - Dynamic timeouts
* Constant Light Timer Queue 1
* - Specializes in 1 shot timers with constant 2+ timeouts. Useful for expirations on spell effects.
*
* private static constant real TIMEOUT Timer Queue
* - Timer Queue expects this value declare at the top of the struct
* - This value represents the constant timeout of the queue
*
* real timeout Merged Timers
* - How often the timer expires
* readonly real elapsed Merged Timers and Timer Queue
* - How long the timer has run since its last expiration
* readonly real remaining Merged Timers and Timer Queue
* - How long the timer has left before it next expires
*
* static method create takes real to returns thistype Merged Timers
* - Creates a new timer given a timeout
* static method create takes nothing returns thistype Timer Queue, Light Timer Queue 1
* - Creates a new timer of a constant timeout
*
* method destroy takes nothing returns nothing Timer Queue, Light Timer Queue 1, Merged Timers
* Note: Light Timer Queue auto destroys in expiration method
* - Destroys created timer
*
* Module
* - Implement these three modules into the struct in order to do a Constant Merged Timer. Code
* - written in between the modules is run whenever a timer expires.
* -
* - The first section allows local declarations and ini. It runs before a set of expiring timers
* - are about to run, meaning that there is no access to a timer in this section.
* -
* - The second section runs for each timer. Access the expiring timer via the this keyword.
*
* module CTM Merged Timers
* module CTQ Timer Queue
* module CLTQ1 Light Timer Queue
* - Declare locals in here
* - Run ini code
* module CTMExpire Merged Timers
* module CTQExpire Timer Queue
* - Run timer code
* -
* - thistype this refers to current expiring timer\
* module CTMNull Merged Timers
* module CTQNull Timer Queue
* - Null locals here
* module CTMEnd Merged Timers
* module CTQEnd Timer Queue
* module CLTQ1End Light Timer Queue
*
* Example of Merged Timers
* struct MyTimer extends array
* integer myValue
* implement CTM
* local string s="My value is "
* implement CTMExpire
* call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,s+I2S(myValue))
* call destroy()
* implement CTMNull
* set s=null //pointless, but shows how to use null block
* implement CTMEnd
* endstruct
*
* set MyTimer.create(5).myValue=16 //will display "My value is 16" in 5 seconds
*
************************************************************************************/
globals
private timer array st //segment timers
private integer ic=0 //instance count
private integer array sn //segment next
private integer array sp //segment previous
private boolean array sr //segment running
private integer array sf //segment first
private integer array tn //timer next, list recycler
private integer array tp //timer previous
private integer array tf //timer first
private integer array nh //node head
private real array nt //node timeout
private integer array qt //queue->timeout id, segment->handle id
private integer array an //after next
private integer array ap //after prev
private integer array as //after segment
private Table array tl
private hashtable tt=InitHashtable()
endglobals
//hiveworkshop.com/forums/jass-functions-413/snippet-natural-logarithm-108059/
//credits to BlinkBoy
private function Ln takes real a returns real
local real s=0
loop
exitwhen a<2.71828
set a=a/2.71828
set s=s+1
endloop
return s+(a-1)*(1+8/(1+a)+1/a)/6
endfunction
//! textmacro TIMER_TOOLS_ALLOCATE_TIMER takes TIMER_REF, TIMEOUT_REF, TABLE_REF
if (0==tn[0]) then
set $TIMER_REF$=ic+1
set ic=$TIMER_REF$
else
set $TIMER_REF$=tn[0]
set tn[0]=tn[$TIMER_REF$]
set nh[$TIMER_REF$]=0
endif
set nt[$TIMER_REF$]=$TIMEOUT_REF$
set tl[$TIMER_REF$]=$TABLE_REF$
//! endtextmacro
//! textmacro TIMER_TOOLS_GET_TIMER_QUEUE takes THIS_REF, QUEUE_REF, ID_REF
set $QUEUE_REF$=$THIS_REF$[$ID_REF$]
if (0==$QUEUE_REF$) then
if (0==tn[0]) then
set $QUEUE_REF$=ic+1
set ic=$QUEUE_REF$
else
set $QUEUE_REF$=tn[0]
set tn[0]=tn[$QUEUE_REF$]
endif
set sf[$QUEUE_REF$]=0
set nt[$QUEUE_REF$]=tio
set $THIS_REF$[$ID_REF$]=$QUEUE_REF$
set qt[$QUEUE_REF$]=$ID_REF$
set tl[$QUEUE_REF$]=$THIS_REF$
endif
//! endtextmacro
//! textmacro TIMER_TOOLS_PREPARE_TIMEOUT takes REF_TIMEOUT, ID_REF
set $REF_TIMEOUT$=RELATIVE_ACCURACY/R2I(RELATIVE_ACCURACY/$REF_TIMEOUT$+.5)
set $ID_REF$=R2I($REF_TIMEOUT$*CONSTANT_ACCURACY+.5)
if (0==$ID_REF$) then
set $ID_REF$=1
endif
set $REF_TIMEOUT$=$ID_REF$/CONSTANT_ACCURACY
//! endtextmacro
//! textmacro TIMER_TOOLS_PREPARE_TICK takes TIMEOUT_REF, TICK_LENIANCY_REF
set $TICK_LENIANCY_REF$=Ln(RELATIVE_MERGE/$TIMEOUT_REF$)/230.258509*$TIMEOUT_REF$+CONSTANT_MERGE
//! endtextmacro
//! textmacro TIMER_TOOLS_CANT_MERGE_RIGHT takes QUEUE_REF, SEGMENT_REF, TICK_LENIANCY_REF, REMAINING_TIME_REF, TIMEOUT_REF
set $SEGMENT_REF$=sp[sf[$QUEUE_REF$]]
set $REMAINING_TIME_REF$=TimerGetRemaining(st[$SEGMENT_REF$])
if (not sr[$SEGMENT_REF$] or 0<$TIMEOUT_REF$-$REMAINING_TIME_REF$-$TICK_LENIANCY_REF$) then
//! endtextmacro
//! textmacro TIMER_TOOLS_CAN_MERGE_LEFT takes QUEUE_REF, SEGMENT_REF, TICK_LENIANCY_REF, REMAINING_TIME_REF, TIMEOUT_REF
set $SEGMENT_REF$=sf[$QUEUE_REF$]
set $REMAINING_TIME_REF$=TimerGetRemaining(st[$SEGMENT_REF$])
if (0!=$SEGMENT_REF$ and 0>=$REMAINING_TIME_REF$-$TICK_LENIANCY_REF$) then
//! endtextmacro
//! textmacro TIMER_TOOLS_ALLOCATE_SEGMENT takes QUEUE_REF, SEGMENT_REF, TIMEOUT_REF, CODE_REF, SEGMENT_FIRST
if (0==tn[0]) then
set $SEGMENT_REF$=ic+1
set ic=$SEGMENT_REF$
else
set $SEGMENT_REF$=tn[0]
set tn[0]=tn[$SEGMENT_REF$]
endif
set $SEGMENT_FIRST$=sf[$QUEUE_REF$]
if (0==$SEGMENT_FIRST$) then
set sn[$SEGMENT_REF$]=$SEGMENT_REF$
set sp[$SEGMENT_REF$]=$SEGMENT_REF$
set sf[$QUEUE_REF$]=$SEGMENT_REF$
else
set sp[$SEGMENT_REF$]=sp[$SEGMENT_FIRST$]
set sn[$SEGMENT_REF$]=$SEGMENT_FIRST$
set sn[sp[$SEGMENT_FIRST$]]=$SEGMENT_REF$
set sp[$SEGMENT_FIRST$]=$SEGMENT_REF$
endif
set tf[$SEGMENT_REF$]=0
set st[$SEGMENT_REF$]=CreateTimer()
set nt[$SEGMENT_REF$]=$TIMEOUT_REF$
call TimerStart(st[$SEGMENT_REF$],$TIMEOUT_REF$,true,$CODE_REF$)
set sr[$SEGMENT_REF$]=true
set an[$SEGMENT_REF$]=$SEGMENT_REF$
set ap[$SEGMENT_REF$]=$SEGMENT_REF$
//! endtextmacro
//! textmacro TIMER_TOOLS_ATTACH_SEGMENT takes QUEUE_REF, SEGMENT_REF
set nh[$SEGMENT_REF$]=$QUEUE_REF$
set qt[$SEGMENT_REF$]=-GetHandleId(st[$SEGMENT_REF$])
call SaveInteger(tt,qt[$SEGMENT_REF$],0,$QUEUE_REF$)
//! endtextmacro
//! textmacro TIMER_TOOLS_PUSH_AFTER takes SEGMENT_REF, SEGMENT_REF_TARGET, TIMER_REF
if ($SEGMENT_REF_TARGET$!=nh[$TIMER_REF$]) then
set an[$TIMER_REF$]=an[$SEGMENT_REF$]
set ap[$TIMER_REF$]=$SEGMENT_REF$
set ap[an[$SEGMENT_REF$]]=$TIMER_REF$
set an[$SEGMENT_REF$]=$TIMER_REF$
set as[$TIMER_REF$]=$SEGMENT_REF_TARGET$
endif
//! endtextmacro
//! textmacro TIMER_TOOLS_POP_AFTER takes SEGMENT_REF, TIMER_REF
set an[ap[$TIMER_REF$]]=an[$TIMER_REF$]
set ap[an[$TIMER_REF$]]=ap[$TIMER_REF$]
set $SEGMENT_REF$=as[$TIMER_REF$]
set as[$TIMER_REF$]=0
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_AFTER takes TIMER_REF
if (0!=as[$TIMER_REF$]) then
//! endtextmacro
//! textmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT takes SEGMENT_REF, TIMER_REF
set tn[$TIMER_REF$]=tf[$SEGMENT_REF$]
set tp[tf[$SEGMENT_REF$]]=$TIMER_REF$
set tp[$TIMER_REF$]=0
set tf[$SEGMENT_REF$]=$TIMER_REF$
set nh[$TIMER_REF$]=$SEGMENT_REF$
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_ALLOCATED takes TIMER_REF, ERROR_MESSAGE
if (0==nt[$TIMER_REF$]) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"$ERROR_MESSAGE$")
else
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_NOT_PAUSED takes SEGMENT_REF
if (0!=$SEGMENT_REF$) then
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_PAUSED takes SEGMENT_REF
if (0==$SEGMENT_REF$) then
//! endtextmacro
//! textmacro TIMER_TOOLS_DEL takes THIS
set tn[$THIS$]=tn[0]
set tn[0]=$THIS$
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_SEGMENT_RUNNING takes SEGMENT_REF, TIMER_REF
if (sr[$SEGMENT_REF$]) then
//! endtextmacro
//! textmacro TIMER_TOOLS_REMOVE_FROM_SEGMENT takes SEGMENT_REF, TIMER_REF
if (0==tp[$TIMER_REF$]) then
set tf[$SEGMENT_REF$]=tn[$TIMER_REF$]
set tp[tn[$TIMER_REF$]]=0
else
set tp[tn[$TIMER_REF$]]=tp[$TIMER_REF$]
set tn[tp[$TIMER_REF$]]=tn[$TIMER_REF$]
endif
set nh[$TIMER_REF$]=0
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_SEGMENT_EMPTY takes SEGMENT_REF
if (sr[$SEGMENT_REF$] and 0==tf[$SEGMENT_REF$] and $SEGMENT_REF$==an[$SEGMENT_REF$]) then
//! endtextmacro
//! textmacro TIMER_TOOLS_DEL_SEGMENT takes QUEUE_REF, SEGMENT_REF
if ($SEGMENT_REF$==sf[$QUEUE_REF$]) then
if ($SEGMENT_REF$==sn[$SEGMENT_REF$]) then
set sf[$QUEUE_REF$]=0
else
set sf[$QUEUE_REF$]=sn[$SEGMENT_REF$]
set sn[sp[$SEGMENT_REF$]]=sn[$SEGMENT_REF$]
set sp[sn[$SEGMENT_REF$]]=sp[$SEGMENT_REF$]
endif
else
set sn[sp[$SEGMENT_REF$]]=sn[$SEGMENT_REF$]
set sp[sn[$SEGMENT_REF$]]=sp[$SEGMENT_REF$]
endif
set tn[$SEGMENT_REF$]=tn[0]
set tn[0]=$SEGMENT_REF$
call PauseTimer(st[$SEGMENT_REF$])
call DestroyTimer(st[$SEGMENT_REF$])
set st[$SEGMENT_REF$]=null
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_QUEUE_EMPTY takes QUEUE_REF
if (0==sf[$QUEUE_REF$]) then
//! endtextmacro
//! textmacro TIMER_TOOLS_UNATTACH takes THIS, REF
call $THIS$.remove(qt[$REF$])
//! endtextmacro
//! textmacro TIMER_TOOLS_UNATTACH2 takes REF
call RemoveSavedInteger(tt,qt[$REF$],0)
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_NEW_TIMEOUT takes TIMEOUT_REF, NEW_TIMEOUT
if ($NEW_TIMEOUT$!=$TIMEOUT_REF$ and $NEW_TIMEOUT$>0) then
//! endtextmacro
//! textmacro TIMER_TOOLS_GET_NODE_HEAD takes HEAD_REF, NODE_REF
set $HEAD_REF$=nh[$NODE_REF$]
//! endtextmacro
//! textmacro TIMER_TOOLS_SET_TIMER_RUNNING_FLAG takes SEGMENT, FLAG
set sr[$SEGMENT$]=$FLAG$
//! endtextmacro
//! textmacro TIMER_TOOLS_PREPARE_TIMER takes QUEUE, SEGMENT
set sf[$QUEUE$]=sn[$SEGMENT$]
//! endtextmacro
//! textmacro TIMER_TOOLS_RUN_AFTER_QUEUE takes SEGMENT2, TIMER, TIMER2
set $TIMER$=an[$SEGMENT2$]
set an[$SEGMENT2$]=$SEGMENT2$
loop
set $TIMER2$=an[$TIMER$]
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_DESTROYING takes TIMER
if (0==nt[$TIMER$]) then
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_PAUSING takes TIMER
if (0==as[$TIMER$]) then
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_ADDING takes SEGMENT2, TIMER
elseif ($SEGMENT2$==as[$TIMER$]) then
set as[$TIMER$]=0
//! endtextmacro
//! textmacro TIMER_TOOLS_IS_MOVING takes TIMER
else
set as[$TIMER$]=0
//! endtextmacro
//! textmacro TIMER_TOOLS_GET_NEXT_AFTER takes SEGMENT, SEGMENT2, TIMER
endif
set $TIMER$=$TIMER$2
exitwhen $SEGMENT2$==$TIMER$
endloop
//! endtextmacro
private function CQ takes integer f, real tio, code c returns integer
local integer t
local real l=Ln(RELATIVE_MERGE/tio)/230.258509*tio+CONSTANT_MERGE
local integer s=sp[f]
local real x
if (0==tn[0]) then
set t=ic+1
set ic=t
else
set t=tn[0]
set tn[0]=tn[t]
set nh[t]=0
endif
set nt[t]=tio
set x=TimerGetRemaining(st[s])
if (not sr[s] or 0<tio-x-l) then
set x=TimerGetRemaining(st[f])
if (0!=f and 0>=x-l) then
//! runtextmacro TIMER_TOOLS_PUSH_AFTER("f","f","t")
else
if (0==tn[0]) then
set s=ic+1
set ic=s
else
set s=tn[0]
set tn[0]=tn[s]
endif
if (0==f) then
set sn[s]=s
set sp[s]=s
else
set sp[s]=sp[f]
set sn[s]=f
set sn[sp[f]]=s
set sp[f]=s
endif
set tn[t]=0
set tp[t]=0
set tf[s]=t
set nh[t]=s
set st[s]=CreateTimer()
call TimerStart(st[s],tio,true,c)
set sr[s]=true
set an[s]=s
set ap[s]=s
endif
else
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","t")
endif
return t
endfunction
private function DT takes integer t, integer f returns integer
local integer s
//! runtextmacro TIMER_TOOLS_IS_ALLOCATED("t","TIMER ERROR: ATTEMPTED TO DESTROY NULL TIMER")
set nt[t]=0
//! runtextmacro TIMER_TOOLS_IS_AFTER("t")
//! runtextmacro TIMER_TOOLS_POP_AFTER("s","t")
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_EMPTY("s")
if (s==f) then
if (s==sn[s]) then
set f=0
else
set f=sn[s]
set sn[sp[s]]=sn[s]
set sp[sn[s]]=sp[s]
endif
else
set sn[sp[s]]=sn[s]
set sp[sn[s]]=sp[s]
endif
set tn[s]=tn[0]
set tn[0]=s
call PauseTimer(st[s])
call DestroyTimer(st[s])
set st[s]=null
endif
endif
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("s","t")
//! runtextmacro TIMER_TOOLS_IS_PAUSED("s")
//! runtextmacro TIMER_TOOLS_DEL("t")
else
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_RUNNING("s","t")
//! runtextmacro TIMER_TOOLS_REMOVE_FROM_SEGMENT("s","t")
//! runtextmacro TIMER_TOOLS_DEL("t")
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_EMPTY("s")
if (s==f) then
if (s==sn[s]) then
set f=0
else
set f=sn[s]
set sn[sp[s]]=sn[s]
set sp[sn[s]]=sp[s]
endif
else
set sn[sp[s]]=sn[s]
set sp[sn[s]]=sp[s]
endif
set tn[s]=tn[0]
set tn[0]=s
call PauseTimer(st[s])
call DestroyTimer(st[s])
set st[s]=null
endif
else
//! runtextmacro TIMER_TOOLS_PUSH_AFTER("s","0","t")
endif
endif
endif
return f
endfunction
private keyword f
private keyword c
private keyword e
private keyword s
module CTQ
static integer f=0
static code c
static method create takes nothing returns thistype
local integer t=CQ(f,TIMEOUT,c)
if (0==f) then
set f=nh[t]
endif
return t
endmethod
method destroy takes nothing returns nothing
set f=DT(this,f)
endmethod
method operator elapsed takes nothing returns real
return TimerGetElapsed(st[nh[this]])
endmethod
method operator remaining takes nothing returns real
return TimerGetRemaining(st[nh[this]])
endmethod
static method e takes nothing returns nothing
local integer s=f
local thistype this=tf[s]
endmodule
module CTQExpire
set sr[s]=false
set f=sn[s]
loop
exitwhen 0==this
endmodule
module CTQNull
set this=tn[this]
endloop
endmodule
module CTQEnd
set this=an[s]
set an[s]=s
loop
exitwhen s==this
//! runtextmacro TIMER_TOOLS_IS_PAUSING("this")
//! runtextmacro TIMER_TOOLS_REMOVE_FROM_SEGMENT("s","this")
//! runtextmacro TIMER_TOOLS_IS_DESTROYING("this")
//! runtextmacro TIMER_TOOLS_DEL("this")
endif
else
set as[this]=0
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","this")
endif
set this=an[this]
endloop
if (0==tf[s]) then
if (s==f) then
if (s==sn[s]) then
set f=0
else
set f=sn[s]
set sn[sp[s]]=sn[s]
set sp[sn[s]]=sp[s]
endif
else
set sn[sp[s]]=sn[s]
set sp[sn[s]]=sp[s]
endif
set tn[s]=tn[0]
set tn[0]=s
call PauseTimer(st[s])
call DestroyTimer(st[s])
set st[s]=null
else
set sr[s]=true
endif
endmethod
private static method onInit takes nothing returns nothing
set c=function thistype.e
endmethod
endmodule
private function LCQ takes integer f, real tio, code c returns integer
local integer t
if (0==tn[0]) then
set t=ic+1
set ic=t
else
set t=tn[0]
set tn[0]=tn[t]
endif
if (0==f) then
set f=t
set tn[t]=0
set tp[t]=t
else
set tn[t]=0
set tp[t]=tp[f]
set tn[tp[f]]=t
set tp[f]=t
endif
set st[t]=CreateTimer()
call TimerStart(st[t],tio,false,c)
return t
endfunction
module CLTQ1
static integer f=0
static code c
static method create takes nothing returns thistype
local integer t=LCQ(f,TIMEOUT,c)
if (0==f) then
set f=t
endif
return t
endmethod
method destroy takes nothing returns nothing
set tn[tp[this]]=tn[this]
set tp[tn[this]]=tp[this]
if (this==f) then
set f=tn[this]
endif
set tn[this]=tn[0]
set tn[0]=this
call PauseTimer(st[this])
call DestroyTimer(st[this])
set st[this]=null
endmethod
static method e takes nothing returns nothing
local thistype this=f
endmodule
module CLTQ1End
set f=tn[this]
set tn[tp[this]]=tn[this]
set tp[tn[this]]=tp[this]
set tn[this]=tn[0]
set tn[0]=this
call DestroyTimer(st[this])
set st[this]=null
endmethod
private static method onInit takes nothing returns nothing
set c=function thistype.e
endmethod
endmodule
private struct Mt extends array
private method operator [] takes integer i returns thistype
return Table(this)[i]
endmethod
private method operator []= takes integer i, integer v returns nothing
set Table(this)[i]=v
endmethod
private method remove takes integer i returns nothing
call Table(this).remove(i)
endmethod
method operator timeout takes nothing returns real
return nt[this]
endmethod
method operator elapsed takes nothing returns real
return TimerGetElapsed(st[nh[this]])
endmethod
method operator remaining takes nothing returns real
return TimerGetRemaining(st[nh[this]])
endmethod
method setTimeout takes real tio, code c returns nothing
local integer t=this
local integer s
local integer h
local integer i
local real x
local real l
local boolean b=true
set this=tl[t]
//! runtextmacro TIMER_TOOLS_IS_ALLOCATED("t","TIMER ERROR: ATTEMPTED TO MANIPULATE NULL TIMER")
//! runtextmacro TIMER_TOOLS_PREPARE_TIMEOUT("tio","i")
//! runtextmacro TIMER_TOOLS_IS_NEW_TIMEOUT("nt[t]","tio")
set nt[t]=tio
//! runtextmacro TIMER_TOOLS_IS_AFTER("t")
//! runtextmacro TIMER_TOOLS_POP_AFTER("s","t")
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_EMPTY("s")
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("h","s")
//! runtextmacro TIMER_TOOLS_DEL_SEGMENT("h","s")
//! runtextmacro TIMER_TOOLS_UNATTACH2("s")
//! runtextmacro TIMER_TOOLS_IS_QUEUE_EMPTY("h")
//! runtextmacro TIMER_TOOLS_DEL("h")
//! runtextmacro TIMER_TOOLS_UNATTACH("this","h")
endif
endif
endif
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("s","t")
//! runtextmacro TIMER_TOOLS_IS_NOT_PAUSED("s")
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_RUNNING("s","t")
//! runtextmacro TIMER_TOOLS_REMOVE_FROM_SEGMENT("s","t")
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_EMPTY("s")
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("h","s")
//! runtextmacro TIMER_TOOLS_DEL_SEGMENT("h","s")
//! runtextmacro TIMER_TOOLS_UNATTACH2("s")
//! runtextmacro TIMER_TOOLS_IS_QUEUE_EMPTY("h")
//! runtextmacro TIMER_TOOLS_DEL("h")
//! runtextmacro TIMER_TOOLS_UNATTACH("this","h")
endif
endif
else
//! runtextmacro TIMER_TOOLS_PUSH_AFTER("s","-1","t")
set b=false
endif
endif
if (b) then
//! runtextmacro TIMER_TOOLS_PREPARE_TICK("tio","l")
//! runtextmacro TIMER_TOOLS_GET_TIMER_QUEUE("this","h","i")
//! runtextmacro TIMER_TOOLS_CANT_MERGE_RIGHT("h","s","l","x","tio")
//! runtextmacro TIMER_TOOLS_CAN_MERGE_LEFT("h","s","l","x","tio")
//! runtextmacro TIMER_TOOLS_PUSH_AFTER("s","s","t")
else
//! runtextmacro TIMER_TOOLS_ALLOCATE_SEGMENT("h","s","tio","c","i")
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","t")
//! runtextmacro TIMER_TOOLS_ATTACH_SEGMENT("h","s")
endif
else
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","t")
endif
endif
endif
endif
endmethod
method new takes real tio, code c returns thistype
local integer t
local integer i
local integer h
local integer s
local real x
local real l
//! runtextmacro TIMER_TOOLS_PREPARE_TIMEOUT("tio","i")
//! runtextmacro TIMER_TOOLS_PREPARE_TICK("tio","l")
//! runtextmacro TIMER_TOOLS_ALLOCATE_TIMER("t","tio","this")
//! runtextmacro TIMER_TOOLS_GET_TIMER_QUEUE("this","h","i")
//! runtextmacro TIMER_TOOLS_CANT_MERGE_RIGHT("h","s","l","x","tio")
//! runtextmacro TIMER_TOOLS_CAN_MERGE_LEFT("h","s","l","x","tio")
//! runtextmacro TIMER_TOOLS_PUSH_AFTER("s","s","t")
else
//! runtextmacro TIMER_TOOLS_ALLOCATE_SEGMENT("h","s","tio","c","i")
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","t")
//! runtextmacro TIMER_TOOLS_ATTACH_SEGMENT("h","s")
endif
else
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","t")
endif
return t
endmethod
method destroy takes nothing returns nothing
local integer t=this
local integer s
local integer h
set this=tl[t]
//! runtextmacro TIMER_TOOLS_IS_ALLOCATED("t","TIMER ERROR: ATTEMPTED TO DESTROY NULL TIMER")
set nt[t]=0
//! runtextmacro TIMER_TOOLS_IS_AFTER("t")
//! runtextmacro TIMER_TOOLS_POP_AFTER("s","t")
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_EMPTY("s")
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("h","s")
//! runtextmacro TIMER_TOOLS_DEL_SEGMENT("h","s")
//! runtextmacro TIMER_TOOLS_UNATTACH2("s")
//! runtextmacro TIMER_TOOLS_IS_QUEUE_EMPTY("h")
//! runtextmacro TIMER_TOOLS_DEL("h")
//! runtextmacro TIMER_TOOLS_UNATTACH("this","h")
endif
endif
endif
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("s","t")
//! runtextmacro TIMER_TOOLS_IS_PAUSED("s")
//! runtextmacro TIMER_TOOLS_DEL("t")
else
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_RUNNING("s","t")
//! runtextmacro TIMER_TOOLS_REMOVE_FROM_SEGMENT("s","t")
//! runtextmacro TIMER_TOOLS_DEL("t")
//! runtextmacro TIMER_TOOLS_IS_SEGMENT_EMPTY("s")
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("h","s")
//! runtextmacro TIMER_TOOLS_DEL_SEGMENT("h","s")
//! runtextmacro TIMER_TOOLS_UNATTACH2("s")
//! runtextmacro TIMER_TOOLS_IS_QUEUE_EMPTY("h")
//! runtextmacro TIMER_TOOLS_DEL("h")
//! runtextmacro TIMER_TOOLS_UNATTACH("this","h")
endif
endif
else
//! runtextmacro TIMER_TOOLS_PUSH_AFTER("s","0","t")
endif
endif
endif
endmethod
endstruct
private function MTM takes integer h, integer s, integer t, code c returns nothing
local integer s2=s
local integer t2
local Table this=tl[t]
local real l
local real x
local real tio
local integer i
//! runtextmacro TIMER_TOOLS_RUN_AFTER_QUEUE("s2","t","t2")
//! runtextmacro TIMER_TOOLS_IS_PAUSING("t")
//! runtextmacro TIMER_TOOLS_REMOVE_FROM_SEGMENT("s2","t")
//! runtextmacro TIMER_TOOLS_IS_DESTROYING("t")
//! runtextmacro TIMER_TOOLS_DEL("t")
endif
//! runtextmacro TIMER_TOOLS_IS_ADDING("s2","t")
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s2","t")
//! runtextmacro TIMER_TOOLS_IS_MOVING("t")
set tio=nt[t]
set i=R2I(tio/CONSTANT_ACCURACY+.5)
//! runtextmacro TIMER_TOOLS_REMOVE_FROM_SEGMENT("s2","t")
//! runtextmacro TIMER_TOOLS_PREPARE_TICK("tio","l")
//! runtextmacro TIMER_TOOLS_GET_TIMER_QUEUE("this","h","i")
//! runtextmacro TIMER_TOOLS_CANT_MERGE_RIGHT("h","s","l","x","tio")
//! runtextmacro TIMER_TOOLS_CAN_MERGE_LEFT("h","s","l","x","tio")
//! runtextmacro TIMER_TOOLS_PUSH_AFTER("s","s","t")
else
//! runtextmacro TIMER_TOOLS_ALLOCATE_SEGMENT("h","s","tio","c","i")
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","t")
//! runtextmacro TIMER_TOOLS_ATTACH_SEGMENT("h","s")
endif
else
//! runtextmacro TIMER_TOOLS_ADD_TIMER_TO_SEGMENT("s","t")
endif
//! runtextmacro TIMER_TOOLS_GET_NEXT_AFTER("s","s2","t")
endfunction
module CTM
static Mt f
static code c
static method create takes real tio returns thistype
return f.new(tio,c)
endmethod
method destroy takes nothing returns nothing
call Mt(this).destroy()
endmethod
method operator timeout takes nothing returns real
return Mt(this).timeout
endmethod
method operator timeout= takes real tio returns nothing
call Mt(this).setTimeout(tio,c)
endmethod
static method e takes nothing returns nothing
local integer s=LoadInteger(tt,-GetHandleId(GetExpiredTimer()),0)
local thistype this=sf[s]
endmodule
module CTMExpire
//! runtextmacro TIMER_TOOLS_SET_TIMER_RUNNING_FLAG("this","false")
//! runtextmacro TIMER_TOOLS_PREPARE_TIMER("s","this")
set s=this
set this=tf[this]
loop
exitwhen 0==this
endmodule
module CTMNull
set this=tn[this]
endloop
endmodule
module CTMEnd
if (s!=an[s]) then
call MTM(nh[s],s,tf[s],function thistype.e)
endif
if (0==tf[s]) then
//! runtextmacro TIMER_TOOLS_GET_NODE_HEAD("this","s")
//! runtextmacro TIMER_TOOLS_DEL_SEGMENT("this","s")
//! runtextmacro TIMER_TOOLS_UNATTACH2("s")
//! runtextmacro TIMER_TOOLS_IS_QUEUE_EMPTY("this")
//! runtextmacro TIMER_TOOLS_DEL("this")
//! runtextmacro TIMER_TOOLS_UNATTACH("tl[this]","this")
endif
else
//! runtextmacro TIMER_TOOLS_SET_TIMER_RUNNING_FLAG("s","true")
endif
endmethod
private static method onInit takes nothing returns nothing
set f=Table.create()
set c=function thistype.e
endmethod
endmodule
endlibrary
//TESH.scrollpos=69
//TESH.alwaysfold=0
library UnitInRangeEvent /* v2.0.0.1
*************************************************************************************
*
* Trigger condition UnitInRangeEvent
*
*************************************************************************************
*
* */uses/*
*
* */ Table /* hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
* */ UnitIndexer /* hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
*
************************************************************************************
*
* function RegisterUnitInRangeEvent takes code condition, unit whichUnit, real range returns triggercondition
* function UnregisterUnitInRangeEvent takes triggercondition condition, unit whichUnit, real range returns nothing
*
* function GetEventSourceUnitId takes nothing returns UnitIndex
* function GetEventSourceUnit takes nothing returns unit
*
************************************************************************************/
globals
private integer instanceCount = 0
private integer array first
private integer array next //recycler
private integer array prev
private trigger array trig
private integer array source
private integer array handleId
private Table rangeEvent
endglobals
static if DEBUG_MODE then
private struct Debug extends array
static boolean array allocated
endstruct
endif
function GetEventSourceUnitId takes nothing returns UnitIndex
return source[rangeEvent[GetHandleId(GetTriggeringTrigger())]]
endfunction
function GetEventSourceUnit takes nothing returns unit
return GetUnitById(GetEventSourceUnitId())
endfunction
function RegisterUnitInRangeEvent takes code eventCode, unit whichUnit, real range returns integer
local integer sourceUnit=GetUnitUserData(whichUnit)
local integer this
local trigger eventTrigger
local integer head
local integer triggerId
//if the unit isn't null
debug if (GetUnitById(sourceUnit) == whichUnit and null != whichUnit) then
//allocate
if (0 == next[0]) then
set this = instanceCount + 1
set instanceCount = this
else
set this = next[0]
set next[0]=next[this]
endif
debug set Debug.allocated[this] = true
//add to list
set head = first[sourceUnit]
if (0 == head) then
set first[sourceUnit] = this
set next[this] = this
set prev[this] = this
else
set prev[this] = prev[head]
set next[this] = head
set next[prev[head]] = this
set prev[head] = this
endif
//register trigger
set eventTrigger = CreateTrigger()
call TriggerRegisterUnitInRange(eventTrigger, whichUnit, range, null)
call TriggerAddCondition(eventTrigger, Condition(eventCode))
//store fields
set triggerId = GetHandleId(eventTrigger)
set handleId[this] = triggerId
set trig[this] = eventTrigger
set source[this] = sourceUnit
set rangeEvent[triggerId] = this
//clean
set eventTrigger = null
return this
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"RANGE EVENT ERROR: ATTEMPT TO REGISTER NULL UNIT")
debug endif
return 0
endfunction
function UnregisterUnitInRangeEvent takes integer this returns nothing
local integer sourceUnit
//if event was allocated
debug if (Debug.allocated[this]) then
set sourceUnit = source[this]
//remove from list
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]
if (first[sourceUnit] == this) then
set first[sourceUnit] = next[this]
if (first[sourceUnit] == this) then
set first[sourceUnit] = 0
endif
endif
//deallocate
set next[this] = next[0]
set next[0] = this
debug set Debug.allocated[this] = false
//clean
call DestroyTrigger(trig[this])
set trig[this] = null
call rangeEvent.remove(handleId[this])
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"RANGE EVENT ERROR: ATTEMPT TO UNREGISTER NULL RANGE EVENT")
debug endif
endfunction
private module Init
private static method onDeindex takes nothing returns boolean
local integer sourceUnit = GetIndexedUnitId()
local integer node = first[sourceUnit]
//if there are any events on the unit
if (0 != node) then
//clean all events
set next[prev[node]] = 0
loop
call DestroyTrigger(trig[node])
set trig[node] = null
call rangeEvent.remove(handleId[node])
debug set Debug.allocated[node] = false
set node = next[node]
exitwhen 0 == node
endloop
//deallocate list
set node = first[sourceUnit]
set next[prev[node]] = next[0]
set next[0] = node
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.onDeindex),UnitIndexer.DEINDEX)
set rangeEvent=Table.create()
endmethod
endmodule
private struct Inits extends array
implement Init
endstruct
endlibrary
//TESH.scrollpos=10
//TESH.alwaysfold=0
library AuraStruct /* v2.1.0.2
*************************************************************************************
*
* An efficient and easy to use module for fully custom aura design.
*
*************************************************************************************
*
* */uses/*
*
* */ UnitEvent /* hiveworkshop.com/forums/jass-functions-413/extension-unit-event-172365/
* */ UnitInRangeEvent /* hiveworkshop.com/forums/submissions-414/unitinrangeevent-205036/
* */ Tt /* hiveworkshop.com/forums/jass-functions-413/system-timer-tools-201165/
* */ RegisterPlayerUnitEvent /* hiveworkshop.com/forums/jass-functions-413/snippet-registerplayerunitevent-203338/
*
************************************************************************************
*
* static method getActiveAuraCount takes UnitIndex unitId returns integer
* static method getAuraCount takes UnitIndex unitId returns integer
* static method getUnitsUnderAura takes UnitIndex sourceId returns integer
* static method getUnitsUnderActiveAura takes UnitIndex sourceId returns integer
*
* static method onCreateAura takes UnitIndex sourceId returns nothing
* - Call this when the unit initially gets the aura. This can also be
* - called whenever the aura's level changes for an instant update.
*
* Interface
*
* private static constant boolean ANIMATED_BESTOW_AURA
* (required) - Determine whether animated units bestow auras or not
*
* private static constant real TIMEOUT
* (required) - How often the aura effect runs
*
* private static constant boolean STACKS
* (required) - Does the aura stack?
*
* private static method getLevel takes UnitIndex sourceId returns integer
* (required) - Returns the level of the aura on the unit
*
* private static method onLevel takes UnitIndex source, integer level returns nothing
* (optional) - Runs when aura levels up
*
* private static method getRange takes UnitIndex source, integer level returns real
* (required) - Should return the range of the aura
*
* private method onEndEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
* (optional) - Runs when the aura effect ends (aura no longer on unit)
*
* private method onEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
* (optional) - Runs when aura effect starts (aura just went on to unit)
*
* private method onPeriodicEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
* (optional) - Runs every period of the aura. First run is right after onEffect
*
* private static method absFilter takes UnitIndex source, UnitIndex entering returns boolean
* (optional) - Runs when the unit initially enters in the range of the aura. If this returns false, the
* - unit is ignored as if it doesn't exist and it will never be able to get the aura
*
* private method filter takes UnitIndex source, UnitIndex affected, integer level returns boolean
* (optional) - Runs whenever the aura cycles (every TIMEOUT seconds). This helps determine if the
* - aura is active or not for the unit.
*
* (it is either both of these at once or neither of them)
* private static method removeBuff takes unit whichUnit, integer level returns nothing
* (optional) - Runs when the buff icon should be removed from the unit
*
* private static method addBuff takes unit whichUnit, integer level returns nothing
* (optional) - Runs when the buff icon should be added to the unit
*
************************************************************************************/
private function InitModule takes code index, code deindex, code death, code revive, boolean animatedBestow returns nothing
call RegisterUnitIndexEvent(Condition(index), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(deindex), UnitIndexer.DEINDEX)
call UnitEvent.START_REINCARNATE.register(Condition(death))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(death))
call UnitEvent.REINCARNATE.register(Condition(revive))
call UnitEvent.RESURRECT.register(Condition(revive))
if (animatedBestow) then
call UnitEvent.ANIMATE.register(Condition(revive))
endif
endfunction
module AuraStruct
private static integer array auraLevel
private integer affectedLevel
private static Table array affecting
private static integer array buffCount
private static integer array auraCount
private static integer array auraInstance
private static integer array activeAura
private static integer array prevLevel
private static integer array level
private static boolean array learning
private static integer array onEnterT
private static integer array onEnterT2
private boolean ran
private boolean active
private UnitIndex source
private UnitIndex affected
static method getActiveAuraCount takes UnitIndex affectedId returns integer
return buffCount[affectedId]
endmethod
static method getAuraCount takes UnitIndex affectedId returns integer
return auraCount[affectedId]
endmethod
static method getUnitsUnderAura takes UnitIndex sourceId returns integer
return auraInstance[sourceId]
endmethod
static method getUnitsUnderActiveAura takes UnitIndex sourceId returns integer
return activeAura[sourceId]
endmethod
private method isActive takes nothing returns boolean
static if not thistype.STACKS then
static if thistype.filter.exists then
return filter(source, affected, level[source]) and (level[source] > auraLevel[affected] or affectedLevel == auraLevel[affected])
else
return (level[source] > auraLevel[affected]) or affectedLevel == auraLevel[affected]
endif
else
static if thistype.filter.exists then
return filter(source, affected, level[source])
endif
endif
return true
endmethod
private method doEffect takes nothing returns nothing
if (not ran) then
set ran = true
static if thistype.onEffect.exists then
call onEffect(source, affected, level[source])
endif
endif
static if thistype.onPeriodicEffect.exists then
call onPeriodicEffect(source, affected, level[source])
endif
endmethod
private static thistype array next
private static thistype array prev
private static timer levelCheckTimer = CreateTimer()
private static method removeCheck takes UnitIndex sourceId returns nothing
set next[prev[sourceId]]=next[sourceId]
set prev[next[sourceId]]=prev[sourceId]
call sourceId.unlock()
if (0 == next[0]) then
call PauseTimer(levelCheckTimer)
endif
endmethod
implement CTQ
local boolean wasActive
local UnitIndex source
local UnitIndex affected
local integer lev
implement CTQExpire
set source = this.source
set affected = this.affected
set lev = level[source]
if (not learning[source]) then
if (/*
*/0 == lev or /*
*/IsUnitDead(affected) or /*
*/IsUnitReincarnating(affected) or /*
*/not IsUnitInRange(GetUnitById(source), GetUnitById(affected), getRange(source, lev)) /*
*/) then
set auraCount[affected] = auraCount[affected] - 1
set auraInstance[source] = auraInstance[source] - 1
if (active) then
set buffCount[affected] = buffCount[affected] - 1
set activeAura[source] = activeAura[source] - 1
static if thistype.addBuff.exists then
if (0 == buffCount[affected]) then
call removeBuff(GetUnitById(affected), auraLevel[affected])
endif
endif
if (affectedLevel == auraLevel[affected]) then
set auraLevel[affected] = 0
endif
static if thistype.onEndEffect.exists then
call onEndEffect(source, affected, affectedLevel)
endif
endif
call destroy()
if (null != GetUnitById(source)) then
call affecting[source].remove(affected)
elseif (0 == auraInstance[source]) then
call affecting[source].destroy()
endif
call source.unlock()
call affected.unlock()
else
set wasActive = active
set active = isActive()
if (active) then
if (lev > auraLevel[affected]) then
if (not wasActive) then
set buffCount[affected] = buffCount[affected] + 1
set activeAura[source] = activeAura[source] + 1
endif
static if thistype.addBuff.exists then
call removeBuff(GetUnitById(affected), auraLevel[affected])
endif
set auraLevel[affected] = lev
set ran = false
static if thistype.addBuff.exists then
call addBuff(GetUnitById(affected), lev)
endif
else
call doEffect()
endif
elseif (wasActive) then
set buffCount[affected] = buffCount[affected] - 1
set activeAura[source] = activeAura[source] - 1
static if thistype.addBuff.exists then
if (0 == buffCount[affected]) then
call removeBuff(GetUnitById(affected), auraLevel[affected])
endif
endif
if (affectedLevel == auraLevel[affected]) then
set auraLevel[affected] = 0
endif
static if thistype.onEndEffect.exists then
call onEndEffect(source, affected, affectedLevel)
endif
endif
endif
endif
implement CTQNull
implement CTQEnd
private static method doEnter takes UnitIndex sourceId, UnitIndex entering returns nothing
local thistype time = affecting[sourceId][entering]
local boolean canEnter = true
local boolean wasActive = true
local integer buffs
local integer lev
static if thistype.absFilter.exists then
set canEnter = absFilter(sourceId, entering)
endif
set learning[sourceId] = false
if (0 != entering and GetUnitUserData(GetUnitById(entering)) == entering and canEnter and (0 == time or time.affectedLevel != level[sourceId])) then
if (0 == time) then
call entering.lock()
call sourceId.lock()
set time = create()
set time.source = sourceId
set time.affected = entering
set time.active = false
set affecting[sourceId][entering] = time
set time.ran = false
set auraCount[entering] = auraCount[entering] + 1
set auraInstance[sourceId] = auraInstance[sourceId] + 1
endif
if (not time.active) then
set wasActive = false
else
set auraLevel[entering] = 0
endif
set lev = level[sourceId]
set time.affectedLevel = lev
set time.active = time.isActive()
static if thistype.addBuff.exists then
if (time.active and not wasActive) then
if (0 < buffCount[entering] and auraLevel[entering] < lev) then
call removeBuff(GetUnitById(entering), auraLevel[entering])
endif
endif
endif
if (time.ran) then
set time.ran = false
static if thistype.onEndEffect.exists then
call time.onEndEffect(sourceId, entering, prevLevel[sourceId])
endif
endif
if (time.active and not wasActive) then
set buffCount[entering] = buffCount[entering] + 1
set activeAura[sourceId] = activeAura[sourceId] + 1
static if thistype.addBuff.exists then
if (auraLevel[entering] < lev) then
call addBuff(GetUnitById(entering), lev)
endif
endif
set auraLevel[entering] = lev
set time.ran = true
static if thistype.onEffect.exists then
call time.onEffect(sourceId, entering, lev)
endif
endif
endif
endmethod
private static method onEnter takes nothing returns boolean
call doEnter(GetEventSourceUnitId(), GetUnitUserData(GetTriggerUnit()))
return false
endmethod
private static method unregisterRange takes integer sourceId, unit sourceUnit, real range returns nothing
if (0 != prevLevel[sourceId]) then
call UnregisterUnitInRangeEvent(onEnterT[sourceId])
endif
endmethod
private static method registerRange takes integer sourceId, unit sourceUnit, real range returns nothing
call doEnter(sourceId, sourceId)
set learning[sourceId] = true
set onEnterT[sourceId] = RegisterUnitInRangeEvent(function thistype.onEnter, sourceUnit, range)
endmethod
private static method checkLevel takes nothing returns nothing
local thistype sourceId = next[0]
local integer newLevel
loop
exitwhen 0 == sourceId
set newLevel = getLevel(sourceId)
if (newLevel != level[sourceId]) then
call unregisterRange(sourceId, GetUnitById(sourceId), getRange(sourceId, level[sourceId]))
set prevLevel[sourceId] = level[sourceId]
set level[sourceId] = newLevel
if (0 == newLevel) then
call removeCheck(sourceId)
endif
static if thistype.onLevel.exists then
call onLevel(sourceId, level[sourceId])
endif
if (0 != newLevel) then
call registerRange(sourceId, GetUnitById(sourceId), getRange(sourceId, level[sourceId]))
endif
endif
set sourceId = next[sourceId]
endloop
endmethod
private static method addCheck takes UnitIndex sourceId returns nothing
call sourceId.lock()
set prev[sourceId]=prev[0]
set next[sourceId]=0
set next[prev[0]]=sourceId
set prev[0]=sourceId
if (0 == prev[sourceId]) then
call TimerStart(levelCheckTimer, TIMEOUT, true, function thistype.checkLevel)
endif
endmethod
static method onCreateAura takes UnitIndex sourceId returns boolean
local integer newLevel = getLevel(sourceId)
local unit sourceUnit = GetUnitById(sourceId)
if (not (IsUnitDead(sourceId) and IsUnitReincarnating(sourceId)) and null != sourceUnit and GetUnitUserData(sourceUnit) == sourceId and newLevel != level[sourceId]) then
call unregisterRange(sourceId, sourceUnit, getRange(sourceId, level[sourceId]))
set prevLevel[sourceId] = level[sourceId]
set level[sourceId] = newLevel
if (0 != newLevel) then
if (0 == prevLevel[sourceId]) then
call addCheck(sourceId)
endif
endif
static if thistype.onLevel.exists then
call onLevel(sourceId, newLevel)
endif
if (0 != newLevel) then
call registerRange(sourceId, sourceUnit, getRange(sourceId, newLevel))
endif
endif
set sourceUnit = null
return false
endmethod
private static method onIndex takes nothing returns boolean
set affecting[GetIndexedUnitId()] = Table.create()
return false
endmethod
private static method onDeath takes nothing returns boolean
if (0 != level[GetEventUnitId()]) then
call UnregisterUnitInRangeEvent(onEnterT[GetEventUnitId()])
call removeCheck(GetEventUnitId())
set prevLevel[GetEventUnitId()] = 0
set level[GetEventUnitId()] = 0
endif
return false
endmethod
private static method onRevive takes nothing returns boolean
if (0 != getLevel(GetEventUnitId())) then
set level[GetEventUnitId()] = getLevel(GetEventUnitId())
call addCheck(GetEventUnitId())
call registerRange(GetEventUnitId(), GetEventUnit(), getRange(GetEventUnitId(), level[GetEventUnitId()]))
endif
return false
endmethod
private static method onDeindex takes nothing returns boolean
if (0 != level[GetIndexedUnitId()]) then
set prevLevel[GetIndexedUnitId()] = level[GetIndexedUnitId()]
call UnregisterUnitInRangeEvent(onEnterT[GetIndexedUnitId()])
set level[GetIndexedUnitId()] = 0
set prevLevel[GetIndexedUnitId()] = 0
call removeCheck(GetIndexedUnitId())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
static if thistype.ANIMATED_BESTOW_AURA then
call InitModule(function thistype.onIndex, function thistype.onDeindex, function thistype.onDeath, function thistype.onRevive, true)
else
call InitModule(function thistype.onIndex, function thistype.onDeindex, function thistype.onDeath, function thistype.onRevive, false)
endif
endmethod
endmodule
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library IsPathable /* v1.0.2.2
*************************************************************************************
*
* The IsTerrainPathable native does not work.
*
* This library will also check if a point is currently pathable. Will even be
* able to detect buildings and large clusters of units (avoids the 1024 warcraft
* limit to pathing)
*
************************************************************************************
*
* */uses/*
*
* */ WorldBounds /* hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
* */ optional UnitIndexer /* hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
*
************************************************************************************
*
* SETTINGS
*/
globals
/*
Enables the 1024 path checking for warcraft 3 (100% accurate path checking)
The 1024 case is a very rare case and may not be present in the map
Only enable this if it is truly needed (major performance hit).
*/
private constant boolean SAFE_PATHING = false
endglobals
/*
************************************************************************************
*
* constant integer PATH_TYPE_AMPHIBIOUS
* constant integer PATH_TYPE_BLIGHT
* constant integer PATH_TYPE_BUILDABILITY
* constant integer PATH_TYPE_FLOATABILITY
* constant integer PATH_TYPE_FLYABILITY
* constant integer PATH_TYPE_WALKABILITY
*
* function IsPathable takes integer x, integer y, integer pathingType returns boolean
* - i.e. call IsPathable(0,0,PATH_TYPE_AMPHIBIOUS)
*
************************************************************************************/
globals
//pathing types
constant integer PATH_TYPE_AMPHIBIOUS=0
constant integer PATH_TYPE_BLIGHT=1
constant integer PATH_TYPE_BUILDABILITY=2
constant integer PATH_TYPE_FLOATABILITY=3
constant integer PATH_TYPE_FLYABILITY=4
constant integer PATH_TYPE_WALKABILITY=5
private pathingtype array pt
private unit array u //unit pathability checkers array
endglobals
function GetPathingUnit takes integer pt returns unit
return u[pt]
endfunction
function IsPathable takes integer x, integer y, integer p returns boolean
local boolean b //was point pathable?
call SetUnitPosition(u[p],x,y) //use SetUnitPosition to determine if point is pathable
set b=GetUnitX(u[p])==x and GetUnitY(u[p])==y //if coordinates are identical, coordinate *may* be
//pathable
static if SAFE_PATHING then
if (b) then
//if the point was found as pathable, it may not be pathable
//units are placed at the original coordinates if the closest pathable point is
//at least 1024 units out
set x=x+32 //go out by 32
call SetUnitPosition(u[p],x,y) //set unit to new position
set b=GetUnitX(u[p])<x //check to see if unit shifted towards original position
//if unit didn't shift towards original position, check second position with another unit
//where all points are not pathable, place a unit at an arbitrary point
//it will stay at that point even though it isn't pathable
/*
* * * *
* * * *
* U * *
* * * *
*/
//shift the unit over by 1 and see if it doesn't shift
//if it did shift, then the original position was pathable
//if it didn't shift, then both positions may or may not be pathable
/*
* * * *
* * * *
* * U *
* * * *
*/
//place a second unit on top of the first unit
//if it didn't shift left, then the first position was not pathable
/*
* * * *
* * * *
* * <-UU *
* * * *
--------------------------
* * * *
* * * *
* U U *
* * * *
*/
//the reason it will shift left is because 64 is only half a square, meaning it
//will still be closest to the first position
//the reason why two units are required
/*
* * * *
* * * *
* *
* * * *
*/
//in this case, both positions are pathable, meaning the unit will not shift
//it would be identical to this case
/*
* * * *
* * * *
* * * *
* * * *
*/
//and the reason for moving right is due to this case
/*
* * * *
* * * *
* * *
* * * *
*/
//in this case, a unit placed on top of the original unit will not shift anywhere
//and nothing is known
if (not b) then
call SetUnitPosition(u[p+6],x-32,y)
set b=GetUnitX(u[p+6])<x
call SetUnitX(u[p+6],WorldBounds.minX)
call SetUnitY(u[p+6],WorldBounds.minY)
endif
endif
endif
call SetUnitX(u[p],WorldBounds.minX)
call SetUnitY(u[p],WorldBounds.minY)
return b
endfunction
private module N
private static method onInit takes nothing returns nothing
local player p=Player(15)
set pt[PATH_TYPE_FLYABILITY]=PATHING_TYPE_FLYABILITY
set pt[PATH_TYPE_AMPHIBIOUS]=PATHING_TYPE_AMPHIBIOUSPATHING
set pt[PATH_TYPE_BUILDABILITY]=PATHING_TYPE_BUILDABILITY
set pt[PATH_TYPE_WALKABILITY]=PATHING_TYPE_WALKABILITY
set pt[PATH_TYPE_FLOATABILITY]=PATHING_TYPE_FLOATABILITY
set pt[PATH_TYPE_BLIGHT]=PATHING_TYPE_BLIGHTPATHING
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled = false
endif
set u[PATH_TYPE_FLYABILITY]=CreateUnit(p,UNITS_PATH_unflyable,0,0,0)
set u[PATH_TYPE_AMPHIBIOUS]=CreateUnit(p,UNITS_PATH_unamph,0,0,0)
set u[PATH_TYPE_BUILDABILITY]=CreateUnit(p,UNITS_PATH_unbuildable,0,0,0)
set u[PATH_TYPE_WALKABILITY]=CreateUnit(p,UNITS_PATH_unwalkable,0,0,0)
set u[PATH_TYPE_FLOATABILITY]=CreateUnit(p,UNITS_PATH_unfloat,0,0,0)
set u[PATH_TYPE_BLIGHT]=CreateUnit(p,UNITS_PATH_blighted,0,0,0)
set u[PATH_TYPE_FLYABILITY+6]=CreateUnit(p,UNITS_PATH_unflyable,0,0,0)
set u[PATH_TYPE_AMPHIBIOUS+6]=CreateUnit(p,UNITS_PATH_unamph,0,0,0)
set u[PATH_TYPE_BUILDABILITY+6]=CreateUnit(p,UNITS_PATH_unbuildable,0,0,0)
set u[PATH_TYPE_WALKABILITY+6]=CreateUnit(p,UNITS_PATH_unwalkable,0,0,0)
set u[PATH_TYPE_FLOATABILITY+6]=CreateUnit(p,UNITS_PATH_unfloat,0,0,0)
set u[PATH_TYPE_BLIGHT+6]=CreateUnit(p,UNITS_PATH_blighted,0,0,0)
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled = true
endif
call SetUnitX(u[PATH_TYPE_FLYABILITY],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_FLYABILITY],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_AMPHIBIOUS],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_AMPHIBIOUS],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_BUILDABILITY],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_BUILDABILITY],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_WALKABILITY],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_WALKABILITY],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_FLOATABILITY],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_FLOATABILITY],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_BLIGHT],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_BLIGHT],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_FLYABILITY+6],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_FLYABILITY+6],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_AMPHIBIOUS+6],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_AMPHIBIOUS+6],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_BUILDABILITY+6],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_BUILDABILITY+6],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_WALKABILITY+6],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_WALKABILITY+6],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_FLOATABILITY+6],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_FLOATABILITY+6],WorldBounds.minY)
call SetUnitX(u[PATH_TYPE_BLIGHT+6],WorldBounds.minX)
call SetUnitY(u[PATH_TYPE_BLIGHT+6],WorldBounds.minY)
set p=null
endmethod
endmodule
private struct I extends array
implement N
endstruct
endlibrary
//TESH.scrollpos=169
//TESH.alwaysfold=0
library UnitEvent /* v3.0.1.2
*************************************************************************************
*
* Makes new unit events for Warcraft 3.
*
*************************************************************************************
*
* */uses/*
*
* */ UnitIndexer /* (4.0.2.3) - hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
* */ RegisterPlayerUnitEvent /* hiveworkshop.com/forums/jass-functions-413/snippet-registerplayerunitevent-203338/
*
************************************************************************************
*
* Events: registered via Event API
* static constant Event UnitEvent.REMOVE
* static constant Event UnitEvent.DECAY
* static constant Event UnitEvent.EXPLODE
* static constant Event UnitEvent.RESURRECT
* static constant Event UnitEvent.REINCARNATE
* static constant Event UnitEvent.ANIMATE
* static constant Event UnitEvent.START_REINCARNATE
*
* Functions:
* function IsUnitDead takes integer index returns boolean
* function IsUnitReincarnating takes integer index returns boolean
* function IsUnitAnimated takes integer index returns boolean
* function GetEventUnitId takes nothing returns integer
* function GetEventUnit takes nothing returns unit
*
*******************************************************************
*
* module UnitEventStruct
*
* - A pseudo module interface that runs a set of methods if they exist.
*
* - implements UnitIndexStruct automatically
*
* Interface:
*
* - These methods don't have to exist. If they don't exist, the code
* - that calls them won't even be in the module.
*
* private method remove takes nothing returns nothing
* private method decay takes nothing returns nothing
* private method explode takes nothing returns nothing
* private method resurrect takes nothing returns nothing
* private method startReincarnate takes nothing returns nothing
* private method reincarnate takes nothing returns nothing
* private method animate takes nothing returns nothing
*
************************************************************************************/
//! textmacro UNIT_EVENT_MACRO
globals
private real h=1000
private timer time=null
private real array j
private boolean array k
private boolean array z
private boolean array x
private boolean array v
private integer array b
private timer m=CreateTimer()
endglobals
function GetEventUnitId takes nothing returns integer
return o
endfunction
function GetEventUnit takes nothing returns unit
return e[o]
endfunction
function IsUnitDead takes integer index returns boolean
return z[index]
endfunction
function IsUnitReincarnating takes integer index returns boolean
return x[index]
endfunction
function IsUnitAnimated takes integer index returns boolean
return k[index]
endfunction
private function OnReincarnateStart takes nothing returns nothing
local integer i=o
set o=b[0]
loop
if (x[o]) then
call FireEvent(UnitEvent.START_REINCARNATE)
endif
set o=b[o]
exitwhen 0==o
endloop
set b[0]=0
set o=i
endfunction
private function OnDeath takes nothing returns boolean
local unit u=GetTriggerUnit()
local integer i=GetUnitUserData(u)
local integer d=o
if (u==e[i]) then
set z[i]=true
set x[i]=false
if (not k[i]) then
set j[i]=TimerGetElapsed(time)
else
set v[i]=true
set k[i]=false
set o=i
call FireEvent(UnitEvent.EXPLODE)
set o=d
endif
endif
set u=null
return false
endfunction
private module UnitEventModule
local unit u=GetFilterUnit()
local integer s=GetUnitUserData(u)
local integer d=o
if (u==e[s]) then
set o=s
if (0==GetUnitAbilityLevel(u,ABILITIES_UNIT_INDEXER)) then
set x[s]=false
set k[s]=false
if (not v[s]) then
if (z[s] and h<=TimerGetElapsed(time)-j[s]) then
set z[s]=false
call FireEvent(UnitEvent.DECAY)
else
set z[s]=false
call FireEvent(UnitEvent.REMOVE)
endif
else
set z[s]=false
set v[s]=false
endif
static if not LIBRARY_UnitList then
if (not a)then
set n[p[s]]=n[s]
set p[n[s]]=p[s]
endif
else
set n[p[s]]=n[s]
set p[n[s]]=p[s]
call GroupRemoveUnit(g,e[s])
endif
call FireEvent(DEINDEX)
if (0==lc[s]) then
set n[s]=y
set y=s
endif
set e[s]=null
elseif (.405<GetWidgetLife(u) and 0!=GetUnitTypeId(u)) then
if (x[s]) then
call FireEvent(UnitEvent.REINCARNATE)
set x[s]=false
elseif (z[s]) then
set z[s]=false
if (IsUnitType(u,UNIT_TYPE_SUMMONED)) then
set k[s]=true
call FireEvent(UnitEvent.ANIMATE)
else
call FireEvent(UnitEvent.RESURRECT)
endif
endif
else
set x[s]=true
set b[s]=b[0]
set b[0]=s
call TimerStart(m,0,false,function OnReincarnateStart)
endif
set o=d
endif
set u=null
endmodule
//! endtextmacro
//! textmacro UNIT_EVENT_MACRO_2
private module UnitEventInits
private static method decayer takes nothing returns boolean
set h=TimerGetElapsed(time)-.9375
call DestroyTrigger(GetTriggeringTrigger())
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t=CreateTrigger()
local unit u
set REMOVE=CreateEvent()
set DECAY=CreateEvent()
set EXPLODE=CreateEvent()
set RESURRECT=CreateEvent()
set REINCARNATE=CreateEvent()
set ANIMATE=CreateEvent()
set START_REINCARNATE=CreateEvent()
set UnitIndexer.enabled=false
set u=CreateUnit(Player(14),UNITS_UNIT_EVENT,WorldBounds.maxX,WorldBounds.maxY,0)
set UnitIndexer.enabled=true
call KillUnit(u)
call ShowUnit(u,false)
call TriggerRegisterUnitEvent(t,u,EVENT_UNIT_ISSUED_ORDER)
call TriggerAddCondition(t,function thistype.decayer)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function OnDeath))
call TimerStart(time,1000000,false,null)
set u=null
set t=null
endmethod
endmodule
struct UnitEvent extends array
readonly static Event REMOVE
readonly static Event DECAY
readonly static Event EXPLODE
readonly static Event RESURRECT
readonly static Event REINCARNATE
readonly static Event ANIMATE
readonly static Event START_REINCARNATE
implement UnitEventInits
endstruct
//! endtextmacro
//! textmacro UNIT_EVENT_STRUCT_MACRO
private static method onInit takes nothing returns nothing
static if thistype.remove.exists then
call RegisterEvent(Condition(function thistype.onRemoveEvent),UnitEvent.REMOVE)
endif
static if thistype.decay.exists then
call RegisterEvent(Condition(function thistype.onDecayEvent),UnitEvent.DECAY)
endif
static if thistype.explode.exists then
call RegisterEvent(Condition(function thistype.onExplodeEvent),UnitEvent.EXPLODE)
endif
static if thistype.resurrect.exists then
call RegisterEvent(Condition(function thistype.onResurrectEvent),UnitEvent.RESURRECT)
endif
static if thistype.startReincarnate.exists then
call RegisterEvent(Condition(function thistype.onStartReincarnateEvent),UnitEvent.START_REINCARNATE)
endif
static if thistype.reincarnate.exists then
call RegisterEvent(Condition(function thistype.onReincarnateEvent),UnitEvent.REINCARNATE)
endif
static if thistype.animate.exists then
call RegisterEvent(Condition(function thistype.onAnimateEvent),UnitEvent.ANIMATE)
endif
endmethod
//! endtextmacro
module UnitEventStruct
implement UnitIndexStruct
static if thistype.remove.exists then
private static method onRemoveEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).remove()
endif
return false
endmethod
endif
static if thistype.decay.exists then
private static method onDecayEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).decay()
endif
return false
endmethod
endif
static if thistype.explode.exists then
private static method onExplodeEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).explode()
endif
return false
endmethod
endif
static if thistype.resurrect.exists then
private static method onResurrectEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).resurrect()
endif
return false
endmethod
endif
static if thistype.startReincarnate.exists then
private static method onStartReincarnateEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).startReincarnate()
endif
return false
endmethod
endif
static if thistype.reincarnate.exists then
private static method onReincarnateEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).reincarnate()
endif
return false
endmethod
endif
static if thistype.animate.exists then
private static method onAnimateEvent takes nothing returns boolean
if (thistype(GetEventUnitId()).allocated) then
call thistype(GetEventUnitId()).animate()
endif
return false
endmethod
endif
static if thistype.remove.exists then
//! runtextmacro UNIT_EVENT_STRUCT_MACRO()
elseif thistype.decay.exists then
//! runtextmacro UNIT_EVENT_STRUCT_MACRO()
elseif thistype.explode.exists then
//! runtextmacro UNIT_EVENT_STRUCT_MACRO()
elseif thistype.resurrect.exists then
//! runtextmacro UNIT_EVENT_STRUCT_MACRO()
elseif thistype.startReincarnate.exists then
//! runtextmacro UNIT_EVENT_STRUCT_MACRO()
elseif thistype.reincarnate.exists then
//! runtextmacro UNIT_EVENT_STRUCT_MACRO()
elseif thistype.animate.exists then
//! runtextmacro UNIT_EVENT_STRUCT_MACRO()
endif
endmodule
endlibrary
//TESH.scrollpos=25
//TESH.alwaysfold=0
library GetUnitCollision /* v2.0.1.0
*************************************************************************************
*
* Retrieves collision size for a unit (different from pathing map)
*
* Assumes collision will always be an integer
*
* 100% accurate to 1 decimal for collision sizes >= 5.1
*
*************************************************************************************
*
* */uses/*
*
* */ Table /* hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
*
*************************************************************************************
*
* Functions
*
* function GetUnitCollision takes unit whichUnit returns real
*
************************************************************************************/
globals
private Table uc
endglobals
private function C takes unit u, real x, real y, integer i returns real
local real l = 0
local real h = 300
local real m = 150
local real nm
loop
if (IsUnitInRangeXY(u, x+m, y, 0)) then
set l = m
else
set h = m
endif
set nm = (l+h)/2
exitwhen nm+.001 > m and nm-.001 < m
set m = nm
endloop
set m = R2I(m*10)/10.
set uc.real[i] = m
return m
endfunction
function GetUnitCollision takes unit u returns real
local integer i = GetUnitTypeId(u)
if (uc.real.has(i)) then
return uc.real[i]
endif
return C(u, GetUnitX(u), GetUnitY(u), i)
endfunction
private struct init extends array
private static method onInit takes nothing returns nothing
set uc = Table.create()
endmethod
endstruct
endlibrary
//TESH.scrollpos=24
//TESH.alwaysfold=0
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
//TESH.scrollpos=0
//TESH.alwaysfold=0
library IsPlaying
function IsPlaying takes player p returns boolean
static if LIBRARY_Tester then
return /*p != Player(1) and*/ p != Player(2)
else
return GetPlayerController(p) == MAP_CONTROL_USER and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING
endif
endfunction
constant function LeaveEvent takes nothing returns playerevent
return EVENT_PLAYER_LEAVE
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct RemoveCorpses extends array
private static constant real TIMEOUT = 3
private unit clean
implement CLTQ1
call RemoveUnit(clean)
set clean = null
implement CLTQ1End
private static method death takes nothing returns boolean
set create().clean = GetTriggerUnit()
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.death))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Compensate uses UnitIndexer
struct Compensate extends array
boolean give
private static method i takes nothing returns boolean
set thistype(GetIndexedUnitId()).give = true
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.i), UnitIndexer.INDEX)
endmethod
endstruct
endlibrary
//TESH.scrollpos=51
//TESH.alwaysfold=0
library DummyCaster /* v2.0.0.1
*************************************************************************************
*
* Dummy caster for casting spells
*
* Spells must have 0 cooldown, 92083 range, and cost 0 mana. Spells must be instant and
* can't share the same order as other spells on the dummy caster.
*
*************************************************************************************
*
* */uses/*
* */ optional UnitIndexer /* hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
*
************************************************************************************
* SETTINGS
*/
globals
/*************************************************************************************
*
* PLAYER_OWNER
*
* Owner of dummy caster
*
*************************************************************************************/
private constant player PLAYER_OWNER = Player(15)
endglobals
/*
************************************************************************************
*
* Dummy at position 32256,32256
*
* struct DummyCaster extends array
*
* method cast takes player castingPlayer, integer abilityLevel, integer order, real x, real y returns boolean
* - call DummyCaster[abilityId].cast(...)
* method castTarget takes player castingPlayer, integer abilityLevel, integer order, widget t returns boolean
* - call DummyCaster[abilityId].castTarget(...)
* method castPoint takes player castingPlayer, integer abilityLevel, integer order, real x, real y returns boolean
* - call DummyCaster[abilityId].castPoint(...)
*
************************************************************************************/
globals
private unit u
endglobals
private module N
private static method onInit takes nothing returns nothing
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled=false
set u=CreateUnit(PLAYER_OWNER,UNITS_DUMMY_CASTER,0,0,0)
set UnitIndexer.enabled=true
else
set u=CreateUnit(PLAYER_OWNER,UNITS_DUMMY_CASTER,0,0,0)
endif
call SetUnitPosition(u,32256,32256)
endmethod
endmodule
struct DummyCaster extends array
implement N
private static method prep takes integer a, player p, integer l returns nothing
call UnitAddAbility(u, a)
if (1 < l) then
call SetUnitAbilityLevel(u, a, l)
endif
if (null != p) then
call SetUnitOwner(u, p, false)
endif
endmethod
private static method finish takes integer a returns nothing
call SetUnitOwner(u, PLAYER_OWNER, false)
call UnitRemoveAbility(u, a)
endmethod
method cast takes player p, integer level, integer order, real x, real y returns boolean
local boolean b
call SetUnitX(u, x)
call SetUnitY(u, y)
call prep(this, p, level)
set b = IssueImmediateOrderById(u,order)
call finish(this)
call SetUnitPosition(u, 32256, 32256)
return b
endmethod
method castTarget takes player p, integer level, integer order, widget t returns boolean
local boolean b
call prep(this, p, level)
set b = IssueTargetOrderById(u,order,t)
call finish(this)
return b
endmethod
method castPoint takes player p, integer level, integer order, real x, real y returns boolean
local boolean b
call prep(this, p, level)
set b = IssuePointOrderById(u,order,x,y)
call finish(this)
return b
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DamageEvent uses /*
*/UnitIndexer /*hiveworkshop.com/forums/jass-functions-413/unit-indexer-172090/
*/Event //hiveworkshop.com/forums/submissions-414/snippet-event-186555/
//Version 2.1.0.7
//struct DamageEvent extends array
//static constant Event ANY
//readonly static integer targetId
//readonly static integer sourceId
//readonly static unit target
//readonly static unit source
//readonly static real amount
//static method disable takes nothing returns nothing
//static method enable takes nothing returns nothing
//static method operator enabled takes nothing returns boolean
globals
private constant integer MAX_WASTED = 15
endglobals
//! runtextmacro optional ADV_DAMAGE_EVENT_EXT_GLOB_1()
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_0()
private module DamageEventMod
readonly static Event ANY = 0
readonly static UnitIndex targetId = 0
readonly static UnitIndex sourceId = 0
readonly static real amount = 0
private thistype next
private thistype previous
private static trigger trig = CreateTrigger()
private static integer wasted = 0
private static integer count = 0
private static boolexpr dmg = null
static method operator target takes nothing returns unit
return GetUnitById(targetId)
endmethod
static method operator source takes nothing returns unit
return GetUnitById(sourceId)
endmethod
static method disable takes nothing returns nothing
call DisableTrigger(trig)
endmethod
static method enable takes nothing returns nothing
call EnableTrigger(trig)
endmethod
static method operator enabled takes nothing returns boolean
return IsTriggerEnabled(trig)
endmethod
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_2()
private static method damage takes nothing returns boolean
static if not LIBRARY_AdvDamageEvent then
local integer prev = targetId
local integer prev2 = sourceId
local real prev3 = amount
set targetId = GetUnitUserData(GetTriggerUnit())
set sourceId = GetUnitUserData(GetEventDamageSource())
set amount = GetEventDamage()
if (0 != targetId) then
call targetId.lock()
endif
if (0 != sourceId) then
call sourceId.lock()
endif
else
local UnitIndex targetId = GetUnitUserData(GetTriggerUnit())
local UnitIndex sourceId = GetUnitUserData(GetEventDamageSource())
local real amount = GetEventDamage()
local real life
local boolean update = false
local integer i = eventCount
endif
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_4()
static if not LIBRARY_AdvDamageEvent then
call ANY.fire()
if (0 != targetId) then
call targetId.unlock()
endif
if (0 != sourceId) then
call sourceId.unlock()
endif
set targetId = prev
set sourceId = prev2
set amount = prev3
endif
return false
endmethod
private static method index takes nothing returns boolean
local thistype this = GetIndexedUnitId()
set previous = thistype(0).previous
set next = 0
set thistype(0).previous.next = this
set thistype(0).previous = this
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_6()
set count = count + 1
if (count > MAX_WASTED and wasted > count) then
set count = 0
set wasted = 0
call DestroyTrigger(trig)
set trig = CreateTrigger()
call TriggerAddCondition(trig, dmg)
set this = thistype(0).next
loop
call TriggerRegisterUnitEvent(trig, GetUnitById(this), EVENT_UNIT_DAMAGED)
set count = count + 1
set this = next
exitwhen this == 0
endloop
else
call TriggerRegisterUnitEvent(trig, GetUnitById(this), EVENT_UNIT_DAMAGED)
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local thistype this = GetIndexedUnitId()
set wasted = wasted + 1
set count = count - 1
set previous.next = next
set next.previous = previous
return false
endmethod
private static method onInit takes nothing returns nothing
set dmg = Condition(function thistype.damage)
call TriggerAddCondition(trig, dmg)
set ANY = CreateEvent()
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_7()
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
endmethod
endmodule
struct DamageEvent extends array
implement DamageEventMod
endstruct
//! runtextmacro optional DAMAGE_EVENT_ADV_EXT_1()
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library IPB /* v3.0.2.6
*************************************************************************************
*
* Determines if the path between two points, the target point having a radius, is blocked.
*
************************************************************************************
*
* */uses/*
*
* */ IsPathable /* hiveworkshop.com/forums/submissions-414/snippet-ispathable-199131/
* */ Tile /* hiveworkshop.com/forums/submissions-414/snippet-tile-211368/
* */ RegisterPlayerUnitEvent /* hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
* */ UnitIndexer /* hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
* */ GetUnitCollision /* hiveworkshop.com/forums/submissions-414/snippet-needs-work-getunitcollision-180495/
*
************************************************************************************
*
* SETTINGS
*
* This is how much work is done per thread when loading pathing map.
* Tweak this value in debug mode until the pathing map crash message goes away to minimize load time.
*/
globals
private constant integer BUFFER = 6300
endglobals
/*
*
************************************************************************************
*
* function IsPathBlocked takes unit obstruction returns boolean
* - Determines whether or not there is a path after a new obstruction is placed
* - obstruction refers to the new obstruction
*
************************************************************************************/
private keyword P
private function NormalizeAngle takes real angle returns real
local integer a
if (0 > angle) then
set a = R2I(angle*180/bj_PI - 45)/90*90
else
set a = R2I(angle*180/bj_PI + 45)/90*90
endif
if (0 > a or 360 < a) then
set a = a - a/360*360
if (0 > a) then
set a = a + 360
endif
endif
return a/180.*bj_PI
endfunction
private function CalculateAngleBetweenPoints takes real x, real y, real x2, real y2 returns real
return Atan2(y2 - y, x2 - x)
endfunction
private function CalculateComponentX takes real angle returns real
return 64*Cos(angle)
endfunction
private function CalculateComponentY takes real angle returns real
return 64*Sin(angle)
endfunction
globals
private integer tS
private P array pS
private hashtable ib
private hashtable ih = null
endglobals
private struct IsHit extends array
method operator [] takes integer y returns boolean
return LoadBoolean(ih, this, y)
endmethod
method operator []= takes integer y, boolean v returns nothing
call SaveBoolean(ih, this, y, v)
endmethod
static method clear takes nothing returns nothing
call FlushParentHashtable(ih)
set ih = InitHashtable()
endmethod
endstruct
private struct IsBlocked extends array
method operator [] takes integer y returns boolean
return LoadBoolean(ib, this, y)
endmethod
method operator []= takes integer y, boolean v returns nothing
call SaveBoolean(ib, this, y, v)
endmethod
endstruct
private struct P extends array
private static integer ic = 0
private static integer array r
readonly static integer tx = 0
readonly static integer ty = 0
readonly static boolean ib = true
readonly integer x
readonly integer y
readonly boolean og0
readonly boolean og90
readonly boolean og180
readonly boolean og270
readonly integer ax
readonly integer ay
private static constant integer R = 8
static method create takes integer x, integer y, integer ax, integer ay returns thistype
local thistype t
set t = r[0]
if (0 == t) then
set t = ic + 1
set ic = t
else
set r[0] = r[t]
endif
set t.x = x
set t.y = y
set IsHit[x][y] = true
set ib = x + R < tx or x - R > tx or y + R < ty or y - R > ty
set t.ax = ax
set t.ay = ay
if (0 == ax) then
set t.og0 = not IsBlocked[x+64][y]
set t.og180 = not IsBlocked[x-64][y]
else
set t.og90 = not IsBlocked[x][y+64]
set t.og270 = not IsBlocked[x][y-64]
endif
return t
endmethod
static method clear takes nothing returns nothing
set ic = 0
set r[0] = 0
endmethod
static method initialize takes integer targetX, integer targetY returns nothing
set thistype.tx = targetX
set thistype.ty = targetY
set thistype.ib = true
endmethod
static method ipc takes nothing returns boolean
static if DEBUG_MODE then
local integer p = 645
else
local integer p = 1725
endif
local thistype t = pS[tS]
local boolean o0
local boolean o1
local integer x = t.x + t.ax
local integer y = t.y + t.ay
set UnitIndexer.enabled = false
loop
exitwhen 0 == t or 0 == p or not ib
set p = p - 1
set x = t.x + t.ax
set y = t.y + t.ay
if (IsHit[x][y]) then
set tS = tS - 1
set r[t] = r[0]
set r[0] = t
set t = pS[tS]
elseif (not IsBlocked[x][y]) then
set IsHit[x][y] = true
set ib = x + R < tx or x - R > tx or y + R < ty or y - R > ty
set t.x = x
set t.y = y
if (0 == t.ax) then //vertical
set o0 = t.og0
set o1 = t.og180
set t.og0 = not IsBlocked[x+64][y]
set t.og180 = not IsBlocked[x-64][y]
if (o0 != t.og0 and not o0 and not IsHit[x+64][y]) then
if (o1 != t.og180 and not o1 and not IsHit[x-64][y]) then
set pS[tS+1] = P.create(x, y, -64, 0)
set tS = tS + 2
set t = P.create(x, y, 64, 0)
set pS[tS] = t
else
set tS = tS + 1
set t = P.create(x, y, 64, 0)
set pS[tS] = t
endif
elseif (o1 != t.og180 and not o1 and not IsHit[x-64][y]) then
set tS = tS + 1
set t = P.create(x, y, -64, 0)
set pS[tS] = t
endif
else //horizantal
set o0 = t.og90
set o1 = t.og270
set t.og90 = not IsBlocked[x][y+64]
set t.og270 = not IsBlocked[x][y-64]
if (o0 != t.og90 and not o0 and not IsHit[x][y+64]) then
if (o1 != t.og270 and not o1 and not IsHit[x][y-64]) then
set pS[tS+1] = P.create(x, y - 64, 0, -64)
set t = P.create(x, y, 0, 64)
set pS[tS] = t
else
set tS = tS + 1
set t = P.create(x, y, 0, 64)
set pS[tS] = t
endif
elseif (o1 != t.og270 and not o1 and not IsHit[x][y-64]) then
set tS = tS + 1
set t = P.create(x, y, 0, -64)
set pS[tS] = t
endif
endif
else
set tS = tS - 1
set x = t.x
set y = t.y
if (0 == t.ax) then
if (not IsBlocked[x+64][y] and not IsHit[x+64][y]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, 64, 0)
endif
if (not IsBlocked[x-64][y] and not IsHit[x-64][y]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, -64, 0)
endif
else
if (not IsBlocked[x][y+64] and not IsHit[x][y+64]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, 0, 64)
endif
if (not IsBlocked[x][y-64] and not IsHit[x][y-64]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, 0, -64)
endif
endif
set r[t] = r[0]
set r[0] = t
set t = pS[tS]
endif
endloop
set UnitIndexer.enabled = true
return true
return not ib or 0 == t
endmethod
endstruct
private function ClearAll takes nothing returns nothing
call P.clear()
set tS = 0
call IsHit.clear()
endfunction
private struct IBS extends array
private static trigger isPathBlockedT
private static method initialize takes integer x, integer y, integer tx, integer ty returns boolean
local real angle
local real m
local integer ax
local integer ay
local boolean init = false
call ClearAll()
call P.initialize(tx, ty)
set angle = NormalizeAngle(CalculateAngleBetweenPoints(x, y, tx, ty))
set m = NormalizeAngle(angle + bj_PI)
set ax = NormalizeXY(CalculateComponentX(m))
set ay = NormalizeXY(CalculateComponentY(m))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
set m = NormalizeAngle(angle + bj_PI/2)
set ax = NormalizeXY(CalculateComponentX(m))
set ay = NormalizeXY(CalculateComponentY(m))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
set m = NormalizeAngle(angle + bj_PI+bj_PI/2)
set ax = NormalizeXY(CalculateComponentX(m))
set ay = NormalizeXY(CalculateComponentY(m))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
set ax = NormalizeXY(CalculateComponentX(angle))
set ay = NormalizeXY(CalculateComponentY(angle))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
return init
endmethod
static method calculate takes integer ox, integer oy, integer tx, integer ty returns boolean
if (initialize(ox, oy, tx, ty)) then
loop
exitwhen TriggerEvaluate(isPathBlockedT)
endloop
endif
return P.ib
endmethod
private static method onInit takes nothing returns nothing
set isPathBlockedT = CreateTrigger()
call TriggerAddCondition(isPathBlockedT, Condition(function P.ipc))
endmethod
endstruct
private struct RL extends array
private static integer x
private static integer y
private static boolean array h
private static method upd takes unit u, boolean ip returns nothing
local integer x
local integer y
local integer s
local integer cx
local integer cy
local integer mx
local integer my
if (h[GetUnitUserData(u)] != ip) then
set h[GetUnitUserData(u)] = ip
set x = NormalizeXY(GetUnitX(u))
set y = NormalizeXY(GetUnitY(u))
set s = NormalizeXY(GetUnitCollision(u))-32
set mx = x - s
set my = y - s
set x = x + s
set y = y + s
set cx = x
set cy = y
if (0 < s) then
loop
loop
set IsBlocked[cx][cy] = ip
exitwhen cy == my
set cy = cy - 64
endloop
exitwhen cx == mx
set cx = cx - 64
set cy = y
endloop
endif
endif
endmethod
private static method updateD takes nothing returns boolean
if (null == GetIndexedUnit()) then
if (IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE)) then
call upd(GetTriggerUnit(), false)
endif
else
if (IsUnitType(GetIndexedUnit(), UNIT_TYPE_STRUCTURE)) then
call upd(GetIndexedUnit(), false)
endif
endif
return false
endmethod
private static method updateI takes nothing returns boolean
if (IsUnitType(GetIndexedUnit(), UNIT_TYPE_STRUCTURE)) then
call upd(GetIndexedUnit(), true)
endif
return false
endmethod
private static unit pc
debug private static boolean crashed
private static method lm takes nothing returns boolean
static if DEBUG_MODE then
local integer p = 300
else
local integer p = BUFFER
endif
local integer x = RL.x
local integer y = RL.y
local integer max = WorldBounds.maxX-32
local integer mx = WorldBounds.minX-32
local integer my = WorldBounds.minY+32
local integer pt = PATH_TYPE_WALKABILITY
local integer m = (WorldBounds.maxX-WorldBounds.minX)/64
local hashtable h = ib
local unit u
if (0 > m) then
set m = -m
endif
set m = m - 1
debug set crashed = true
loop
loop
call SetUnitPosition(pc, x, y)
call SaveBoolean(h, x, y, GetUnitX(pc) != x or GetUnitY(pc) != y)
set x = x - 64
exitwhen x == mx
endloop
set x = max
set p = p - m
set y = y - 64
exitwhen y == my or 1 > p
endloop
debug set crashed = false
set h = null
set RL.x = x
set RL.y = y
return y == my
endmethod
private static method onInit takes nothing returns nothing
local trigger ct = CreateTrigger()
local group g = CreateGroup()
local unit u
set ib = InitHashtable()
call GroupEnumUnitsInRect(g, WorldBounds.world, null)
loop
set u = FirstOfGroup(g)
exitwhen null == u
call GroupRemoveUnit(g,u)
if (IsUnitType(u, UNIT_TYPE_STRUCTURE)) then
set h[GetUnitUserData(u)] = true
endif
endloop
call DestroyGroup(g)
set g = null
call TriggerAddCondition(ct, Condition(function thistype.lm))
set thistype.x = WorldBounds.maxX-32
set thistype.y = WorldBounds.maxY-32
set UnitIndexer.enabled = false
set pc = GetPathingUnit(PATH_TYPE_WALKABILITY)
loop
exitwhen TriggerEvaluate(ct)
debug if (crashed) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"PATHING MAP CRASH")
debug return
debug endif
endloop
set pc = null
call SetUnitX(pc,WorldBounds.minX)
call SetUnitY(pc,WorldBounds.minY)
set UnitIndexer.enabled = true
call TriggerClearConditions(ct)
call DestroyTrigger(ct)
set ct = null
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.updateD))
call RegisterUnitIndexEvent(Condition(function thistype.updateI), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.updateD), UnitIndexer.DEINDEX)
endmethod
endstruct
private struct PC extends array
private static boolean tb
private static boolean bb
private static boolean lb
private static boolean rb
private static boolean trb
private static boolean tlb
private static boolean blb
private static boolean brb
readonly static integer tbx
readonly static integer tby
readonly static integer bbx
readonly static integer bby
readonly static integer lbx
readonly static integer lby
readonly static integer rbx
readonly static integer rby
private static method initBlocks takes integer x, integer y, integer r returns nothing
local integer s = r - 32
local integer so = s + 64
local integer mx
local integer my
local integer cx
local integer cy
local integer off = 32
if (0 == s) then
set off = 0
endif
//top
set cx = x + s
set mx = x - s
set cy = y + so
loop
if (IsBlocked[cx][cy]) then
set tb = true
else
set tb = false
set tbx = cx
set tby = cy
endif
exitwhen cx == mx or not tb
set cx = cx - 64
endloop
//left
set cy = y + s
set my = y - s
set cx = x - so
loop
if (IsBlocked[cx][cy]) then
set lb = true
else
set lb = false
set lbx = cx
set lby = cy
endif
exitwhen cy == my or not lb
set cy = cy - 64
endloop
//bottom
set cx = x + s
set mx = x - s
set cy = y - so
loop
if (IsBlocked[cx][cy]) then
set bb = true
else
set bb = false
set bbx = cx
set bby = cy
endif
exitwhen cx == mx or not bb
set cx = cx - 64
endloop
//right
set cy = y + s
set my = y - s
set cx = x + so
loop
if (IsBlocked[cx][cy]) then
set rb = true
else
set rb = false
set rbx = cx
set rby = cy
endif
exitwhen cy == my or not rb
set cy = cy - 64
endloop
//top left
set tlb = false
if (not lb) then
set cy = y + s
set my = y + off
set cx = x - so
loop
set tlb = tlb or IsBlocked[cx][cy]
exitwhen cy == my or tlb
set cy = cy - 64
endloop
endif
if (not tb) then
set cx = x - off
set mx = x - s
set cy = y + so
loop
set tlb = tlb or IsBlocked[cx][cy]
exitwhen cx == mx or tlb
set cx = cx - 64
endloop
endif
set tlb = tlb or IsBlocked[x-so][y+so]
//top right
set trb = false
if (not rb) then
set cy = y + s
set my = y + off
set cx = x + so
loop
set trb = trb or IsBlocked[cx][cy]
exitwhen cy == my or trb
set cy = cy - 64
endloop
endif
if (not tb) then
set cx = x + s
set mx = x + off
set cy = y + so
loop
set trb = trb or IsBlocked[cx][cy]
exitwhen cx == mx or trb
set cx = cx - 64
endloop
endif
set trb = trb or IsBlocked[x+so][y+so]
//bottom right
set brb = false
if (not rb) then
set cy = y - off
set my = y - s
set cx = x + so
loop
set brb = brb or IsBlocked[cx][cy]
exitwhen cy == my or brb
set cy = cy - 64
endloop
endif
if (not bb) then
set cx = x + s
set mx = x + off
set cy = y - so
loop
set brb = brb or IsBlocked[cx][cy]
exitwhen cx == mx or brb
set cx = cx - 64
endloop
endif
set brb = brb or IsBlocked[x+so][y-so]
//bottom left
set blb = false
if (not lb) then
set cy = y - off
set my = y - s
set cx = x - so
loop
set blb = blb or IsBlocked[cx][cy]
exitwhen cy == my or blb
set cy = cy - 64
endloop
endif
if (not bb) then
set cx = x - off
set mx = x - s
set cy = y - so
loop
set blb = blb or IsBlocked[cx][cy]
exitwhen cx == mx or blb
set cx = cx - 64
endloop
endif
set blb = blb or IsBlocked[x-so][y-so]
endmethod
static method init takes integer x, integer y, integer r returns boolean
local boolean p
call initBlocks(x, y, r)
if (not tb and not (bb and rb and lb)) then
set p = (trb or (brb and not bb) or rb) and (tlb or lb or (blb and not bb))
if (p) then
if (((rb and bb) or (lb and bb)) and ((trb != blb) or (tlb != brb))) then
set p = not bb or (not (rb and lb) and tlb and trb)
endif
endif
if (p) then
if (not bb) then //bottom to top
return IBS.calculate(PC.bbx, PC.bby, PC.tbx, PC.tby)
elseif (not rb and trb) then //right to top
return IBS.calculate(PC.rbx, PC.rby, PC.tbx, PC.tby)
elseif (tlb) then //left to top
return IBS.calculate(PC.lbx, PC.lby, PC.tbx, PC.tby)
endif
endif
endif
if (not bb and not (rb and tb and lb)) then
set p = ((trb and not tb) or brb or rb) and ((tlb and not tb) or lb or blb)
if (p) then
if (((rb and tb) or (lb and tb)) and ((trb != blb) or (tlb != brb))) then
set p = not tb or (not (rb and lb) and blb and brb)
endif
endif
if (p) then
if (not rb and brb) then //right to bottom
return IBS.calculate(PC.rbx, PC.rby, PC.bbx, PC.bby)
elseif (not tb) then //top to bottom
return IBS.calculate(PC.tbx, PC.tby, PC.bbx, PC.bby)
elseif (blb) then //left to bototm
return IBS.calculate(PC.lbx, PC.lby, PC.bbx, PC.bby)
endif
endif
endif
if (not lb and not (bb and rb and tb)) then
set p = (tlb or tb or (trb and not rb)) and (blb or bb or (brb and not rb))
if (p) then
if (((tb and rb) or (rb and bb)) and ((trb != blb) or (tlb != brb))) then
set p = not rb or (not (tb and bb) and tlb and blb)
endif
endif
if (p) then
if (not bb and blb) then //bottom to left
return IBS.calculate(PC.bbx, PC.bby, PC.lbx, PC.lby)
elseif (not tb and tlb) then //top to left
return IBS.calculate(PC.tbx, PC.tby, PC.lbx, PC.lby)
else //right to left
return IBS.calculate(PC.rbx, PC.rby, PC.lbx, PC.lby)
endif
endif
endif
if (not rb and not (tb and lb and bb)) then
set p = ((tlb and not lb) or tb or trb) and ((blb and not lb) or bb or brb)
if (p) then
if (((lb and bb) or (lb and tb)) and ((trb != blb) or (tlb != brb))) then
set p = not lb or (not (tb and bb) and trb and brb)
endif
endif
if (p) then
if (not tb and trb) then //top to right
return IBS.calculate(PC.tbx, PC.tby, PC.rbx, PC.rby)
elseif (not lb) then //left to right
return IBS.calculate(PC.lbx, PC.lby, PC.rbx, PC.rby)
elseif (brb) then //bottom to right
return IBS.calculate(PC.bbx, PC.bby, PC.rbx, PC.rby)
endif
endif
endif
return false
endmethod
endstruct
function IsPathBlocked takes unit u returns boolean
return PC.init(NormalizeXY(GetUnitX(u)), NormalizeXY(GetUnitY(u)), NormalizeXY(GetUnitCollision(u)))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct AntiBlock extends array
private static method checkBlock takes nothing returns boolean
if (Compensate[GetUnitUserData(GetTriggerUnit())].give and IsPathBlocked(GetTriggerUnit())) then
set Compensate[GetUnitUserData(GetTriggerUnit())].give = false
call WriteTextTag("Attempted to Block With "+GetUnitName(GetTriggerUnit()), 10, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), GetLocalPlayer() == GetTriggerPlayer())
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD) + GetUnitTotalGoldCost(GetTriggerUnit()))
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER) + GetUnitTotalWoodCost(GetTriggerUnit()))
call RemoveUnit(GetTriggerUnit())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_START, Condition(function thistype.checkBlock))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
globals
constant integer DIFFICULTY_BEGINNER = 'R000'
constant integer DIFFICULTY_INTERMEDIATE = 'R003'
constant integer DIFFICULTY_MASTER = 'R002'
constant integer DIFFICULTY_LEAGUE = 'R001'
endglobals
struct Difficulty extends array
private static constant integer MODE_PICKER = 'h017'
private static method pick takes nothing returns boolean
local integer i
local integer dif = GetResearched()
set i = 15
loop
call SetPlayerTechResearched(Player(i), dif, 1)
exitwhen 0 == i
set i = i - 1
endloop
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,GetPlayerColorStringById(GetPlayerId(GetTriggerPlayer()))+GetPlayerName(GetTriggerPlayer())+"|r has chosen "+GetObjectName(dif)+" Mode")
call TriggerClearConditions(GetTriggeringTrigger())
call DestroyTrigger(GetTriggeringTrigger())
call RemoveUnit(GetTriggerUnit())
call Game.init(dif)
return false
endmethod
private static method onInit takes nothing returns nothing
local integer i = 0
local trigger t
local unit u
if (not Game.isOver) then
loop
exitwhen IsPlaying(Player(i))
set i = i + 1
endloop
set t = CreateTrigger()
set u = CreateUnit(Player(i), MODE_PICKER, GetStartLocationX(i), GetStartLocationY(i), 270)
call TriggerRegisterUnitEvent(t, u, EVENT_UNIT_RESEARCH_START)
call TriggerAddCondition(t, Condition(function thistype.pick))
call SelectUnit(u, GetLocalPlayer() == Player(i))
set u = null
endif
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Game uses WorldBounds, Event, Chatroom, IsPlaying
struct Game extends array
private static integer array teamCount
private static boolean array playing
private static constant real TIME_TO_END = 30
readonly static boolean isOver = false
readonly static Event onEnd
readonly static Event onEndSolo
readonly static Event onInitialize
readonly static Event onInitializeSolo
readonly static Event onStart
readonly static Event onStartSolo
static integer difficulty = 0
static real startGame = 0
private static timerdialog window = null
readonly static boolean isOnline = not ReloadGameCachesFromDisk()
readonly static boolean solo = false
//ending
private static method endGame takes nothing returns nothing
call EndGame(false)
endmethod
static method end takes integer winner returns nothing
local timer t
local group g
local unit u
if (not isOver) then
set isOver = true
call DestroyTimerDialog(thistype.window)
if (solo) then
call onEndSolo.fire()
else
call onEnd.fire()
endif
set t = CreateTimer()
call TimerStart(t,TIME_TO_END,false,function thistype.endGame)
set window = CreateTimerDialog(t)
call TimerDialogSetTitle(window,"Game Ends: ")
call TimerDialogDisplay(window,true)
set g = CreateGroup()
call GroupEnumUnitsInRect(g,WorldBounds.world,null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
call GroupRemoveUnit(g,u)
call RemoveUnit(u)
endloop
set g = null
if (winner == -1) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Game ended due to lack of players")
else
if (solo) then
if (GetPlayerId(GetLocalPlayer()) < 6) then
if (1 == winner) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"You have won")
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"You have lost")
endif
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Game ended")
endif
else
if (GetPlayerId(GetLocalPlayer()) < 6) then
if (GetPlayerId(GetLocalPlayer())/3 == winner) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Your team has won")
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Your team has lost")
endif
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Team "+I2S(winner+1)+" has won")
endif
endif
endif
endif
endmethod
static method removePlayer takes integer pid returns nothing
if (playing[pid]) then
set playing[pid] = false
set teamCount[pid/3] = teamCount[pid/3] - 1
if (0 == teamCount[pid/3] and not solo) then
if (0==pid/3) then
call end(1)
else
call end(0)
endif
endif
endif
endmethod
private static method leave takes nothing returns boolean
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,names[GetPlayerId(GetTriggerPlayer())]+" has left")
call removePlayer(GetPlayerId(GetTriggerPlayer()))
return false
endmethod
//starting
private static method start takes nothing returns nothing
if (not Game.isOver) then
call DestroyTimerDialog(window)
set window = null
if (solo) then
call onStartSolo.fire()
else
call onStart.fire()
endif
endif
call DestroyTimer(GetExpiredTimer())
endmethod
static method init takes integer difficulty returns nothing
local real timeout
local timer t
if (not Game.isOver) then
set thistype.difficulty = difficulty
if (solo) then
call onInitializeSolo.fire()
else
call onInitialize.fire()
endif
if (difficulty == DIFFICULTY_BEGINNER) then
set timeout = 60 - 1
elseif (difficulty == DIFFICULTY_INTERMEDIATE) then
set timeout = 30 - 1
else
if (solo) then
call onStartSolo.fire()
else
call onStart.fire()
endif
return
endif
set t = CreateTimer()
call TimerStart(t, timeout, false, function thistype.start)
set window = CreateTimerDialog(t)
call TimerDialogSetTitle(window, "First Send")
call TimerDialogDisplay(window, true)
set t = null
endif
endmethod
private static method onInit takes nothing returns nothing
local integer i
local trigger t
local player p
set i = 5
set t = CreateTrigger()
call TriggerAddCondition(t,Condition(function thistype.leave))
loop
set p = Player(i)
set playing[i] = IsPlaying(p)
if (playing[i]) then
call TriggerRegisterPlayerEvent(t, p, LeaveEvent())
set teamCount[i/3] = teamCount[i/3] + 1
endif
exitwhen 0 == i
set i = i - 1
endloop
set t = null
set p = null
set solo = (0 == teamCount[0] and 1 == teamCount[1]) or (1 == teamCount[0] and 0 == teamCount[1])
set onEnd = Event.create()
set onInitialize = Event.create()
set onStart = Event.create()
set onEndSolo = Event.create()
set onInitializeSolo = Event.create()
set onStartSolo = Event.create()
call SetGameSpeed(MAP_SPEED_FASTEST)
call SetMapFlag(MAP_LOCK_SPEED, true)
call SetFloatGameState(GAME_STATE_TIME_OF_DAY, 18.01)
call SetTimeOfDayScale(0)
if (not solo) then
if ((0==teamCount[0] and 0==teamCount[1])) then
call end(-1)
elseif (0==teamCount[0]) then
call end(1)
elseif (0==teamCount[1]) then
call end(0)
endif
endif
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct Balancing extends array
private static constant integer BALANCE = 'R004'
private static method onInit takes nothing returns nothing
local integer i = 5
loop
call SetPlayerTechResearched(Player(i), BALANCE, 1)
exitwhen 0 == i
set i = i - 1
endloop
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Balancing Enabled")
endmethod
endstruct
//TESH.scrollpos=44
//TESH.alwaysfold=0
library Tester uses GetUnitCost, PlayerBuilder, Boards, Race
struct Tester extends array
private static method getGold takes nothing returns boolean
local group g = CreateGroup()
local integer gold = 0
local unit u
call GroupEnumUnitsOfPlayer(g, GetTriggerPlayer(), null)
loop
set u = FirstOfGroup(g)
exitwhen null == u
call GroupRemoveUnit(g,u)
set gold = gold + GetUnitTotalGoldCost(u)
endloop
call DestroyGroup(g)
set g = null
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"Gold Spent: "+I2S(gold))
return false
endmethod
private static method registerGold takes player p returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterPlayerChatEvent(t,p,"-gold",true)
call TriggerAddCondition(t,Condition(function thistype.getGold))
set t = null
endmethod
private static method init takes nothing returns boolean
local player p = Player(1)
local integer i
local integer i2
call registerGold(p)
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
call PlayerBuilder[GetPlayerId(p)].addBuilder()
set i = 5
loop
set i2 = i - 1
loop
call SetPlayerAlliance(Player(i),Player(i2),ALLIANCE_SHARED_ADVANCED_CONTROL,true)
call SetPlayerAlliance(Player(i),Player(i2),ALLIANCE_SHARED_CONTROL,true)
call SetPlayerAlliance(Player(i2),Player(i),ALLIANCE_SHARED_ADVANCED_CONTROL,true)
call SetPlayerAlliance(Player(i2),Player(i),ALLIANCE_SHARED_CONTROL,true)
exitwhen 0 == i2
set i2 = i2 - 1
endloop
//call SetPlayerState(Player(i),PLAYER_STATE_RESOURCE_GOLD,1000000)
//call SetPlayerState(Player(i),PLAYER_STATE_RESOURCE_LUMBER,1000000)
//set Income[i].lumber = 50
set i = i - 1
exitwhen 0 == i
endloop
//call SetPlayerState(Player(0),PLAYER_STATE_RESOURCE_GOLD,1000000)
//call SetPlayerState(Player(0),PLAYER_STATE_RESOURCE_LUMBER,1000000)
//set Income[0].gold = 2050
set p = null
if (GetPlayerId(GetLocalPlayer()) > 5) then
set Boards.observer.display = true
else
set Boards[GetPlayerId(GetLocalPlayer())].display = true
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TextTag
function WriteTextTag takes string msg, real size, real x, real y, boolean visible returns nothing
local texttag tag = CreateTextTag()
call SetTextTagText(tag, msg, size*0.023/10)
call SetTextTagPos(tag, x, y, 128)
call SetTextTagLifespan(tag, 2)
call SetTextTagPermanent(tag, false)
call SetTextTagVelocity(tag, 0, .1)
call SetTextTagFadepoint(tag, 1.5)
call SetTextTagVisibility(tag, visible)
set tag = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct FogOfWar extends array
private static method initialize takes nothing returns boolean
local integer i
local player p
set i = 11
loop
set p = Player(i)
if (IsPlaying(p)) then
call FogModifierStart(CreateFogModifierRect(p, FOG_OF_WAR_VISIBLE, WorldBounds.world, false, false))
endif
exitwhen 0 == i
set i = i - 1
endloop
set p = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.initialize))
call Game.onInitializeSolo.register(Condition(function thistype.initialize))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct TextTagBuildTip extends array
private static method initialize takes nothing returns boolean
local texttag tag
set tag = CreateTextTag()
if (Game.solo) then
call SetTextTagText(tag, "Creeps Have To Touch Large Buildable Square Outlined By Bolts Don't forget to get income, type -help income for more details Your final score is based on your income\nand what wave you lasted to", 10 * 0.023 / 10)
else
call SetTextTagText(tag, "Creeps Have To Touch Large Buildable Square Outlined By Bolts", 10 * 0.023 / 10)
endif
call SetTextTagPermanent(tag, true)
call SetTextTagPos(tag, GetStartLocationX(GetPlayerId(GetLocalPlayer()))-180, GetStartLocationY(GetPlayerId(GetLocalPlayer())), 128)
call SetTextTagVisibility(tag, GetPlayerId(GetLocalPlayer()) < 6)
set tag = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.initialize))
call Game.onInitializeSolo.register(Condition(function thistype.initialize))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct StartResources extends array
readonly static integer GOLD = 0
readonly static integer LUMBER = 0
private static method initialize takes nothing returns boolean
local integer i = 5
local player p
if (Game.difficulty == DIFFICULTY_BEGINNER) then
set GOLD = 110
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
set GOLD = 100
elseif (Game.difficulty == DIFFICULTY_MASTER) then
set GOLD = 90
else
set GOLD = 125
endif
loop
set p = Player(i)
if (IsPlaying(p)) then
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)+GOLD)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER)+LUMBER)
endif
exitwhen 0 == i
set i = i - 1
endloop
set p = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.initialize))
call Game.onInitializeSolo.register(Condition(function thistype.initialize))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct PreventCommand extends array
private static method order takes nothing returns boolean
if (GetIssuedOrderId() == 851971 and GetUnitRace(GetTriggerUnit()) == RACE_DEMON) then
call DisableTrigger(GetTriggeringTrigger())
call IssueImmediateOrderById(GetTriggerUnit(), 851972)
call IssuePointOrderByIdLoc(GetTriggerUnit(), 851986, UnitPath(GetUnitUserData(GetTriggerUnit())).checkpoint.point)
call EnableTrigger(GetTriggeringTrigger())
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, Condition(function thistype.order))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, Condition(function thistype.order))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onStart.register(Condition(function thistype.init))
call Game.onStartSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=38
//TESH.alwaysfold=0
struct ShareBounty extends array
private static Table bountyBonusTeamP
private static Table bountyBonusUnitP
private static Table bountyBonusTeamS
private static Table bountyBonusUnitS
private static method onDeath takes nothing returns boolean
local integer t
local integer i
local integer p = GetUnitPointValue(GetTriggerUnit())
local integer uid = GetUnitTypeId(GetTriggerUnit())
local real pv = (p-p/100000*100000)/100.
local integer g = GetUnitTypeIdGoldCost(uid)
local integer l = GetUnitTypeIdWoodCost(uid)
local integer m = 1
local string sg = "+"
local string sl = "+"
local string msg
local real bb
if (0 > p) then
set p = -p
set pv = pv*-15
endif
set bb = (p/100000)/100.
set t = GetPlayerId(GetOwningPlayer(GetKillingUnit()))/3
if (0 == t) then
set m = -1
endif
set g = R2I((g/pv+g/pv*(bountyBonusTeamP[t]+bountyBonusUnitP[m*uid])+bountyBonusTeamS[t]+bountyBonusUnitS[m*uid])*bb)
set l = R2I((l/pv+l/pv*(bountyBonusTeamP[t]+bountyBonusUnitP[m*uid])+bountyBonusTeamS[t]+bountyBonusUnitS[m*uid])*bb)
if (0 > g) then
set sg = "-"
endif
if (0 > l) then
set sl = "-"
endif
if (0 != g or 0 != l) then
set m = t
set t = t + 2
loop
if (IsPlaying(Player(t))) then
call SetPlayerState(Player(t), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(Player(t), PLAYER_STATE_RESOURCE_GOLD) + g)
call SetPlayerState(Player(t), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(Player(t), PLAYER_STATE_RESOURCE_LUMBER) + l)
endif
exitwhen m == t
set t = t - 1
endloop
set g = IAbsBJ(g)
set l = IAbsBJ(l)
if (0 == g) then
set msg = "|c00347235"+sl+I2S(l)+"|r"
elseif (0 == l) then
set msg = "|c00FDD017"+sg+I2S(g)+"|r"
else
set msg = "|c00FDD017"+sg+I2S(g)+" |r|c00347235"+sl+I2S(l)+"|r"
endif
call WriteTextTag(msg, 10, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), GetPlayerId(GetLocalPlayer())/3 == t or GetPlayerId(GetLocalPlayer()) > 5)
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.onDeath))
return false
endmethod
private static method onInit takes nothing returns nothing
set bountyBonusTeamP = Table.create()
set bountyBonusUnitP = Table.create()
set bountyBonusTeamS = Table.create()
set bountyBonusUnitS = Table.create()
call init()
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=51
//TESH.alwaysfold=0
library ResourceExchange uses IsPlaying, Game
struct ResourceExchange extends array
static constant integer GOLD_EXCHANGE_RATE = 100000
static method goldToLumber takes integer gold returns integer
return gold/GOLD_EXCHANGE_RATE
endmethod
static method getRemainingGold takes integer gold returns integer
return gold - gold/GOLD_EXCHANGE_RATE*GOLD_EXCHANGE_RATE
endmethod
static method lumberToGold takes integer lumber returns integer
return lumber*GOLD_EXCHANGE_RATE
endmethod
private static method toLumber takes nothing returns boolean
local player p = GetTriggerPlayer()
local integer gold = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)
local integer exchanged = (gold-GOLD_EXCHANGE_RATE)/GOLD_EXCHANGE_RATE
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER)+exchanged)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, gold-exchanged*GOLD_EXCHANGE_RATE)
set p = null
return false
endmethod
private static method toGold takes nothing returns boolean
local player p = GetTriggerPlayer()
local integer gold = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)
local integer lumber = GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER)
if (gold < GOLD_EXCHANGE_RATE and 0 < lumber) then
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, gold+GOLD_EXCHANGE_RATE)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, lumber-1)
endif
set p = null
return false
endmethod
private static method init takes nothing returns boolean
local trigger t
local trigger t2
local integer i
local player p
local integer gold
local integer lumber
local integer exchanged
set t = CreateTrigger()
set t2 = CreateTrigger()
set i = 11
loop
set p = Player(i)
if (IsPlaying(p)) then
set gold = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)
set lumber = GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER)
if (gold < GOLD_EXCHANGE_RATE and 0 < lumber) then
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, gold+GOLD_EXCHANGE_RATE)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, lumber-1)
elseif (gold >= GOLD_EXCHANGE_RATE*2) then
set exchanged = (gold-GOLD_EXCHANGE_RATE)/GOLD_EXCHANGE_RATE
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, lumber+exchanged)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, gold-exchanged*GOLD_EXCHANGE_RATE)
endif
call TriggerRegisterPlayerStateEvent(t, p, PLAYER_STATE_RESOURCE_GOLD, GREATER_THAN_OR_EQUAL, GOLD_EXCHANGE_RATE*2)
call TriggerRegisterPlayerStateEvent(t2, p, PLAYER_STATE_RESOURCE_LUMBER, GREATER_THAN, 0)
call TriggerRegisterPlayerStateEvent(t2, p, PLAYER_STATE_RESOURCE_GOLD, LESS_THAN, GOLD_EXCHANGE_RATE)
endif
exitwhen 0 == i
set i = i - 1
endloop
call TriggerAddCondition(t, Condition(function thistype.toLumber))
call TriggerAddCondition(t2, Condition(function thistype.toGold))
set t = null
set t2 = null
set p = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Income uses Boards, Game, ResourceExchange
struct Income extends array
private static integer array goldIncomet
private static integer array lumberIncomet
private integer goldIncomep
private integer lumberIncomep
static method getBonusGold takes nothing returns integer
if (Game.difficulty == DIFFICULTY_BEGINNER) then
return R2I(30*(round+1.)*((round+1.)/14))
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
return R2I(10*(round+1.)*(round+0.)/14)
endif
return 0
endmethod
static method getBonusLumber takes nothing returns integer
return 0
endmethod
private static method updateBoard takes nothing returns nothing
local integer gold1 = Income[0].gold + Income[1].gold + Income[2].gold
local integer lumber1 = Income[0].lumber + Income[1].lumber + Income[2].lumber
local integer gold2 = Income[3].gold + Income[4].gold + Income[5].gold
local integer lumber2 = Income[3].lumber + Income[4].lumber + Income[5].lumber
if (gold1 == gold2 and lumber1 == lumber2) then
set Boards.team1.highestIncome = -1
set Boards.team2.highestIncome = -1
set Boards.observer.highestIncome = -1
elseif (lumber1 > lumber2 or (lumber1 == lumber2 and gold1 > gold2)) then
set Boards.team1.highestIncome = 0
set Boards.team2.highestIncome = 0
set Boards.observer.highestIncome = 0
else
set Boards.team1.highestIncome = 1
set Boards.team2.highestIncome = 1
set Boards.observer.highestIncome = 1
endif
endmethod
method operator goldTotal takes nothing returns integer
return goldIncomet[this]
endmethod
method operator lumberTotal takes nothing returns integer
return lumberIncomet[this]
endmethod
method operator lumber takes nothing returns integer
return lumberIncomep
endmethod
method operator lumber= takes integer i returns nothing
set lumberIncomep = i
set lumberIncomet[this/3] = Income[this/3].lumber+Income[this/3+1].lumber+Income[this/3+2].lumber
call Boards[this].setLumberIncome(this,I2S(i)+"+"+I2S(getBonusLumber()))
if (not Game.solo) then
call Boards.observer.setLumberIncome(this,I2S(i)+"+"+I2S(getBonusLumber()))
call updateBoard()
endif
endmethod
method operator gold takes nothing returns integer
return goldIncomep
endmethod
method operator gold= takes integer i returns nothing
set lumber = lumber + ResourceExchange.goldToLumber(i)
set goldIncomep = ResourceExchange.getRemainingGold(i)
set goldIncomet[this/3] = Income[this/3].gold+Income[this/3+1].gold+Income[this/3+2].gold
call Boards[this].setGoldIncome(this,I2S(goldIncomep)+"+"+I2S(getBonusGold()))
if (not Game.solo) then
call Boards.observer.setGoldIncome(this,I2S(goldIncomep)+"+"+I2S(getBonusGold()))
call updateBoard()
endif
endmethod
private static method onUpdate2 takes nothing returns boolean
local Gameboard board = Gameboard.eventBoard
local thistype this = 0
local integer end
local player p
if (board == Boards.team1) then
set this = 2
set end = 0
else
set this = 5
set end = 3
endif
loop
set p = Player(this)
if (IsPlaying(p)) then
call board.setGoldIncome(this,I2S(gold)+"+"+I2S(getBonusGold()))
call board.setLumberIncome(this,I2S(lumber)+"+"+I2S(getBonusLumber()))
endif
exitwhen end == this
set this = this - 1
endloop
set p = null
return false
endmethod
private static method onUpdate takes nothing returns boolean
local thistype this
local player p
set this = 5
loop
set p = Player(this)
if (IsPlaying(p)) then
call Boards.observer.setGoldIncome(this,I2S(gold)+"+"+I2S(getBonusGold()))
call Boards.observer.setLumberIncome(this,I2S(lumber)+"+"+I2S(getBonusLumber()))
endif
exitwhen 0 == this
set this = this - 1
endloop
call updateBoard()
set p = null
return false
endmethod
private static method init takes nothing returns boolean
call Boards.team1.onUpdate.register(Condition(function thistype.onUpdate2))
call Boards.team2.onUpdate.register(Condition(function thistype.onUpdate2))
call Boards.observer.onUpdate.register(Condition(function thistype.onUpdate))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct StartIncome extends array
readonly static integer START_GOLD = 0
readonly static integer START_LUMBER = 0
private static method init takes nothing returns boolean
local thistype this
local player p
if (Game.difficulty == DIFFICULTY_BEGINNER) then
set START_GOLD = 30
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
set START_GOLD = 25
elseif (Game.difficulty == DIFFICULTY_MASTER) then
set START_GOLD = 20
else
set START_GOLD = -5
endif
set this = 5
loop
set p = Player(this)
if (IsPlaying(p)) then
set Income[this].gold = Income[this].gold + START_GOLD
set Income[this].lumber = Income[this].lumber + START_LUMBER
endif
exitwhen 0 == this
set this = this - 1
endloop
set p = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
library ApplyIncome uses Income, Game
struct ApplyIncome extends array
static method run takes nothing returns nothing
local Income this = 5
local player p
local integer lumberTarget
local integer goldTarget
local integer gold
local integer lumber
local integer pc
local integer bg
local integer bl
local integer bg2
local integer bl2
set round = round - 1
set bg = Income.getBonusGold()
set bl = Income.getBonusLumber()
set round = round + 1
set bg2 = Income.getBonusGold()
set bl2 = Income.getBonusLumber()
loop
set p = Player(this)
if (IsPlaying(p)) then
set pc = Boards[this].playerCount
set gold = Income[this/3].goldTotal/pc + bg
set lumber = Income[this/3].lumberTotal/pc + bl
set lumber = ResourceExchange.goldToLumber(gold) + lumber
set gold = ResourceExchange.getRemainingGold(gold)
set lumberTarget = 0
set goldTarget = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) + gold
if (goldTarget < 0) then
set goldTarget = goldTarget + ResourceExchange.GOLD_EXCHANGE_RATE
set lumberTarget = -1
endif
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, goldTarget)
set lumberTarget = lumberTarget + GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER) + lumber
if (-1 > lumberTarget) then
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, 0)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, 0)
elseif (0 > lumberTarget) then
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, lumberTarget + 1)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) - ResourceExchange.GOLD_EXCHANGE_RATE)
else
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, lumberTarget)
endif
call Boards[this].setGoldIncome(this,I2S(this.gold)+"+"+I2S(bg2))
call Boards.observer.setGoldIncome(this,I2S(this.gold)+"+"+I2S(bg2))
call Boards[this].setLumberIncome(this,I2S(this.lumber)+"+"+I2S(bl2))
call Boards.observer.setLumberIncome(this,I2S(this.lumber)+"+"+I2S(bl2))
static if LIBRARY_Tester then
call DisplayTimedTextToPlayer(p,0,0,.1,"Gold Income: "+I2S(this.gold))
call DisplayTimedTextToPlayer(p,0,0,.1,"Lumber Income: "+I2S(this.lumber))
endif
endif
exitwhen 0 == this
set this = this - 1
endloop
set p = null
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Round uses Income, SoloWaves, Game
globals
constant real ROUND_TIME = 15
integer round = 1
integer sendCount = 0
endglobals
struct Round extends array
private static timer incomeTimer
private static timerdialog incomeWindow
private static method next takes nothing returns nothing
if (Game.solo) then
if (SoloWaves.send(round)) then
call PauseTimer(GetExpiredTimer())
call TimerDialogSetTitle(incomeWindow, "Last Wave")
set round = round - 1
else
call TimerDialogSetTitle(incomeWindow, "Wave "+I2S(round+1)+" In: ")
endif
call SoloIncome.run()
else
call TimerDialogSetTitle(incomeWindow, "Income "+I2S(round+1)+" In: ")
call ApplyIncome.run()
endif
set round = round + 1
endmethod
private static method stop takes nothing returns boolean
call PauseTimer(incomeTimer)
call DestroyTimerDialog(incomeWindow)
call DestroyTimer(incomeTimer)
set incomeTimer = null
set incomeWindow = null
return false
endmethod
private static method init takes nothing returns boolean
set incomeTimer = CreateTimer()
call TimerStart(incomeTimer, ROUND_TIME, true, function thistype.next)
set incomeWindow = CreateTimerDialog(incomeTimer)
if (Game.solo) then
call TimerDialogSetTitle(incomeWindow, "Wave 1: ")
else
call TimerDialogSetTitle(incomeWindow, "Income 1: ")
endif
call TimerDialogDisplay(incomeWindow, true)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onStart.register(Condition(function thistype.init))
call Game.onEnd.register(Condition(function thistype.stop))
call Game.onStartSolo.register(Condition(function thistype.init))
call Game.onEndSolo.register(Condition(function thistype.stop))
endmethod
endstruct
endlibrary
//TESH.scrollpos=33
//TESH.alwaysfold=0
library AddIncome uses Income, Game
struct AddIncome extends array
readonly static real incomeRate
real penaltyReduction
real bonusPercent
real bonusScalar
method get takes real amount returns integer
local real reduction
local real bp
local real bs
local real rnd
local boolean isNegative
if (0 == amount) then
return 0
endif
set isNegative = 0 > amount
set reduction = penaltyReduction
if (1 < reduction) then
set reduction = 1
endif
if (not isNegative) then
set reduction = 0
set bp = bonusPercent
set bs = bonusScalar
set rnd = .5
else
set bp = 0
set bs = 0
set rnd = -.5
endif
return R2I((amount*(1+bp)*(1-reduction) + bs)*incomeRate + rnd)
endmethod
private static method init takes nothing returns boolean
if (Game.difficulty == DIFFICULTY_BEGINNER) then
if (Game.solo) then
set incomeRate = .45
else
set incomeRate = .25
endif
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
if (Game.solo) then
set incomeRate = .95
else
set incomeRate = .75
endif
elseif (Game.difficulty == DIFFICULTY_MASTER) then
if (Game.solo) then
set incomeRate = 1.25
else
set incomeRate = 1.05
endif
else
if (Game.solo) then
set incomeRate = 1.45
else
set incomeRate = 1.25
endif
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=1
//TESH.alwaysfold=0
/*
Base on Point Value
Is Negative? Bounty Multiplier Value
+- X.XX XXX.XX
1: Positive
2: Negative
*/
struct UnitIncome extends array
private static method train takes nothing returns boolean
local unit u = GetSummon()
local integer uid = GetUnitTypeId(u)
static if LIBRARY_Tester then
local thistype this = GetPlayerId(GetOwningPlayer(u))
else
local thistype this = GetPlayerId(GetTriggerPlayer())
endif
local integer points = GetUnitPointValue(u)
local real pointsv
set pointsv = points-points/100000*100000
set pointsv = pointsv/100
if (GetUnitRace(u) == RACE_DEMON) then
set Income[this].gold = Income[this].gold + AddIncome[this].get(GetUnitTypeIdGoldCost(uid)/pointsv)
set Income[this].lumber = Income[this].lumber + AddIncome[this].get(GetUnitTypeIdWoodCost(uid)/pointsv)
endif
set u = null
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SELL, Condition(function thistype.train))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_TRAIN_FINISH, Condition(function thistype.train))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onStart.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct TransferOnLeave extends array
private static method getNewOwner takes player prevOwner returns player
local integer i = GetPlayerId(prevOwner)/3*3+2
local integer i2 = i - 2
local integer p = -1
loop
if (IsPlaying(Player(i)) and prevOwner != Player(i) and (-1 == p or Income[i].lumber > Income[p].lumber or (Income[i].lumber == Income[p].lumber and Income[i].gold > Income[p].gold))) then
set p = i
endif
exitwhen i == i2
set i = i - 1
endloop
if (-1 == p) then
return null
endif
return Player(p)
endmethod
private static method displayTransferMessage takes player from, player tio returns nothing
if (null != tio) then
if (GetLocalPlayer() == tio) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"You have gained control of the resources of "+names[GetPlayerId(from)])
elseif (GetPlayerId(GetLocalPlayer())/3 == GetPlayerId(tio)/3 or GetPlayerId(GetLocalPlayer()) > 5) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,names[GetPlayerId(tio)]+" has gained control of the resources of "+names[GetPlayerId(from)])
endif
endif
endmethod
private static method transferUnits takes player from, player tio returns nothing
local group g = CreateGroup()
local unit u
local integer i
local Summon summon
call GroupEnumUnitsInRect(g, WorldBounds.world, null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
call GroupRemoveUnit(g,u)
if (GetUnitRace(u) == RACE_DEMON) then
set summon = GetUnitUserData(u)
if (summon.owner == from) then
if (null == tio) then
set i = UnitInventorySize(u)
loop
exitwhen 0 == i
set i = i - 1
call RemoveItem(UnitItemInSlot(u, i))
endloop
call RemoveUnit(u)
else
set summon.owner = tio
endif
endif
elseif (GetOwningPlayer(u) == from) then
if (null == tio or IsRaceBuilder(u)) then
set i = UnitInventorySize(u)
loop
exitwhen 0 == i
set i = i - 1
call RemoveItem(UnitItemInSlot(u, i))
endloop
call RemoveUnit(u)
else
call SetUnitOwner(u, tio, true)
endif
endif
endloop
call DestroyGroup(g)
set g = null
endmethod
private static method transferResources takes player from, player tio returns nothing
local integer fromId = GetPlayerId(from)
local integer toId = GetPlayerId(tio)
if (null != tio) then
set Income[toId].gold = Income[toId].gold + Income[fromId].gold
set Income[toId].lumber = Income[toId].lumber + Income[fromId].lumber
call SetPlayerState(tio, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(tio, PLAYER_STATE_RESOURCE_GOLD) + GetPlayerState(from, PLAYER_STATE_RESOURCE_GOLD))
call SetPlayerState(tio, PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(tio, PLAYER_STATE_RESOURCE_LUMBER) + GetPlayerState(from, PLAYER_STATE_RESOURCE_LUMBER))
endif
set Income[fromId].gold = 0
set Income[fromId].lumber = 0
call SetPlayerState(from, PLAYER_STATE_RESOURCE_GOLD, 0)
call SetPlayerState(from, PLAYER_STATE_RESOURCE_LUMBER, 0)
endmethod
private static method transferRaces takes player from, player tio returns nothing
local integer i = Race.count - 1
if (0 < PlayerBuilder[GetPlayerId(from)].raceCount) then
call DisplayTimedTextToPlayer(tio, 0, 0, 10, "You can now build another race. Check your race builder.")
endif
if (0 < PlayerBuilder[GetPlayerId(from)].builderCount) then
call DisplayTimedTextToPlayer(tio, 0, 0, 10, "You can now build another another tower builder. Check the race building of "+names[GetPlayerId(from)])
endif
loop
set Race[i][tio] = Race[i][tio] + Race[i][from]
exitwhen 0 == i
set i = i - 1
endloop
endmethod
private static method transfer takes nothing returns boolean
local player originalOwner
local player newOwner
if (not Game.isOver) then
set originalOwner = GetTriggerPlayer()
set newOwner = getNewOwner(originalOwner)
call displayTransferMessage(originalOwner, newOwner)
call transferUnits(originalOwner,newOwner)
call transferResources(originalOwner, newOwner)
call transferRaces(originalOwner, newOwner)
set originalOwner = null
set newOwner = null
else
set Income[GetPlayerId(GetTriggerPlayer())].gold = 0
set Income[GetPlayerId(GetTriggerPlayer())].lumber = 0
endif
return false
endmethod
private static method init takes nothing returns boolean
local integer i
local trigger t
local player p
set i = 5
set t = CreateTrigger()
call TriggerAddCondition(t, Condition(function thistype.transfer))
loop
set p = Player(i)
if (IsPlaying(p)) then
call TriggerRegisterPlayerEvent(t, p, LeaveEvent())
endif
exitwhen 0 == i
set i = i - 1
endloop
set p = null
set t = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Lives uses Gameboard, IsPlaying, Game
struct Lives extends array
private static constant integer START_LIFE = 25
private static integer array life
integer steal
static method operator [] takes integer i returns integer
return life[i]
endmethod
static method operator []= takes integer i, integer v returns nothing
set life[i] = v
call Boards.team1.setTeamLives(i,v)
if (not Game.solo) then
call Boards.team2.setTeamLives(i,v)
call Boards.observer.setTeamLives(i,v)
endif
if (0 >= v) then
if (Game.solo) then
call Game.end(0)
else
if (0 == i) then
call Game.end(1)
else
call Game.end(0)
endif
endif
endif
endmethod
method leak takes integer amount returns nothing
if (GetPlayerId(GetLocalPlayer())/3 == this and GetPlayerId(GetLocalPlayer()) < 6) then
call StartSound(gg_snd_Loading)
endif
if (0 == this) then
set Lives[1] = Lives[1] + thistype(1).steal
else
set Lives[0] = Lives[0] + thistype(0).steal
endif
set Lives[this] = Lives[this] - amount
endmethod
private static method onUpdate takes nothing returns boolean
call Boards.team1.setTeamLives(0,life[0])
call Boards.team2.setTeamLives(0,life[0])
call Boards.observer.setTeamLives(0,life[0])
call Boards.team1.setTeamLives(1,life[1])
call Boards.team2.setTeamLives(1,life[1])
call Boards.observer.setTeamLives(1,life[1])
return false
endmethod
private static method init takes nothing returns boolean
set life[0] = START_LIFE
set life[1] = START_LIFE
call Boards.team1.setTeamLives(0,START_LIFE)
call Boards.team1.setTeamLives(1,START_LIFE)
if (not Game.solo) then
call Boards.team2.setTeamLives(0,START_LIFE)
call Boards.observer.setTeamLives(0,START_LIFE)
call Boards.team2.setTeamLives(1,START_LIFE)
call Boards.observer.setTeamLives(1,START_LIFE)
call Boards.observer.onUpdate.register(Condition(function thistype.onUpdate))
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Race uses IsPlaying, Game
private module Init
private static integer array index2Race
private static Table race2Index
static constant integer count = 11+2
static method operator beam takes nothing returns thistype
return beamp
endmethod
static method operator army takes nothing returns thistype
return armyp
endmethod
static method operator bomb takes nothing returns thistype
return bombp
endmethod
static method operator hero takes nothing returns thistype
return herop
endmethod
static method operator warrior takes nothing returns thistype
return warriorp
endmethod
static method operator qwest takes nothing returns thistype
return qwestp
endmethod
static method operator god takes nothing returns thistype
return godp
endmethod
static method operator soulReaver takes nothing returns thistype
return soulReaverp
endmethod
static method operator gladus takes nothing returns thistype
return gladusp
endmethod
static method operator devil takes nothing returns thistype
return devilp
endmethod
static method operator elemental takes nothing returns thistype
return elementalp
endmethod
static method operator sniper takes nothing returns thistype
return sniperp
endmethod
static method operator tdoc takes nothing returns thistype
return tdocp
endmethod
private static method onInit takes nothing returns nothing
set index2Race[0] = beamp
set index2Race[1] = armyp
set index2Race[2] = bombp
set index2Race[3] = herop
set index2Race[4] = warriorp
set index2Race[5] = qwestp
set index2Race[6] = godp
set index2Race[7] = soulReaverp
set index2Race[8] = gladusp
set index2Race[9] = devilp
set index2Race[10] = elementalp
set index2Race[11] = sniperp
set index2Race[12] = tdocp
set race2Index = Table.create()
set race2Index[beamp] = 0
set race2Index[armyp] = 1
set race2Index[bombp] = 2
set race2Index[herop] = 3
set race2Index[warriorp] = 4
set race2Index[qwestp] = 5
set race2Index[godp] = 6
set race2Index[soulReaverp] = 7
set race2Index[gladusp] = 8
set race2Index[devilp] = 9
set race2Index[elementalp] = 10
set race2Index[sniperp] = 11
set race2Index[tdocp] = 12
endmethod
static method operator [] takes integer index returns Race
return index2Race[index]
endmethod
method operator [] takes player p returns integer
return GetPlayerTechMaxAllowed(p,this)-GetPlayerTechCount(p,this,true)
endmethod
method operator []= takes player p, integer v returns nothing
call SetPlayerTechMaxAllowed(p,this,v+GetPlayerTechCount(p,this,true))
endmethod
method operator index takes nothing returns integer
return race2Index[this]
endmethod
method operator exists takes nothing returns boolean
return race2Index.has(this)
endmethod
endmodule
struct RaceBuilder extends array
//builder 1
private static constant integer beamp = 'e008'
private static constant integer armyp = 'oC25'
private static constant integer bombp = 'u000'
private static constant integer herop = 'o00C'
private static constant integer warriorp = 'oC22'
private static constant integer qwestp = 'e003'
private static constant integer godp = 'u00B'
private static constant integer soulReaverp = 'nC03'
private static constant integer gladusp = 'o00X'
private static constant integer devilp = 'uC88'
private static constant integer elementalp = 'u001'
//builder 2
private static constant integer sniperp = 'u002'
private static constant integer tdocp = 'u00D'
implement Init
endstruct
struct Race extends array
//builder 1
private static constant integer beamp = 'e007'
private static constant integer armyp = 'eC23'
private static constant integer bombp = 'e000'
private static constant integer herop = 'o00B'
private static constant integer warriorp = 'hC20'
private static constant integer qwestp = 'e002'
private static constant integer godp = 'eC12'
private static constant integer soulReaverp = 'hC01'
private static constant integer gladusp = 'hC06'
private static constant integer devilp = 'hC87'
private static constant integer elementalp = 'h00E'
//builder 2
private static constant integer sniperp = 'n000'
private static constant integer tdocp = 'n003'
implement Init
endstruct
struct AdvRaceBuilder extends array
//builder 1
private static constant integer beamp = 'e006'
private static constant integer armyp = '0000'
private static constant integer bombp = '0000'
private static constant integer herop = '0000'
private static constant integer warriorp = '0000'
private static constant integer qwestp = '0000'
private static constant integer godp = '0000'
private static constant integer soulReaverp = '0000'
private static constant integer gladusp = '0000'
private static constant integer devilp = '0000'
private static constant integer elementalp = '0000'
//builder 2
private static constant integer sniperp = '0000'
private static constant integer tdocp = '0000'
implement Init
endstruct
struct RaceTech extends array
//builder 1
private static constant integer beamp = 'e005'
private static constant integer armyp = '0000'
private static constant integer bombp = '0000'
private static constant integer herop = '0000'
private static constant integer warriorp = '0000'
private static constant integer qwestp = '0000'
private static constant integer godp = '0000'
private static constant integer soulReaverp = '0000'
private static constant integer gladusp = '0000'
private static constant integer devilp = '0000'
private static constant integer elementalp = '0000'
//builder 2
private static constant integer sniperp = '0000'
private static constant integer tdocp = '0000'
implement Init
endstruct
struct AdvRaceTech extends array
//builder 1
private static constant integer beamp = 'e009'
private static constant integer armyp = '0000'
private static constant integer bombp = '0000'
private static constant integer herop = '0000'
private static constant integer warriorp = '0000'
private static constant integer qwestp = '0000'
private static constant integer godp = '0000'
private static constant integer soulReaverp = '0000'
private static constant integer gladusp = '0000'
private static constant integer devilp = '0000'
private static constant integer elementalp = '0000'
//builder 2
private static constant integer sniperp = '0000'
private static constant integer tdocp = '0000'
implement Init
endstruct
endlibrary
//TESH.scrollpos=93
//TESH.alwaysfold=0
library PlayerBuilder uses Table, Race, UnitIndexer, IsPlaying, Game
globals
private Table abilityId2Index //ability id -> index
private Table raceTypeId2Index //race id -> index
private Table unitTypeId2Index //unit type id -> index
private integer array index2UnitTypeId //index -> unit type id
private integer array index2AbilityId //index -> ability id
private unit array builderp
private constant integer builderCountp = 2
private constant integer RACE_SELECTOR_UNIT_0 = 'e001'
private constant integer RACE_SELECTOR_ABILITY_0 = 'A00E'
private constant integer RACE_SELECTOR_UNIT_1 = 'eC00'
private constant integer RACE_SELECTOR_ABILITY_1 = 'A00F'
endglobals
function IsRaceBuilder takes unit u returns boolean
return unitTypeId2Index.has(GetUnitTypeId(u))
endfunction
struct PlayerBuilder extends array
private method isBuilderEnabled takes integer index returns boolean
local integer i = index*11+10
local integer count = 0
set index = index*11
if (i >= Race.count) then
set i = Race.count - 1
endif
loop
set count = count+Race[i][Player(this)]
exitwhen index == i
set i = i - 1
endloop
return 0 < count
endmethod
private method operator builder takes nothing returns integer
return unitTypeId2Index[GetUnitTypeId(builderp[this])]
endmethod
private method updateAbilities takes nothing returns nothing
local integer i = builderCountp - 1
loop
call SetPlayerAbilityAvailable(Player(this),index2AbilityId[i],isBuilderEnabled(i))
exitwhen 0 == i
set i = i - 1
endloop
endmethod
private method operator builder= takes integer index returns nothing
local unit original
local unit new
if (builder != index) then
set original = builderp[this]
set new = CreateUnit(Player(this), index2UnitTypeId[index], GetUnitX(original), GetUnitY(original), GetUnitFacing(original))
set builderp[this] = new
call SetUnitX(new, GetUnitX(original))
call SetUnitY(new, GetUnitY(original))
call SelectUnit(new, IsUnitSelected(original, GetLocalPlayer()))
call SelectUnit(original, false)
set new = null
call RemoveUnit(original)
set original = null
endif
endmethod
method limitToRace takes Race r returns nothing
local integer i = Race.count - 1
if (0 < Race[i][Player(this)]) then
set builder = raceTypeId2Index[r]
loop
if (Race[i] != r) then
set Race[i][Player(this)] = Race[i][Player(this)] - 1
endif
exitwhen 0 == i
set i = i - 1
endloop
call updateAbilities()
endif
endmethod
method addBuilder takes nothing returns nothing
local integer i = Race.count - 1
loop
set Race[i][Player(this)] = Race[i][Player(this)] + 1
exitwhen 0 == i
set i = i - 1
endloop
call updateAbilities()
endmethod
method operator raceCount takes nothing returns integer
local integer i = Race.count - 1
local integer count = 0
loop
set count = count + Race[i][Player(this)]
exitwhen 0 == i
set i = i - 1
endloop
return count
endmethod
method operator builderCount takes nothing returns integer
local integer i = Race.count - 1
local integer count = 0
loop
set count = count + RaceBuilder[i][Player(this)]
exitwhen 0 == i
set i = i - 1
endloop
return count
endmethod
private static method removeBuilder takes nothing returns boolean
if (Race(GetUnitTypeId(GetTriggerUnit())).exists and 0 == RaceBuilder[Race(GetUnitTypeId(GetTriggerUnit())).index][GetTriggerPlayer()]) then
set RaceBuilder[Race(GetUnitTypeId(GetTriggerUnit())).index][GetTriggerPlayer()] = 1
set RaceTech[Race(GetUnitTypeId(GetTriggerUnit())).index][GetTriggerPlayer()] = 1
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set AdvRaceBuilder[Race(GetUnitTypeId(GetTriggerUnit())).index][GetTriggerPlayer()] = 1
set AdvRaceTech[Race(GetUnitTypeId(GetTriggerUnit())).index][GetTriggerPlayer()] = 1
else
set AdvRaceBuilder[Race(GetUnitTypeId(GetTriggerUnit())).index][GetTriggerPlayer()] = 0
set AdvRaceTech[Race(GetUnitTypeId(GetTriggerUnit())).index][GetTriggerPlayer()] = 0
endif
call PlayerBuilder[GetPlayerId(GetTriggerPlayer())].limitToRace(GetUnitTypeId(GetTriggerUnit()))
endif
return false
endmethod
private static method replaceBuilder takes nothing returns boolean
if (unitTypeId2Index.has(GetUnitTypeId(GetTriggerUnit()))) then
set PlayerBuilder[GetPlayerId(GetTriggerPlayer())].builder = abilityId2Index[GetSpellAbilityId()]
endif
return false
endmethod
private static method check takes nothing returns boolean
if (Race(GetUnitTypeId(GetTriggerUnit())).exists) then
call thistype(GetPlayerId(GetTriggerPlayer())).updateAbilities()
endif
return false
endmethod
private static method init takes nothing returns boolean
local integer i
local integer i2
local player p
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, Condition(function thistype.replaceBuilder))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_START, Condition(function thistype.removeBuilder))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, Condition(function thistype.check))
set index2UnitTypeId[0] = RACE_SELECTOR_UNIT_0
set index2UnitTypeId[1] = RACE_SELECTOR_UNIT_1
set unitTypeId2Index = Table.create()
set unitTypeId2Index[RACE_SELECTOR_UNIT_0] = 0
set unitTypeId2Index[RACE_SELECTOR_UNIT_1] = 1
set abilityId2Index = Table.create()
set abilityId2Index[RACE_SELECTOR_ABILITY_0] = 0
set abilityId2Index[RACE_SELECTOR_ABILITY_1] = 1
set index2AbilityId[0] = RACE_SELECTOR_ABILITY_0
set index2AbilityId[1] = RACE_SELECTOR_ABILITY_1
set raceTypeId2Index = Table.create()
set i = Race.count - 1
loop
set raceTypeId2Index[Race[i]] = i/11
exitwhen 0 == i
set i = i - 1
endloop
set i = 5
loop
set p = Player(i)
if (IsPlaying(p)) then
set builderp[i] = CreateUnit(p, RACE_SELECTOR_UNIT_0, GetStartLocationX(i), GetStartLocationY(i), 270)
if (GetLocalPlayer() == p) then
call SelectUnit(builderp[i],true)
endif
set i2 = Race.count - 1
loop
set RaceBuilder[i2][p] = 0
set Race[i2][p] = 1
exitwhen 0 == i2
set i2 = i2 - 1
endloop
endif
exitwhen 0 == i
set i = i - 1
endloop
set p = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=11
//TESH.alwaysfold=0
struct Sell extends array
private static constant real SELL_RATE = .75
private static constant integer SELL_UNIT = 'nC57'
private static constant timer des = CreateTimer()
private static integer efc = 0
private static effect array efs
private static method clean takes nothing returns nothing
loop
exitwhen 0 == efc
set efc = efc - 1
call DestroyEffect(efs[efc])
endloop
endmethod
private static method sell takes nothing returns boolean
local unit u
local integer g
local integer l
local string msg
if (GetUnitTypeId(GetTrainedUnit()) == SELL_UNIT) then
set u = GetTriggerUnit()
//create sell effect
set efs[efc] = AddSpecialEffect("Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl", GetUnitX(u), GetUnitY(u))
set efc = efc + 1
call TimerStart(des, 10, false, function thistype.clean)
//add cost
set g = R2I(GetUnitTotalGoldCost(u)*SELL_RATE*(GetWidgetLife(u)/GetUnitState(u, UNIT_STATE_MAX_LIFE)))
set l = R2I(GetUnitTotalWoodCost(u)*SELL_RATE*(GetWidgetLife(u)/GetUnitState(u, UNIT_STATE_MAX_LIFE)))
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD) + g)
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER) + l)
//display sell message
if (0 == g) then
set msg = "|c00347235+"+I2S(l)+"|r"
elseif (0 == l) then
set msg = "|c00FDD017+"+I2S(g)+"|r"
else
set msg = "|c00FDD017+"+I2S(g)+" |r|c00347235+"+I2S(l)+"|r"
endif
call WriteTextTag(msg, 10, GetUnitX(u), GetUnitY(u), GetLocalPlayer() == GetTriggerPlayer() or GetPlayerId(GetLocalPlayer()) > 5)
//clean
call RemoveUnit(u)
call RemoveUnit(GetTrainedUnit())
set u = null
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_TRAIN_FINISH, Condition(function thistype.sell))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct PreventBuild extends array
private static group g
private static rect r
private static method prevent takes nothing returns boolean
local unit u
local integer id = GetUnitTypeId(GetTriggerUnit())
local player p
local real x
local real y
local real range
if (GetUnitRace(GetTriggerUnit()) == RACE_UNDEAD and Compensate[GetUnitUserData(GetTriggerUnit())].give) then
set range = GetUnitCollision(GetTriggerUnit())
set x = GetUnitX(GetTriggerUnit())
set y = GetUnitY(GetTriggerUnit())
call MoveRectTo(r,x,y)
call SetRect(r,x-range,y-range,x+range,y+range)
call GroupEnumUnitsInRect(g,r,null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if (GetUnitRace(u) == RACE_DEMON and not IsUnitType(u, UNIT_TYPE_DEAD) and not IsUnitType(u, UNIT_TYPE_FLYING)) then
set p = GetTriggerPlayer()
call WriteTextTag("Attempted to build on unit "+GetUnitName(u), 10, x, y, GetLocalPlayer() == GetTriggerPlayer())
call SetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD,GetPlayerState(p,PLAYER_STATE_RESOURCE_GOLD)+GetUnitTypeIdGoldCost(id))
call SetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER,GetPlayerState(p,PLAYER_STATE_RESOURCE_LUMBER)+GetUnitTypeIdWoodCost(id))
set Compensate[GetUnitUserData(GetTriggerUnit())].give = false
call RemoveUnit(GetTriggerUnit())
call GroupClear(g)
set u = null
set p = null
return false
endif
call GroupRemoveUnit(g,u)
endloop
endif
return false
endmethod
private static method init takes nothing returns boolean
set g = CreateGroup()
set r = Rect(0,0,0,0)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_START,Condition(function thistype.prevent))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Towers uses Bonus, UnitIndexer, Game
struct Towers extends array
private static integer array next
private static integer array prev
private static boolean array a
static method operator [] takes integer pid returns thistype
return next[pid/3]
endmethod
method operator n takes nothing returns thistype
return next[this]
endmethod
private static method index takes nothing returns boolean
local integer i
local integer u
if (GetUnitRace(GetIndexedUnit()) == RACE_UNDEAD and IsUnitType(GetIndexedUnit(), UNIT_TYPE_STRUCTURE) and not Race(GetUnitTypeId(GetIndexedUnit())).exists and not RaceTech(GetUnitTypeId(GetIndexedUnit())).exists and not AdvRaceTech(GetUnitTypeId(GetIndexedUnit())).exists) then
set i = GetPlayerId(GetOwningPlayer(GetIndexedUnit()))/3
set u = GetIndexedUnitId()+1
if (0 == next[i]) then
set next[i] = u
set next[u] = 0
set prev[u] = 0
else
set next[u] = next[i]
set prev[u] = 0
set prev[next[u]] = u
set next[i] = u
endif
set a[u] = true
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local integer i
local integer u
local unit m
if (0 == GetIndexedUnitId()) then
set m = GetTriggerUnit()
else
set m = GetIndexedUnit()
endif
if (GetUnitRace(m) == RACE_UNDEAD and IsUnitType(m, UNIT_TYPE_STRUCTURE) and not Race(GetUnitTypeId(m)).exists and not RaceTech(GetUnitTypeId(m)).exists and not AdvRaceTech(GetUnitTypeId(m)).exists) then
if (0 == GetIndexedUnitId()) then
set i = GetPlayerId(GetTriggerPlayer())/3
set u = GetUnitUserData(m)+1
else
set i = GetPlayerId(GetOwningPlayer(GetIndexedUnit()))/3
set u = GetIndexedUnitId()+1
endif
if (a[u]) then
if (0 == prev[u]) then
set next[i] = next[u]
else
set next[prev[u]] = next[u]
endif
if (0 != next[u]) then
set prev[next[u]] = prev[u]
endif
set a[u] = false
endif
endif
set m = null
return false
endmethod
private static method init takes nothing returns boolean
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.deindex))
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Sends uses Bonus, UnitIndexer, Game
struct Sends extends array
private static integer array next
private static integer array prev
private static boolean array a
static method operator [] takes integer pid returns thistype
return next[pid/3]
endmethod
method operator n takes nothing returns thistype
return next[this]
endmethod
private static method index takes nothing returns boolean
local integer i
local integer u
local boolean array test
if (GetUnitRace(GetIndexedUnit()) == RACE_DEMON) then
set i = GetPlayerId(GetOwningPlayer(GetIndexedUnit()))/3
set u = GetIndexedUnitId()+1
if (0 == next[i]) then
set next[i] = u
set next[u] = 0
set prev[u] = 0
else
set next[u] = next[i]
set prev[u] = 0
set prev[next[u]] = u
set next[i] = u
endif
set a[u] = true
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local integer i
local integer u
local unit m
local boolean array test
if (0 == GetIndexedUnitId()) then
set m = GetTriggerUnit()
else
set m = GetIndexedUnit()
endif
if (GetUnitRace(m) == RACE_DEMON) then
if (0 == GetIndexedUnitId()) then
set u = GetUnitUserData(m)+1
else
set u = GetIndexedUnitId()+1
endif
set i = GetPlayerId(Summon(u-1).owner)/3
if (a[u]) then
if (0 == prev[u]) then
set next[i] = next[u]
else
set next[prev[u]] = next[u]
endif
if (0 != next[u]) then
set prev[next[u]] = prev[u]
endif
set a[u] = false
endif
endif
set m = null
return false
endmethod
private static method init takes nothing returns boolean
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.deindex))
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct ShrineUpgrade extends array
private static method upgrade takes nothing returns boolean
local unit old
local unit new
local boolean isSelected
set old = GetTriggerUnit()
if (GetUnitRace(old) == RACE_HUMAN and IsUnitType(old, UNIT_TYPE_TOWNHALL)) then
set isSelected = IsUnitSelected(old, GetLocalPlayer())
set new = CreateUnit(GetOwningPlayer(old), GetUnitTypeId(old), GetUnitX(old), GetUnitY(old), 270)
call SetUnitX(new, GetUnitX(old))
call SetUnitY(new, GetUnitY(old))
call RemoveUnit(old)
call SelectUnit(new, isSelected)
set new = null
endif
set old = null
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH, Condition(function thistype.upgrade))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onStart.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct PlaceShrines extends array
private static constant integer SHRINE_1 = 'h00M'
private static constant integer SHRINE_1_INTERMEDIATE = 'h00N'
private static constant integer SHRINE_1_BEGINNER = 'hC15'
private static method place takes nothing returns boolean
local integer shrine
if (Game.difficulty == DIFFICULTY_BEGINNER) then
set shrine = SHRINE_1_BEGINNER
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
set shrine = SHRINE_1_INTERMEDIATE
else
set shrine = SHRINE_1
endif
if (IsPlaying(Player(0))) then
call CreateUnit(Player(0), shrine, GetRectCenterX(gg_rct_Shrine_0), GetRectCenterY(gg_rct_Shrine_0), 270)
endif
if (IsPlaying(Player(1))) then
call CreateUnit(Player(1), shrine, GetRectCenterX(gg_rct_Shrine_1), GetRectCenterY(gg_rct_Shrine_1), 270)
endif
if (IsPlaying(Player(2))) then
call CreateUnit(Player(2), shrine, GetRectCenterX(gg_rct_Shrine_2), GetRectCenterY(gg_rct_Shrine_2), 270)
endif
if (IsPlaying(Player(3))) then
call CreateUnit(Player(3), shrine, GetRectCenterX(gg_rct_Shrine_3), GetRectCenterY(gg_rct_Shrine_3), 90)
endif
if (IsPlaying(Player(4))) then
call CreateUnit(Player(4), shrine, GetRectCenterX(gg_rct_Shrine_4), GetRectCenterY(gg_rct_Shrine_4), 90)
endif
if (IsPlaying(Player(5))) then
call CreateUnit(Player(5), shrine, GetRectCenterX(gg_rct_Shrine_5), GetRectCenterY(gg_rct_Shrine_5), 90)
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onStart.register(Condition(function thistype.place))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
library GetSummon uses Game
function GetSummon takes nothing returns unit
if (null == GetSoldUnit()) then
return GetTrainedUnit()
endif
return GetSoldUnit()
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitTeam uses Game
struct UnitTeam extends array
private static integer array team
static method operator [] takes unit u returns integer
return team[GetPlayerId(GetOwningPlayer(u))]
endmethod
private static method init takes nothing returns boolean
set team[0] = 0
set team[1] = 0
set team[2] = 0
set team[6] = 0
set team[7] = 0
set team[10] = 0
set team[3] = 1
set team[4] = 1
set team[5] = 1
set team[8] = 1
set team[9] = 1
set team[11] = 1
return false
endmethod
private static method initSolo takes nothing returns boolean
local integer i = 0
local integer i2 = 11
local integer t
loop
exitwhen IsPlaying(Player(i))
set i = i + 1
endloop
if (0 == i/3) then
set t = 1
set team[i] = 0
else
set t = 0
set team[i] = 1
endif
loop
if (i2 != i) then
set team[i2] = t
endif
exitwhen 0 == i2
set i2 = i2 - 1
endloop
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.initSolo))
endmethod
endstruct
endlibrary
//TESH.scrollpos=56
//TESH.alwaysfold=0
library SendPlayer uses Paths, Game
struct SendPlayer extends array
private static integer array q
private static integer array qf
private static Paths pa = 0
method get takes nothing returns player
local integer i = qf[this]
set qf[this] = q[qf[this]]
return Player(i)
endmethod
static method operator [] takes integer i returns thistype
if (Game.solo) then
return 0
endif
return i/3
endmethod
static method operator soloPath takes nothing returns Paths
return pa
endmethod
private static method init takes nothing returns boolean
set q[0] = 1
set q[1] = 2
set q[2] = 6
set q[6] = 7
set q[7] = 10
set q[10] = 0
set q[3] = 4
set q[4] = 5
set q[5] = 8
set q[8] = 9
set q[9] = 11
set q[11] = 3
call Ally(Player(0),Player(6),ALLIANCE_NEUTRAL)
call Ally(Player(0),Player(7),ALLIANCE_NEUTRAL)
call Ally(Player(0),Player(10),ALLIANCE_NEUTRAL)
call Ally(Player(1),Player(6),ALLIANCE_NEUTRAL)
call Ally(Player(1),Player(7),ALLIANCE_NEUTRAL)
call Ally(Player(1),Player(10),ALLIANCE_NEUTRAL)
call Ally(Player(2),Player(6),ALLIANCE_NEUTRAL)
call Ally(Player(2),Player(7),ALLIANCE_NEUTRAL)
call Ally(Player(2),Player(10),ALLIANCE_NEUTRAL)
call Ally(Player(3),Player(8),ALLIANCE_NEUTRAL)
call Ally(Player(3),Player(9),ALLIANCE_NEUTRAL)
call Ally(Player(3),Player(11),ALLIANCE_NEUTRAL)
call Ally(Player(4),Player(8),ALLIANCE_NEUTRAL)
call Ally(Player(4),Player(9),ALLIANCE_NEUTRAL)
call Ally(Player(4),Player(11),ALLIANCE_NEUTRAL)
call Ally(Player(5),Player(8),ALLIANCE_NEUTRAL)
call Ally(Player(5),Player(9),ALLIANCE_NEUTRAL)
call Ally(Player(5),Player(11),ALLIANCE_NEUTRAL)
set qf[0] = 0
set qf[1] = 3
return false
endmethod
private static method initSolo takes nothing returns boolean
local integer i = 0
local integer i2
loop
exitwhen IsPlaying(Player(i))
set i = i + 1
endloop
if (0 == i/3) then
set pa = 1
else
set pa = 0
endif
set i2 = 11
loop
if (i2 != i) then
call Ally(Player(i), Player(i2), ALLIANCE_UNALLIED)
if (i2 - 1 == i) then
if (i2 - 2 == -1) then
set q[i2] = 11
else
set q[i2] = i2 - 2
endif
elseif (i2 - 1 == -1) then
set q[i2] = 11
else
set q[i2] = i2 - 1
endif
endif
exitwhen 0 == i2
set i2 = i2 - 1
endloop
set qf[i] = 11
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.initSolo))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Summon uses SendPlayer, Paths, GetSummon, Game
globals
private player array ownerp
private constant integer ABILITY_GHOST_VISIBLE = 'Aeth'
private unit returnedUnit
endglobals
private function AddGhost takes unit u returns nothing
call UnitAddAbility(u,ABILITY_GHOST_VISIBLE)
call UnitMakeAbilityPermanent(u,true,ABILITY_GHOST_VISIBLE)
endfunction
function SummonUnit takes player owner, integer unitTypeId, real x, real y, real facing, integer checkpoint returns unit
local UnitPath summon
set returnedUnit = CreateUnit(owner, unitTypeId, x, y, facing)
set summon = GetUnitUserData(returnedUnit)
set ownerp[summon] = owner
call SetUnitOwner(returnedUnit, SendPlayer[GetPlayerId(owner)].get(), false)
call AddGhost(returnedUnit)
set summon.checkpoint = checkpoint
return returnedUnit
endfunction
struct SummonHandler extends array
private static constant real TIMEOUT = .15
private static integer ic = 1
private static timer run
private thistype last
private integer next
private integer unitTypeId
private integer owner
private integer count
private boolean perm
private static integer array sn
private static integer array sp
private real x
private real y
private real x2
private real y2
private real facing
private real facing2
private Checkpoint checkpoint1
private Checkpoint checkpoint2
private static method runm takes nothing returns nothing
local thistype this = sn[0]
local thistype node
loop
exitwhen 0 == this
set node = next
if (0 != node) then
set node.count = node.count - 1
if (0 == node.count) then
set next = node.next
set node.next = thistype(0).next
set thistype(0).next = node
if (node == last) then
set last = this
if (not perm) then
set sn[sp[this]] = sn[this]
set sp[sn[this]] = sp[this]
set next = thistype(0).next
set thistype(0).next = this
endif
endif
endif
call SummonUnit(Player(node.owner),node.unitTypeId,x,y,facing,checkpoint1)
if (0 != checkpoint2) then
call SummonUnit(Player(node.owner),node.unitTypeId,x2,y2,facing2,checkpoint2)
endif
endif
set this = sn[this]
endloop
endmethod
method summon takes integer unitTypeId, integer owner, integer count returns nothing
local thistype node
if (0 < count and 0 != unitTypeId) then
set node = thistype(0).next
if (0 == node) then
set node = ic + 1
set ic = node
else
set thistype(0).next = node.next
endif
if (1 == last) then
endif
set node.next = 0
set last.next = node
set last = node
set node.owner = owner
set node.unitTypeId = unitTypeId
set node.count = count
endif
endmethod
static method create takes boolean permanent, real x, real y, real facing, real x2, real y2, real facing2, Checkpoint checkpoint1, Checkpoint checkpoint2 returns thistype
local thistype this = thistype(0).next
if (0 == this) then
set this = ic + 1
set ic = this
else
set thistype(0).next = next
endif
set perm = permanent
set next = 0
set last = this
set this.x = x
set this.y = y
set this.x2 = x2
set this.y2 = y2
set this.facing = facing
set this.facing2 = facing2
set this.checkpoint1 = checkpoint1
set this.checkpoint2 = checkpoint2
set sn[this] = sn[0]
set sp[this] = 0
set sp[sn[this]] = this
set sn[0] = this
return this
endmethod
private static method end takes nothing returns boolean
call PauseTimer(run)
call DestroyTimer(run)
set run = null
return false
endmethod
private static method init takes nothing returns boolean
set run = CreateTimer()
if (Game.solo) then
call TimerStart(run,.25,true,function thistype.runm)
else
call TimerStart(run,TIMEOUT,true,function thistype.runm)
endif
call Game.onEnd.register(Condition(function thistype.end))
call Game.onEndSolo.register(Condition(function thistype.end))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
globals
SummonHandler array summonHandler
endglobals
struct Summon extends array
real sendBonus
method operator path takes nothing returns UnitPath
return this
endmethod
method operator owner takes nothing returns player
return ownerp[this]
endmethod
method operator owner= takes player p returns nothing
set ownerp[this] = p
call SetUnitColor(GetUnitById(this), GetPlayerColor(p))
endmethod
private static method train takes nothing returns boolean
local integer id = GetPlayerId(GetTriggerPlayer())
local unit u = GetSummon()
local integer i = GetUnitUserData(u)
if (GetUnitRace(GetTriggerUnit()) == RACE_HUMAN and GetUnitRace(u) == RACE_DEMON) then
call summonHandler[id/3].summon(GetUnitTypeId(u), id, R2I(thistype(id).sendBonus + 1))
set Summon(i).owner = GetOwningPlayer(u)
call RemoveUnit(u)
endif
set u = null
return false
endmethod
private static method init takes nothing returns boolean
if (Game.solo) then
set summonHandler[0] = SummonHandler.create(true, /*
*/GetLocationX(SendPlayer.soloPath.left.firstCheckpoint.point), GetLocationY(SendPlayer.soloPath.left.firstCheckpoint.point), 180, /*
*/GetLocationX(SendPlayer.soloPath.right.firstCheckpoint.point), GetLocationY(SendPlayer.soloPath.right.firstCheckpoint.point), 0, /*
*/SendPlayer.soloPath.left.firstCheckpoint + 1, SendPlayer.soloPath.right.firstCheckpoint + 1)
else
set summonHandler[0] = SummonHandler.create(true, /*
*/GetLocationX(Paths[0].left.firstCheckpoint.point), GetLocationY(Paths[0].left.firstCheckpoint.point), 180, /*
*/GetLocationX(Paths[0].right.firstCheckpoint.point), GetLocationY(Paths[0].right.firstCheckpoint.point), 0, /*
*/Paths[0].left.firstCheckpoint + 1, Paths[0].right.firstCheckpoint + 1)
set summonHandler[1] = SummonHandler.create(true, /*
*/GetLocationX(Paths[3].left.firstCheckpoint.point), GetLocationY(Paths[3].left.firstCheckpoint.point), 180, /*
*/GetLocationX(Paths[3].right.firstCheckpoint.point), GetLocationY(Paths[3].right.firstCheckpoint.point), 0, /*
*/Paths[3].left.firstCheckpoint + 1, Paths[3].right.firstCheckpoint + 1)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SELL, Condition(function thistype.train))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_TRAIN_FINISH, Condition(function thistype.train))
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=65
//TESH.alwaysfold=0
library Path uses Lives, UnitTeam, IsPlaying, Game
struct Checkpoint extends array
private integer end
readonly region region
readonly location point
static method operator [] takes integer i returns thistype
return i*60
endmethod
method add takes rect r returns thistype
set end = end + 1
set this = this + end - 1
set region = CreateRegion()
set point = Location(GetRectCenterX(r),GetRectCenterY(r))
call RegionAddRect(region, r)
return this
endmethod
endstruct
struct UnitPath extends array
private delegate Checkpoint checkpointp
method operator atEnd takes nothing returns boolean
return null == point
endmethod
method order takes nothing returns boolean
local integer id
call IssueImmediateOrder(GetUnitById(this),"stop")
if (atEnd) then
return false
endif
set id = GetPlayerId(GetOwningPlayer(GetUnitById(this)))
call IssuePointOrderLoc(GetUnitById(this),"move",point)
return true
endmethod
method operator checkpoint takes nothing returns Checkpoint
return checkpointp
endmethod
method operator checkpoint= takes integer cp returns nothing
set checkpointp = cp
if (atEnd) then
set checkpointp = 0
else
call order()
endif
endmethod
endstruct
struct Path extends array
private static trigger enterTrig
private static integer c = 0
method operator firstCheckpoint takes nothing returns Checkpoint
return Checkpoint[this]
endmethod
private static method onEnter takes nothing returns boolean
local unit u = GetTriggerUnit()
local UnitPath i = GetUnitUserData(u)
local integer team
if (i.checkpoint.region == GetTriggeringRegion()) then
set i.checkpoint = i.checkpoint + 1
if (i.atEnd) then
set team = UnitTeam[u]
if (0 == team) then
set team = 1
else
set team = 0
endif
if (0 < R2I(GetUnitState(u, UNIT_STATE_MAX_MANA)+.5)) then
call Lives(team).leak(R2I(GetUnitState(u, UNIT_STATE_MAX_MANA)+.5))
endif
call RemoveUnit(u)
endif
endif
set u = null
return false
endmethod
static method create takes nothing returns thistype
set c = c + 1
return c
endmethod
method add takes rect r returns nothing
call TriggerRegisterEnterRegion(enterTrig,Checkpoint[this].add(r).region,null)
endmethod
private static method init takes nothing returns boolean
set enterTrig = CreateTrigger()
call TriggerAddCondition(enterTrig,Condition(function thistype.onEnter))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=15
//TESH.alwaysfold=0
library Paths uses Path, IsPlaying, Game
struct Paths extends array
private static Path array leftp
private static Path array rightp
static method operator [] takes integer pid returns thistype
return pid/3
endmethod
method operator left takes nothing returns Path
return leftp[this]
endmethod
method operator right takes nothing returns Path
return rightp[this]
endmethod
private static method init takes nothing returns boolean
local Path topLeft = Path.create()
local Path topRight = Path.create()
local Path bottomLeft = Path.create()
local Path bottomRight = Path.create()
set leftp[0] = bottomLeft
set rightp[0] = bottomRight
set leftp[1] = topLeft
set rightp[1] = topRight
call topLeft.add(gg_rct_Middle_Center_Top_Left)
call topLeft.add(gg_rct_Middle_Top_Left)
call topLeft.add(gg_rct_Top_Left)
call topLeft.add(gg_rct_Top_Center)
call topLeft.add(gg_rct_Load_Top)
call topRight.add(gg_rct_Middle_Center_Top_Right)
call topRight.add(gg_rct_Middle_Top_Right)
call topRight.add(gg_rct_Top_Right)
call topRight.add(gg_rct_Top_Center)
call topRight.add(gg_rct_Load_Top)
call bottomLeft.add(gg_rct_Middle_Center_Bottom_Left)
call bottomLeft.add(gg_rct_Middle_Bottom_Left)
call bottomLeft.add(gg_rct_Bottom_Left)
call bottomLeft.add(gg_rct_Bottom_Center)
call bottomLeft.add(gg_rct_Load_Bottom)
call bottomRight.add(gg_rct_Middle_Center_Bottom_Right)
call bottomRight.add(gg_rct_Middle_Bottom_Right)
call bottomRight.add(gg_rct_Bottom_Right)
call bottomRight.add(gg_rct_Bottom_Center)
call bottomRight.add(gg_rct_Load_Bottom)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=314
//TESH.alwaysfold=0
library Gameboard uses Multiboard, Event, IsPlaying, Game
struct Gameboard extends array
private static integer count = 0
private static Gameboard array boards
private static boolean array playing
private delegate Multiboard board
private static Table teams
private static Table teamSlots
private static Table players
private static Table playerSlots
private integer teamCountp
private integer ownerTeam
private integer playerCountp
readonly Event onUpdate
readonly static Gameboard eventBoard = 0
private static method operator extraRows takes nothing returns integer
if (Game.solo) then
return 5
endif
return 8
endmethod
private method operator incomeSubtitleRow takes nothing returns integer
return 0
endmethod
private method operator incomeRowStart takes nothing returns integer
return 1
endmethod
private method operator incomeRowEnd takes nothing returns integer
return playerCountp
endmethod
private method operator spaceRow1 takes nothing returns integer
return playerCountp + 1
endmethod
private method operator livesSubtitleRow takes nothing returns integer
return playerCountp + 2
endmethod
private method operator livesRowStart takes nothing returns integer
return playerCountp + 3
endmethod
private method operator livesRowEnd takes nothing returns integer
return playerCountp + 3 + teamCountp - 1
endmethod
private method operator spaceRow2 takes nothing returns integer
return playerCountp + 3 + teamCountp
endmethod
private method operator highestIncomeSubtitleRow takes nothing returns integer
return playerCountp + 3 + teamCountp + 1
endmethod
private method operator highestIncomeRow takes nothing returns integer
return playerCountp + 3 + teamCountp + 2
endmethod
private method operator spaceRow3 takes nothing returns integer
if (Game.solo) then
return playerCountp + 3 + teamCountp
endif
return playerCountp + 3 + teamCountp + 3
endmethod
private method operator helpRow takes nothing returns integer
if (Game.solo) then
return playerCountp + 3 + teamCountp + 1
endif
return playerCountp + 3 + teamCountp + 4
endmethod
private method operator team takes nothing returns integer
return ownerTeam
endmethod
private method init takes nothing returns nothing
local MultiboardItem mi
local integer i
local integer pos
local integer pid
//income gold lumber
// player 1 ??? ???
// player 2 ??? ???
// player 3 ??? ???
//SPACE SPACE SPACE
//lives SPACE SPACE
// team 1 life SPACE
// team 2 life SPACE
//SPACE SPACE SPACE
//highest income SPACE SPACE
// team SPACE SPACE
//SPACE SPACE SPACE
//type -help
//income
set board[incomeSubtitleRow][0].text = "|c0000cdf9Team Income-|r"
set board[incomeSubtitleRow][1].text = "Gold"
set board[incomeSubtitleRow][2].text = "Lumber"
if (0 != playerCountp) then
set i = incomeRowStart
set pos = this*12-i
loop
set pid = players[pos+i]
if (playing[pid]) then
set board[i][0].text = " "+GetPlayerColorStringById(pid)+names[pid]+":|r"
set board[i][1].text = "|c00FDD0170|r"
set board[i][2].text = "|c003472350|r"
else
set board[i][0].text = "NA"
set board[i][1].text = ""
set board[i][2].text = ""
endif
exitwhen i == incomeRowEnd
set i = i + 1
endloop
endif
set board[spaceRow1][0].text = ""
set board[spaceRow1][1].text = ""
set board[spaceRow1][2].text = ""
set board[livesSubtitleRow][0].text = "|c0000cdf9Lives-|r"
set board[livesSubtitleRow][1].text = ""
set board[livesSubtitleRow][2].text = ""
if (0 != teamCountp) then
set i = livesRowStart
set pos = this*60-i
loop
set board[i][0].text = " |c0000ff00Team "+I2S(teams[pos+i]+1)+" Lives:|r"
set board[i][1].text = "|c00ff00000|r"
set board[i][2].text = ""
exitwhen i == livesRowEnd
set i = i + 1
endloop
endif
if (not Game.solo) then
set board[spaceRow2][0].text = ""
set board[spaceRow2][1].text = ""
set board[spaceRow2][2].text = ""
set board[highestIncomeSubtitleRow][0].text = "|c0000cdf9Highest Team Income-|r"
set board[highestIncomeSubtitleRow][1].text = ""
set board[highestIncomeSubtitleRow][2].text = ""
set board[highestIncomeRow][0].text = " |c00C35617Equal|r"
set board[highestIncomeRow][1].text = ""
set board[highestIncomeRow][2].text = ""
endif
set board[spaceRow3][0].text = ""
set board[spaceRow3][1].text = ""
set board[spaceRow3][2].text = ""
set board[helpRow][0].text = "Type -help for commands"
set board[helpRow][1].text = ""
set board[helpRow][2].text = ""
set board.column[0].width = .15
set board.column[1].width = .05
set board.column[2].width = .05
endmethod
private method update takes nothing returns nothing
local integer prevBoard
set board.row.count = playerCountp+teamCountp+extraRows
call init()
set prevBoard = eventBoard
set eventBoard = this
call onUpdate.fire()
set eventBoard = prevBoard
endmethod
method operator teamCount takes nothing returns integer
return teamCountp
endmethod
method removeTeam takes integer teamId returns nothing
local integer start = this*60
local integer pos = start
local integer last = teamCount-1
local integer slot
if (0 != this and teamSlots.has(pos+teamId)) then
set slot = teamSlots[pos+teamId]
call teamSlots.remove(pos+teamId)
set pos = pos + slot
loop
exitwhen slot == last
set teamId = teams[pos+1]
set teams[pos] = teamId
set teamSlots[start+teamId] = slot
set slot = slot + 1
set pos = pos + 1
endloop
set teamCountp = teamCountp - 1
call update()
endif
endmethod
method setTeamSlot takes integer slot, integer teamId returns nothing
if (0 != this and slot <= teamCount and slot >= 0) then
set teams[this*60+slot] = teamId
set teamSlots[this*60+teamId] = slot
set board[livesRowStart+slot][0].text = " |c0000ff00Team "+I2S(teamId+1)+" Lives:|r"
endif
endmethod
method operator playerCount takes nothing returns integer
return playerCountp
endmethod
method removePlayer takes integer playerId returns nothing
local integer start = this*12
local integer pos = start
local integer last = playerCount-1
local integer slot
if (0 != this and playerSlots.has(pos+playerId)) then
set slot = playerSlots[pos+playerId]
call playerSlots.remove(pos+playerId)
set pos = pos + slot
loop
exitwhen slot == last
set playerId = players[pos+1]
set players[pos] = playerId
set playerSlots[start+playerId] = slot
set slot = slot + 1
set pos = pos + 1
endloop
set playerCountp = playerCountp - 1
call update()
endif
endmethod
method setPlayerSlot takes integer slot, integer playerId returns nothing
if (0 != this and slot <= playerCount and slot >= 0 and playing[playerId]) then
set players[this*12+slot] = playerId
set playerSlots[this*12+playerId] = slot
set board[incomeRowStart+slot][0].text = " "+GetPlayerColorStringById(playerId)+names[playerId]+":|r"
endif
endmethod
method setTeamLives takes integer teamId, integer lives returns nothing
if (0 != this and teamSlots.has(this*60+teamId)) then
set board[teamSlots[this*60+teamId]+livesRowStart][1].text = "|c00ff0000"+I2S(lives)+"|r"
endif
endmethod
method setGoldIncome takes integer playerId, string income returns nothing
if (0 != this and playerSlots.has(this*12+playerId)) then
set board[playerSlots[this*12+playerId]+incomeRowStart][1].text = "|c00FDD017"+income+"|r"
endif
endmethod
method setLumberIncome takes integer playerId, string income returns nothing
if (0 != this and playerSlots.has(this*12+playerId)) then
set board[playerSlots[this*12+playerId]+incomeRowStart][2].text = "|c00347235"+income+"|r"
endif
endmethod
method operator highestIncome= takes integer i returns nothing
if (not Game.solo) then
if (-1 == i) then
set board[highestIncomeRow][0].text = " |c00C35617Equal|r"
else
if (teamSlots.has(this*60+ownerTeam)) then
if (i == ownerTeam) then
set board[highestIncomeRow][0].text = " |c0000cdf9Team "+I2S(i+1)+"|r"
else
set board[highestIncomeRow][0].text = " |c00800517Team "+I2S(i+1)+"|r"
endif
else
set board[highestIncomeRow][0].text = " |c00C35617Team "+I2S(i+1)+"|r"
endif
endif
endif
endmethod
static method create takes string title, integer pc, integer tc, integer ot returns Gameboard
local thistype this
local integer counted
local integer i
if (tc > 60) then
set tc = 60
endif
if (pc > 12) then
set pc = 12
endif
if (Game.solo) then
set this = Multiboard.create(pc+tc+extraRows,3)
else
set this = Multiboard.create(pc+tc+extraRows,3)
endif
set board = this
call board.setStyle(true,false)
set boards[count] = this
set count = count + 1
set playerCountp = pc
set teamCountp = tc
set ownerTeam = ot
set board.title = title
set onUpdate = Event.create()
call init()
return this
endmethod
private static method leave takes nothing returns boolean
local integer i
local integer pid
if (not Game.isOver) then
set pid = GetPlayerId(GetTriggerPlayer())
set i = count
loop
exitwhen 0 == i
set i = i - 1
call boards[i].removePlayer(pid)
endloop
set playing[pid] = false
endif
return false
endmethod
private static method initialize takes nothing returns boolean
local trigger t
local integer i
if (not Game.solo) then
set t = CreateTrigger()
call TriggerAddCondition(t,Condition(function thistype.leave))
endif
set i = 11
loop
set playing[i] = IsPlaying(Player(i))
if (not Game.solo) then
if (playing[i]) then
call TriggerRegisterPlayerEvent(t, Player(i), LeaveEvent())
endif
endif
exitwhen 0 == i
set i = i - 1
endloop
set t = null
set teams = Table.create()
set teamSlots = Table.create()
set players = Table.create()
set playerSlots = Table.create()
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.initialize))
call Game.onInitializeSolo.register(Condition(function thistype.initialize))
endmethod
endstruct
endlibrary
//TESH.scrollpos=31
//TESH.alwaysfold=0
library Boards uses Gameboard, Game, IsPlaying
struct Boards extends array
private static Gameboard array boards
private static Gameboard soloBoard
static method operator observer takes nothing returns Gameboard
if (Game.solo) then
return soloBoard
endif
return boards[2]
endmethod
static method operator team1 takes nothing returns Gameboard
if (Game.solo) then
return soloBoard
endif
return boards[0]
endmethod
static method operator team2 takes nothing returns Gameboard
if (Game.solo) then
return soloBoard
endif
return boards[1]
endmethod
static method operator [] takes integer playerId returns Gameboard
return boards[playerId/3]
endmethod
private static method displayObservers takes nothing returns boolean
set observer.display = true
return false
endmethod
private static method init takes nothing returns boolean
local integer array teamSize
local integer array players
local integer array slots
local integer pc = 0
local integer i
local integer i2
local player p
local Gameboard obsBoard
local Gameboard board
if (Game.solo) then
set i = 0
loop
exitwhen IsPlaying(Player(i))
set i = i + 1
endloop
else
set i = 0
loop
set p = Player(i)
if (IsPlaying(p)) then
set players[pc] = i
set pc = pc + 1
set teamSize[i/3] = teamSize[i/3] + 1
endif
exitwhen 5 == i
set i = i + 1
endloop
endif
if (Game.solo) then
set boards[i/3] = Gameboard.create("Game Stats",1,1,i/3)
else
set boards[0] = Gameboard.create("Game Stats",teamSize[0],2,0)
set boards[1] = Gameboard.create("Game Stats",teamSize[1],2,1)
set boards[2] = Gameboard.create("Game Stats",teamSize[0]+teamSize[1],2,2)
endif
if (Game.solo) then
set board = boards[i/3]
set soloBoard = board
call board.setPlayerSlot(0, i)
call board.setTeamSlot(0, i/3)
else
set i = 0
loop
set i2 = 1
loop
set board = boards[i2]
if (players[i]/3 == i2) then
call board.setPlayerSlot(slots[i2],players[i]+0)
set slots[i2] = slots[i2] + 1
endif
exitwhen 0 == i2
set i2 = i2 - 1
endloop
call observer.setPlayerSlot(i,players[i])
set i = i + 1
exitwhen pc == i
endloop
set i = 2
loop
set board = boards[i]
call board.setTeamSlot(0,0)
call board.setTeamSlot(1,1)
exitwhen 0 == i
set i = i - 1
endloop
endif
if (Game.solo) then
set soloBoard.display = true
else
if (GetPlayerId(GetLocalPlayer()) > 5) then
set boards[2].display = true
else
set boards[GetPlayerId(GetLocalPlayer())/3].display = true
endif
call Game.onEnd.register(Condition(function thistype.displayObservers))
endif
set p = null
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TowerBuilders uses Game, UnitIndexer, Race
struct TowerBuilders extends array
private static unit u
private static integer s
readonly group builders
readonly group advancedBuilders
private static method index takes nothing returns boolean
local thistype this = GetPlayerId(GetOwningPlayer(GetIndexedUnit()))
if (RaceBuilder(GetUnitTypeId(GetIndexedUnit())).exists) then
call GroupAddUnit(builders, GetIndexedUnit())
elseif (AdvRaceBuilder(GetUnitTypeId(GetIndexedUnit())).exists) then
call GroupAddUnit(advancedBuilders, GetIndexedUnit())
endif
return false
endmethod
private static method init takes nothing returns boolean
local thistype this
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
set this = 5
loop
if (IsPlaying(Player(this))) then
set builders = CreateGroup()
set advancedBuilders = CreateGroup()
endif
exitwhen 0 == this
set this = this - 1
endloop
return false
endmethod
private static method g takes nothing returns nothing
if (GetUnitTypeId(GetEnumUnit()) == s) then
set u = GetEnumUnit()
endif
endmethod
method get takes integer unitTypeId returns unit
set s = unitTypeId
set u = null
if (RaceBuilder(unitTypeId).exists) then
call ForGroup(builders, function thistype.g)
elseif (AdvRaceBuilder(unitTypeId).exists) then
call ForGroup(advancedBuilders, function thistype.g)
endif
return u
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=131
//TESH.alwaysfold=0
library AddBonus uses Bonus, UnitIndexer, Game, Summon, RegisterPlayerUnitEvent, WorldBounds
globals
private integer array sbpl
private integer array sbpm
private real array sbp
private integer array sbs
private real array tbp
private integer array tbs
private hashtable table
private integer array ud
private group g
private hashtable utb
private real array ubl
private real array ubm
private constant integer OP = 100
private unit u
private integer pid
private integer uid
private real percent
private integer value
private integer bonus
private integer i
private integer b
private trigger addBonusHealthToTypem
private trigger addBonusManaToTypem
private trigger addBonusToTypem
private trigger addBonusToSendsm
private trigger addBonusToTowersm
private trigger addBonusHealthToSendsm
private trigger addBonusManaToSendsm
private trigger addBonusHealthToTowersm
endglobals
private function AddBonusHealthToTypem takes nothing returns boolean
local integer i
local unit u
local integer b
local integer o = OP
loop
set u = FirstOfGroup(g)
exitwhen null == u or 0 == o
call GroupRemoveUnit(g, u)
if (GetUnitTypeId(u) == uid) then
set i = GetUnitUserData(u)
if (GetUnitRace(u) == RACE_DEMON) then
if (GetPlayerId(Summon(i).owner)/3 == pid) then
set b = R2I((GetUnitState(u, UNIT_STATE_MAX_LIFE)-GetUnitBonus(u,BONUS_LIFE))*percent)
call AddUnitBonus(u, BONUS_LIFE, b)
set sbpl[i] = sbpl[i] + b
endif
elseif (GetPlayerId(GetOwningPlayer(u))/3 == pid) then
set b = R2I((GetUnitState(u, UNIT_STATE_MAX_LIFE)-GetUnitBonus(u,BONUS_LIFE))*percent)
call AddUnitBonus(u, BONUS_LIFE, b)
set sbpl[i] = sbpl[i] + b
endif
endif
set o = o - 1
endloop
if (null == u) then
return true
endif
set u = null
return false
endfunction
private function AddBonusManaToTypem takes nothing returns boolean
local integer i
local unit u
local integer b
local integer o = OP
loop
set u = FirstOfGroup(g)
exitwhen null == u or 0 == o
call GroupRemoveUnit(g, u)
if (GetUnitTypeId(u) == uid) then
set i = GetUnitUserData(u)
if (GetUnitRace(u) == RACE_DEMON) then
if (GetPlayerId(Summon(i).owner)/3 == pid) then
set b = R2I((GetUnitState(u, UNIT_STATE_MAX_MANA)-GetUnitBonus(u,BONUS_MANA))*percent)
call AddUnitBonus(u, BONUS_MANA, b)
set sbpm[i] = sbpm[i] + b
endif
elseif (GetPlayerId(GetOwningPlayer(u))/3 == pid) then
set b = R2I((GetUnitState(u, UNIT_STATE_MAX_MANA)-GetUnitBonus(u,BONUS_MANA))*percent)
call AddUnitBonus(u, BONUS_MANA, b)
set sbpm[i] = sbpm[i] + b
endif
endif
set o = o - 1
endloop
if (null == u) then
return true
endif
set u = null
return false
endfunction
private function AddBonusToTypem takes nothing returns boolean
local unit u
local integer o = OP
loop
set u = FirstOfGroup(g)
exitwhen null == u or 0 == o
call GroupRemoveUnit(g, u)
if (GetUnitRace(u) == RACE_DEMON) then
if (GetPlayerId(Summon(GetUnitUserData(u)).owner)/3 == pid) then
call AddUnitBonus(u, bonus, value)
endif
elseif (GetPlayerId(GetOwningPlayer(u))/3 == pid) then
call AddUnitBonus(u, bonus, value)
endif
set o = o - 1
endloop
if (null == u) then
return true
endif
set u = null
return false
endfunction
private function AddBonusToSendsm takes nothing returns boolean
local integer o = OP
loop
exitwhen 0 == i or 0 == o
call AddUnitBonus(GetUnitById(i-1), bonus, value)
set i = Sends(i).n
set o = o - 1
endloop
return 0 == i
endfunction
private function AddBonusToTowersm takes nothing returns boolean
local integer o = OP
loop
exitwhen 0 == i or 0 == o
call AddUnitBonus(GetUnitById(i-1), bonus, value)
set i = Towers(i).n
set o = o - 1
endloop
return 0 == i
endfunction
private function AddBonusHealthToSendsm takes nothing returns boolean
local integer b
local integer o = OP
loop
exitwhen 0 == i or 0 == o
set b = R2I((GetUnitState(GetUnitById(i-1), UNIT_STATE_MAX_LIFE)-GetUnitBonus(GetUnitById(i-1),BONUS_LIFE))*percent)
call AddUnitBonus(GetUnitById(i-1), BONUS_LIFE, b)
set sbpl[i - 1] = sbpl[i - 1] + b
set i = Sends(i).n
set o = o - 1
endloop
return 0 == i
endfunction
private function AddBonusManaToSendsm takes nothing returns boolean
local integer b
local integer o = OP
loop
exitwhen 0 == i or 0 == o
set b = R2I((GetUnitState(GetUnitById(i-1), UNIT_STATE_MAX_MANA)-GetUnitBonus(GetUnitById(i-1),BONUS_MANA))*percent)
call AddUnitBonus(GetUnitById(i-1), BONUS_MANA, b)
set sbpm[i - 1] = sbpm[i - 1] + b
set i = Sends(i).n
set o = o - 1
endloop
return 0 == i
endfunction
private function AddBonusHealthToTowersm takes nothing returns boolean
local integer b
local integer o = OP
loop
exitwhen 0 == i or 0 == o
set b = R2I((GetUnitState(GetUnitById(i-1), UNIT_STATE_MAX_LIFE)-GetUnitBonus(GetUnitById(i-1),BONUS_LIFE))*percent)
call AddUnitBonus(GetUnitById(i-1), BONUS_LIFE, b)
set sbpl[i - 1] = sbpl[i - 1] + b
set i = Towers(i).n
set o = o - 1
endloop
return 0 == i
endfunction
function AddBonusHealthToUnit takes unit u, real percent returns nothing
local integer i = GetUnitUserData(u)
local integer b = R2I((GetUnitState(u, UNIT_STATE_MAX_LIFE)-GetUnitBonus(u,BONUS_LIFE))*percent)
call AddUnitBonus(u, BONUS_LIFE, b)
set ubl[i] = ubl[i] + percent
set sbpl[i] = sbpl[i] + b
endfunction
function AddBonusManaToUnit takes unit u, real percent returns nothing
local integer i = GetUnitUserData(u)
local integer b = R2I((GetUnitState(u, UNIT_STATE_MAX_LIFE)-GetUnitBonus(u,BONUS_MANA))*percent)
call AddUnitBonus(u, BONUS_LIFE, b)
set ubm[i] = ubm[i] + percent
set sbpm[i] = sbpm[i] + b
endfunction
function AddBonusHealthToType takes integer pida, integer uida, real percenta returns nothing
if (0 != percenta) then
set pida = pida/3
call SaveReal(utb, -uida, pida, LoadReal(utb, -uida, pida) + percenta)
call GroupEnumUnitsInRect(g, WorldBounds.world, null)
set pid = pida
set uid = uida
set percent = percenta
loop
exitwhen TriggerEvaluate(addBonusHealthToTypem)
endloop
endif
endfunction
function AddBonusManaToType takes integer pida, integer uida, real percenta returns nothing
if (0 != percent) then
set pida = pida/3
call SaveReal(utb, uida, pida, LoadReal(utb, uida, pida) + percenta)
call GroupEnumUnitsInRect(g, WorldBounds.world, null)
set pid = pida
set uid = uida
set percent = percenta
loop
exitwhen TriggerEvaluate(addBonusManaToTypem)
endloop
endif
endfunction
function AddBonusToType takes integer pida, integer uida, integer bonusa, integer valuea returns nothing
if (0 != valuea) then
set pida = pida/3
call SaveInteger(table, uida, bonusa*2+pida, valuea + LoadInteger(table, uida, bonusa*2+pida))
call GroupEnumUnitsOfType(g, GetObjectName(uida), null)
set pid = pida
set uid = uida
set bonus = bonusa
set value = valuea
loop
exitwhen TriggerEvaluate(addBonusToTypem)
endloop
endif
endfunction
function AddBonusToSends takes integer pida, integer bonusa, integer valuea returns nothing
set i = Sends[pida]
if (0 != valuea) then
set pida = pida/3
set sbs[bonusa*2+pida] = sbs[bonusa*2+pida] + valuea
set pid = pida
set bonus = bonusa
set value = valuea
loop
exitwhen TriggerEvaluate(addBonusToSendsm)
endloop
endif
endfunction
function AddBonusToTowers takes integer pida, integer bonusa, integer valuea returns nothing
set i = Towers[pida]
if (0 != valuea) then
set pida = pida/3
set tbs[bonusa*2+pida] = tbs[bonusa*2+pida] + valuea
set pid = pida
set bonus = bonusa
set value = valuea
loop
exitwhen TriggerEvaluate(addBonusToTowersm)
endloop
endif
endfunction
function AddBonusHealthToSends takes integer pida, real percenta returns nothing
set i = Sends[pida]
if (0 != percenta) then
set pida = pida/3
set sbp[BONUS_LIFE*2+pida] = sbp[BONUS_LIFE*2+pida] + percenta
set pid = pida
set percent = percenta
loop
exitwhen TriggerEvaluate(addBonusHealthToSendsm)
endloop
endif
endfunction
function AddBonusManaToSends takes integer pida, real percenta returns nothing
set i = Sends[pida]
if (0 != percenta) then
set pida = pida/3
set sbp[BONUS_MANA*2+pida] = sbp[BONUS_MANA*2+pida] + percenta
set pid = pida
set percent = percenta
loop
exitwhen TriggerEvaluate(addBonusManaToSendsm)
endloop
endif
endfunction
function AddBonusHealthToTowers takes integer pida, real percenta returns nothing
set i = Towers[pida]
if (0 != percenta) then
set pida = pida/3
set tbp[BONUS_LIFE*2+pida] = tbp[BONUS_LIFE*2+pida] + percenta
set pid = pida
set percent = percenta
loop
exitwhen TriggerEvaluate(addBonusHealthToTowersm)
endloop
endif
endfunction
private struct Init extends array
private static method index takes nothing returns boolean
local unit u
local integer i
local integer id
if (null == GetIndexedUnit()) then
set u = GetTriggerUnit()
set i = GetUnitUserData(u)
else
set u = GetIndexedUnit()
set i = GetIndexedUnitId()
set sbpm[i] = 0
set sbpl[i] = 0
set ubl[i] = 0
set ubm[i] = 0
endif
set id = GetPlayerId(GetOwningPlayer(u))/3
if (GetUnitRace(u) == RACE_DEMON) then
if (null == GetIndexedUnit()) then
call AddUnitBonus(u, BONUS_LIFE, -sbpl[i])
call AddUnitBonus(u, BONUS_MANA, -sbpm[i])
call AddUnitBonus(u, BONUS_ARMOR, -LoadInteger(table, ud[i], BONUS_ARMOR*2+id))
call AddUnitBonus(u, BONUS_DAMAGE, -LoadInteger(table, ud[i], BONUS_DAMAGE*2+id))
call AddUnitBonus(u, BONUS_LIFE, -LoadInteger(table, ud[i], BONUS_LIFE*2+id))
call AddUnitBonus(u, BONUS_LIFE_REGEN, -LoadInteger(table, ud[i], BONUS_LIFE_REGEN*2+id))
call AddUnitBonus(u, BONUS_MANA, -LoadInteger(table, ud[i], BONUS_MANA*2+id))
else
set ud[i] = GetUnitTypeId(u)
call AddUnitBonus(u, BONUS_ARMOR, sbs[BONUS_ARMOR*2+id])
call AddUnitBonus(u, BONUS_DAMAGE, sbs[BONUS_DAMAGE*2+id])
call AddUnitBonus(u, BONUS_LIFE, sbs[BONUS_LIFE*2+id])
call AddUnitBonus(u, BONUS_LIFE_REGEN, sbs[BONUS_MANA*2+id])
call AddUnitBonus(u, BONUS_MANA, sbs[BONUS_LIFE_REGEN*2+id])
endif
set ud[i] = GetUnitTypeId(u)
set sbpl[i] = R2I((GetUnitState(u, UNIT_STATE_MAX_LIFE)-GetUnitBonus(u, BONUS_LIFE))*(sbp[BONUS_LIFE*2+id]+LoadReal(utb,-ud[i],id)+ubl[i]))
set sbpm[i] = R2I((GetUnitState(u, UNIT_STATE_MAX_MANA)-GetUnitBonus(u, BONUS_MANA))*(sbp[BONUS_MANA*2+id]+LoadReal(utb,ud[i],id)+ubm[i]))
call AddUnitBonus(u, BONUS_LIFE, sbpl[i])
call AddUnitBonus(u, BONUS_MANA, sbpm[i])
call AddUnitBonus(u, BONUS_ARMOR, LoadInteger(table, ud[i], BONUS_ARMOR*2+id))
call AddUnitBonus(u, BONUS_DAMAGE, LoadInteger(table, ud[i], BONUS_DAMAGE*2+id))
call AddUnitBonus(u, BONUS_LIFE, LoadInteger(table, ud[i], BONUS_LIFE*2+id))
call AddUnitBonus(u, BONUS_LIFE_REGEN, LoadInteger(table, ud[i], BONUS_LIFE_REGEN*2+id))
call AddUnitBonus(u, BONUS_MANA, LoadInteger(table, ud[i], BONUS_MANA*2+id))
elseif (GetUnitRace(u) == RACE_UNDEAD and IsUnitType(u, UNIT_TYPE_STRUCTURE) and not Race(GetUnitTypeId(u)).exists and not RaceTech(GetUnitTypeId(u)).exists and not AdvRaceTech(GetUnitTypeId(u)).exists) then
if (null == GetIndexedUnit()) then
call AddUnitBonus(u, BONUS_LIFE, -sbpl[i])
call AddUnitBonus(u, BONUS_DAMAGE, -LoadInteger(table, ud[i], BONUS_DAMAGE*2+id))
call AddUnitBonus(u, BONUS_LIFE, -LoadInteger(table, ud[i], BONUS_LIFE*2+id))
call AddUnitBonus(u, BONUS_LIFE_REGEN, -LoadInteger(table, ud[i], BONUS_LIFE_REGEN*2+id))
call AddUnitBonus(u, BONUS_MANA, -LoadInteger(table, ud[i], BONUS_MANA*2+id))
call AddUnitBonus(u, BONUS_MANA_REGEN, -LoadInteger(table, ud[i], BONUS_MANA_REGEN*2+id))
call AddUnitBonus(u, BONUS_ATTACK_SPEED, -LoadInteger(table, ud[i], BONUS_ATTACK_SPEED*2+id))
else
set ud[i] = GetUnitTypeId(u)
call AddUnitBonus(u, BONUS_DAMAGE, tbs[BONUS_DAMAGE*2+id])
call AddUnitBonus(u, BONUS_LIFE, tbs[BONUS_LIFE*2+id])
call AddUnitBonus(u, BONUS_LIFE_REGEN, tbs[BONUS_LIFE_REGEN*2+id])
call AddUnitBonus(u, BONUS_MANA, tbs[BONUS_MANA*2+id])
call AddUnitBonus(u, BONUS_MANA_REGEN, tbs[BONUS_MANA_REGEN*2+id])
call AddUnitBonus(u, BONUS_ATTACK_SPEED, tbs[BONUS_ATTACK_SPEED*2+id])
endif
set ud[i] = GetUnitTypeId(u)
set sbpl[i] = R2I((GetUnitState(u, UNIT_STATE_MAX_LIFE)-GetUnitBonus(u, BONUS_LIFE))*(tbp[BONUS_LIFE*2+id]+LoadReal(utb,-ud[i],id)+ubl[i]))
call AddUnitBonus(u, BONUS_LIFE, sbpl[i])
call AddUnitBonus(u, BONUS_DAMAGE, LoadInteger(table, ud[i], BONUS_DAMAGE*2+id))
call AddUnitBonus(u, BONUS_LIFE, LoadInteger(table, ud[i], BONUS_LIFE*2+id))
call AddUnitBonus(u, BONUS_LIFE_REGEN, LoadInteger(table, ud[i], BONUS_LIFE_REGEN*2+id))
call AddUnitBonus(u, BONUS_MANA, LoadInteger(table, ud[i], BONUS_MANA*2+id))
call AddUnitBonus(u, BONUS_MANA_REGEN, LoadInteger(table, ud[i], BONUS_MANA_REGEN*2+id))
call AddUnitBonus(u, BONUS_ATTACK_SPEED, LoadInteger(table, ud[i], BONUS_ATTACK_SPEED*2+id))
endif
set u = null
return false
endmethod
private static method init takes nothing returns boolean
set addBonusHealthToTypem = CreateTrigger()
set addBonusManaToTypem = CreateTrigger()
set addBonusToTypem = CreateTrigger()
set addBonusToSendsm = CreateTrigger()
set addBonusToTowersm = CreateTrigger()
set addBonusHealthToSendsm = CreateTrigger()
set addBonusManaToSendsm = CreateTrigger()
set addBonusHealthToTowersm = CreateTrigger()
call TriggerAddCondition(addBonusHealthToTypem, Condition(function AddBonusHealthToTypem))
call TriggerAddCondition(addBonusManaToTypem, Condition(function AddBonusManaToTypem))
call TriggerAddCondition(addBonusToTypem, Condition(function AddBonusToTypem))
call TriggerAddCondition(addBonusToSendsm, Condition(function AddBonusToSendsm))
call TriggerAddCondition(addBonusToTowersm, Condition(function AddBonusToTowersm))
call TriggerAddCondition(addBonusHealthToSendsm, Condition(function AddBonusHealthToSendsm))
call TriggerAddCondition(addBonusManaToSendsm, Condition(function AddBonusManaToSendsm))
call TriggerAddCondition(addBonusHealthToTowersm, Condition(function AddBonusHealthToTowersm))
set table = InitHashtable()
set utb = InitHashtable()
set g = CreateGroup()
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH, Condition(function thistype.index))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_CANCEL, Condition(function thistype.index))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library AddBonusRegen uses UnitIndexer, Game, Summon, RegisterPlayerUnitEvent
globals
private constant real TIMEOUT = .1
//all percent
private real array htp
private real array hsp
//all scalar
private real array hts
private real array hss
//type
private hashtable ut
//unit percent
private real array hup
//unit scaler
private real array hus
private constant integer OP = 2700
private integer i
endglobals
function AddBonusHealthRegenToUnitPercent takes integer u, real percent returns nothing
set hup[u] = hup[u] + percent*TIMEOUT
endfunction
function AddBonusHealthRegenToUnit takes integer u, real value returns nothing
set hus[u] = hus[u] + value*TIMEOUT
endfunction
function AddBonusHealthRegenToUnitTypePercent takes integer pid, integer uid, real percent returns nothing
call SaveReal(ut, -uid, pid/3, LoadReal(ut, -uid, pid/3) + percent*TIMEOUT)
endfunction
function AddBonusHealthRegenToUnitType takes integer pid, integer uid, real value returns nothing
call SaveReal(ut, uid, pid/3, LoadReal(ut, uid, pid/3) + value*TIMEOUT)
endfunction
function AddBonusHealthRegenToTowersPercent takes integer pid, real percent returns nothing
set htp[pid/3] = htp[pid/3] + percent*TIMEOUT
endfunction
function AddBonusHealthRegenToTowers takes integer pid, real value returns nothing
set hts[pid/3] = hts[pid/3] + value*TIMEOUT
endfunction
function AddBonusHealthRegenToSendsPercent takes integer pid, real percent returns nothing
set hsp[pid/3] = hsp[pid/3] + percent*TIMEOUT
endfunction
function AddBonusHealthRegenToSends takes integer pid, real value returns nothing
set hss[pid/3] = hss[pid/3] + value*TIMEOUT
endfunction
private struct Init extends array
private static trigger towert
private static trigger sendt
private static integer tm
private static method tower takes nothing returns boolean
local integer t = tm/3
local real pa = htp[t]
local real sa = hts[t]
local integer d
local unit u
local integer o = OP
loop
exitwhen 0 == i or 0 == o
set u = GetUnitById(i - 1)
set d = GetUnitTypeId(u)
call SetWidgetLife(u, GetWidgetLife(u) + GetUnitState(u, UNIT_STATE_MAX_LIFE)*(pa+LoadReal(ut,-d,t)+hup[i - 1])+sa+LoadReal(ut,d,t)+hus[i-1])
set i = Towers(i).n
set o = o - 1
endloop
set u = null
return 0 == i
endmethod
private static method send takes nothing returns boolean
local integer t = tm/3
local real pa = hsp[t]
local real sa = hss[t]
local integer d
local unit u
local integer o = OP
loop
exitwhen 0 == i or 0 == o
set u = GetUnitById(i - 1)
set d = GetUnitTypeId(u)
call SetWidgetLife(u, GetWidgetLife(u) + GetUnitState(u, UNIT_STATE_MAX_LIFE)*(pa+LoadReal(ut,-d,t)+hup[i - 1])+sa+LoadReal(ut,d,t)+hus[i-1])
set i = Sends(i).n
set o = o - 1
endloop
set u = null
return 0 == i
endmethod
private static method regen takes nothing returns nothing
set tm = 0
set i = Towers[0]
loop
exitwhen TriggerEvaluate(towert)
endloop
set i = Sends[0]
loop
exitwhen TriggerEvaluate(sendt)
endloop
set tm = 3
set i = Towers[3]
loop
exitwhen TriggerEvaluate(towert)
endloop
set i = Sends[3]
loop
exitwhen TriggerEvaluate(sendt)
endloop
endmethod
private static method index takes nothing returns boolean
set hup[GetIndexedUnitId()] = 0
set hus[GetIndexedUnitId()] = 0
return false
endmethod
private static method init takes nothing returns boolean
set towert = CreateTrigger()
set sendt = CreateTrigger()
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
call TriggerAddCondition(towert, Condition(function thistype.tower))
call TriggerAddCondition(sendt, Condition(function thistype.send))
call TimerStart(CreateTimer(),TIMEOUT,true,function thistype.regen)
return false
endmethod
private static method onInit takes nothing returns nothing
set ut = InitHashtable()
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Plans uses RegisterPlayerUnitEvent, UnitIndexer, Table, TowerBuilders, Race
struct Plans extends array
private static Table researchTime
private static Table builderId
private static Table itemId
private static Table co
private static Table coi
private static Table table
private static Table item2Tech
private static hashtable plans
private static timer array tm
private static integer array researchId
private static boolean enabled = false
private static integer array rid
private static integer rc = 0
private static method onResearchFinish takes nothing returns nothing
local integer h = GetHandleId(GetExpiredTimer())
local integer techIndex = table[h]
local unit tech = GetUnitById(techIndex)
local integer g = GetPlayerState(GetOwningPlayer(tech), PLAYER_STATE_RESOURCE_GOLD)
local integer l = GetPlayerState(GetOwningPlayer(tech), PLAYER_STATE_RESOURCE_LUMBER)
local integer builderIndex
local unit builder
local integer c
local integer itd
local item pln
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
set tm[techIndex] = null
call table.remove(h)
set enabled = true
call IssueImmediateOrderById(tech, 851976)
call IssueImmediateOrderById(tech, 851976)
call IssueImmediateOrderById(tech, 851976)
call IssueImmediateOrderById(tech, 851976)
call IssueImmediateOrderById(tech, 851976)
call IssueImmediateOrderById(tech, 851976)
set enabled = false
call SetPlayerState(GetOwningPlayer(tech), PLAYER_STATE_RESOURCE_LUMBER, l)
call SetPlayerState(GetOwningPlayer(tech), PLAYER_STATE_RESOURCE_GOLD, g)
call SetPlayerState(GetOwningPlayer(tech), PLAYER_STATE_RESOURCE_LUMBER, l)
loop
exitwhen 0 == rc
set rc = rc - 1
call IssueImmediateOrderById(tech, rid[rc])
endloop
set builder = TowerBuilders[GetPlayerId(GetOwningPlayer(tech))].get(builderId[GetUnitTypeId(tech)])
if (null != builder) then
set builderIndex = GetUnitUserData(builder)
set itd = itemId[researchId[techIndex]]
set pln = LoadItemHandle(plans, builderIndex, itd)
set c = GetItemCharges(pln)
if (0 == c) then
call SaveItemHandle(plans, builderIndex, itd, UnitAddItemById(builder, itd))
else
call SetItemCharges(pln, GetItemCharges(pln)+1)
endif
endif
set tech = null
set builder = null
set tech = null
endmethod
private static method onResearchStart takes nothing returns boolean
local thistype this
local timer t
if (researchTime.real.has(GetResearched())) then
set this = GetUnitUserData(GetTriggerUnit())
set researchId[this] = GetResearched()
set t = CreateTimer()
set tm[this] = t
set table[GetHandleId(t)] = this
call TimerStart(t, researchTime.real[GetResearched()]-.01, false, function thistype.onResearchFinish)
set t = null
endif
return false
endmethod
private static method onResearchCancel takes nothing returns boolean
local thistype this = GetUnitUserData(GetTriggerUnit())
local timer t = tm[this]
if (GetResearched() == researchId[this]) then
if (null != t) then
call table.remove(GetHandleId(t))
call PauseTimer(t)
call DestroyTimer(t)
set tm[this] = null
set researchId[this] = 0
set t = null
endif
elseif (enabled) then
set rid[rc] = GetResearched()
set rc = rc + 1
endif
return false
endmethod
static method gen takes integer tid, integer bid returns nothing
set builderId[tid] = bid
endmethod
static method add takes integer tid, integer upgrade, integer itd, real time returns nothing
set researchTime.real[upgrade] = time
set itemId[upgrade] = itd
set item2Tech[itd] = tid
endmethod
static method setUnitReq takes integer towerId, integer itd, integer count returns nothing
set co[towerId] = count
set coi[towerId] = itd
endmethod
private static timer cp
private static integer array cph
private static integer cpc = 0
private static method checkConstruct takes nothing returns nothing
local unit tower
local integer towerIndex
local integer builderIndex
local item pln
local integer count
local integer c
local integer itd
local unit builder
local integer towerId
loop
exitwhen 0 == cpc
set cpc = cpc - 1
set towerIndex = cph[cpc]
set tower = GetUnitById(towerIndex)
set towerId = GetUnitTypeId(tower)
if (0 != towerId) then
set itd = coi[towerId]
set count = co[towerId]
set builder = TowerBuilders[GetPlayerId(GetOwningPlayer(tower))].get(builderId[item2Tech[itd]])
set builderIndex = GetUnitUserData(builder)
set pln = LoadItemHandle(plans, builderIndex, itd)
set c = GetItemCharges(pln)
if (c >= count) then
set c = c - count
if (0 == c) then
call RemoveItem(pln)
call RemoveSavedHandle(plans, builderIndex, itd)
else
call SetItemCharges(pln, c)
endif
else
call WriteTextTag("Not Enough "+GetObjectName(itd)+" To Build "+GetUnitName(tower), 10, GetUnitX(tower), GetUnitY(tower), GetLocalPlayer() == GetOwningPlayer(tower))
call IssueImmediateOrderById(tower, 851976)
if (towerId == GetUnitTypeId(tower)) then
call KillUnit(tower)
endif
endif
endif
call UnitIndex(towerIndex).unlock()
endloop
set pln = null
set builder = null
set tower = null
endmethod
private static method constructStart takes nothing returns boolean
local integer i = GetUnitUserData(GetTriggerUnit())
if (0 < co[GetUnitTypeId(GetTriggerUnit())]) then
if (IsUnitIndexed(GetTriggerUnit())) then
call UnitIndex(i).lock()
set cph[cpc] = i
set cpc = cpc + 1
call TimerStart(cp, 0, false, function thistype.checkConstruct)
endif
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_RESEARCH_START,Condition(function thistype.onResearchStart))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_RESEARCH_CANCEL,Condition(function thistype.onResearchCancel))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_START, Condition(function thistype.constructStart))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_START, Condition(function thistype.constructStart))
return false
endmethod
private static method onInit takes nothing returns nothing
set table = Table.create()
set researchTime = Table.create()
set itemId = Table.create()
set plans = InitHashtable()
set co = Table.create()
set coi = Table.create()
set item2Tech = Table.create()
set builderId = Table.create()
set cp = CreateTimer()
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=27
//TESH.alwaysfold=0
library BonusDamage uses DamageEvent, Table, UnitIndexer
globals
//unit
private real array bup
//type
private Table array b
//all
private real array bts
private real array btp
private constant integer SAVE = 'A006'
private constant integer SAVE_AMOUNT = 100000
private unit array rem
private integer array remi
private real array dmg
private real array odmg
private real array lf
private unit array src
private integer array sv
private integer r
private timer t
endglobals
private function Rem takes nothing returns nothing
local real d
call DamageEvent.disable()
loop
exitwhen 0 == r
set r = r - 1
if (0 > dmg[r] and -dmg[r] > odmg[r]) then
set d = 0
else
set d = dmg[r] + odmg[r]
endif
set lf[remi[r]] = lf[remi[r]] - d
set sv[remi[r]] = sv[remi[r]] - 1
if (0 == sv[remi[r]]) then
call UnitRemoveAbility(rem[r], SAVE)
if (lf[remi[r]] < 1) then
call SetWidgetLife(rem[r], GetUnitState(rem[r], UNIT_STATE_MAX_LIFE)/5)
call UnitDamageTarget(src[r], rem[r], GetUnitState(rem[r], UNIT_STATE_MAX_LIFE)*20, true, true, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_UNKNOWN, WEAPON_TYPE_WHOKNOWS)
else
call SetWidgetLife(rem[r], lf[remi[r]])
endif
call UnitIndex(remi[r]).unlock()
endif
set rem[r] = null
set src[r] = null
endloop
call DamageEvent.enable()
endfunction
function AddBonusDamageToUnitPercent takes integer u, real percent returns nothing
set bup[u] = bup[u] + percent
endfunction
function AddBonusDamageToType takes integer pid, integer uid, real value returns nothing
set b[pid/3].real[uid] = b[pid/3].real[uid] + value
endfunction
function AddBonusDamageToTypePercent takes integer pid, integer uid, real percent returns nothing
set b[pid/3].real[-uid] = b[pid/3].real[-uid] + percent
endfunction
function AddBonusDamageToTowers takes integer pid, real value returns nothing
set bts[pid/3] = bts[pid/3] + value
endfunction
function AddBonusDamageToTowersPercent takes integer pid, real percent returns nothing
set btp[pid/3] = btp[pid/3] + percent
endfunction
private function Deindex takes nothing returns boolean
set bup[GetIndexedUnitId()] = 0
return false
endfunction
private function OnDamage takes nothing returns boolean
local integer uid = GetUnitTypeId(DamageEvent.source)
local integer pid = GetPlayerId(GetOwningPlayer(DamageEvent.source))/3
local real amount = DamageEvent.amount*(btp[pid]+b[pid].real[-uid]+bup[DamageEvent.sourceId])+bts[pid]+b[pid].real[uid]
if (amount < -.01 or amount > .01) then
if (0 == sv[DamageEvent.targetId]) then
call DamageEvent.targetId.lock()
set lf[DamageEvent.targetId] = GetWidgetLife(DamageEvent.target)
call UnitAddAbility(DamageEvent.target, SAVE)
endif
call SetWidgetLife(DamageEvent.target, GetUnitState(DamageEvent.target, UNIT_STATE_MAX_LIFE))
set sv[DamageEvent.targetId] = sv[DamageEvent.targetId] + 1
set remi[r] = DamageEvent.targetId
set rem[r] = DamageEvent.target
set dmg[r] = amount
set odmg[r] = DamageEvent.amount
set src[r] = DamageEvent.source
set r = r + 1
call TimerStart(t, 0, false, function Rem)
endif
return false
endfunction
private struct Init extends array
private static method onInit takes nothing returns nothing
set b[0] = Table.create()
set b[1] = Table.create()
set r = 0
set t = CreateTimer()
call DamageEvent.ANY.register(Condition(function OnDamage))
call RegisterUnitIndexEvent(Condition(function Deindex), UnitIndexer.DEINDEX)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SoloEnd uses Game, RegisterPlayerUnitEvent, UnitIndexer
struct SoloEnd extends array
static boolean canEnd = false
private static boolean array isCounted
readonly static integer count = 0
private static method death takes nothing returns boolean
local unit u = GetTriggerUnit()
if (null == u) then
set u = GetIndexedUnit()
endif
if (isCounted[GetUnitUserData(u)]) then
set isCounted[GetUnitUserData(u)] = false
set u = null
set count = count - 1
if (0 == count and canEnd and not Game.isOver) then
call Game.end(1)
endif
endif
return false
endmethod
private static method index takes nothing returns boolean
if (GetUnitRace(GetIndexedUnit()) == RACE_DEMON) then
set count = count + 1
set isCounted[GetIndexedUnitId()] = true
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.death), UnitIndexer.DEINDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.death))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onStartSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=537
//TESH.alwaysfold=0
library SoloWaves uses Game, SendPlayer, SoloEnd
//! textmacro SETUP_WAVES
//Time: 15 Seconds
//1: 7 5 1
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[1] = wave //000090 000000 000030 000000 000000
call wave.add(sends[1], 7) //000055 000000 000007 000000 000007
set incomeg[1] = 37 //000055 000000 000037 000000 000000
//Bounty: //000062 000007
//1: 0 5 1
//Time: 30 Seconds
//1: 7 5 1
//2: 2 10 2
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[2] = wave //000062 000000 000037 000000 000000
call wave.add(sends[2], 2) //000042 000000 000004 000000 000004
call wave.add(sends[1], 7) //000007 000000 000007 000000 000007
set incomeg[1] = 48
//Income: 000055 000000 000048 000000 000000
set incomeg[2] = 48 //000055 000000 000048 000000 000000
//Bounty: //000066 000011
//1: 0 5 1
//2: 0 10 2
//Time: 45 Seconds
//2: 3 10 2
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[3] = wave //000066 000000 000048 000000 000000
//Income: 000114 000000 000048 000000 000000
set incomeg[3] = 48 //000114 000000 000048 000000 000000
//Bounty: //000114 000000
//2: 3 10 2
//Time: 60 Seconds
//2: 6 10 2
//3: 2 20 4
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[4] = wave //000114 000000 000048 000000 000000
call wave.add(sends[3], 2) //000074 000000 000008 000000 000008
call wave.add(sends[2], 6) //000014 000000 000012 000000 000012
set incomeg[3] = 68
//Income: 000082 000000 000068 000000 000000
set incomeg[4] = 68 // 000020
//Bounty: //000102
//2: 0 10 2
//3: 0 20 4
//Time: 75 Seconds
//3: 3 10 2
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[5] = wave //000102 000000 000068 000000 000000
//Income: 000170 000000 000068 000000 000000
set incomeg[5] = 68 //000170 000000 000068 000000 000000
//Bounty: //000170 000000
//3: 3 10 2
//Time: 90 Seconds
//3: 6 20 4
//4: 1 30 6
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[6] = wave //000170 000000 000068 000000 000000
call wave.add(sends[4], 2) //000110 000000 000012 000000 000012
call wave.add(sends[3], 5) //000010 000000 000020 000000 000020
set incomeg[5] = 100
//Income: 000110 000000 000100 000000 000000
set incomeg[6] = 100
//Bounty: //000142 000032
//3: 1 20 4
//4: 0 30 6
//Time: 105 Seconds
//3: 4 10 2
//4: 2 30 6
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[7] = wave //000142 000000 000100 000000 000000
//Income: 000242 000000 000100 000000 000000
set incomeg[7] = 100 //000242 000000 000100 000000 000000
//Bounty: //000242 000000
//3: 4 10 2
//4: 2 30 6
//Time: 120 Seconds
//3: 7 20 4
//4: 4 30 6
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[8] = wave //000242 000000 000100 000000 000000
call wave.add(sends[4], 4) //000122 000000 000024 000000 000024
call wave.add(sends[3], 6) //000002 000000 000024 000000 000024
set incomeg[7] = 148
//Income: 000150 000000 000148 000000 000000
call wave.add(sends[3], 1) //000130 000000 000004 000000 000000
set incomeg[8] = 152 //000130 000000 000152 000000 000000
//Bounty: //000178 000048
//3: 0 20 4
//4: 0 30 6
//Time: 135 Seconds
//3: 2 20 4
//4: 2 30 6
//6: 1 48 8
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[9] = wave //000178 000000 000152 000000 000000
//Income: 000330 000000 000152 000000 000000
set incomeg[9] = 152 //000330 000000 000152 000000 000000
//Bounty: //000330 000000
//3: 2 20 4
//4: 2 30 6
//6: 1 48 8
//Time: 150 Seconds
//3: 5 20 4
//4: 4 30 6
//6: 3 48 8
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[10] = wave //000330 000000 000152 000000 000000
call wave.add(sends[6], 3) //000186 000000 000024 000000 000024
call wave.add(sends[4], 4) //000066 000000 000024 000000 000024
call wave.add(sends[3], 3) //000006 000000 000012 000000 000012
set incomeg[9] = 212
//Income: 000218 000000 000212 000000 000000
call wave.add(sends[3], 2) //000178 000000 000008 000000 000008
set incomeg[10] = 220 //000178 000000 000220 000000 000000
//Bounty: //000246 000068
//Time: 165 Seconds
//3: 2 20 4
//4: 2 30 6
//6: 1 48 8
//7: 1 58 12
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[11] = wave //000246 000000 000220 000000 000000
//Income: 000466 000000 000220 000000 000000
set incomeg[11] = 220 //000466 000000 000220 000000 000000
//Bounty: //000466 000000
//3: 2 20 4
//4: 2 30 6
//6: 1 48 8
//7: 1 58 12
//Time: 180 Seconds
//3: 5 20 4
//4: 4 30 6
//6: 3 48 8
//7: 2 58 12
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[12] = wave //000466 000000 000220 000000 000000
call wave.add(sends[7], 2) //000350 000000 000024 000000 000024
call wave.add(sends[6], 3) //000206 000000 000024 000000 000024
call wave.add(sends[4], 4) //000086 000000 000024 000000 000024
call wave.add(sends[3], 4) //000006 000000 000016 000000 000016
set incomeg[11] = 308
//Income: 000314 000000 000308 000000 000000
call wave.add(sends[3], 1) //000294 000000 000004 000000 000004
call wave.add(sends[2], 10) //000194 000000 000020 000000 000020
call wave.add(sends[1], 10) //000144 000000 000010 000000 000010
set incomeg[12] = 342 //000144 000000 000342 000000 000000
//Bounty: //000266 000122
//3: 0 20 4
//4: 0 30 6
//6: 0 48 8
//7: 0 58 12
//Time: 195 Seconds
//6: 1 48 8
//7: 1 58 12
//8: 1 85 -21
//5: 1 40 1
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[13] = wave //000266 000000 000342 000000 000000
//Income: 000608 000000 000342 000000 000000
set incomeg[13] = 342 //000608 000000 000342 000000 000000
//Bounty: //000608 000000
//6: 1 48 8
//7: 1 58 12
//8: 1 85 -21
//5: 1 40 1
//Time: 210 Seconds
//3: 10 20 4
//4: 10 30 6
//5: 6 40 7
//6: 3 48 8
//7: 2 58 12
//8: 2 85 -21
//9: 1 126 21
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[14] = wave //000608 000000 000342 000000 000000
call wave.add(sends[9], 1) //000482 000000 000021 000000 000021
call wave.add(sends[7], 2) //000366 000000 000024 000000 000024
call wave.add(sends[6], 3) //000222 000000 000024 000000 000024
call wave.add(sends[4], 7) //000012 000000 000042 000000 000042
set incomeg[13] = 453
//Income: 000465 000000 000453 000000 000000
call wave.add(sends[8], 2) //000295 000000 -00042 000000 000042
call wave.add(sends[5], 6) //000055 000000 000042 000000 000042
set incomeg[14] = 453 //000055 000000 000453 000000 000000
//Bounty: //000250 000195
//Time: 235 Seconds
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[15] = wave //000250 000000 000453 000000 000000
//Income: 000703 000000 000453 000000 000000
set incomeg[15] = 453 //000703 000000 000453 000000 000000
//Bounty: //000703 000000
//Time: 250 Seconds
//5: 6 40 7
//6: 3 48 8
//7: 2 58 12
//8: 2 85 -21
//9: 2 126 21
//10: 1 136 23
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[16] = wave //000703 000000 000453 000000 000000
call wave.add(sends[10], 1) //000567 000000 000023 000000 000023
call wave.add(sends[9], 2) //000315 000000 000042 000000 000042
call wave.add(sends[7], 2) //000199 000000 000024 000000 000024
call wave.add(sends[6], 3) //000055 000000 000024 000000 000024
call wave.add(sends[5], 1) //000015 000000 000007 000000 000007
set incomeg[15] = 573
//Income: 000588 000000 000573 000000 000000
call wave.add(sends[5], 5) //000388 000000 000035 000000 000035
call wave.add(sends[4], 4) //000268 000000 000024 000000 000024
set incomeg[16] = 632 //000268 000000 000632 000000 000000
//Bounty: //000447 000179
//Time: 265 Seconds
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[17] = wave //000447 000000 000632 000000 000000
//Income: 001079 000000 000632 000000 000000
set incomeg[17] = 632 //001079 000000 000632 000000 000000
//Bounty: //001079 000000
//Time: 280 Seconds
//5: 6 40 7
//6: 3 48 8
//7: 2 58 12
//8: 2 85 -21
//9: 2 126 21
//10: 2 136 23
//11: 1 155 -39
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[18] = wave //001079 000000 000632 000000 000000
call wave.add(sends[10], 2) //000807 000000 000046 000000 000046
call wave.add(sends[9], 2) //000555 000000 000042 000000 000042
call wave.add(sends[7], 2) //000439 000000 000024 000000 000024
call wave.add(sends[5], 6) //000199 000000 000042 000000 000042
set incomeg[17] = 786
//Income: 000985 000000 000786 000000 000000
call wave.add(sends[8], 2) //000815 000000 -00042 000000 000042
call wave.add(sends[11], 1) //000660 000000 -00039 000000 000039
set incomeg[18] = 705 //000660 000000 000705 000000 000000
//Bounty: //000895 000235
//Time: 295 Seconds
//5: 3 40 7
//6: 1 48 8
//7: 1 58 12
//8: 1 85 -21
//9: 1 126 21
//10: 1 136 23
//11: 1 155 -39
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[19] = wave //000895 000000 000705 000000 000000
call wave.add(sends[7], 1) //000837 000000 000012 000000 000012
call wave.add(sends[6], 1) //000789 000000 000008 000000 000008
call wave.add(sends[4], 10) //000489 000000 000060 000000 000060
call wave.add(sends[3], 10) //000289 000000 000040 000000 000040
set incomeg[18] = 825
//Income: 001114 000000 000825 000000 000000
call wave.add(sends[12], 4) //000114 000000 000112 000000 000112
set incomeg[19] = 937 //000114 000000 000937 000000 000000
//Bounty: //000346 000120
//Time: 15 Seconds
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[20] = wave //000346 000000 000937 000000 000000
//Income: 001283 000000 000937 000000 000000
set incomeg[20] = 937 //001283 000000 000937 000000 000000
//Bounty: //001283 000000
//Time: 30 Seconds
//12: 5 500 56
//13: 2 650 65
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[21] = wave //001283 000000 000937 000000 000000
call wave.add(sends[12], 2) //000783 000000 000056 000000 000056
call wave.add(sends[13], 1) //000133 000000 000065 000000 000065
set incomeg[20] = 1058
//Income: 001191 000000 001058 000000 000000
call wave.add(sends[12], 3) //000191 000000 000112 000000 000112
set incomeg[21] = 1170 //000191 000000 001170 000000 000000
//Bounty: //000424 000233
//Time: 45 Seconds
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[22] = wave //000424 000000 001170 000000 000000
//Income: 001594 000000 001170 000000 000000
set incomeg[22] = 1170 //001594 000000 001170 000000 000000
//Bounty: //001594 000000
//Time: 60 Seconds
//12: 10 500 56
//13: 9 650 65
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[23] = wave //001594 000000 001170 000000 000000
call wave.add(sends[12], 2) //000094 000000 000168 000000 000168
set incomeg[22] = 1338
//Income: 001432 000000 001338 000000 000000
call wave.add(sends[13], 2) //000132 000000 000130 000000 000130
call wave.add(sends[12], 2) //000094 000000 000168 000000 000168
call wave.add(sends[13], 2) //000132 000000 000130 000000 000130
set incomeg[23] = 1468 //000191 000000 001468 000000 000000
//Bounty: //000489 000298
//Time: 75 Seconds
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[24] = wave //000489 000000 001468 000000 000000
//Income: 001957 000000 001468 000000 000000
set incomeg[24] = 1170 //001957 000000 001468 000000 000000
//Bounty: //001957 000000
//Time: 90 Seconds
//12: 10 500 56
//13: 10 650 65
//14: 2 880 74
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[25] = wave //001957 000000 001468 000000 000000
call wave.add(sends[12], 2) //000000 000000 000224 000000 000224
call wave.add(sends[13], 2) //000000 000000 000224 000000 000224
set incomeg[24] = 1692
//Income: 001692 000000 001692 000000 000000
call wave.add(sends[14], 6) //000000 000000 000148 000000 000148
call wave.add(sends[12], 2) //000000 000000 000224 000000 000224
call wave.add(sends[13], 2) //000000 000000 000224 000000 000224
set incomeg[25] = 1840 //000000 000000 001840 000000 000000
//Bounty: //000372 000372
//Time: 105 Seconds
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[26] = wave //000372 000000 001840 000000 000000
//Income: 002212 000000 001840 000000 000000
set incomeg[26] = 1840 //002212 000000 001840 000000 000000
//Bounty: //002212 000000
//Time: 120 Seconds
//12: 10 500 56
//13: 10 650 65
//14: 4 880 74
//15: 2 1050 105
set wave = WaveQueue.create() //Gold Lumber Income G Income L Bounty
set waves[27] = wave //002212 000000 001840 000000 000000
call wave.add(sends[15], 4) //000112 000000 000210 000000 000210
set incomeg[26] = 2050
//Income: 002162 000000 002050 000000 000000
call wave.add(sends[12], 2) //001662 000000 000056 000000 000056
call wave.add(sends[13], 2) //001662 000000 000056 000000 000056
call wave.add(sends[12], 2) //001662 000000 000056 000000 000056
call wave.add(sends[14], 6) //000000 000000 000148 000000 000148
set incomeg[27] = 2254 //000000 000000 002254 000000 000000
//Bounty: //000414 000414
//! endtextmacro
//! textmacro SETUP_MESSAGES
if (Game.difficulty == DIFFICULTY_MASTER or Game.difficulty == DIFFICULTY_LEAGUE) then
set messages[1] = /*
*/"Be happy, you get to play against the best WmW Player in the world 1 on 1. The sending is modeled after me, so it is as though you are facing me. Hopefully you last for more "/*
*/+" than four sends."
set messages[3] = "Sending right before a round and then continuing to send through the next round will double the strength of your sends. Allow me to demonstrate >: )"
set messages[4] = "Fuahahaha, here it is!"
set messages[6] = "Sending the strongest units in first forces the opposing players to have to micro to kill the weaker ones, otherwise they will mass leak if they can't handle the send."
set messages[8] = "Spacing sends is important against splash."
set messages[14] = "This is where the game starts getting difficult. The reason is because of the 85 gold -income send, which is quite a bit stronger than the +income sends. Air can also be massed with it."
set messages[15] = "The -income sends, while they do reduce income, forces the opposing player to build quite a lot more if they haven't already, so you pull out ahead"
set messages[16] = "Fortified units are always targeted after everything else, so they should always be sent in the very front so that they are the first ones through the maze. However, this will make it easier for a decent player to micro target the fortified."
set messages[18] = "The ultimate -income send for shrine 1 is incredibly powerful with high health, regeneration, and massive spawning, but it does lower income by a lot, so when using it, you should use it effectively"
set messages[19] = "Summons get much stronger from shrine to shrine."
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
set messages[1] = "Yo, let's have a fun game."
set messages[2] = "Don't leak too much from this k?"
set messages[3] = "Did you know that if you don't send until a little before a round, your send size doubles O_o. I learned that from Nes."
set messages[4] = "Aren't I awesome?"
set messages[5] = "Ready for another pimp send?"
set messages[6] = "Here it comes!"
set messages[7] = "This is kinda getting repetitive..."
set messages[8] = "Heh, did you see me send a bit before and a bit after that round just now? I ran out of gold o-o"
set messages[14] = "I could go for that -income, but it just hurts too much. How about some air instead? >: )"
set messages[16] = "Time for a little fortified action"
set messages[19] = "Time to go shrine 2. Nestharus told me that the summons get a lot stronger."
set messages[21] = "These attackers look pretty pesky, so let's just not do them."
else
set messages[1] = "My sending is pretty weak, so please go easy"
set messages[2] = "Go go go my little army of people ;D"
set messages[3] = "Did you know that if you don't send until a little before a round, your send size doubles :D. I learned that from Nes."
set messages[4] = "looky looky ^_^"
set messages[5] = "Gotta save again :P"
set messages[6] = "wooo ; D"
set messages[7] = "choo choo"
set messages[8] = "Ah, out of gold!! What do I do? O_o. Oh wait, if I send when income happens, I can send some more =D. Here we go!"
set messages[14] = "I don't really like air or -income sends or attackers, sooo... I'm not going to send them k? : D"
set messages[16] = "Careful now, I sent fortified :o"
set messages[19] = "ahhhh, I'm going shrine 2 :D. Nestharus told me that the summons get WAY stronger in bigger shrines ^)^."
set messages[21] = "I could send some attackers at you, but... I don't want to ^)^"
endif
//! endtextmacro
//! textmacro SETUP_SENDS
//Start Replenish Cost Income
set sends[1] = 'u00E' //0 2 5 +1/5
set sends[2] = 'hC04' //25 5 10 +1/5
set sends[3] = 'eC05' //50 6 20 +1/5
set sends[4] = 'hC16' //85 8 30 +1/5
if (Game.difficulty != DIFFICULTY_BEGINNER) then
set sends[5] = 'nC17' //195 5 40 +1/6 Flying
else
set sends[5] = sends[4]
endif
set sends[6] = 'uC28' //135 10 48 +1/6 Regeneration
set sends[7] = 'nC29' //155 12 58 +1/5
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set sends[8] = 'nC30' //190 14 85 -1/4 Summoning
else
set sends[8] = sends[7]
endif
set sends[9] = 'oC31' //215 14 126 +1/6 Regeneration
set sends[10] = 'nC33' //255 16 136 +1/6 Fortified
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set sends[11] = 'eC38' //275 18 155 -1/4 Summoning + Regeneration
else
set sends[11] = sends[10]
endif
set sends[12] = 'nC39' //5 2 500 +1/8.88
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set sends[13] = 'nC40' //20 4 650 +1/10 Immolation, -Health Regen
else
set sends[13] = sends[12]
endif
if (Game.difficulty != DIFFICULTY_BEGINNER) then
set sends[14] = 'nC41' //80 6 880 +1/12 Flying + Strong Armor
else
set sends[14] = sends[12]
endif
set sends[15] = 'nC42' //110 6 1050 +1/10 Fortified
set sends[16] = 'uC81' //135 12 1590 +1/8.88 Divine
set sends[17] = 'hC44' //165 9 2300 +1/10 Fortified
set sends[18] = 'uC45' //200 9 2830 +1/12 Spawn Spiders
set sends[19] = 'oC47' //230 10 3995 +1/8.88
set sends[20] = 'hC48' //300 10 5330 +1/8.88
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set sends[21] = 'nC49' //330 12 8010 -1/3 +1% hp every 5 secs
set sends[22] = 'nC50' //360 15 12475 -1/6 Lots of Health + 1% regen
else
set sends[21] = sends[20]
set sends[22] = sends[20]
endif
set sends[23] = 'h015' //0 15 15000 +1/12 Immolation
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set sends[24] = 'h00X' //0 15 30000 -1/4 Summoning
else
set sends[24] = sends[23]
endif
set sends[25] = 'h011' //0 15 45000 +1/13 Heavy Armor + Health
set sends[26] = 'h00W' //0 15 90000 +1/16 Fast Reincarnation
if (Game.difficulty != DIFFICULTY_BEGINNER) then
set sends[27] = 'h016' //0 15 175000 +0 Flying
else
set sends[27] = sends[26]
endif
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set sends[28] = 'u00A' //0 15 1200000 -1/2 -10 Lives + Divine + Heavy Armor + Health Regen
else
set sends[28] = sends[27]
endif
//! endtextmacro
private struct WaveQueue extends array
private static integer ic = 0
private static integer array n
private static integer array l
readonly integer count
readonly integer unitTypeId
method operator next takes nothing returns thistype
return n[this]
endmethod
static method create takes nothing returns thistype
set ic = ic + 1
set l[ic] = ic
set n[ic] = 0
return ic
endmethod
method add takes integer unitTypeId, integer count returns nothing
set ic = ic + 1
set n[l[this]] = ic
set l[this] = ic
set thistype(ic).count = count
set thistype(ic).unitTypeId = unitTypeId
endmethod
endstruct
struct SoloWaves extends array
private static integer soloPlayer = 0
private static WaveQueue array waves
private static integer array sends
private static integer array incomeg
private static integer array incomel
private static string array messages
private static string name
static method send takes WaveQueue wave returns boolean
local boolean end = false
if (0 == waves[wave+1]) then
set SoloEnd.canEnd = true
set end = true
endif
if (Game.difficulty == DIFFICULTY_MASTER or Game.difficulty == DIFFICULTY_LEAGUE) then
if (wave == 2 or wave/10*10 == wave) then
if (Income[soloPlayer].gold < incomeg[wave-1]) then
if (Income[soloPlayer].gold < incomeg[wave-1]/1.2) then
set messages[wave] = "You're overbuilding so much that you've already lost, so just give up and try again"
else
set messages[wave] = "You're overbuilding a bit"
endif
else
set messages[wave] = "Not bad"
endif
endif
endif
if (messages[wave] != null) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,name+": "+messages[wave])
endif
//call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,name+" has "+I2S(incomeg[wave])+ " income")
/*
if (0 == waves[wave-1].next) then
if (0 != incomeg[wave] and 0 != incomel[wave]) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Nestharus: I got "+I2S(incomeg[wave])+" gold income and "+I2S(incomel[wave])+" lumber income")
elseif (0 != incomeg[wave]) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Nestharus: I got "+I2S(incomeg[wave])+" gold income")
elseif (0 != incomel[wave]) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"Nestharus: I got "+I2S(incomel[wave])+" lumber income")
endif
endif
*/
set wave = waves[wave]
loop
set wave = wave.next
exitwhen 0 == wave
call summonHandler[0].summon(wave.unitTypeId, 11, wave.count)
endloop
return end
endmethod
private static method init takes nothing returns boolean
local WaveQueue wave
if (Game.difficulty == DIFFICULTY_LEAGUE or Game.difficulty == DIFFICULTY_MASTER) then
set name = "|cffb22222Nestharus|r"
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
set name = "|cff00ced1Wintermaul Warrior|r"
else
set name = "|cff7cfc00Wintermaul Defender|r"
endif
loop
exitwhen IsPlaying(Player(soloPlayer))
set soloPlayer = soloPlayer + 1
endloop
//! runtextmacro SETUP_SENDS()
//! runtextmacro SETUP_WAVES()
//! runtextmacro SETUP_MESSAGES()
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onStartSolo.register(Condition(function thistype.init))
endmethod
endstruct
endlibrary
//TESH.scrollpos=136
//TESH.alwaysfold=0
library SoloIncome uses Game, Income, Command, Lives
struct SoloIncome extends array
private static integer soloPlayer = 0
private static constant real RESOURCE_2_INCOME = 5
private static method operator incomeRate takes nothing returns integer
return (Income[soloPlayer].gold+Income[soloPlayer].lumber*100000)/400+5
endmethod
private static method addIncome takes nothing returns boolean
local integer goldr
local integer lumberr
local integer gold
local integer lumber
local string s
local integer i
local string c
local integer ir = incomeRate
set s = GetEventPlayerChatString()
if (s == GetEventPlayerChatStringMatched()) then
set gold = GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD)
set lumber = GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER)
else
set s = SubString(s, 8, StringLength(s))
set i = StringLength(s)
loop
exitwhen 0 == i
set i = i - 1
set c = SubString(s, i, i + 1)
exitwhen c == ","
endloop
if (c == ",") then
set gold = S2I(SubString(s, 0, i))
set lumber = S2I(SubString(s, i+1, StringLength(s)))
else
set gold = S2I(s)
set lumber = 0
endif
endif
set gold = gold/ir*ir
set lumber = lumber/ir*ir
set goldr = GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD) - gold
set lumberr = GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER) - lumber
if (0 > goldr) then
set gold = goldr/100000*100000 - 1
set lumberr = lumberr + gold
set goldr = goldr - gold*100000
endif
if (0 > lumberr) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"Not Enough Resources")
return false
endif
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD, goldr)
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER, lumberr)
set Income[soloPlayer].gold = Income[soloPlayer].gold + AddIncome[soloPlayer].get((gold+0.)/ir)
set Income[soloPlayer].lumber = Income[soloPlayer].lumber + AddIncome[soloPlayer].get((lumber+0.)/ir)
return false
endmethod
static method run takes nothing returns nothing
local integer lumberTarget
local integer goldTarget
local integer gold
local integer lumber
local integer bg
local integer bl
local integer bg2
local integer bl2
local player p = Player(soloPlayer)
set round = round - 1
set bg = Income.getBonusGold()
set bl = Income.getBonusLumber()
set round = round + 1
set bg2 = Income.getBonusGold()
set bl2 = Income.getBonusLumber()
set gold = Income[soloPlayer].gold + bg
set lumber = Income[soloPlayer].lumber + bl
set lumber = ResourceExchange.goldToLumber(gold) + lumber
set gold = ResourceExchange.getRemainingGold(gold)
set lumberTarget = 0
set goldTarget = GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) + gold
if (goldTarget < 0) then
set goldTarget = goldTarget + ResourceExchange.GOLD_EXCHANGE_RATE
set lumberTarget = -1
endif
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, goldTarget)
set lumberTarget = lumberTarget + GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER) + lumber
if (-1 > lumberTarget) then
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, 0)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, 0)
elseif (0 > lumberTarget) then
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, lumberTarget + 1)
call SetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD) - ResourceExchange.GOLD_EXCHANGE_RATE)
else
call SetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER, lumberTarget)
endif
call Boards[soloPlayer].setGoldIncome(soloPlayer,I2S(Income[soloPlayer].gold)+"+"+I2S(bg2))
call Boards.observer.setGoldIncome(soloPlayer,I2S(Income[soloPlayer].gold)+"+"+I2S(bg2))
call Boards[soloPlayer].setLumberIncome(soloPlayer,I2S(Income[soloPlayer].lumber)+"+"+I2S(bl2))
call Boards.observer.setLumberIncome(soloPlayer,I2S(Income[soloPlayer].lumber)+"+"+I2S(bl2))
static if LIBRARY_Tester then
call DisplayTimedTextToPlayer(p,0,0,.1,"Gold Income: "+I2S(Income[soloPlayer].gold))
call DisplayTimedTextToPlayer(p,0,0,.1,"Lumber Income: "+I2S(Income[soloPlayer].lumber))
endif
set p = null
endmethod
private static method init takes nothing returns boolean
local integer i
local Command income
set income = Command["-income"]
set income.description = "Spends gold on income\n [-income (optional) gold amount to spend, (optional) lumber amount to spend]"
call income.register(function thistype.addIncome)
loop
exitwhen IsPlaying(Player(soloPlayer))
set soloPlayer = soloPlayer + 1
endloop
set i = 11
loop
set income[i].enabled = false
exitwhen 6 == i
set i = i - 1
endloop
return false
endmethod
private static method end takes nothing returns boolean
local real mult
local real score
if (Game.difficulty == DIFFICULTY_BEGINNER) then
set mult = .75
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
set mult = 1
elseif (Game.difficulty == DIFFICULTY_MASTER) then
set mult = 1.25
else
set mult = 1.5
endif
if (0 >= Lives[soloPlayer/3]) then
set round = round - 2
endif
set score = Pow(Income[soloPlayer].gold+Income[soloPlayer].lumber*100000,.5)*Pow(round,mult)
set score = R2I(score*100+.5)/100.
if (not Game.isOnline) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"Unofficial Score: |cffffcc00"+R2SW(score,0,2)+"|r")
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"Official Score: |cffffcc00"+R2SW(score,0,2)+"|r")
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitializeSolo.register(Condition(function thistype.init))
call Game.onEndSolo.register(Condition(function thistype.end))
endmethod
endstruct
endlibrary
//TESH.scrollpos=5
//TESH.alwaysfold=0
struct GodLesserShadow extends array
private static constant real TIMEOUT = 15
private static integer GOD_UNIT_TYPE_ID = 'oC67'
private static constant integer LIFE_TICK = 1
private integer team
private thistype lifeTimer
implement CTQ
implement CTQExpire
set Lives[team] = Lives[team] + LIFE_TICK
implement CTQNull
implement CTQEnd
private static method onStartBuildGod takes nothing returns boolean
if (GetUnitTypeId(GetTriggerUnit()) == GOD_UNIT_TYPE_ID) then
call SetUnitVertexColor(GetTriggerUnit(), 255, 255, 255, 25)
endif
return false
endmethod
private static method onBuildGod takes nothing returns boolean
local thistype t
if (GetUnitTypeId(GetTriggerUnit()) == GOD_UNIT_TYPE_ID) then
set t = create()
set t.team = GetPlayerId(GetTriggerPlayer())/3
set thistype(GetUnitUserData(GetTriggerUnit())).lifeTimer = t
endif
return false
endmethod
private static method onLoseGod takes nothing returns boolean
local thistype this = GetIndexedUnitId()
if (0 != lifeTimer) then
call lifeTimer.destroy()
set lifeTimer.team = 0
set lifeTimer = 0
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH,Condition(function thistype.onBuildGod))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_START,Condition(function thistype.onStartBuildGod))
call RegisterUnitIndexEvent(Condition(function thistype.onLoseGod), UnitIndexer.DEINDEX)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=16
//TESH.alwaysfold=0
struct SatanLesserShadow extends array
private static constant real TIMEOUT = 15
private static integer SATAN_UNIT_TYPE_ID = 'hC86'
private static constant real INCOME_BONUS = 3
private static constant integer LIFE_TICK = -2
private static constant integer SEND_BONUS = 1
private static constant real PENALTY_BONUS = 1/8.
private static constant integer LIVES_TAKEN = 10
private static constant integer LIFE_STEAL = 0
private static constant real PENALTY_RATE = .15
private integer currentPenalty
private integer team
private thistype lifeTimer
implement CTQ
implement CTQExpire
set Lives[team] = Lives[team] + LIFE_TICK
implement CTQNull
implement CTQEnd
private static method onStartBuildSatan takes nothing returns boolean
if (GetUnitTypeId(GetTriggerUnit()) == SATAN_UNIT_TYPE_ID) then
call SetUnitVertexColor(GetTriggerUnit(), 255, 255, 255, 25)
endif
return false
endmethod
private static method onBuildSatan takes nothing returns boolean
local thistype t
local AddIncome income = GetPlayerId(GetTriggerPlayer())
local real penalty
if (GetUnitTypeId(GetTriggerUnit()) == SATAN_UNIT_TYPE_ID) then
set t = create()
set t.team = income/3
set thistype(GetUnitUserData(GetTriggerUnit())).lifeTimer = t
set penalty = Pow(1-PENALTY_RATE,thistype(income).currentPenalty)
set thistype(income).currentPenalty = thistype(income).currentPenalty + 1
set income.penaltyReduction = income.penaltyReduction + PENALTY_BONUS*penalty
set income.bonusPercent = income.bonusPercent + INCOME_BONUS*penalty
set Summon(income).sendBonus = Summon(income).sendBonus + SEND_BONUS*penalty
//set Lives(income/3).steal = Lives(income/3).steal + LIFE_STEAL*bonus
endif
return false
endmethod
private static method onLoseSatan takes nothing returns boolean
local thistype this = GetIndexedUnitId()
local AddIncome income = GetPlayerId(GetOwningPlayer(GetIndexedUnit()))
local real penalty
if (GetUnitTypeId(GetIndexedUnit()) == SATAN_UNIT_TYPE_ID and not Game.isOver and 0 < Lives[income/3]) then
set Lives[income/3] = Lives[income/3] - LIVES_TAKEN
endif
if (0 != lifeTimer) then
call lifeTimer.destroy()
set lifeTimer.team = 0
set lifeTimer = 0
set thistype(income).currentPenalty = thistype(income).currentPenalty - 1
set penalty = Pow(1-PENALTY_RATE,thistype(income).currentPenalty)
set income.penaltyReduction = income.penaltyReduction - PENALTY_BONUS*penalty
set income.bonusPercent = income.bonusPercent - INCOME_BONUS*penalty
set Summon(income).sendBonus = Summon(income).sendBonus - SEND_BONUS*penalty
//set Lives(income/3).steal = Lives(income/3).steal - LIFE_STEAL*penalty
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_START,Condition(function thistype.onStartBuildSatan))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH,Condition(function thistype.onBuildSatan))
call RegisterUnitIndexEvent(Condition(function thistype.onLoseSatan), UnitIndexer.DEINDEX)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=53
//TESH.alwaysfold=0
struct ReparationBeam extends array
private static constant integer UNIT_ID = 'o00Z'
private static constant integer UNIT_ID_2 = 'o010'
private static constant integer UNIT_ID_3 = 'o011'
private static constant integer TECH = 'R00A'
private static Table table
private static real array percent
private static real array scalar
private static real array percents
private static real array scalars
private static integer array level
private static boolean array constructed
private static method onBuild takes nothing returns boolean
local integer i
local integer t
if (table.boolean.has(GetUnitTypeId(GetTriggerUnit()))) then
set i = GetUnitUserData(GetTriggerUnit())
set t = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
set level[i] = level[i] + 1
set constructed[i] = true
call AddBonusHealthRegenToTowersPercent(t, percent[level[i]])
call AddBonusHealthRegenToTowers(t, scalar[level[i]])
call AddBonusHealthRegenToSendsPercent(t, percents[level[i]])
call AddBonusHealthRegenToSends(t, scalars[level[i]])
endif
return false
endmethod
private static method onUpgradeStart takes nothing returns boolean
local integer i = GetUnitUserData(GetTriggerUnit())
local integer t
if (constructed[i]) then
set t = GetPlayerId(GetOwningPlayer(GetTriggerUnit()))
set constructed[i] = false
call AddBonusHealthRegenToTowersPercent(t, -percent[level[i]])
call AddBonusHealthRegenToTowers(t, -scalar[level[i]])
call AddBonusHealthRegenToSendsPercent(t, -percents[level[i]])
call AddBonusHealthRegenToSends(t, -scalars[level[i]])
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local unit u
local integer i
local integer t
if (0 == GetIndexedUnitId()) then
set u = GetTriggerUnit()
set i = GetUnitUserData(u)
else
set u = GetIndexedUnit()
set i = GetIndexedUnitId()
endif
set t = GetPlayerId(GetOwningPlayer(u))
if (constructed[i]) then
set constructed[i] = false
call AddBonusHealthRegenToTowersPercent(t, -percent[level[i]])
call AddBonusHealthRegenToTowers(t, -scalar[level[i]])
call AddBonusHealthRegenToSendsPercent(t, -percents[level[i]])
call AddBonusHealthRegenToSends(t, -scalars[level[i]])
endif
set level[i] = 0
set u = null
return false
endmethod
private static method init takes nothing returns boolean
local integer i = 5
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set table = Table.create()
set table.boolean[UNIT_ID] = true
set table.boolean[UNIT_ID_2] = true
set table.boolean[UNIT_ID_3] = true
set scalar[1] = 4
set scalar[2] = 12.5
set scalars[2] = 12.5
set percent[3] = .01
set percents[3] = .01
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, Condition(function thistype.onBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH, Condition(function thistype.onBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_START, Condition(function thistype.onUpgradeStart))
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.deindex))
else
loop
call SetPlayerTechMaxAllowed(Player(i), TECH, 0)
call SetPlayerTechMaxAllowed(Player(i), UNIT_ID, 0)
exitwhen 0 == i
set i = i - 1
endloop
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=43
//TESH.alwaysfold=0
struct DeconstructionBeam extends array
private static constant integer UNIT_ID = 'o012'
private static constant integer UNIT_ID_2 = 'o013'
private static constant integer UNIT_ID_3 = 'o014'
private static constant integer TECH = 'R00B'
private static Table table
private static real array percent
private static real array scalar
private static integer array level
private static boolean array constructed
private static method onBuild takes nothing returns boolean
local integer i
if (table.boolean.has(GetUnitTypeId(GetTriggerUnit()))) then
set i = GetUnitUserData(GetTriggerUnit())
set level[i] = level[i] + 1
set constructed[i] = true
call AddBonusHealthRegenToTowersPercent(0, percent[level[i]])
call AddBonusHealthRegenToTowers(0, scalar[level[i]])
call AddBonusHealthRegenToTowersPercent(3, percent[level[i]])
call AddBonusHealthRegenToTowers(3, scalar[level[i]])
endif
return false
endmethod
private static method onUpgradeStart takes nothing returns boolean
local integer i = GetUnitUserData(GetTriggerUnit())
if (constructed[i]) then
set constructed[i] = false
call AddBonusHealthRegenToTowersPercent(0, -percent[level[i]])
call AddBonusHealthRegenToTowers(0, -scalar[level[i]])
call AddBonusHealthRegenToTowersPercent(3, -percent[level[i]])
call AddBonusHealthRegenToTowers(3, -scalar[level[i]])
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local unit u
local integer i
if (0 == GetIndexedUnitId()) then
set u = GetTriggerUnit()
set i = GetUnitUserData(u)
else
set u = GetIndexedUnit()
set i = GetIndexedUnitId()
endif
if (constructed[i]) then
set constructed[i] = false
call AddBonusHealthRegenToTowersPercent(0, -percent[level[i]])
call AddBonusHealthRegenToTowers(0, -scalar[level[i]])
call AddBonusHealthRegenToTowersPercent(3, -percent[level[i]])
call AddBonusHealthRegenToTowers(3, -scalar[level[i]])
endif
set level[i] = 0
set u = null
return false
endmethod
private static method init takes nothing returns boolean
local integer i = 5
if (Game.difficulty != DIFFICULTY_BEGINNER and Game.difficulty != DIFFICULTY_INTERMEDIATE) then
set table = Table.create()
set table.boolean[UNIT_ID] = true
set table.boolean[UNIT_ID_2] = true
set table.boolean[UNIT_ID_3] = true
set scalar[1] = -10
set scalar[2] = -40
set percent[3] = -.02
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, Condition(function thistype.onBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH, Condition(function thistype.onBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_START, Condition(function thistype.onUpgradeStart))
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.deindex))
else
loop
call SetPlayerTechMaxAllowed(Player(i), TECH, 0)
call SetPlayerTechMaxAllowed(Player(i), UNIT_ID, 0)
exitwhen 0 == i
set i = i - 1
endloop
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=67
//TESH.alwaysfold=0
struct AncientBeamTower extends array
private static constant integer UNIT_ID = 'o015'
private static constant integer ITEM_ID = 'I000'
private static constant integer INSTABILITY = 'A00P'
private static constant real EXPIRATION = 8
private static constant integer COST = 3
private static boolean array constructed
private static boolean array upgrading
private static boolean array canceled
private static timer array exp
private static Table table
private static method addBonus takes integer m returns nothing
call AddBonusHealthToSends(0, .5*m)
call AddBonusHealthToSends(3, .5*m)
call AddBonusToSends(0, BONUS_LIFE, 4500*m)
call AddBonusToSends(3, BONUS_LIFE, 4500*m)
call AddBonusManaToSends(0, 1*m)
call AddBonusManaToSends(3, 1*m)
call AddBonusToTowers(0, BONUS_LIFE, -5000*m)
call AddBonusToTowers(3, BONUS_LIFE, -5000*m)
call AddBonusHealthToTowers(0, -.25*m)
call AddBonusHealthToTowers(3, -.25*m)
endmethod
private static method remove takes nothing returns nothing
call KillUnit(GetUnitById(table[GetHandleId(GetExpiredTimer())]))
endmethod
private static method onFinishBuild takes nothing returns boolean
local integer i = GetUnitUserData(GetTriggerUnit())
if (GetUnitTypeId(GetTriggerUnit()) == UNIT_ID) then
set constructed[i] = true
call addBonus(1)
call UnitAddAbility(GetTriggerUnit(), INSTABILITY)
set exp[i] = CreateTimer()
set table[GetHandleId(exp[i])] = i
call TimerStart(exp[i], EXPIRATION, false, function thistype.remove)
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local unit u
local integer i
if (0 == GetIndexedUnitId()) then
set u = GetTriggerUnit()
set i = GetUnitUserData(u)
else
set u = GetIndexedUnit()
set i = GetIndexedUnitId()
endif
if (constructed[i]) then
set constructed[i] = false
call addBonus(-1)
endif
if (null != exp[i]) then
call table.remove(GetHandleId(exp[i]))
call PauseTimer(exp[i])
call DestroyTimer(exp[i])
set exp[i] = null
endif
set upgrading[i] = false
set canceled[i] = false
set u = null
return false
endmethod
private static method onUpgradeStart takes nothing returns boolean
local integer i = GetUnitUserData(GetTriggerUnit())
if (constructed[i] and not canceled[i]) then
set upgrading[i] = true
set constructed[i] = false
call addBonus(-1)
call UnitRemoveAbility(GetTriggerUnit(), INSTABILITY)
call PauseTimer(exp[i])
else
set canceled[i] = false
endif
return false
endmethod
private static method onUpgradeFinish takes nothing returns boolean
local integer i = GetUnitUserData(GetTriggerUnit())
call table.remove(GetHandleId(exp[i]))
call DestroyTimer(exp[i])
set exp[i] = null
set upgrading[i] = false
return false
endmethod
private static method onUpgradeCancel takes nothing returns boolean
local integer i = GetUnitUserData(GetTriggerUnit())
if (upgrading[i]) then
call UnitAddAbility(GetTriggerUnit(), INSTABILITY)
set upgrading[i] = false
set constructed[i] = true
call addBonus(1)
call ResumeTimer(exp[i])
else
set canceled[i] = true
endif
return false
endmethod
private static method init takes nothing returns boolean
set table = Table.create()
call Plans.setUnitReq(UNIT_ID, ITEM_ID, COST)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH,Condition(function thistype.onFinishBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_START,Condition(function thistype.onUpgradeStart))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH,Condition(function thistype.onUpgradeFinish))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_CANCEL,Condition(function thistype.onUpgradeCancel))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH,Condition(function thistype.deindex))
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct AncientCorruptionBeamTower extends array
private static constant integer UNIT_ID = 'o016'
private static constant integer ITEM_ID = 'I001'
private static constant integer PLAN_COST = 1
private static boolean array constructed
private static constant real percent = -.05
private static constant real scalar = 0
private static method onFinishBuild takes nothing returns boolean
local integer i
if (GetUnitTypeId(GetTriggerUnit()) == UNIT_ID) then
set i = GetUnitUserData(GetTriggerUnit())
set constructed[i] = true
call AddBonusHealthRegenToTowersPercent(0, percent)
call AddBonusHealthRegenToTowers(0, scalar)
call AddBonusHealthRegenToTowersPercent(3, percent)
call AddBonusHealthRegenToTowers(3, scalar)
call AddBonusHealthRegenToSendsPercent(0, percent)
call AddBonusHealthRegenToSends(0, scalar)
call AddBonusHealthRegenToSendsPercent(3, percent)
call AddBonusHealthRegenToSends(3, scalar)
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local unit u
local integer i
if (0 == GetIndexedUnitId()) then
set u = GetTriggerUnit()
set i = GetUnitUserData(u)
else
set u = GetIndexedUnit()
set i = GetIndexedUnitId()
endif
if (constructed[i]) then
set constructed[i] = false
call AddBonusHealthRegenToTowersPercent(0, -percent)
call AddBonusHealthRegenToTowers(0, -scalar)
call AddBonusHealthRegenToTowersPercent(3, -percent)
call AddBonusHealthRegenToTowers(3, -scalar)
call AddBonusHealthRegenToSendsPercent(0, -percent)
call AddBonusHealthRegenToSends(0, -scalar)
call AddBonusHealthRegenToSendsPercent(3, -percent)
call AddBonusHealthRegenToSends(3, -scalar)
endif
set u = null
return false
endmethod
private static method init takes nothing returns boolean
call Plans.setUnitReq(UNIT_ID, ITEM_ID, PLAN_COST)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH,Condition(function thistype.onFinishBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH,Condition(function thistype.onFinishBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH,Condition(function thistype.deindex))
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct AncientBeamCondensor extends array
//required
private static constant real TIMEOUT = .1
private static constant boolean ANIMATED_BESTOW_AURA = false
private static constant boolean STACKS = true
private static constant integer ORDER = 852662
private static constant integer ABILITY = 'A008'
private static constant integer BUFF = 'B006'
private static constant real BONUS_DAMAGE = 1.25
private static constant real RANGE = 600
private static constant integer UNIT_ID = 'o017'
private static constant integer ITEM_ID = 'I002'
private static constant integer COST = 2
private static method getLevel takes UnitIndex sourceId returns integer
return 1
endmethod
private static method getRange takes UnitIndex source, integer level returns real
return RANGE
endmethod
//optional
private static method removeBuff takes unit whichUnit, integer level returns nothing
call UnitRemoveAbility(whichUnit, BUFF)
endmethod
private static method addBuff takes unit whichUnit, integer level returns nothing
call DummyCaster[ABILITY].castTarget(null, 1, ORDER, whichUnit)
endmethod
//private static method onLevel takes UnitIndex source, integer level returns nothing
//endmethod
private method onEndEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
call AddBonusDamageToUnitPercent(affected, -BONUS_DAMAGE)
endmethod
private method onEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
call AddBonusDamageToUnitPercent(affected, BONUS_DAMAGE)
endmethod
//private method onPeriodicEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
//endmethod
//private static method absFilter takes UnitIndex source, UnitIndex entering returns boolean
//endmethod
private method filter takes UnitIndex source, UnitIndex affected, integer level returns boolean
return IsUnitAlly(GetUnitById(source), GetOwningPlayer(GetUnitById(affected))) and IsUnitType(GetUnitById(affected), UNIT_TYPE_STRUCTURE)
endmethod
//required
implement AuraStruct
private static method onFinishBuild takes nothing returns boolean
if (GetUnitTypeId(GetTriggerUnit()) == UNIT_ID) then
call onCreateAura(GetUnitUserData(GetTriggerUnit()))
endif
return false
endmethod
private static method init takes nothing returns boolean
call Plans.setUnitReq(UNIT_ID, ITEM_ID, COST)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH,Condition(function thistype.onFinishBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH,Condition(function thistype.onFinishBuild))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct AncientBeamDemolisher extends array
private static constant integer UNIT_ID = 'o018'
private static constant integer DEP_UNIT_ID = 'o016'
private static constant integer DEP_COST = 2
private static constant integer ITEM_ID = 'I003'
private static constant integer PLAN_COST = 2
private static boolean array constructed
private static constant real MAX_HEALTH_PERCENT = -.04
private static constant integer MAX_HEALTH = -400
private static constant real MAX_DAMAGE_PERCENT = -.03
private static constant real HEALTH_REGEN_PERCENT = -.01
private static constant real HEALTH_REGEN = -100
private static constant integer OP = 25
private static integer h
private static boolean en
private static integer m
private static integer array count
private static trigger addBonust
private static method addBonus takes nothing returns boolean
local integer o = OP
if (en) then
loop
exitwhen 0 == h or 0 == o
call AddBonusHealthToUnit(GetUnitById(h - 1), MAX_HEALTH_PERCENT*m)
call AddUnitBonus(GetUnitById(h - 1), BONUS_LIFE, MAX_HEALTH*m)
call AddBonusHealthRegenToUnitPercent(h - 1, HEALTH_REGEN_PERCENT*m)
call AddBonusHealthRegenToUnit(h - 1, HEALTH_REGEN*m)
set h = Towers(h).n
set o = o - 1
endloop
else
loop
exitwhen 0 == h or 0 == o
call AddBonusHealthRegenToUnitPercent(h - 1, HEALTH_REGEN_PERCENT*m)
call AddBonusHealthRegenToUnit(h - 1, HEALTH_REGEN*m)
set h = Towers(h).n
set o = o - 1
endloop
endif
return 0 == h
endmethod
private static method apply takes nothing returns nothing
if (Game.isOver) then
call PauseTimer(GetExpiredTimer())
call DestroyTimer(GetExpiredTimer())
return
endif
set m = count[0]
if (0 != m and GetPlayerTechCount(Player(0), DEP_UNIT_ID, true)+GetPlayerTechCount(Player(1), DEP_UNIT_ID, true)+GetPlayerTechCount(Player(2), DEP_UNIT_ID, true) >= m*DEP_COST) then
set h = Towers[0]
set en = false
if (0 != m) then
loop
exitwhen TriggerEvaluate(addBonust)
endloop
set h = Towers[3]
set en = true
loop
exitwhen TriggerEvaluate(addBonust)
endloop
endif
endif
set m = count[1]
if (0 != m and GetPlayerTechCount(Player(3), DEP_UNIT_ID, true)+GetPlayerTechCount(Player(4), DEP_UNIT_ID, true)+GetPlayerTechCount(Player(5), DEP_UNIT_ID, true) >= m*DEP_COST) then
set h = Towers[3]
set en = false
if (0 != m) then
loop
exitwhen TriggerEvaluate(addBonust)
endloop
set h = Towers[0]
set en = true
loop
exitwhen TriggerEvaluate(addBonust)
endloop
endif
endif
endmethod
private static method onFinishBuild takes nothing returns boolean
local integer pid = GetPlayerId(GetTriggerPlayer())/3
if (GetUnitTypeId(GetTriggerUnit()) == UNIT_ID) then
set constructed[GetUnitUserData(GetTriggerUnit())] = true
set count[pid] = count[pid] + 1
endif
return false
endmethod
private static method deindex takes nothing returns boolean
local unit u
local integer i
local integer pid
if (0 == GetIndexedUnitId()) then
set u = GetTriggerUnit()
set i = GetUnitUserData(u)
set pid = GetPlayerId(GetTriggerPlayer())/3
else
set u = GetIndexedUnit()
set i = GetIndexedUnitId()
set pid = GetPlayerId(GetOwningPlayer(u))/3
endif
if (constructed[i]) then
set constructed[i] = false
set count[pid] = count[pid] - 1
set m = -1
set h = Towers[0]
set en = 0 != GetPlayerId(GetTriggerPlayer())/3
loop
exitwhen TriggerEvaluate(addBonust)
endloop
set h = Towers[3]
set en = not en
loop
exitwhen TriggerEvaluate(addBonust)
endloop
endif
set u = null
return false
endmethod
private static method start takes nothing returns boolean
call TimerStart(CreateTimer(), ROUND_TIME, true, function thistype.apply)
return false
endmethod
private static method init takes nothing returns boolean
call Plans.setUnitReq(UNIT_ID, ITEM_ID, PLAN_COST)
set addBonust = CreateTrigger()
call TriggerAddCondition(addBonust, Condition(function thistype.addBonus))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_UPGRADE_FINISH, Condition(function thistype.onFinishBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_FINISH, Condition(function thistype.onFinishBuild))
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.deindex))
call RegisterUnitIndexEvent(Condition(function thistype.deindex), UnitIndexer.DEINDEX)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
call Game.onStart.register(Condition(function thistype.start))
call Game.onStartSolo.register(Condition(function thistype.start))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct BeamTech extends array
private static constant integer TECH = 'e005'
private static constant integer TECH_ADV = 'e009'
private static constant integer BUILDER = 'e008'
private static constant integer BUILDER_ADV = 'e006'
private static constant integer PLANS_BASIC = 'R00C'
private static constant integer ITEM_BASIC = 'I000'
private static constant real TIME_BASIC = 2
private static constant integer PLANS_CORRUPTION = 'R00D'
private static constant integer ITEM_CORRUPTION = 'I001'
private static constant real TIME_CORRUPTION = 4
private static constant integer PLANS_CONDENSER = 'R00E'
private static constant integer ITEM_CONDENSER = 'I002'
private static constant real TIME_CONDENSER = 8
private static constant integer PLANS_DEMOLISHER = 'R00F'
private static constant integer ITEM_DEMOLISHER = 'I003'
private static constant real TIME_DEMOLISHER = 15
private static method init takes nothing returns boolean
call Plans.gen(TECH_ADV, BUILDER_ADV)
call Plans.add(TECH_ADV, PLANS_BASIC, ITEM_BASIC, TIME_BASIC)
call Plans.add(TECH_ADV, PLANS_CORRUPTION, ITEM_CORRUPTION, TIME_CORRUPTION)
call Plans.add(TECH_ADV, PLANS_CONDENSER, ITEM_CONDENSER, TIME_CONDENSER)
call Plans.add(TECH_ADV, PLANS_DEMOLISHER, ITEM_DEMOLISHER, TIME_DEMOLISHER)
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct ReparationBeamTech extends array
private static constant integer TECH = 'R00A'
private static constant real BONUS_HEALTH = .01
private static method research takes nothing returns boolean
if (GetResearched() == TECH) then
call AddBonusHealthToTowers(GetPlayerId(GetTriggerPlayer()), BONUS_HEALTH)
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_RESEARCH_FINISH, Condition(function thistype.research))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct BeamShieldTech extends array
private static constant integer TECH = 'R009'
private static constant integer BONUS_HEALTH = 500
private static method research takes nothing returns boolean
if (GetResearched() == TECH) then
call AddBonusToTowers(GetPlayerId(GetTriggerPlayer()), BONUS_LIFE, BONUS_HEALTH)
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_RESEARCH_FINISH, Condition(function thistype.research))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=74
//TESH.alwaysfold=0
library SummoningTrail uses Summon, Table, Game
struct SummoningTrail extends array
private static Table timerTable
private timer m
private thistype handler
private thistype leader
private integer countp
private integer unitTypeIdp
private real lastX
private real lastY
private real lastFacing
private group summonGroupp
private integer limitp
private boolean destroyed
private static integer ic = 0
private static integer array r
private static thistype toClean = 0
private static trigger cleaning
readonly static Event onLimit
readonly static Summon eventSummon = 0
method operator count takes nothing returns integer
return handler.countp
endmethod
method operator count= takes integer v returns nothing
set handler.countp = v
endmethod
method operator unitTypeId takes nothing returns integer
return handler.unitTypeIdp
endmethod
method operator unitTypeId= takes integer v returns nothing
set handler.unitTypeIdp = v
endmethod
method operator limit takes nothing returns integer
return handler.limitp
endmethod
method operator limit= takes integer v returns nothing
set handler.limitp = v
endmethod
method operator summonGroup takes nothing returns group
return handler.summonGroupp
endmethod
method operator exists takes nothing returns boolean
return 0 != handler
endmethod
private static method doClean takes nothing returns boolean
local thistype this = toClean
local unit u
loop
set u = FirstOfGroup(summonGroupp)
exitwhen null == u
call GroupRemoveUnit(summonGroupp, u)
call SetUnitMoveSpeed(u, 522)
endloop
call DestroyGroup(handler.summonGroupp)
set handler.summonGroupp = null
return false
endmethod
method clean takes nothing returns nothing
if (not destroyed) then
set destroyed = true
set toClean = this
call TriggerEvaluate(cleaning)
call timerTable.remove(GetHandleId(m))
call PauseTimer(m)
call DestroyTimer(m)
set m = null
endif
endmethod
method destroy takes nothing returns nothing
if (exists) then
call handler.clean()
set r[handler] = r[0]
set r[0] = handler
set handler = 0
endif
endmethod
private static method expire takes nothing returns nothing
local unit u
local thistype this = timerTable[GetHandleId(GetExpiredTimer())]
local integer prevSummon
if (0 > limitp or countp < limitp) then
set countp = countp + 1
set u = SummonUnit(Summon(leader).owner, unitTypeIdp, lastX, lastY, lastFacing, UnitPath(leader).checkpoint)
if (TimerGetTimeout(m) < 1) then
call SetUnitMoveSpeed(u, 0.8237*GetUnitMoveSpeed(GetUnitById(leader))*TimerGetTimeout(m))
else
call SetUnitMoveSpeed(u, 0.8237*GetUnitMoveSpeed(GetUnitById(leader)))
endif
call GroupAddUnit(summonGroupp, u)
set lastX = GetUnitX(GetUnitById(leader))
set lastY = GetUnitY(GetUnitById(leader))
set lastFacing = GetUnitFacing(GetUnitById(leader))
endif
if (0 < limitp and countp >= limitp) then
set prevSummon = eventSummon
set eventSummon = leader
call onLimit.fire()
set eventSummon = prevSummon
call clean()
endif
set u = null
endmethod
static method create takes unit leader, real period, integer unitTypeIdToTrail, integer limitp returns thistype
local thistype this = r[0]
local thistype leaderId = GetUnitUserData(leader)
if (0 == this) then
set this = ic + 1
set ic = this
else
set r[0] = r[this]
set this.destroyed = false
endif
set this.leader = leaderId
set leaderId.handler = this
set this.unitTypeIdp = unitTypeIdToTrail
set this.limitp = limitp
set this.summonGroupp = CreateGroup()
set this.lastX = GetUnitX(leader)
set this.lastY = GetUnitY(leader)
set this.lastFacing = GetUnitFacing(leader)
set this.countp = 0
set m = CreateTimer()
set timerTable[GetHandleId(m)] = this
call TimerStart(m, period, true, function thistype.expire)
return leaderId
endmethod
private static method onDeindex takes nothing returns boolean
call thistype(GetIndexedUnitId()).destroy()
return false
endmethod
private static method onInit takes nothing returns nothing
set cleaning = CreateTrigger()
call TriggerAddCondition(cleaning, Condition(function thistype.doClean))
set timerTable = Table.create()
call RegisterUnitIndexEvent(Condition(function thistype.onDeindex), UnitIndexer.DEINDEX)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct Immolation extends array
//required
private static constant real TIMEOUT = .1
private static constant boolean ANIMATED_BESTOW_AURA = false
private static constant boolean STACKS = true
private static constant integer ABILITY = 'A007'
private static real array damage
private static integer array buff
private static real array range
private static constant integer ORDER = 852662
private static Table table
private static constant integer LAVA_DEMON = 'nC40'
private static constant integer BLOOD_FIEND = 'h015'
private static method getLevel takes UnitIndex sourceId returns integer
return table[GetUnitTypeId(GetUnitById(sourceId))]
endmethod
private static method getRange takes UnitIndex source, integer level returns real
return range[level]
endmethod
//optional
private static method removeBuff takes unit whichUnit, integer level returns nothing
call UnitRemoveAbility(whichUnit, buff[level]) //for level?
endmethod
private static method addBuff takes unit whichUnit, integer level returns nothing
call DummyCaster[ABILITY].castTarget(null, level, ORDER, whichUnit)
endmethod
//private static method onLevel takes UnitIndex source, integer level returns nothing
//endmethod
//private method onEndEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
//endmethod
//private method onEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
//endmethod
private method onPeriodicEffect takes UnitIndex source, UnitIndex affected, integer level returns nothing
call SetWidgetLife(GetUnitById(affected), GetWidgetLife(GetUnitById(affected))-damage[level])
endmethod
//private static method absFilter takes UnitIndex source, UnitIndex entering returns boolean
//endmethod
private method filter takes UnitIndex source, UnitIndex affected, integer level returns boolean
return not IsUnitAlly(GetUnitById(source), GetOwningPlayer(GetUnitById(affected))) and IsUnitType(GetUnitById(affected), UNIT_TYPE_STRUCTURE) and 0 ==GetUnitAbilityLevel(GetUnitById(affected), 'Avul')
endmethod
//required
implement AuraStruct
private static method index takes nothing returns boolean
if (table.has(GetUnitTypeId(GetIndexedUnit()))) then
call onCreateAura(GetIndexedUnitId())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
set table = Table.create()
set damage[1] = 5*TIMEOUT
set damage[2] = 450*TIMEOUT
set buff[1] = 'B003'
set buff[2] = 'B004'
set range[1] = 128
set range[2] = 128
set table[LAVA_DEMON] = 1
set table[BLOOD_FIEND] = 2
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct GolemRegeneration extends array
private static constant integer ABILITY = 'A00G'
private static constant real RATE = .01
private static method index takes nothing returns boolean
if (0 != GetUnitAbilityLevel(GetIndexedUnit(), ABILITY)) then
call AddBonusHealthRegenToUnitPercent(GetIndexedUnitId(), RATE)
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterUnitIndexEvent(Condition(function thistype.index), UnitIndexer.INDEX)
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct DifficultySummons extends array
private static method init takes nothing returns boolean
if (Game.difficulty == DIFFICULTY_BEGINNER) then
call AddBonusHealthToSends(0, -.05)
call AddBonusHealthToSends(3, -.05)
elseif (Game.difficulty == DIFFICULTY_INTERMEDIATE) then
elseif (Game.difficulty == DIFFICULTY_MASTER) then
else
call AddBonusHealthToSends(0, .25)
call AddBonusHealthToSends(3, .25)
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct DarkSummoner extends array
private static constant real SUMMON_INTERVAL = 1
private static constant integer DARK_SUMMONER = 'nC30'
private static constant integer SUMMON = 'h018'
private static constant integer SUMMON_DEATH_RATIO = 4
private static constant integer SUMMON_DEATH = 'u00C'
private static method onIndex takes nothing returns boolean
if (GetUnitTypeId(GetIndexedUnit()) == DARK_SUMMONER) then
call SummoningTrail.create(GetIndexedUnit(), SUMMON_INTERVAL, SUMMON, -1)
endif
return false
endmethod
private static method onDeath takes nothing returns boolean
local unit summoner = GetTriggerUnit()
local SummoningTrail this = GetUnitUserData(summoner)
local SummonHandler handler
if (this.exists and GetUnitTypeId(summoner) == DARK_SUMMONER) then
if (0 < this.count/SUMMON_DEATH_RATIO) then
set handler = SummonHandler.create(false, GetUnitX(summoner), GetUnitY(summoner), GetUnitFacing(summoner), 0, 0, 0, UnitPath(this).checkpoint, 0)
call handler.summon(SUMMON_DEATH, GetPlayerId(Summon(this).owner), this.count/SUMMON_DEATH_RATIO)
endif
call this.destroy()
endif
set summoner = null
return false
endmethod
private static method init takes nothing returns boolean
call RegisterUnitIndexEvent(Condition(function thistype.onIndex), UnitIndexer.INDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.onDeath))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct LichLord extends array
private static constant real SUMMON_INTERVAL = 2
private static constant integer LICH_LORD = 'h00X'
private static constant integer SUMMON = 'u00I'
private static constant integer SUMMON_DEATH_RATIO = 4
private static constant integer SUMMON_DEATH = 'u00J'
private static method onIndex takes nothing returns boolean
if (GetUnitTypeId(GetIndexedUnit()) == LICH_LORD) then
call SummoningTrail.create(GetIndexedUnit(), SUMMON_INTERVAL, SUMMON, -1)
endif
return false
endmethod
private static method onDeath takes nothing returns boolean
local unit summoner = GetTriggerUnit()
local SummoningTrail this = GetUnitUserData(summoner)
local SummonHandler handler
if (this.exists and GetUnitTypeId(summoner) == LICH_LORD) then
if (0 < this.count/SUMMON_DEATH_RATIO) then
set handler = SummonHandler.create(false, GetUnitX(summoner), GetUnitY(summoner), GetUnitFacing(summoner), 0, 0, 0, UnitPath(this).checkpoint, 0)
call handler.summon(SUMMON_DEATH, GetPlayerId(Summon(this).owner), this.count/SUMMON_DEATH_RATIO)
endif
call this.destroy()
endif
set summoner = null
return false
endmethod
private static method init takes nothing returns boolean
call RegisterUnitIndexEvent(Condition(function thistype.onIndex), UnitIndexer.INDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.onDeath))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct Zergling extends array
private static constant real SUMMON_INTERVAL = .5
private static constant integer ZERGLING = 'eC38'
private static constant integer SUMMON = 'e004'
private static method onIndex takes nothing returns boolean
if (GetUnitTypeId(GetIndexedUnit()) == ZERGLING) then
call SummoningTrail.create(GetIndexedUnit(), SUMMON_INTERVAL, SUMMON, -1)
endif
return false
endmethod
private static method onDeath takes nothing returns boolean
local SummoningTrail this = GetUnitUserData(GetTriggerUnit())
if (this.exists and GetUnitTypeId(GetTriggerUnit()) == ZERGLING) then
call this.destroy()
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterUnitIndexEvent(Condition(function thistype.onIndex), UnitIndexer.INDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.onDeath))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=6
//TESH.alwaysfold=0
struct NetherMage extends array
private static constant real TIMEOUT = 5
private static constant real HEALTH_PERCENT = .005
private static constant integer NETHER_MAGE = 'nC49'
private integer pl
private thistype tm
implement CTQ
implement CTQExpire
call AddBonusHealthToSends(pl, HEALTH_PERCENT)
implement CTQNull
implement CTQEnd
private static method onIndex takes nothing returns boolean
local thistype t
if (GetUnitTypeId(GetIndexedUnit()) == NETHER_MAGE) then
set t = create()
set t.pl = GetPlayerId(GetOwningPlayer(GetIndexedUnit()))
set thistype(GetIndexedUnitId()).tm = t
endif
return false
endmethod
private static method onDeath takes nothing returns boolean
local thistype this
if (0 == GetIndexedUnitId()) then
set this = GetUnitUserData(GetTriggerUnit())
else
set this = GetIndexedUnitId()
endif
if (0 != tm) then
call tm.destroy()
set tm = 0
endif
return false
endmethod
private static method init takes nothing returns boolean
call RegisterUnitIndexEvent(Condition(function thistype.onIndex), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.onDeath), UnitIndexer.DEINDEX)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, Condition(function thistype.onDeath))
return false
endmethod
private static method onInit takes nothing returns nothing
call Game.onInitialize.register(Condition(function thistype.init))
call Game.onInitializeSolo.register(Condition(function thistype.init))
endmethod
endstruct
//TESH.scrollpos=32
//TESH.alwaysfold=0
library Chatroom uses PlayerColorUtils
globals
private constant string PRIVATE_CHAT = "-"
private constant string PRIVATE_CHAT_ROOM = "Private"
private constant real CHAT_TIME = 7
string array names
endglobals
struct PlayerChat extends array
private static boolean array listeningP
private static integer array talkingP
private static boolean array ignoredP
method ignore takes integer pid, boolean b returns nothing
set ignoredP[this*12+pid] = b
endmethod
method isIgnored takes integer pid returns boolean
return ignoredP[this*12+pid]
endmethod
method listen takes Chatroom room, boolean b returns nothing
set listeningP[room*12+this] = b
endmethod
method isListening takes Chatroom room returns boolean
return listeningP[room*12+this]
endmethod
method operator room= takes Chatroom room returns nothing
set talkingP[this] = room
endmethod
method operator room takes nothing returns Chatroom
return talkingP[this]
endmethod
endstruct
struct Chatroom extends array
string name
private static integer cc = 0
static method create takes string n returns thistype
set cc = cc + 1
set thistype(cc).name = n
return cc
endmethod
private static method chat takes nothing returns boolean
local string text = GetEventPlayerChatString()
local player talker = GetTriggerPlayer()
local integer talkerId = GetPlayerId(talker)
local player listener = GetLocalPlayer()
local integer listenerId = GetPlayerId(listener)
local Chatroom room = PlayerChat[talkerId].room
local boolean isPrivate = PRIVATE_CHAT == SubString(text,0,StringLength(PRIVATE_CHAT))
local boolean listening = listenerId == talkerId or (not isPrivate and PlayerChat[listenerId].isListening(room) and not PlayerChat[listenerId].isIgnored(talkerId))
if (isPrivate) then
set room = 0
endif
if (listening) then
call DisplayTimedTextToPlayer(listener,0,0,CHAT_TIME,"["+room.name+"] "+GetPlayerColorStringById(talkerId)+names[talkerId]+"|r: "+text)
endif
set talker = null
set listener = null
return false
endmethod
private static method onInit takes nothing returns nothing
local integer i
local trigger t
set t = CreateTrigger()
call TriggerAddCondition(t, Condition(function thistype.chat))
set i = 11
loop
set names[i] = GetPlayerName(Player(i))
//call SetPlayerName(Player(i), " ")
call TriggerRegisterPlayerChatEvent(t, Player(i), "", false)
exitwhen 0 == i
set i = i - 1
endloop
set t = null
set Chatroom(0).name = PRIVATE_CHAT_ROOM
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct ChatroomAll extends array
private static Chatroom room
private static method all takes nothing returns boolean
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Now Talking to All Players")
set PlayerChat[GetPlayerId(GetTriggerPlayer())].room = room
return false
endmethod
private static method onInit takes nothing returns nothing
local Command all
local integer i
set room = Chatroom.create("All")
set all = Command["-all"]
set all.description = "Talk to all people in game."
call all.register(function thistype.all)
set i = 11
loop
set all[i].enabled = false
exitwhen 6 == i
set i = i - 1
endloop
set i = 11
loop
call PlayerChat[i].listen(room,true)
exitwhen 0 == i
set i = i - 1
endloop
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct ChatroomAllies extends array
private static Chatroom array room
private static method allies takes nothing returns boolean
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Now Talking to Allies")
set PlayerChat[GetPlayerId(GetTriggerPlayer())].room = room[GetPlayerId(GetTriggerPlayer())/3]
return false
endmethod
private static method onInit takes nothing returns nothing
local Command allies
local integer i
set room[0] = Chatroom.create("Allies")
set room[1] = Chatroom.create("Allies")
set allies = Command["-allies"]
set allies.description = "Talk to only your allies."
call allies.register(function thistype.allies)
set i = 11
loop
set allies[i].enabled = false
exitwhen 6 == i
set i = i - 1
endloop
set i = 5
loop
call PlayerChat[i].listen(room[i/3],true)
set PlayerChat[i].room = room[i/3]
exitwhen 0 == i
set i = i - 1
endloop
set i = 11
loop
call PlayerChat[i].listen(room[0],true)
call PlayerChat[i].listen(room[1],true)
exitwhen 6 == i
set i = i - 1
endloop
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct ChatroomObservers extends array
private static Chatroom room
private static method onInit takes nothing returns nothing
local integer i
set room = Chatroom.create("Observers")
set i = 11
loop
call PlayerChat[i].listen(room,true)
set PlayerChat[i].room = room
exitwhen 6 == i
set i = i - 1
endloop
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct ChatroomAdmin extends array
private static Table isAdmin
private static Chatroom room
private static method admin takes nothing returns boolean
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Now Talking via Admin")
set PlayerChat[GetPlayerId(GetTriggerPlayer())].room = room
return false
endmethod
private static method onInit takes nothing returns nothing
local Command admin
local integer i
set isAdmin = Table.create()
set isAdmin.string[StringHash("TWM-Nestharus")] = "TWM-Nestharus"
set room = Chatroom.create("Admin")
set admin = Command["-admin"]
set admin.description = "Talk via admin chatroom."
call admin.register(function thistype.admin)
set i = 11
loop
set admin[i].enabled = isAdmin.string[StringHash(names[i])] == names[i]
exitwhen 0 == i
set i = i - 1
endloop
set i = 11
loop
call PlayerChat[i].listen(room,true)
exitwhen 0 == i
set i = i - 1
endloop
endmethod
endstruct
//TESH.scrollpos=79
//TESH.alwaysfold=0
library Command uses Table, RemoveString
globals
private Table enabledd
private trigger array commandt
private string array commandCheck
private string array descriptionc
private Table array commandPlayer
private Table commandPointer
private integer cc = 0
private trigger evalT
private boolean array displayd
private boolean array enableda
endglobals
struct CommandPlayer extends array
method operator enabled takes nothing returns boolean
return enabledd.boolean[this]
endmethod
method operator enabled= takes boolean b returns nothing
set enabledd.boolean[this] = b
endmethod
method operator commands takes nothing returns string
local string s = ""
local integer i = cc
loop
if (displayd[i] and enabledd.boolean[i*12+this] and enableda[i]) then
if ("" == s) then
set s = SubString(commandCheck[i],1,StringLength(commandCheck[i]))
else
set s = s + ", " + SubString(commandCheck[i],1,StringLength(commandCheck[i]))
endif
endif
set i = i - 1
exitwhen 0 == i
endloop
return s
endmethod
endstruct
struct Command extends array
method operator enabled takes nothing returns boolean
return enableda[this]
endmethod
method operator enabled= takes boolean b returns nothing
set enableda[this] = b
endmethod
static method getCommand takes string command returns integer
local integer i = StringHash(command)
local thistype id
local string s
loop
set id = commandPointer[i]
set s = commandCheck[id]
exitwhen null == s or s == command
set i = i + 1
endloop
if (null == s) then
return 0
endif
return id
endmethod
private static method eval takes nothing returns boolean
local integer p = GetPlayerId(GetTriggerPlayer())
local string entered = GetEventPlayerChatString()
local thistype eventCommand = getCommand(GetEventPlayerChatStringMatched())
local integer i = StringLength(commandCheck[eventCommand])
local integer max = StringLength(GetEventPlayerChatString())
local string s = ""
local string check = commandCheck[eventCommand]
loop
exitwhen i == max
set s = SubString(entered,i,i+1)
set i = i + 1
exitwhen s == " "
endloop
if (s == " ") then
set check = check + " "
endif
if (SubString(entered,0,i) == check and enableda[eventCommand] and enabledd.boolean[eventCommand*12+p]) then
call TriggerEvaluate(commandt[eventCommand])
endif
set eventCommand = 0
return false
endmethod
static method operator [] takes string command returns Command
local integer i = StringHash(command)
local string s
local thistype id
local integer pi
local trigger t
loop
set id = commandPointer[i]
set s = commandCheck[id]
exitwhen null == s or s == command
set i = i + 1
endloop
if (null == s) then
set id = cc + 1
set cc = id
set displayd[id] = true
set enableda[id] = true
set commandCheck[id] = command
set commandt[id] = CreateTrigger()
set commandPointer[i] = id
set pi = 11
loop
call TriggerRegisterPlayerChatEvent(evalT, Player(pi), command, false)
set enabledd.boolean[id*12+pi] = true
exitwhen 0 == pi
set pi = pi - 1
endloop
set t = null
endif
return id
endmethod
method operator func takes nothing returns string
return commandCheck[this]
endmethod
method register takes code func returns nothing
call TriggerAddCondition(commandt[this], Filter(func))
endmethod
method operator [] takes integer pid returns CommandPlayer
return this*12+pid
endmethod
method operator description takes nothing returns string
return descriptionc[this]
endmethod
method operator description= takes string s returns nothing
set descriptionc[this] = s
endmethod
method operator display takes nothing returns boolean
return displayd[this]
endmethod
method operator display= takes boolean b returns nothing
set displayd[this] = b
endmethod
private static method onInit takes nothing returns nothing
local integer i
set enabledd = Table.create()
set commandPointer = Table.create()
set i = 11
loop
set commandPlayer[i] = Table.create()
exitwhen 0 == i
set i = i - 1
endloop
set evalT = CreateTrigger()
call TriggerAddCondition(evalT, Condition(function thistype.eval))
endmethod
endstruct
endlibrary
//TESH.scrollpos=9
//TESH.alwaysfold=0
struct CommandHelp extends array
private static method help takes nothing returns boolean
local string s = RemoveString(GetEventPlayerChatString(),"-help",1,0)
local Command command
local boolean exists
local integer i = 0
local integer max = StringLength(s)
loop
exitwhen 0 == max or SubString(s,0,1) != " "
set s = SubString(s,1,max)
set max = max - 1
endloop
if (0 == max) then
set s = CommandPlayer[GetPlayerId(GetTriggerPlayer())].commands
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"Type [-help command] for details on how to use that command")
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10," ")
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"Commands-")
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"--------------------------------------------------------------")
if ("" == s) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10," No Commands Available")
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10," "+s)
endif
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"--------------------------------------------------------------")
else
set command = Command.getCommand("-"+s)
set exists = 0 != command and command[GetPlayerId(GetTriggerPlayer())].enabled
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,s)
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"--------------------------------------------------------------")
if (exists) then
if ("" == command.description or null == command.description) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10," No Description Available")
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10," "+command.description)
endif
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10," Command does not exist")
endif
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"--------------------------------------------------------------")
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local Command help
set help = Command["-help"]
call help.register(function thistype.help)
set help.display = false
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct CommandClear extends array
private static method clear takes nothing returns boolean
if (GetLocalPlayer() == GetTriggerPlayer()) then
call ClearTextMessages()
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local Command clear
set clear = Command["-clear"]
set clear.description = "Clears all text."
call clear.register(function thistype.clear)
endmethod
endstruct
//TESH.scrollpos=11
//TESH.alwaysfold=0
struct CommandIgnore extends array
private static method ignore takes nothing returns boolean
local string color = RemoveString(GetEventPlayerChatString(), "-ignore ", 1, 0)
local boolean ignore = -1 != FindString(color, "true", 0)
local boolean listen = -1 != FindString(color, "false", 0)
local integer playerId
if (ignore or listen) then
if (ignore) then
set color = SubString(color, 0, StringLength(color)-5)
else
set color = SubString(color, 0, StringLength(color)-6)
endif
endif
set playerId = GetPlayerIdByColor(color)
set ignore = not listen
if (-1 != playerId and GetPlayerSlotState(Player(playerId)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(playerId)) == MAP_CONTROL_USER and playerId != GetPlayerId(GetTriggerPlayer())) then
if (ignore) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"Squelched "+names[playerId])
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"Unsquelched "+names[playerId])
endif
elseif (GetPlayerId(GetTriggerPlayer()) == playerId) then
if (ignore) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"You can't squelch yourself")
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"You can't unsquelch yourself")
endif
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"|"+color+"| is not a player")
endif
call PlayerChat[GetPlayerId(GetTriggerPlayer())].ignore(playerId,ignore)
return false
endmethod
private static method onInit takes nothing returns nothing
local Command ignore
set ignore = Command["-ignore"]
set ignore.description = "Ignores a player\n [-ignore color true/false]"
call ignore.register(function thistype.ignore)
endmethod
endstruct
//TESH.scrollpos=1
//TESH.alwaysfold=0
struct CommandRandom extends array
private static Command randomc
private static method random takes nothing returns boolean
local integer i
local integer raceCount
local integer id
set id = GetPlayerId(GetTriggerPlayer())
set raceCount = PlayerBuilder[id].raceCount
if (1 < raceCount) then
call UpdateSeed()
set i = Race[GetRandomInt(0, Race.count - 1)]
call PlayerBuilder[id].limitToRace(i)
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"Randomed "+GetObjectName(i))
elseif (0 == raceCount) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"You have no races remaining to random")
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,10,"You currently only have 1 race available to you")
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local integer i
set randomc = Command["-random"]
set randomc.description = "Removes all but one random race"
call randomc.register(function thistype.random)
set i = 11
loop
set randomc[i].enabled = false
exitwhen 6 == i
set i = i - 1
endloop
endmethod
endstruct