Name | Type | is_array | initial_value |
chance | real | No | |
effect | string | No | |
interval | real | No | |
terrain | terraintype | No | |
x | real | No | |
y | real | No |
//TESH.scrollpos=250
//TESH.alwaysfold=0
library TerrainInfection/* v2.1 By IcemanBo
TerrainInfection will start at given coordinates and infect nearby tiles. (change terrain type)
TerrainInfection also allows to undo the infection.
Furthermore it provides events for(un-)infection.
*/ requires /*
*/ TileDefinition /* hiveworkshop.com/forums/submissions-414/snippet-tiledefinition-259347/
*/ WorldBounds /* github.com/nestharus/JASS/blob/master/jass/Systems/WorldBounds/script.j
*/ List /* as Nestharus removed it check out the demo
*/ Table /* hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
API
¯¯¯¯¯¯
function CreateTerrainInfection takes integer t, real x, real y, real chance, real interval returns TerrainInfection
t = infected terrain type
x = x of start
y = y of start
chance = chance to infect nearby tiles between 0 and 1
interval = interval to potentialy infect nearby tiles
you also can set/read public members:
real maxDistance = max distance to RootInfection
real chance = chance on infection between 0 and 1
real maxX = maxX of Infection
real minX = minX of Infection
real maxY = maxY of Infection
real minY = minY of Infection
region bound = bound region for infection
boolean diagonal = should Infection act diagonal
boolean enabled = is Infection currently enabled
you can read readonly members:
real x = x of infectionStart
real y = y of infectionStart
integer size = amount of infected tiles
integer terrainTypeInfected = terrain type of infection
methods (TerrainInfection)
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
destroy() returns nothing
undoInfection() returns nothing
Will un-infect all tiles.
undoInfection_last() returns boolean
Will un-infect the last tile.
Returns false if there is no tile anymore.
static methods (TerrainInfection)
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
enableResistor(integer Infector, integer Resistor, boolean b returns nothing
Takes terrain types as paramater.
Resistor will be immune against Infector. (true/false)
enableInfections(boolean b) returns nothing
Enables/disables all current running Infections.
isTileInfected takes real x, real y returns boolean
Events
¯¯¯¯¯¯¯¯
You can use TriggerRegisterVariableEvent to catch following events:
s__TerrainInfection_infection_state == 1 -> onInfection
s__TerrainInfection_infection_state == 2 -> Infection has completly finished.
s__TerrainInfection_infection_state == 3 -> onUnInfection
s__TerrainInfection_infection_state == 4 -> Infection has been completly removed.
onEvents you can use TerrainInfection_currrent as current instance.
onEvents (1 and 3) you can use TerrainInfection_currentTileId to refer to operated tile.
Look into "Event Example" for more info.
Credits:
¯¯¯¯¯¯¯¯¯
List (Nestharus)
Table (Bribe)
WorldBounds (Nestharus)
*/
globals
private hashtable hash = InitHashtable()
private timer tim = CreateTimer()
private constant real TIMEOUT = .031250000
private constant real TILE_SIDE_LENGTH = 128.
private constant real TILE_DIAGONAL_LENGTH = TILE_SIDE_LENGTH*SquareRoot(2.)
endglobals
private struct InfectionData extends array
implement List
integer tileId
integer originTerrainType
endstruct
struct TerrainInfection
private InfectionData list
private real timeCountMax // Interval of Infecion.
private real timeCountCurrent // Time left until next Infection.
readonly real x // x of RootInfection
readonly real y // y of RootInfection
readonly integer size // size == amount of infected tiles
readonly integer terrainTypeInfected // new (infected) terrain type.
// public members
real maxDistance = -1
real chance = 1
real maxX = WorldBounds.maxX
real minX = WorldBounds.minX
real maxY = WorldBounds.maxY
real minY = WorldBounds.minY
region bound = null
boolean diagonal = true
boolean enabled = true
// for list
private thistype prev
private thistype next
private static thistype first = 0
// for events
static real infection_state = 0
static thistype current = 0
static integer currentTileId = 0
// to save if a tile is infected
private static key k
private static Table table = k
/*
* These methods check if a point matches all conditions,
* so it can be infected successfully.
*/
private method coordinateCheck takes real x, real y returns boolean
return (bound == null or IsPointInRegion(bound, x, y)) and(x <= maxX and x >= minX and y <= maxY and y >= minY)
endmethod
private method distanceCheck takes real x, real y returns boolean
return (maxDistance < 0 or SquareRoot((x-this.x)*(x-this.x) + (y-this.y)*(y-this.y)) <= maxDistance)
endmethod
private method terrainCheck takes real x, real y returns boolean
return (GetTerrainType(x, y) != terrainTypeInfected) and not(LoadBoolean(hash, terrainTypeInfected, GetTerrainType(x, y)))
endmethod
private method isPointValid takes real x, real y returns boolean
return coordinateCheck(x,y) and distanceCheck(x,y) and terrainCheck(x,y)
endmethod
/*
* This method will make a circular check around given
* coordinates to find a terrain tile which is not
* infected yet. It will return boolean, if there exists
* a (new/old) tile around for potential infection.
*/
private method checkNearbyTiles takes real x, real y returns boolean
local real angle = 0
local real angleChange
local real xNew
local real yNew
local real offset
local boolean diagonalCheck = true
local InfectionData element
if (this.diagonal) then
set angleChange = bj_PI/4
else
set angleChange = bj_PI/2
endif
loop
if (this.diagonal) then
// For 45/135/225/315 degrees the centre
// of the tile has an other distance, so
// we check if it's a digonal.
set diagonalCheck = not(diagonalCheck)
if (diagonalCheck) then
set offset = TILE_DIAGONAL_LENGTH
else
set offset = TILE_SIDE_LENGTH
endif
else
set offset = TILE_SIDE_LENGTH
endif
set xNew = x + offset * Cos(angle)
set yNew = y + offset * Sin(angle)
if (this.isPointValid(xNew, yNew)) then
if (GetRandomReal(0, 1) <= this.chance) then
set element = this.list.enqueue()
set element.tileId = GetTileId(xNew,yNew)
set element.originTerrainType = GetTerrainType(xNew, yNew)
call SetTerrainType(xNew, yNew, this.terrainTypeInfected, -1, 1, 1)
set thistype.table.boolean[element.tileId] = true
set this.size = (this.size + 1)
// Fire onInfection event.
set thistype.current = this
set thistype.currentTileId = element.tileId
set thistype.infection_state = 1
set thistype.infection_state = 0
set thistype.current = 0
set thistype.currentTileId = 0
endif
return true
endif
set angle = angle + angleChange
exitwhen (angle >= 2*bj_PI) // Full circular check was done.
endloop
return false
endmethod
// callback is called periodicly
private static method callback takes nothing returns nothing
local thistype this = thistype.first
local InfectionData element
local integer i
local boolean b // Will check if infection is completly finished.
// loop through all instances (root infections)
loop
exitwhen (this == 0)
if (this.enabled) then
set this.timeCountCurrent = this.timeCountCurrent - TIMEOUT
if (this.timeCountCurrent <= 0) then
set this.timeCountCurrent = this.timeCountMax
set element = this.list.first
set i = this.size
set b = false
// We use pre-loop defined integer to define
// the cancel condition, because the list itself
// is dynamic, not static. (size can be changed during loop)
// loop through all infected tiles of an instance
loop
exitwhen (i < 1)
if this.checkNearbyTiles(GetTileCenterXById(element.tileId), GetTileCenterYById(element.tileId)) then
set b = true
endif
set element = element.next
set i = (i - 1)
endloop
// if there is no potential tile left for infection
if not(b) then
// Fire onFinish event.
set thistype.current = this
set thistype.infection_state = 2
set thistype.infection_state = 0
set thistype.current = 0
endif
endif
endif
set this = this.next
endloop
endmethod
static method create takes integer t, real x, real y, real chance, real interval returns thistype
local thistype this = thistype.allocate()
local InfectionData element
set this.list = InfectionData.create()
set element = this.list.enqueue()
set element.tileId = GetTileId(x,y)
set element.originTerrainType = GetTerrainType(x, y)
set this.x = x
set this.y = y
set this.terrainTypeInfected = t
set this.chance = chance
set this. size = 1
if (interval < TIMEOUT) then
set this.timeCountMax = TIMEOUT
else
set this.timeCountMax = interval
endif
set this.timeCountCurrent = this.timeCountMax
call SetTerrainType(x, y, t, -1, 1, 1)
set thistype.table.boolean[element.tileId] = true
// Fire onInfection event.
set thistype.current = this
set thistype.currentTileId = element.tileId
set thistype.infection_state = 1
set thistype.infection_state = 0
set thistype.current = 0
set thistype.currentTileId = 0
if (thistype.first == 0) then
call TimerStart(tim, TIMEOUT, true, function thistype.callback)
endif
set this.next = thistype.first
set thistype.first.prev = this
set thistype.first = this
set this.prev = 0
return this
endmethod
method destroy takes nothing returns nothing
set this.bound = null
call this.deallocate()
call this.list.destroy()
if (this == thistype.first) then
set thistype.first = this.next
endif
set this.next.prev = this.prev
set this.prev.next = this.next
if (thistype.first == 0) then
call PauseTimer(tim)
endif
endmethod
method undoInfection_last takes nothing returns boolean
local InfectionData element = this.list.last
local integer tileId = element.tileId
if (element == 0) then
// Fire onRemoved event.
set thistype.current = this
set thistype.infection_state = 4
set thistype.infection_state = 0
set thistype.current = 0
return false
endif
call SetTerrainType(GetTileCenterXById(tileId), GetTileCenterYById(tileId), element.originTerrainType, -1, 1, 1)
set this.size = this.size - 1
call thistype.table.remove(tileId)
call element.remove()
// Fire onUnInfection event.
set thistype.current = this
set thistype.currentTileId = tileId
set thistype.infection_state = 3
set thistype.infection_state = 0
set thistype.current = 0
set thistype.currentTileId = 0
return true
endmethod
// loop until all infected tiles are removed
method undoInfection takes nothing returns nothing
loop
exitwhen not (this.undoInfection_last())
endloop
endmethod
static method isTileInfected takes real x, real y returns boolean
return thistype.table.has(GetTileId(x,y))
endmethod
static method enableResistor takes integer infector, integer resistor, boolean b returns nothing
call SaveBoolean(hash, infector, resistor, b)
endmethod
static method enableInfections takes boolean b returns nothing
if (b) then
call TimerStart(tim, TIMEOUT, true, function thistype.callback)
else
call PauseTimer(tim)
endif
endmethod
endstruct
function CreateTerrainInfection takes integer t, real x, real y, real chance, real interval returns TerrainInfection
return TerrainInfection.create(t, x, y, chance, interval)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct InfectionEvent extends array
private static string InfectEffect = "Abilities\\Spells\\Demon\\RainOfFire\\RainOfFireTarget.mdl"
private static string UninfectEffect = "Abilities\\Spells\\Undead\\ReplenishMana\\SpiritTouchTarget.mdl"
private static string StartEffect = "Units\\Demon\\Infernal\\InfernalBirth.mdl"
private static string EndEffect = "Abilities\\Spells\\Human\\MarkOfChaos\\MarkOfChaosTarget.mdl"
private static method infection_finished takes nothing returns nothing
local TerrainInfection this = TerrainInfection.current
// No more checks/operations will be done for this infection.
set this.enabled = false
call TriggerSleepAction(1.)
call BJDebugMsg("======================================")
call BJDebugMsg("Infection finished with " + I2S(this.size) + " tiles.")
call BJDebugMsg("======================================")
call TriggerSleepAction(3.)
call BJDebugMsg("Un-Infection starts")
call BJDebugMsg("======================================")
call TriggerSleepAction(3.)
// Infection will be removed and all tiles will change to origin terrain type.
loop
call TriggerSleepAction(0.5)
if (GetRandomInt(1, 4) > 1) then
// Simulate a bit randomness
if (GetRandomInt(1, 3) > 1) then
exitwhen not this.undoInfection_last()
exitwhen not this.undoInfection_last()
else
exitwhen not this.undoInfection_last()
endif
endif
endloop
call BJDebugMsg("======================================")
call BJDebugMsg("Infection has been completly removed.")
call BJDebugMsg("======================================")
call BJDebugMsg("Demo is over.")
call BJDebugMsg("======================================")
endmethod
private static method onRemoved takes nothing returns boolean
call DestroyEffect(AddSpecialEffect(thistype.EndEffect, TerrainInfection.current.x, TerrainInfection.current.y))
call TerrainInfection.current.destroy()
return false
endmethod
private static method onUnInfection takes nothing returns boolean
local integer tileId = TerrainInfection.currentTileId
call DestroyEffect(AddSpecialEffect(thistype.UninfectEffect, GetTileCenterXById(tileId), GetTileCenterYById(tileId)))
call BJDebugMsg(I2S(TerrainInfection.current.size) + " infected tiles left.")
return false
endmethod
private static method onInfection takes nothing returns boolean
local TerrainInfection this = TerrainInfection.current
local integer tileId = TerrainInfection.currentTileId
call BJDebugMsg("Tile " + I2S(tileId) + " has been infected.")
call BJDebugMsg("x: " + R2S(GetTileCenterXById(tileId)))
call BJDebugMsg("y: " + R2S(GetTileCenterYById(tileId)))
call BJDebugMsg("Infection has currently " + I2S(this.size) + " tiles.")
call DestroyEffect(AddSpecialEffect(thistype.InfectEffect, GetTileCenterXById(tileId), GetTileCenterYById(tileId)))
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "s__TerrainInfection_infection_state", EQUAL, 2 )
call TriggerAddAction(t, function thistype.infection_finished)
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "s__TerrainInfection_infection_state", EQUAL, 1 )
call TriggerAddCondition(t, Condition(function thistype.onInfection))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "s__TerrainInfection_infection_state", EQUAL, 3 )
call TriggerAddCondition(t, Condition(function thistype.onUnInfection))
set t = CreateTrigger()
call TriggerRegisterVariableEvent(t, "s__TerrainInfection_infection_state", EQUAL, 4)
call TriggerAddCondition(t, Condition(function thistype.onRemoved))
endmethod
endstruct
//TESH.scrollpos=119
//TESH.alwaysfold=0
library TileDefinition /* v1.2b By IcemanBo
*/ requires /*
*/ WorldBounds /* github.com/nestharus/JASS/blob/master/jass/Systems/WorldBounds/script.j
**
**
** Information
** _____________
**
** TileDefinition provides an API to give information about a terrain tile.
**
**
** API
** _______
**
**
** function AreCoordinatesInSameTile takes real a, real b returns boolean
** Checks if two coordinates share the same terrain tile.
**
** Attention: Only makes sense if both coordinates are of same type. Or x- or y coordinates.
** May bring wrong result, if you compare x with y coordinates.
**
** function ArePointsInSameTile takes real x1, real y1, real x2, real y2 returns boolean
** Checks if two points share the same terrain tile.
**
**
** function GetTileCenterCoordinate takes real a returns real
** Returns the cooridnate for the center of the tile.
** Works for x- and y coordiantes.
**
**
** function GetTileMax takes real a returns real
** Returns the max value, that is still in same terrain tile.
** Works for x- and y coordiantes.
**
** function GetTileMin takes real a returns real
** Returns the min value, that is still in same terrain tile.
** Works for x- and y coordiantes.
**
**
** funtion GetTileId takes real x, real y returns integer
** Returns an unique index for tile of given coordinates.
** Will return "-1" if it's invalid.
**
** function GetTileCenterXById takes integer id returns real
**
** function GetTileCenterYById takes integer id returns real
**
**
** Credtis to Waterknight for some functions
**
***********************************************************************************************************/
/*
* TileDistance evaluates how many tiles the given
* cooridnate is away from reference tile. (located at 0/0)
*/
private function TileDistance takes real a returns integer
if (a >= 0) then
return R2I((a + 64)/128)
endif
return R2I((a - 64)/128)
endfunction
function GetTileMax takes real a returns real
local integer aCount = TileDistance(a)
if (aCount == 0) then
return 64.
elseif (aCount > 0) then
return (aCount + 1.)*128. - 64.
endif
return (aCount)* 128. + 64.
endfunction
function GetTileMin takes real a returns real
local integer aCount = TileDistance(a)
if (aCount == 0) then
return -64.
elseif (aCount > 0) then
return (aCount)*128. - 64.
endif
return (aCount - 1.)* 128. + 64.
endfunction
function AreCoordinatesInSameTile takes real a, real b returns boolean
return (GetTileMin(a) == GetTileMin(b))
endfunction
function ArePointsInSameTile takes real x1, real y1, real x2, real y2 returns boolean
return ((TileDistance(x1) == (TileDistance(x2)) and (TileDistance(y1) == (TileDistance(y2)))))
endfunction
function GetTileCenterCoordinate takes real a returns real
if (a >= 0) then
return GetTileMin(a) + 64.
endif
return GetTileMin(a) - 64.
endfunction
// Credits to Waterknight for following functions
globals
private integer WorldTiles_X
private integer WorldTiles_Y
endglobals
function GetTileId takes real x, real y returns integer
local integer xI = R2I(x - WorldBounds.minX + 64) / 128
local integer yI = R2I(y - WorldBounds.minY + 64) / 128
if ((xI < 0) or (xI >= WorldTiles_X) or (yI < 0) or (yI >= WorldTiles_Y)) then
return -1
endif
return (yI * WorldTiles_X + xI)
endfunction
function GetTileCenterXById takes integer id returns real
if ((id < 0) or (id >= WorldTiles_X * WorldTiles_Y)) then
return 0.
endif
return (WorldBounds.minX + ModuloInteger(id, WorldTiles_X) * 128.)
endfunction
function GetTileCenterYById takes integer id returns real
if ((id < 0) or (id >= WorldTiles_X * WorldTiles_Y)) then
return 0.
endif
return (WorldBounds.minY + id / WorldTiles_X * 128.)
endfunction
private module Init
private static method onInit takes nothing returns nothing
set WorldTiles_X = R2I(WorldBounds.maxX - WorldBounds.minX) / 128 + 1
set WorldTiles_Y = R2I(WorldBounds.maxY - WorldBounds.minY) / 128 + 1
endmethod
endmodule
private struct TileDefinition extends array
implement Init
endstruct
endlibrary
//TESH.scrollpos=15
//TESH.alwaysfold=0
library Table /* made by Bribe, special thanks to Vexorian & Nestharus, version 3.1.1.0
One map, one hashtable. Welcome to NewTable 3.1
This library was originally called NewTable so it didn't conflict with
the API of Table by Vexorian. However, the damage is done and it's too
late to change the library name now. To help with damage control, I
have provided an extension library called TableBC, which bridges all
the functionality of Vexorian's Table except for 2-D string arrays &
the ".flush(integer)" method. I use ".flush()" to flush a child hash-
table, because I wanted the API in NewTable to reflect the API of real
hashtables (I thought this would be more intuitive).
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 integer less = 0 //Index generation for TableArrays (below 0).
private integer more = 8190 //Index generation for Tables.
//Configure it if you use more than 8190 "key" variables in your map (this will never happen though).
private hashtable ht = InitHashtable()
private key sizeK
private key listK
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return sizeK
endmethod
static method operator list takes nothing returns Table
return listK
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
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 module $TYPE$m
method operator $TYPE$ takes nothing returns $TYPE$s
return this
endmethod
endmodule
//! endtextmacro
//Run these textmacros to include the entire hashtable API as wrappers.
//Don't be intimidated by the number of macros - Vexorian's map optimizer is
//supposed to kill functions which inline (all of these functions inline).
//! runtextmacro NEW_ARRAY_BASIC("Real", "Real", "real")
//! runtextmacro NEW_ARRAY_BASIC("Boolean", "Boolean", "boolean")
//! runtextmacro NEW_ARRAY_BASIC("String", "Str", "string")
//New textmacro to allow table.integer[] syntax for compatibility with textmacros that might desire it.
//! runtextmacro NEW_ARRAY_BASIC("Integer", "Integer", "integer")
//! 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 syntax (tb.handle; tb.unit; etc.)
implement realm
implement integerm
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 = tb[GetSpellAbilityId()]
method operator [] takes integer key returns Table
return LoadInteger(ht, this, key) //return this.integer[key]
endmethod
//set tb[389034] = 8192
method operator []= takes integer key, Table tb returns nothing
call SaveInteger(ht, this, key, tb) //set this.integer[key] = tb
endmethod
//set b = tb.has(2493223)
method has takes integer key returns boolean
return HaveSavedInteger(ht, this, key) //return this.integer.has(key)
endmethod
//call tb.remove(294080)
method remove takes integer key returns nothing
call RemoveSavedInteger(ht, this, key) //call this.integer.remove(key)
endmethod
//Remove all data from a Table instance
method flush takes nothing returns nothing
call FlushChildHashtable(ht, this)
endmethod
//local Table tb = Table.create()
static method create takes nothing returns Table
local Table this = dex.list[0]
if this == 0 then
set this = more + 1
set more = this
else
set dex.list[0] = dex.list[this]
call dex.list.remove(this) //Clear hashed memory
endif
debug set dex.list[this] = -1
return this
endmethod
// Removes all data from a Table instance and recycles its index.
//
// call tb.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
//! runtextmacro optional TABLE_BC_METHODS()
endstruct
//! runtextmacro optional TABLE_BC_STRUCTS()
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 tb = dex.size[array_size] //Get the unique recycle list for this array size
local TableArray this = tb[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 this = less - array_size
set less = this
else
set tb[0] = tb[this] //Set the last destroyed to the last-last destroyed
call tb.remove(this) //Clear hashed 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
//This magic method enables two-dimensional[array][syntax] for Tables,
//similar to the two-dimensional utility provided by hashtables them-
//selves.
//
//ta[integer a].unit[integer b] = unit u
//ta[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; I assume you call .flush()
//if you want it flushed too. This is a public method so that you don't
//have to loop through all TableArray indices to flush them if you don't
//need to (ie. if you were flushing all child-keys as you used them).
//
method destroy takes nothing returns nothing
local Table tb = 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 tb == 0 then
//Create a Table to index recycled instances with their array size
set tb = Table.create()
set dex.size[this.size] = tb
endif
call dex.size.remove(this) //Clear the array size from hash memory
set tb[this] = tb[0]
set tb[0] = this
endmethod
private static Table tempTable
private static integer tempEnd
//Avoids hitting the op limit
private static method clean takes nothing returns nothing
local Table tb = .tempTable
local integer end = tb + 0x1000
if end < .tempEnd then
set .tempTable = end
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
else
set end = .tempEnd
endif
loop
call tb.flush()
set tb = tb + 1
exitwhen tb == 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
debug if this.size == 0 then
debug call BJDebugMsg("TypeError: Tried to flush an invalid TableArray instance: " + I2S(this))
debug return
debug endif
set .tempTable = this
set .tempEnd = this + this.size
call ForForce(bj_FORCE_PLAYER[0], function thistype.clean)
call this.destroy()
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library List /* v1.0.0.3
************************************************************************************
*
* */uses/*
*
* */ ErrorMessage /* hiveworkshop.com/forums/submissions-414/snippet-error-message-239210/
*
************************************************************************************
*
* module List
*
* Description
* -------------------------
*
* NA
*
* Fields
* -------------------------
*
* readonly static integer sentinel
*
* readonly thistype list
*
* readonly thistype first
* readonly thistype last
*
* readonly thistype next
* readonly thistype prev
*
* Methods
* -------------------------
*
* static method create takes nothing returns thistype
* method destroy takes nothing returns nothing
* - May only destroy lists
*
* method push takes nothing returns thistype
* method enqueue takes nothing returns thistype
*
* method pop takes nothing returns nothing
* method dequeue takes nothing returns nothing
*
* method remove takes nothing returns nothing
*
* method clear takes nothing returns nothing
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
************************************************************************************/
module List
private static thistype collectionCount = 0
private static thistype nodeCount = 0
debug private boolean isNode
debug private boolean isCollection
private thistype _list
method operator list takes nothing returns thistype
debug call ThrowError(this == 0, "List", "list", "thistype", this, "Attempted To Read Null Node.")
debug call ThrowError(not isNode, "List", "list", "thistype", this, "Attempted To Read Invalid Node.")
return _list
endmethod
private thistype _next
method operator next takes nothing returns thistype
debug call ThrowError(this == 0, "List", "next", "thistype", this, "Attempted To Go Out Of Bounds.")
debug call ThrowError(not isNode, "List", "next", "thistype", this, "Attempted To Read Invalid Node.")
return _next
endmethod
private thistype _prev
method operator prev takes nothing returns thistype
debug call ThrowError(this == 0, "List", "prev", "thistype", this, "Attempted To Go Out Of Bounds.")
debug call ThrowError(not isNode, "List", "prev", "thistype", this, "Attempted To Read Invalid Node.")
return _prev
endmethod
private thistype _first
method operator first takes nothing returns thistype
debug call ThrowError(this == 0, "List", "first", "thistype", this, "Attempted To Read Null List.")
debug call ThrowError(not isCollection, "List", "first", "thistype", this, "Attempted To Read Invalid List.")
return _first
endmethod
private thistype _last
method operator last takes nothing returns thistype
debug call ThrowError(this == 0, "List", "last", "thistype", this, "Attempted To Read Null List.")
debug call ThrowError(not isCollection, "List", "last", "thistype", this, "Attempted To Read Invalid List.")
return _last
endmethod
static method operator sentinel takes nothing returns integer
return 0
endmethod
private static method allocateCollection takes nothing returns thistype
local thistype this = thistype(0)._first
if (0 == this) then
debug call ThrowError(collectionCount == 8191, "List", "allocateCollection", "thistype", 0, "Overflow.")
set this = collectionCount + 1
set collectionCount = this
else
set thistype(0)._first = _first
endif
return this
endmethod
private static method allocateNode takes nothing returns thistype
local thistype this = thistype(0)._next
if (0 == this) then
debug call ThrowError(nodeCount == 8191, "List", "allocateNode", "thistype", 0, "Overflow.")
set this = nodeCount + 1
set nodeCount = this
else
set thistype(0)._next = _next
endif
return this
endmethod
static method create takes nothing returns thistype
local thistype this = allocateCollection()
debug set isCollection = true
set _first = 0
return this
endmethod
method push takes nothing returns thistype
local thistype node = allocateNode()
debug call ThrowError(this == 0, "List", "push", "thistype", this, "Attempted To Push On To Null List.")
debug call ThrowError(not isCollection, "List", "push", "thistype", this, "Attempted To Push On To Invalid List.")
debug set node.isNode = true
set node._list = this
if (_first == 0) then
set _first = node
set _last = node
set node._next = 0
else
set _first._prev = node
set node._next = _first
set _first = node
endif
set node._prev = 0
return node
endmethod
method enqueue takes nothing returns thistype
local thistype node = allocateNode()
debug call ThrowError(this == 0, "List", "enqueue", "thistype", this, "Attempted To Enqueue On To Null List.")
debug call ThrowError(not isCollection, "List", "enqueue", "thistype", this, "Attempted To Enqueue On To Invalid List.")
debug set node.isNode = true
set node._list = this
if (_first == 0) then
set _first = node
set _last = node
set node._prev = 0
else
set _last._next = node
set node._prev = _last
set _last = node
endif
set node._next = 0
return node
endmethod
method pop takes nothing returns nothing
local thistype node = _first
debug call ThrowError(this == 0, "List", "pop", "thistype", this, "Attempted To Pop Null List.")
debug call ThrowError(not isCollection, "List", "pop", "thistype", this, "Attempted To Pop Invalid List.")
debug call ThrowError(node == 0, "List", "pop", "thistype", this, "Attempted To Pop Empty List.")
debug set node.isNode = false
set _first._list = 0
set _first = _first._next
if (_first == 0) then
set _last = 0
else
set _first._prev = 0
endif
set node._next = thistype(0)._next
set thistype(0)._next = node
endmethod
method dequeue takes nothing returns nothing
local thistype node = _last
debug call ThrowError(this == 0, "List", "dequeue", "thistype", this, "Attempted To Dequeue Null List.")
debug call ThrowError(not isCollection, "List", "dequeue", "thistype", this, "Attempted To Dequeue Invalid List.")
debug call ThrowError(node == 0, "List", "dequeue", "thistype", this, "Attempted To Dequeue Empty List.")
debug set node.isNode = false
set _last._list = 0
set _last = _last._prev
if (_last == 0) then
set _first = 0
else
set _last._next = 0
endif
set node._next = thistype(0)._next
set thistype(0)._next = node
endmethod
method remove takes nothing returns nothing
local thistype node = this
set this = node._list
debug call ThrowError(node == 0, "List", "remove", "thistype", this, "Attempted To Remove Null Node.")
debug call ThrowError(not node.isNode, "List", "remove", "thistype", this, "Attempted To Remove Invalid Node (" + I2S(node) + ").")
debug set node.isNode = false
set node._list = 0
if (0 == node._prev) then
set _first = node._next
else
set node._prev._next = node._next
endif
if (0 == node._next) then
set _last = node._prev
else
set node._next._prev = node._prev
endif
set node._next = thistype(0)._next
set thistype(0)._next = node
endmethod
method clear takes nothing returns nothing
debug local thistype node = _first
debug call ThrowError(this == 0, "List", "clear", "thistype", this, "Attempted To Clear Null List.")
debug call ThrowError(not isCollection, "List", "clear", "thistype", this, "Attempted To Clear Invalid List.")
static if DEBUG_MODE then
loop
exitwhen node == 0
set node.isNode = false
set node = node._next
endloop
endif
if (_first == 0) then
return
endif
set _last._next = thistype(0)._next
set thistype(0)._next = _first
set _first = 0
set _last = 0
endmethod
method destroy takes nothing returns nothing
debug call ThrowError(this == 0, "List", "destroy", "thistype", this, "Attempted To Destroy Null List.")
debug call ThrowError(not isCollection, "List", "destroy", "thistype", this, "Attempted To Destroy Invalid List.")
static if DEBUG_MODE then
debug call clear()
debug set isCollection = false
else
if (_first != 0) then
set _last._next = thistype(0)._next
set thistype(0)._next = _first
set _last = 0
endif
endif
set _first = thistype(0)._first
set thistype(0)._first = this
endmethod
static if DEBUG_MODE then
static method calculateMemoryUsage takes nothing returns integer
local thistype start = 1
local thistype end = 8191
local integer count = 0
loop
exitwhen integer(start) > integer(end)
if (integer(start) + 500 > integer(end)) then
return count + checkRegion(start, end)
else
set count = count + checkRegion(start, start + 500)
set start = start + 501
endif
endloop
return count
endmethod
private static method checkRegion takes thistype start, thistype end returns integer
local integer count = 0
loop
exitwhen integer(start) > integer(end)
if (start.isNode) then
set count = count + 1
endif
if (start.isCollection) then
set count = count + 1
endif
set start = start + 1
endloop
return count
endmethod
static method getAllocatedMemoryAsString takes nothing returns string
local thistype start = 1
local thistype end = 8191
local string memory = null
loop
exitwhen integer(start) > integer(end)
if (integer(start) + 500 > integer(end)) then
if (memory != null) then
set memory = memory + ", "
endif
set memory = memory + checkRegion2(start, end)
set start = end + 1
else
if (memory != null) then
set memory = memory + ", "
endif
set memory = memory + checkRegion2(start, start + 500)
set start = start + 501
endif
endloop
return memory
endmethod
private static method checkRegion2 takes thistype start, thistype end returns string
local string memory = null
loop
exitwhen integer(start) > integer(end)
if (start.isNode) then
if (memory == null) then
set memory = I2S(start)
else
set memory = memory + ", " + I2S(start) + "N"
endif
endif
if (start.isCollection) then
if (memory == null) then
set memory = I2S(start)
else
set memory = memory + ", " + I2S(start) + "C"
endif
endif
set start = start + 1
endloop
return memory
endmethod
endif
endmodule
endlibrary
//TESH.scrollpos=25
//TESH.alwaysfold=0
library WorldBounds /* v2.0.0.0
************************************************************************************
*
* struct WorldBounds extends array
*
* Fields
* -------------------------
*
* 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=9
//TESH.alwaysfold=0
library ErrorMessage /* v1.0.1.4
*************************************************************************************
*
* Issue Compliant Error Messages
*
************************************************************************************
*
* debug function ThrowError takes boolean expression, string libraryName, string functionName, string objectName, integer objectInstance, string description returns nothing
* - In the event of an error the game will be permanently paused
*
* debug function ThrowWarning takes boolean expression, string libraryName, string functionName, string objectName, integer objectInstance, string description returns nothing
*
************************************************************************************/
static if DEBUG_MODE then
private struct Fields extends array
static constant string COLOR_RED = "|cffff0000"
static constant string COLOR_YELLOW = "|cffffff00"
static string lastError = null
endstruct
private function Pause takes nothing returns nothing
call PauseGame(true)
endfunction
private function ThrowMessage takes string libraryName, string functionName, string objectName, integer objectInstance, string description, string errorType, string color returns nothing
local string str
local string color_braces = "|cff66FF99"
local string orange = "|cffff6600"
set str = "->\n-> " + color_braces + "{|r " + "Library" + color_braces + "(" + orange + libraryName + color_braces + ")"
if (objectName != null) then
if (objectInstance > 0) then
set str = str + "|r.Object" + color_braces + "(" + orange + objectName + color_braces + " (|rinstance = " + orange + I2S(objectInstance) + color_braces + ") )" + "|r." + "Method" + color_braces + "(" + orange + functionName + color_braces + ")"
else
set str = str + "|r.Object" + color_braces + "(" + orange + objectName + color_braces + ")|r." + "Method" + color_braces + "(" + orange + functionName + color_braces + ")"
endif
else
set str = str + "|r." + "Function" + color_braces + "(" + orange + functionName + color_braces + ")"
endif
set str = str + color_braces + " }|r " + "has thrown an exception of type " + color_braces + "(" + color + errorType + color_braces + ")|r."
set Fields.lastError = str + "\n->\n" + "-> " + color + description + "|r\n->"
endfunction
function ThrowError takes boolean expression, string libraryName, string functionName, string objectName, integer objectInstance, string description returns nothing
if (Fields.lastError != null) then
set objectInstance = 1/0
endif
if (expression) then
call ThrowMessage(libraryName, functionName, objectName, objectInstance, description, "Error", Fields.COLOR_RED)
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60000,Fields.lastError)
call TimerStart(CreateTimer(), 0, true, function Pause)
set objectInstance = 1/0
endif
endfunction
function ThrowWarning takes boolean expression, string libraryName, string functionName, string objectName, integer objectInstance, string description returns nothing
if (Fields.lastError != null) then
set objectInstance = 1/0
endif
if (expression) then
call ThrowMessage(libraryName, functionName, objectName, objectInstance, description, "Warning", Fields.COLOR_YELLOW)
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60000,Fields.lastError)
set Fields.lastError = null
endif
endfunction
endif
endlibrary