Name | Type | is_array | initial_value |
s | string | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Demo initializer Init
private function Start takes nothing returns nothing
call NewSlider(Player(6), CATCHER)
endfunction
private function testAction takes nothing returns nothing
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerAddAction(t, function testAction)
call TimerStart(CreateTimer(), 1, false, function Start)
endfunction
endscope
//TESH.scrollpos=146
//TESH.alwaysfold=0
library Default uses Print, CTL, TimerUtils, Table, UnitIndexer, SuspendUnit
globals
constant integer ALIEN = 'H003'
constant integer CATCHER = 'H004'
constant integer JUMPER = 'H002'
constant integer SAVER = 'H00D'
constant integer SNIPER = 'H009'
constant integer SPY = 'H007'
constant integer STEAMROLLER = 'H001'
constant integer TANK = 'H00C'
constant rect RECT_LEFT = Rect(-16000, 3800, -9400, 11400)
constant rect RECT_RIGHT = Rect(1050, 5270, 7800, 12400)
constant integer ROCKET_EFFECT = 'rEff'
constant integer NET_EFFECT = 'cEff'
constant string MISSLE_BLUE_MODELPATH = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
constant string MISSLE_RED_MODELPATH = "Abilities\\Weapons\\VengeanceMissile\\VengeanceMissile.mdl"
constant string MISSLE_SNIPER_MODELPATH = "Abilities\\Weapons\\ColdArrow\\ColdArrowMissile.mdl"
constant string MISSLE_ROCKET_MODELPATH = "Abilities\\Weapons\\RocketMissile\\RocketMissile.mdl"
constant string SECRET_ITEM_MODELPATH = "Objects\\InventoryItems\\BundleofGifts\\BundleofGifts.mdl"
constant real SCALE_ROCKET = 2.2
constant real SCALE_ENERGY_BALL = 2.8
constant real SCALE_SNIPER_ARROW = 1.4
constant real SCALE_SECRET_ITEM = 2.0
constant integer MISSLE_BLUE = 'h000'
constant integer MISSLE_RED = 'h00F'
constant integer MISSLE_SNIPER = 'h006'
constant integer MISSLE_ROCKET = 'h00E'
constant integer MISSLE_HOLYRA = 'holy'
constant integer FLAG_BLUE = 'blue'
constant integer FLAG_RED = 'redf'
constant integer ENERGY_BALL = 'ENER'
constant integer SNIPER_ARROW = 'ARRO'
constant integer JUMP = 'JUMP'
constant integer ROCKET = 'ROCK'
constant integer FLAG_DROP = 'drop'
constant integer INVISIBILITY = 'INVI'
constant integer HOLYRA = 'HOLY'
constant integer NET = 'NET1'
constant integer RANGE_ON = 'RANG'
constant integer RANGE_OFF = 'ROFF'
constant integer EXPLOSIVE_EGG = 'EGGa'
constant integer EXPLOSION = 'EGGb'
constant integer CAM_LOCK = 'CAM0'
constant integer CAM_UNLOCK = 'CAM1'
integer ORDER_ENERGY_BALL
integer ORDER_SNIPER_ARROW
integer ORDER_ROCKET
integer ORDER_INVISIBILITY
integer ORDER_JUMP
constant integer SMART = 851971
constant integer STOP = 851972
constant integer PATROL = 851990
constant integer MOVE = 851986
constant real INTERVAL = 0.031250000
constant real TPS = 1/INTERVAL
constant integer SLIDE_FAST = 'Iice'
constant integer SLIDE_SNOW = 'cIc1'
constant integer SLIDE_NORMAL = 'Nice'
constant integer SLIDE_DARK = 'Idki'
constant integer SAVE_CIRCLE = 'save'
//constant integer SLIDE_SNOW = 'Nsnw' oldsnow
// MIRROR = 'Glav'
// MIRROW_SLOW = 'Glvc'
constant real CENTER_X = -4230
constant real CENTER_Y = 8050
constant real DEFAULT_SPEED = 580.
constant hashtable HASH = InitHashtable()
group G = CreateGroup()
RSound array Sound[30]
constant integer FIRSTBLOOD = 14
constant integer HEADHUNTER = 15
constant integer HATTRICK = 16
constant integer PLAY = 17
constant integer PREPARE = 18
constant integer ERROR = 19
constant integer LAUNCH_SNIPERARROW = 20
constant integer LAUNCH_ROCKET = 21
constant integer LAUNCH_ENERGYBALL = 22
constant integer RESCUE = 23
constant integer WARNING = 24
constant integer STARTROUND = 25
constant integer TICK = 26
constant integer GOODJOB = 27
constant integer ROOTSOUND = 28
constant integer LAUNCH_HOLYRA = 29
player LOCAL_PLAYER
endglobals
struct Init extends array
private static method preload takes nothing returns nothing
call AbilityPreload(ENERGY_BALL)
call AbilityPreload(SNIPER_ARROW)
call AbilityPreload(JUMP)
call AbilityPreload(ROCKET)
call AbilityPreload(FLAG_DROP)
call AbilityPreload(INVISIBILITY)
call AbilityPreload(HOLYRA)
call AbilityPreload(NET)
call AbilityPreload(RANGE_ON)
call AbilityPreload(RANGE_OFF)
call AbilityPreload(EXPLOSIVE_EGG)
call AbilityPreload(EXPLOSION)
call AbilityPreload(CAM_LOCK)
call AbilityPreload(CAM_UNLOCK)
call AbilityPreload('ZxLa')
call AbilityPreload('ZxLb')
call AbilityPreload('ZxLc')
call AbilityPreload('ZxLd')
call AbilityPreload('ZxLe')
call AbilityPreload('ZxLf')
call AbilityPreload('ZxMa')
call AbilityPreload('ZxMb')
call AbilityPreload('ZxMc')
call AbilityPreload('ZxMd')
call AbilityPreload('ZxMe')
call AbilityPreload('ZxMf')
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method init takes nothing returns nothing
set LOCAL_PLAYER = GetLocalPlayer()
call TimerStart(NewTimer(), 0, false, function thistype.preload)
set Sound[1] = RSound.create("war3mapImported\\doublekill.mp3", false, false, 0, 0)
set Sound[2] = RSound.create("war3mapImported\\triplekill.mp3", false, false, 0, 0)
set Sound[3] = RSound.create("war3mapImported\\multikill.mp3", false, false, 0, 0)
set Sound[4] = RSound.create("war3mapImported\\rampage.mp3", false, false, 0, 0)
set Sound[5] = RSound.create("war3mapImported\\megakill.mp3", false, false, 0, 0)
set Sound[6] = RSound.create("war3mapImported\\dominating.mp3", false, false, 0, 0)
set Sound[7] = RSound.create("war3mapImported\\monsterkill.mp3", false, false, 0, 0)
set Sound[8] = RSound.create("war3mapImported\\holyshit.mp3", false, false, 0, 0)
set Sound[9] = RSound.create("war3mapImported\\ultrakill.mp3", false, false, 0, 0)
set Sound[10] = RSound.create("war3mapImported\\unstoppable.mp3", false, false, 0, 0)
set Sound[11] = RSound.create("war3mapImported\\ludicrouskill.mp3", false, false, 0, 0)
set Sound[12] = RSound.create("war3mapImported\\wickedsick.mp3", false, false, 0, 0)
set Sound[13] = RSound.create("war3mapImported\\godlike.mp3", false, false, 0, 0)
set Sound[FIRSTBLOOD] = RSound.create("war3mapImported\\firstblood.mp3", false, false, 0, 0)
set Sound[HEADHUNTER] = RSound.create("war3mapImported\\headhunter.mp3", false, false, 0, 0)
set Sound[HATTRICK] = RSound.create("war3mapImported\\hattrick.wav", false, false, 0, 0)
set Sound[PLAY] = RSound.create("war3mapImported\\play.wav", false, false, 0, 0)
set Sound[PREPARE] = RSound.create("war3mapImported\\Prepare.mp3", false, false, 0, 0)
set Sound[ERROR] = RSound.create("Sound\\Interface\\Error.wav", false, false, 0, 0)
set Sound[LAUNCH_SNIPERARROW] = RSound.create("Abilities\\Weapons\\BristleBackMissile\\BristleBackMissileLaunch3.wav", false, false, 0, 0)
set Sound[LAUNCH_ENERGYBALL] = RSound.create("Abilities\\Weapons\\FarseerMissile\\FarseerMissileLaunch.wav", true, false, 0, 0)
set Sound[LAUNCH_ROCKET] = RSound.create("Abilities\\Weapons\\CannonTowerMissile\\CannonTowerMissileLaunch2.wav", true, false, 0, 0)
set Sound[LAUNCH_HOLYRA] = RSound.create("Units\\Human\\Phoenix\\PhoenixYes1.wav", true, false, 0, 0)
set Sound[RESCUE] = RSound.create("Sound\\Interface\\Rescue.wav", false, false, 0, 0)
set Sound[WARNING] = RSound.create("Sound\\Interface\\Warning.wav", false, false, 0, 0)
set Sound[STARTROUND] = RSound.create("Sound\\Interface\\ArrangedTeamInvitation.wav", false, false, 0, 0)
set Sound[TICK] = RSound.create("Sound\\Interface\\BattleNetTick.wav", false, false, 0, 0)
set Sound[GOODJOB] = RSound.create("Sound\\Interface\\GoodJob.wav", false, false, 0, 0)
set Sound[ROOTSOUND] = RSound.create("Abilities\\Spells\\NightElf\\EntanglingRoots\\EntanglingRootsTarget1.wav", false, false, 0, 0)
set ORDER_ENERGY_BALL = OrderId("berserk")
set ORDER_SNIPER_ARROW = OrderId("berserk")
set ORDER_ROCKET = OrderId("berserk")
set ORDER_INVISIBILITY = OrderId("divineshield")
set ORDER_JUMP = OrderId("divineshield")
endmethod
implement InitTimer
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
// Set and Get the default shoot ability of a unit
struct DefaultShootAbility extends array
private static key k
static Table table = k
public static method apply takes integer unitType, integer abilityId returns nothing
set thistype.table[unitType] = abilityId
endmethod
public static method operator [] takes unit u returns integer
return thistype.table[GetUnitTypeId(u)]
endmethod
endstruct
// Set and Get the current shoot ability of a unit
struct CurrentShootAbility extends array
private static key k
static Table table = k
public static method apply takes unit who, integer abilityId returns nothing
call UnitRemoveAbility(who, thistype.table[GetHandleId(who)])
call UnitAddAbility(who, abilityId)
set thistype.table[GetHandleId(who)] = abilityId
endmethod
public static method operator [] takes unit who returns integer
return thistype.table[GetHandleId(who)]
endmethod
private static method init takes nothing returns nothing
call DefaultShootAbility.apply(ALIEN, ENERGY_BALL)
call DefaultShootAbility.apply(CATCHER, ENERGY_BALL)
call DefaultShootAbility.apply(JUMPER, ENERGY_BALL)
call DefaultShootAbility.apply(SAVER, ENERGY_BALL)
call DefaultShootAbility.apply(SNIPER, SNIPER_ARROW)
call DefaultShootAbility.apply(SPY, ENERGY_BALL)
call DefaultShootAbility.apply(STEAMROLLER, ENERGY_BALL)
call DefaultShootAbility.apply(TANK, ENERGY_BALL)
endmethod
implement InitTimer
endstruct
//TESH.scrollpos=19
//TESH.alwaysfold=0
struct Hero extends array
static key k
static Table table = k
integer unittypeId
static integer counter = 0
public static method operator [] takes integer who returns thistype
return thistype(who).unittypeId
endmethod
private static method onInit takes nothing returns nothing
local thistype this
set counter = counter + 1
set this = counter
set this.unittypeId = ALIEN
set table.string[ALIEN] = "ReplaceableTextures\\CommandButtons\\BTNAcolyte.blp"
set counter = counter + 1
set this = counter
set this.unittypeId = CATCHER
set table.string[CATCHER] = "ReplaceableTextures\\CommandButtons\\BTNCagedIllidan.blp"
set counter = counter + 1
set this = counter
set this.unittypeId = JUMPER
set table.string[JUMPER] = "ReplaceableTextures\\CommandButtons\\BTNHeroDeathKnight.blp"
set counter = counter + 1
set this = counter
set this.unittypeId = SAVER
set table.string[SAVER] = "ReplaceableTextures\\CommandButtons\\BTNFlyingMachine.blp"
set counter = counter + 1
set this = counter
set this.unittypeId = SNIPER
set table.string[SNIPER] = "ReplaceableTextures\\CommandButtons\\BTNClockWerkGoblin.blp"
set counter = counter + 1
set this = counter
set this.unittypeId = TANK
set table.string[TANK] = "ReplaceableTextures\\CommandButtons\\BTNDwarfCar.blp"
/*
set counter = counter + 1
set this = counter
set this.unittypeId = SPY
set counter = counter + 1
set this = counter
set this.unittypeId = STEAMROLLER
*/
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
// Define spawn (rects)
struct Spawn extends array
readonly static constant integer LEFT = 1
readonly static constant integer RIGHT = 2
real xMax
real yMax
real xMin
real yMin
real xCenter
real yCenter
public static method operator [] takes integer who returns thistype
return thistype(who)
endmethod
private static method init takes nothing returns nothing
set thistype[LEFT].xCenter = -11472
set thistype[LEFT].yCenter = 8064
set thistype[LEFT].xMax = -11155
set thistype[LEFT].xMin = -11808
set thistype[LEFT].yMax = 8615
set thistype[LEFT].yMin = 7500
set thistype[RIGHT].xCenter = 3104
set thistype[RIGHT].yCenter = 8064
set thistype[RIGHT].xMax = 3456
set thistype[RIGHT].xMin = 2752
set thistype[RIGHT].yMax = 8615
set thistype[RIGHT].yMin = 7500
endmethod
implement Init
method GetRandomX takes nothing returns real
return GetRandomReal(.xMin, .xMax)
endmethod
method GetRandomY takes nothing returns real
return GetRandomReal(.yMin, .yMax)
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
// Define teams with individual spawns
struct Team
readonly static thistype BLUE
readonly static thistype RED
Spawn spawn
string color
playercolor unitcolor
integer r
integer g
integer b
integer score
string name
readonly integer count
player array user[11]
public static method operator [] takes integer who returns thistype
return thistype(who)
endmethod
method add takes player p returns nothing
set this.count = this.count + 1
set this.user[this.count] = p
endmethod
method remove takes player p returns nothing
local integer i = 0
local integer j
local player temp
loop
exitwhen i > .count
if(.user[i] == p) then
loop
set j = i + 1
exitwhen j > .count
set .user[i] = .user[j]
set i = i + 1
endloop
set .count = .count - 1
exitwhen true
endif
set i = i + 1
endloop
endmethod
method sort takes nothing returns nothing
local integer i
local integer offset
if(.count < 1)then
return
endif
set i = 0
loop
exitwhen i > .count
set QuickSortValue[i] = KD[.user[i]].kills
set QuickSortIndex[i] = GetPlayerId(.user[i])
set i = i + 1
endloop
call QuickSort(0, .count)
if this == BLUE then
set offset = 1
else
set offset = Team.BLUE.count + 3
endif
set i = 0
loop
exitwhen i > .count
set offset = offset + 1
set user[i] = Player(QuickSortIndex[i])
set Board.playerRow[QuickSortIndex[i]] = offset
call Board.update(.user[i])
set i = i + 1
endloop
endmethod
static method onLeave takes nothing returns nothing
call User[GetTriggerPlayer()].team.remove(GetTriggerPlayer())
endmethod
private static method init takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
local thistype this
call TriggerAddAction(t, function thistype.onLeave)
loop
exitwhen i > 11
call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_LEAVE)
call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_DEFEAT)
set i = i + 1
endloop
set BLUE = allocate()
set this = BLUE
set this.spawn = Spawn.LEFT
set this.color = Color[1]
set this.r = 85
set this.g = 85
set this.b = 255
set this.unitcolor = PLAYER_COLOR_BLUE
set this.name = this.color + "Blue Team|r"
set this.count = -1
set RED = allocate()
set this = RED
set this.spawn = Spawn.RIGHT
set this.color = Color[0]
set this.r = 255
set this.g = 85
set this.b = 85
set this.unitcolor = PLAYER_COLOR_RED
set this.name = this.color + "Red Team|r"
set this.count = -1
endmethod
implement Init
endstruct
//TESH.scrollpos=2
//TESH.alwaysfold=0
// each user belongs to a team
// each user owns a slider
struct User
Team team
Slider slider
public static method operator [] takes player who returns thistype
return thistype(GetPlayerId(who)+1)
endmethod
private static method init takes nothing returns nothing
local integer i = 0
local player p
loop
exitwhen i > 5
set p = Player(i)
if PlayerTools.isPlayerUser(p) then
set thistype[p].team = Team.BLUE
call Team[Team.BLUE].add(p)
endif
set i = i + 1
endloop
loop
exitwhen i > 11
set p = Player(i)
if PlayerTools.isPlayerUser(p) then
call Team[Team.RED].add(p)
set thistype[p].team = Team.RED
endif
set i = i + 1
endloop
endmethod
implement Init
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
//! inject config
// Wow this shit needs to be takes from .j file.
call SetMapName("TRIGSTR_010")
call SetMapDescription("TRIGSTR_300")
call SetPlayers(12)
call SetTeams(12)
call SetGamePlacement(MAP_PLACEMENT_TEAMS_TOGETHER)
call PlayMusic("war3mapImported\\PureAndTheTainted.mp3")
call DefineStartLocation(0, - 13952.0, 8192.0)
call DefineStartLocation(1, - 13952.0, 8192.0)
call DefineStartLocation(2, - 13952.0, 8192.0)
call DefineStartLocation(3, - 13952.0, 8192.0)
call DefineStartLocation(4, - 13952.0, 8192.0)
call DefineStartLocation(5, - 13952.0, 8192.0)
call DefineStartLocation(6, 5760.0, 8128.0)
call DefineStartLocation(7, 5760.0, 8128.0)
call DefineStartLocation(8, 5760.0, 8128.0)
call DefineStartLocation(9, 5760.0, 8128.0)
call DefineStartLocation(10, 5760.0, 8128.0)
call DefineStartLocation(11, 5760.0, 8128.0)
// Player setup
call InitCustomPlayerSlots()
call InitCustomTeams()
call InitAllyPriorities()
//! endinject
//TESH.scrollpos=0
//TESH.alwaysfold=0
library GameHandler initializer Init uses Default
globals
integer SCORE_BLUE
integer SCORE_RED
integer SCORE_MAX
string PICKMODE
boolean Firstblood
integer startcounter
endglobals
function ShowDialog_car takes player p returns nothing
call DialogDisplay(p, dialog_car, true)
endfunction
function ShowDialog_score takes player p returns nothing
call DialogDisplay(p, dialog_score, true)
endfunction
function ShowDialog_pickmode takes player p returns nothing
call DialogDisplay(p, dialog_pickmode, true)
endfunction
function ScoreDisplayRefresh takes nothing returns nothing
local integer j = 0
loop
exitwhen j > 11
call SetPlayerState(Player(j), PLAYER_STATE_RESOURCE_FOOD_USED, SCORE_MAX)
call SetPlayerState(Player(j), PLAYER_STATE_RESOURCE_GOLD, Team(Team.BLUE).score)
call SetPlayerState(Player(j), PLAYER_STATE_RESOURCE_LUMBER, Team(Team.RED).score)
set j = j + 1
endloop
endfunction
function IsPlayerActive takes player p returns boolean
return GetPlayerController(p) == MAP_CONTROL_USER and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING
endfunction
function SetMaxScore takes integer i returns nothing
set SCORE_MAX = i
call Print(Color[5] + "Game-Mode: |r" + I2S(SCORE_MAX) + " score to win.", 8)
call ScoreDisplayRefresh()
endfunction
function SliderRemoveAll takes nothing returns nothing
local Slider s
set s = Slider.first
loop
exitwhen s == 0
call KillUnit(s.slider)
call s.destroy()
set s = s.next
endloop
endfunction
function PickModeDialog_Start takes nothing returns nothing
local integer i = 0
set KD.firstblood = false
loop
if IsPlayerActive(Player(i))then
call ShowDialog_pickmode(Player(i))
call Sound[PREPARE].play(0, 0, 0, 200)
call ReleaseTimer(GetExpiredTimer())
return
endif
set i = i + 1
exitwhen i > 11
endloop
call ReleaseTimer(GetExpiredTimer())
endfunction
function ScoreCarDialog_Start takes nothing returns nothing
local integer i = 0
loop
if IsPlayerActive(Player(i))then
call ShowDialog_car(Player(i))
endif
set i = i + 1
exitwhen i > 11
endloop
call ReleaseTimer(GetExpiredTimer())
endfunction
function SliderScores takes Slider s returns nothing
local integer j = 0
local string scoreString
local User user = User[s.owner]
set user.team.score = user.team.score + 1
set scoreString = "[" + Team(Team.BLUE).color + I2S(Team(Team.BLUE).score) + "|r]" + " : " + "[" + Team(Team.RED).color + I2S(Team(Team.RED).score) + "|r]"
call Print(User[s.owner].team.color + GetPlayerName(s.owner) + "|r scores! " + scoreString, 8)
set KD[s.owner].score = KD[s.owner].score + 1
if ModuloInteger(KD[s.owner].score, 3) == 0 then
call Sound[HATTRICK].play(0, 0, 0, 200)
endif
call Sound[GOODJOB].play(GetUnitX(s.slider), GetUnitY(s.slider), 0, 200)
set KD.enabled = false
call SliderRemoveAll()
set KD.enabled = true
call ScoreDisplayRefresh()
if( user.team.score >= SCORE_MAX)then
call Print(User[s.owner].team.name + " has won!", 9)
call StopMusic( false )
call PlayMusic(gg_snd_War2IntroMusic)
call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_MUSIC, 2)
call GameEnd()
else
call TimerStart(NewTimer(), 2, false, function PickModeDialog_Start)
endif
endfunction
function Cars_AllRandom takes nothing returns nothing
local integer i = 0
loop
if IsPlayerActive(Player(i))then
call NewRandomSlider(Player(i))
endif
set i = i + 1
exitwhen i > 11
endloop
call ReleaseTimer(GetExpiredTimer())
endfunction
function StartPlaySound takes nothing returns nothing
set startcounter = startcounter + 1
if startcounter > 3 then
if PICKMODE == "Pick" then
call TimerStart(GetExpiredTimer(), 0.1, false, function ScoreCarDialog_Start)
elseif PICKMODE == "Random" then
call TimerStart(GetExpiredTimer(), 0.1, false, function Cars_AllRandom)
endif
call Sound[PLAY].play(0, 0, 0, 200)
call Print(" ", 0)
call Print(Color[7] + " ~ Play! ~|r", 4.5)
else
call Sound[TICK].play(0, 0, 0, 200)
call Print(Color[12] + I2S(startcounter) + "|r", 1.2)
endif
endfunction
function PlayerToSpawn takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 11
if User[LOCAL_PLAYER].team == Team.RED then
call PanCameraToTimed(Spawn[Team.RED].xCenter, Spawn[Team.RED].yCenter, 1)
elseif User[LOCAL_PLAYER].team == Team.BLUE then
call PanCameraToTimed(Spawn[Team.BLUE].xCenter, Spawn[Team.BLUE].yCenter, 1)
endif
set i = i + 1
endloop
endfunction
function SetPickMode takes string s returns nothing
set PICKMODE = s
call ClearTextMessages()
call PlayerToSpawn()
call Print(Color[5] + "Game-Mode: |r" + I2S(SCORE_MAX) + " score to win.", 9)
call Print(Color[5] + "Game-Mode: |rAll " + s, 9)
call Print(" ", 0)
set startcounter = 0
call TimerStart(NewTimer(), 1, true, function StartPlaySound)
endfunction
function PickModeDialog_End takes nothing returns nothing
//
endfunction
function ScoreModeDialog_End takes nothing returns nothing
call TimerStart(NewTimer(), 0.5, false, function PickModeDialog_Start)
endfunction
function ScoreModeDialog_Start takes nothing returns nothing
local integer i = 0
loop
if IsPlayerActive(Player(i))then
call ShowDialog_score(Player(i))
call Sound[STARTROUND].play(0, 0, 0, 200)
call ReleaseTimer(GetExpiredTimer())
return
endif
set i = i + 1
exitwhen i > 11
endloop
call ReleaseTimer(GetExpiredTimer())
endfunction
function SomeMusicRandomLoliloOaSettings takes nothing returns nothing
call PlayMusic(gg_snd_PH1)
call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_MUSIC, 2)
call VolumeGroupSetVolume(SOUND_VOLUMEGROUP_AMBIENTSOUNDS, 2)
call ReleaseTimer(GetExpiredTimer())
endfunction
function MusicStop takes nothing returns nothing
call StopMusic( false )
call ReleaseTimer(GetExpiredTimer())
endfunction
private function Init takes nothing returns nothing
call TimerStart(NewTimer(), 0., false, function MusicStop)
call TimerStart(NewTimer(), 0.5, false, function SomeMusicRandomLoliloOaSettings)
call TimerStart(NewTimer(), 2., false, function ScoreModeDialog_Start)
call CinematicFadeBJ( bj_CINEFADETYPE_FADEOUT, 0, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
call CinematicFadeBJ( bj_CINEFADETYPE_FADEIN, 3.00, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library CreateSlider uses Default
function NewSlider takes player who, integer unitId returns nothing
local real x = User[who].team.spawn.GetRandomX()
local real y = User[who].team.spawn.GetRandomY()
local unit u
set User[who].slider = Slider.create(CreateUnit(who, unitId, x, y, GetRandomReal(0, 360)))
call Board.update(who)
set u = User[who].slider.slider
call SetUnitVertexColor(u, User[who].team.r, User[who].team.g, User[who].team.b, 255)
call SetUnitColor(u, User[who].team.unitcolor)
call CurrentShootAbility.apply(u, DefaultShootAbility[u])
if (LOCAL_PLAYER == who) then
call SetCameraTargetController(u, 0, 0, false)
call SelectUnit(u, true)
endif
set u = null
endfunction
function NewRandomSlider takes player who returns nothing
local real x = User[who].team.spawn.GetRandomX()
local real y = User[who].team.spawn.GetRandomY()
local unit u
set User[who].slider = Slider.create(CreateUnit(who, Hero[GetRandomInt(1, Hero.counter)], x, y, GetRandomReal(0, 360)))
call Board.update(who)
set u = User[who].slider.slider
call SetUnitVertexColor(u, User[who].team.r, User[who].team.g, User[who].team.b, 255)
call SetUnitColor(u, User[who].team.unitcolor)
call CurrentShootAbility.apply(u, DefaultShootAbility[u])
if (LOCAL_PLAYER == who) then
call SetCameraTargetController(u, 0, 0, false)
call SelectUnit(u, true)
endif
set u = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope LeaveSystem initializer Init
private function onLeave takes nothing returns nothing
local player p = GetTriggerPlayer()
if (User[p].slider.slider != null) then
call User[p].slider.destroy()
endif
call Print(User[p].team.color + GetPlayerName(p) + "|r has left the game.", 8)
call TimerStart(NewTimer(),0.1,false,function Board.NewBoard)
endfunction
private function Init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > 11
call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_LEAVE)
call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_DEFEAT)
set i = i + 1
endloop
call TriggerAddAction(t, function onLeave)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
library GameEnd uses Default
function KickPlayers takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 11
call CustomVictoryBJ( Player(i), false, false )
set i = i + 1
endloop
call ReleaseTimer(GetExpiredTimer())
endfunction
function GameEnd takes nothing returns nothing
call CinematicFadeBJ( bj_CINEFADETYPE_FADEOUT, 6.00, "ReplaceableTextures\\CameraMasks\\Black_mask.blp", 0, 0, 0, 0 )
call TimerStart(NewTimer(), 6, false, function KickPlayers)
endfunction
endlibrary
//TESH.scrollpos=31
//TESH.alwaysfold=0
struct KD
public static boolean enabled = true
public static boolean firstblood
integer streak_current
integer streak_max
integer deaths
integer kills
real kd
integer score
integer score_loaded
integer streak_loaded
integer kills_loaded
integer deaths_loaded
integer kd_loaded
public static method operator [] takes player who returns thistype
return thistype(GetPlayerId(who)+1)
endmethod
public static method apply takes player killer, player victim returns nothing
if null != killer then
set KD[killer].kills = KD[killer].kills + 1
set KD[killer].streak_current = KD[killer].streak_current + 1
if (KD[killer].streak_current > KD[killer].streak_max) then
set KD[killer].streak_max = KD[killer].streak_current
endif
call ApplyPendingTextTag(User[killer].slider, User[killer].team.color + "Kills +1|r", 8, 1.5, 3, 0, 85, GetRandomReal(90-15, 90+15))
if not firstblood then
call Sound[FIRSTBLOOD].play(GetUnitX(User[killer].slider.slider), GetUnitY(User[killer].slider.slider), 0, 200)
set firstblood = true
endif
if(KD[killer].streak_current > 2) then
if (KD[killer].streak_current > 12) then
call Sound[13].play(GetUnitX(User[killer].slider.slider), GetUnitY(User[killer].slider.slider), 0, 200)
else
call Sound[KD[killer].streak_current].play(GetUnitX(User[killer].slider.slider), GetUnitY(User[killer].slider.slider), 0, 200)
endif
endif
if(KD[killer].deaths > 0) then
set KD[killer].kd = R2I(KD[killer].kills)/R2I(KD[killer].deaths)
else
set KD[killer].kd = KD[killer].kills
endif
call Board.update(killer)
call Print(User[killer].team.color + GetPlayerName(killer) + " |r(" + I2S(KD[killer].streak_current) + ") killed " + User[victim].team.color + GetPlayerName(victim) + " |r(" + I2S(KD[victim].streak_current) + ")" , 7)
else
call Print(User[killer].team.color + GetPlayerName(victim) + " (" + I2S(KD[victim].streak_current) + ") " + "|r died.", 5)
endif
call Team.BLUE.sort()
call Team.RED.sort()
set KD[victim].streak_current = 0
set KD[victim].deaths = KD[victim].deaths + 1
set KD[victim].kd = R2I(KD[victim].kills)/R2I(KD[victim].deaths)
call Board.update(victim)
endmethod
endstruct
//TESH.scrollpos=86
//TESH.alwaysfold=0
struct Respawn
public static integer counter_max = 6
public static constant real COLLISION = 100.
texttag tt
integer counter
timer clock
timer circle_clock
unit circle
boolean enabled
real x
real y
unit reviver
public static method operator [] takes player who returns thistype
return thistype(GetPlayerId(who)+1)
endmethod
method revive takes unit reviver returns nothing
local real x
local real y
if(null == reviver) then
set x = User(this).team.spawn.GetRandomX()
set y = User(this).team.spawn.GetRandomY()
else
set x = GetUnitX(reviver)
set y = GetUnitY(reviver)
endif
set .enabled = false
call ReviveHero(User(this).slider.slider, x, y, true)
if(User(this).slider.owner == LOCAL_PLAYER)then
call SelectUnit(User(this).slider.slider, true)
endif
call PauseTimer(.clock)
call PauseTimer(.circle_clock)
call SetTextTagVisibility(.tt, false)
call ShowUnit(.circle, false)
endmethod
private static method circleCheck takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local Slider s = Slider.first
loop
exitwhen s == 0
if UnitAlive(s.slider) and User[s.owner].team == User(this).team and /*
*/SquareRoot((GetUnitX(s.slider)-.x) * (GetUnitX(s.slider)-.x) + (GetUnitY(s.slider)-.y) * (GetUnitY(s.slider)-.y)) < .COLLISION then
call .revive(s.slider)
endif
set s = s.next
endloop
endmethod
private static method callback takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
if(.counter <= 1) then
call .revive(null)
else
set .counter = .counter - 1
call SetTextTagText(.tt, User(this).team.color + I2S(.counter), 0.023)
endif
endmethod
public static method apply takes player p returns nothing
local thistype this = Respawn[p]
set this.counter = counter_max
call TimerStart(.clock, 1, true, function thistype.callback)
call TimerStart(.circle_clock, 0.075, true, function thistype.circleCheck)
call SetTextTagVisibility(.tt, true)
call SetTextTagText(.tt, User(this).team.color + I2S(.counter), 0.023)
call SetTextTagPosUnit(tt, User(this).slider.slider, 50)
set .x = GetUnitX(User(this).slider.slider)
set .y = GetUnitY(User(this).slider.slider)
set .enabled = true
call SetUnitX(.circle, x)
call SetUnitY(.circle, y)
call ShowUnit(.circle, true)
call UnitRemoveAbility(.circle, 'Aloc')
call UnitAddAbility(.circle, 'Aloc')
endmethod
private static method setup takes nothing returns nothing
local integer i = 1
local thistype this
call ReleaseTimer(GetExpiredTimer())
loop
set this = Respawn(i)
set .tt = CreateTextTag()
call SetTextTagPermanent(.tt, true)
call SetTextTagVisibility(.tt, false)
call SetTextTagColor(.tt, 255, 255, 255, 255)
set .clock = NewTimerEx(Respawn(i))
set .circle_clock = NewTimerEx(Respawn(i))
set .circle = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), SAVE_CIRCLE, 0, 0, 0)
if User(i).team == Team.BLUE then
call SetUnitVertexColor(.circle, 0, 0, 200, 255)
else
call SetUnitVertexColor(.circle, 200, 0, 0, 255)
endif
call ShowUnit(.circle, false)
set i = i + 1
exitwhen i > 12
endloop
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(NewTimer(), 0, false, function thistype.setup)
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct Kill
private static method onDeath takes nothing returns nothing
local unit u = GetTriggerUnit()
local player killerOwner
local player victimOwner
local RangeData rangeElement
if KD.enabled and Slider.isUnitSlider(u) then
call SetHeroLevel(u, 1, false)
if IsUnitType(GetKillingUnit(), UNIT_TYPE_HERO) then
set killerOwner = GetOwningPlayer(GetKillingUnit())
else
set killerOwner = null
endif
set victimOwner = GetOwningPlayer(u)
call KD.apply(killerOwner, victimOwner)
call Respawn.apply(victimOwner)
call CurrentShootAbility.apply(u, DefaultShootAbility[u])
call SetUnitMaxState(u, UNIT_STATE_MAX_MANA, 0)
if GetUnitAbilityLevel(u, RANGE_OFF) != 0 then
set rangeElement = Slider[u].RangeList.first
loop
exitwhen 0 == rangeElement
call KillUnit(rangeElement.u)
set rangeElement.u = null
set rangeElement = rangeElement.next
endloop
set Slider[u].showRange = false
call Slider[u].RangeList.clear()
call UnitRemoveAbility(u, RANGE_OFF)
call UnitAddAbility(u, RANGE_ON)
endif
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH )
call TriggerAddAction(t, function thistype.onDeath)
endmethod
endstruct
//TESH.scrollpos=244
//TESH.alwaysfold=0
struct Flag extends array
readonly static constant integer BLUE = 1
readonly static constant integer RED = 2
private static key k
private static Table table = k
static constant real COLLISION = 120
static constant real INTERVAL = 0.075
real x
real y
real x_goal
real y_goal
real angle
unit flag
Slider holder
timer clock
boolean captured
boolean saveable
real scale_captured
real scale_default
string name
boolean enabled
real zOffset
Team team
// call SetUnitVertexColor(.flagPointer_blue, 20, 150, 255, 255)
// call SetUnitVertexColor(.flagPointer_red, 255, 55, 55, 255)
public static method operator [] takes unit who returns thistype
return thistype.table[GetHandleId(who)]
endmethod
private method save takes Slider s returns nothing
local Slider sl = Slider.first
loop
exitwhen sl == 0
if this == Flag.BLUE then
call SetUnitVertexColor(sl.flagPointer_blue, 255, 240, 0, 150)
else
call SetUnitVertexColor(sl.flagPointer_red, 255, 240, 0, 150)
endif
set sl = sl.next
endloop
if(s == 0)then
call Print(.name + " has returned to base", 6)
set table[GetHandleId(.holder.slider)] = 0
call UnitRemoveAbility(.holder.slider, FLAG_DROP)
set .holder.flag = 0
set .holder = 0
call SetUnitScale(.flag, .scale_default, 0, 0)
set .captured = false
else
call Print(.name + "saved by " + GetPlayerName(s.owner), 6)
set .saveable = false
endif
call Sound[RESCUE].play(GetUnitX(.flag), GetUnitY(.flag), 50, 200)
call SetUnitX(.flag, .x)
call SetUnitY(.flag, .y)
call SetUnitFacing(.flag, .angle)
call Sound[RESCUE].play(0, 0, 0, 150)
endmethod
private method capture takes Slider s returns nothing
local Slider sl = Slider.first
loop
exitwhen sl == 0
if this == Flag.BLUE then
call SetUnitVertexColor(sl.flagPointer_blue, 20, 20, 255, 150)
else
call SetUnitVertexColor(sl.flagPointer_red, 255, 20, 20, 150)
endif
set sl = sl.next
endloop
set .captured = true
set .saveable = false
set s.flag = this
set .holder = s
call SetUnitScale(.flag, .scale_captured, 0, 0)
call UnitAddAbility(.holder.slider, FLAG_DROP)
set table[GetHandleId(s.slider)] = this
call Print(.name + "captured by " + GetPlayerName(s.owner), 7)
call Sound[WARNING].play(0, 0, 0, 100)
endmethod
// is called from slider system
method updatePosition takes nothing returns nothing
local real x = GetUnitX(.holder.slider)
local real y = GetUnitY(.holder.slider)
local real z = GetUnitFlyHeight(.holder.slider)
call SetUnitX(.flag, x)
call SetUnitY(.flag, y)
call SetUnitFlyHeight(.flag, z + .zOffset, 0)
call SetUnitFacingTimed(.flag, GetUnitFacing(.holder.slider), 0.3)
endmethod
method isDropable takes nothing returns boolean
local integer i = Teleport.counter
local Teleport tp
loop
exitwhen i < 1
set tp = Teleport(i)
if tp.isUnitInRange(.flag)then
return false
endif
set i = i - 1
endloop
return (GetTerrainType(GetUnitX(.flag), GetUnitY(.flag)) != SLIDE_SNOW)
endmethod
private static method removeAbility takes nothing returns nothing
call UnitRemoveAbility(Slider(GetTimerData(GetExpiredTimer())).slider, FLAG_DROP)
call ReleaseTimer(GetExpiredTimer())
endmethod
method drop takes nothing returns nothing
if .isDropable() then
set table[GetHandleId(.holder.slider)] = 0
call TimerStart(NewTimerEx(.holder), 0, false, function thistype.removeAbility)
set .holder.flag = 0
call Print(.name + " dropped by " + GetPlayerName(.holder.owner), 7)
set .holder = 0
call SetUnitScale(.flag, .scale_default, 0, 0)
set .captured = false
set .saveable = true
else
call .save(0)
endif
endmethod
private static method onDeath takes nothing returns nothing
local thistype this = thistype[GetTriggerUnit()]
if (this != 0 and KD.enabled)then
call .drop()
endif
endmethod
method reset takes nothing returns nothing
set table[GetHandleId(.holder.slider)] = 0
set .holder.flag = 0
set .holder = 0
call SetUnitScale(.flag, .scale_default, 0, 0)
set .captured = false
set .saveable = false
call SetUnitX(.flag, .x)
call SetUnitY(.flag, .y)
call SetUnitFacing(.flag, .angle)
endmethod
private method score takes nothing returns nothing
call SliderScores(.holder)
call TimerStart(NewTimerEx(.holder), 0, false, function thistype.removeAbility)
call Flag(BLUE).reset()
call Flag(RED).reset()
endmethod
private method filter_capture takes Slider s returns boolean
return IsUnitInRange(s.slider, .flag, thistype.COLLISION) and User[s.owner].team != .team /*
*/ and UnitAlive(s.slider)/*
*/ and not s.jump/*
*/ and not s.cata
endmethod
private method filter_save takes Slider s returns boolean
return IsUnitInRange(s.slider, .flag, thistype.COLLISION) and User[s.owner].team == .team /*
*/ and UnitAlive(s.slider)/*
*/ and not s.jump/*
*/ and not s.cata
endmethod
private static method callback takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local Slider s
if (.enabled)then
if(.captured)then
if IsUnitInRangeXY(.flag, x_goal, y_goal, thistype.COLLISION)then
call .score()
endif
return
endif
set s = Slider.first
loop
exitwhen s == 0
if .filter_capture(s) then
call .capture(s)
return
elseif .saveable and .filter_save(s) then
call .save(s)
return
endif
set s = s.next
endloop
endif
endmethod
private static method onCast takes nothing returns nothing
local thistype this = thistype[GetTriggerUnit()]
local real x
local real y
local real angle
if (this != 0)then
if GetSpellAbilityId() == FLAG_DROP then
set x = GetUnitX(.holder.slider)
set y = GetUnitY(.holder.slider)
set angle = GetUnitFacing(.holder.slider)*bj_DEGTORAD
call SetUnitX(.flag, x - 150 *Cos(angle))
call SetUnitY(.flag, y - 150 *Sin(angle))
if .isDropable() then
call .drop()
else
call SetUnitX(.flag, x)
call SetUnitY(.flag, y)
call ApplyErrorTextTag(.holder)
endif
endif
endif
endmethod
private static method onInit takes nothing returns nothing
local thistype this
local trigger t = CreateTrigger()
call TriggerAddAction(t, function thistype.onDeath)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
call RegisterSpellEffectEvent(FLAG_DROP, function thistype.onCast)
set this = Flag.BLUE
set .clock = NewTimerEx(this)
set .x = -13963
set .y = 8194
set .x_goal = 5758
set .y_goal = 8190
set .angle = 270
set .scale_captured = 1.5
set .scale_default = 2.0
set .name = Color[1] + "Blue Flag |r"
set .team = Team[BLUE]
set .zOffset = .55
set .flag = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), FLAG_BLUE, .x, .y, .angle)
set .enabled = true
call TimerStart(.clock, Flag.INTERVAL, true, function thistype.callback)
set this = Flag.RED
set .clock = NewTimerEx(this)
set .x = 5758
set .y = 8190
set .x_goal = -13962
set .y_goal = 8190
set .angle = 270
set .scale_captured = 1
set .scale_default = 1.4
set .name = Color[0] + "Red Flag |r"
set .team = Team[RED]
set .zOffset = .10
set .enabled = true
set .flag = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), FLAG_RED, .x, .y, .angle)
call TimerStart(.clock, Flag.INTERVAL, true, function thistype.callback)
endmethod
endstruct
//TESH.scrollpos=559
//TESH.alwaysfold=0
library SlidingSystem/* v3.4 By IcemanBo -- much specified for Battle of Flags
*/ requires /*
*/ UnitIndexer /* The one in test map. (by Nestharus v4.0.2.6)
*/ TimerUtils /* http://www.wc3c.net/showthread.php?t=101322
*/ Table /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*/ WorldBounds /* https://github.com/nestharus/JASS/blob/master/jass/Systems/WorldBounds/script.j
*/ Event /* The one in test map.
*/ TextHandler /*
** Info
** ¯¯¯¯¯¯¯¯
**
** Sliders can have a special sliding behaviour on different terrain types.
** Each slider also can have it's own movement speed while sliding,
** seperated and indepentand from the terrain type.
**
** This library provides various possibilities
** to create an individual behaviour for each terrain type. (Config - Part)
**
**
** Struct Terrain:
**
**
** static method create takes integer terainType, real terrainSpeed returns thistype
**
** Furthermore you can define and read these public members:
** (by default all values are "0" or "false".
**
** pullSpeed = Unit will be constantly pulled with this speed. (real)
** pullDirection = Direction for pulling, in degrees. (real)
** angle = Angle that will be added, when steering. (real)
** lifeAddition = Life that will be added each second. Negagtive values are also possible. (real)
** allowSteer = If unit can steer on the tarrainType or not. (boolean)
** allowCast = If unit can cast on the terrainType or not. (boolean)
** kill = Kill the unit on the terrainType or not. (boolean)
**
**
** You can have a look into folder TestMap -> "Terrain Settings" for a better understanding and examples.
**
**
** Struct Slider:
**
**
** static methods:
** ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
**
** static method create takes unit u returns thistype
**
** static method getSliderId takes unit u returns thistype
**
** static method isUnitSlider takes unit u returns boolean
**
**
**
** methods:
** ¯¯¯¯¯¯¯¯¯¯
**
** method destroy takes nothing returns nothing
**
** method enable takes boolean b returns nothing (disabled instance can't slide)
**
** method isEnabled takes nothing returns boolean
**
** method getDefaultSpeed takes nothing returns real
**
** method getTempSpeed takes nothing returns real
**
** method setDefaultSpeed takes real s returns nothing
**
** method addDefaultSpeed takes real s returns nothing
**
** method addTempSpeed takes real speed, real duration returns nothing
**
**
**
** Deindexed units will be automatically removed from system.
** You can have a look into folder TestMap -> "Create Slider" for a better understanding and examples.
**
***************************************************************************
**
** Credits to guys named in brackets.
**
** Requires:
** - Table (Bribe)
** - TimerUtils (Vexorian)
** - UnitIndexer (Nestharus)
** • WorldBounds (Nestharus)
** • Event (Nestharus)
**
**
**************************************************************************
*
*
************************ Configuration - Start ***************************/
globals
private constant boolean SLIDER_UNCLICKABLE = true // Make Slider unclickable.
private constant boolean SLIDER_NO_PATHING = true // Disable pathing for Slider.
private constant boolean CHECK_PATHING = true // Check for pathability while sliding.
/************************ Configuration - End *****************************/
private trigger steerTrigger = CreateTrigger()
private trigger moveTrigger = CreateTrigger() // Sliding looks smoother with trigger instead of a timer.
constant real STUN_TIMEOUT = 1.5
endglobals
/*
* Terrain struct, to define sliding behaviour.
*/
native UnitAlive takes unit u returns boolean
struct Terrain
private static key k
static Table table = k
readonly integer terrainType
real factor
real speed
real pullSpeed = 0
real pullDirection = 0
real angle = 0
real lifeAddition = 0
boolean allowSteer = false
boolean allowCast = false
boolean kill = false
boolean stun
static method create takes integer whichTerrain returns thistype
local thistype this = thistype.allocate()
set thistype.table[whichTerrain] = this
set this.terrainType = whichTerrain
set this.speed = DEFAULT_SPEED
return this
endmethod
static method operator [] takes integer i returns thistype
return thistype.table[i]
endmethod
endstruct
/*
* Acceleration struct, to manipulate Slider's temporary speed
*/
private struct Acceleration
public timer tim
public real speedChange
public Slider instance
static method create takes Slider slider, real speed returns thistype
local thistype this = thistype.allocate()
set this.instance = slider
set this.speedChange = speed
return this
endmethod
method destroy takes nothing returns nothing
call this.deallocate()
call ReleaseTimer(tim)
endmethod
endstruct
struct RangeData extends array
static constant real OFFSET = 500.
implement List
unit u
real angle
real change
endstruct
struct TextData extends array
implement List
texttag t
real x
real z
endstruct
struct Slider extends array
static thistype array sliderlist
static boolean array is // Is unit a slider
unit slider
public real defaultSpeed // Permanent speed
public real bonusSpeed // Temporary speed
boolean steer
boolean stunned
real stunnedTime
effect stunEffect
integer snowCount
boolean snowImmune
boolean jump
boolean cata
player owner
boolean invisible
boolean roots
boolean showRange
RangeData RangeList
real rangeTime
boolean rangeChangePositive
real rangeChange
TextData TextList
Flag flag
boolean pointToFlag
unit flagPointer_blue
unit flagPointer_red
real propWindow
real turnSpeed
boolean enabled // If slider is currently enabled.
thistype prev
thistype next
static thistype first = 0
static method operator [] takes unit u returns thistype
return thistype(GetUnitUserData(u))
endmethod
static method isUnitSlider takes unit u returns boolean
return is[GetUnitUserData(u)]
endmethod
static method create takes unit u returns thistype
local thistype this = GetUnitUserData(u)
set this.TextList = TextData.create()
set this.RangeList = RangeData.create()
set is[this] = true
set .owner = GetOwningPlayer(u)
set .snowImmune = false
set .slider = u
set .enabled = true
set .steer = true
set .stunned = false
set .snowCount = 0
set .cata = false
set .stunnedTime = 0
set .snowCount = 0
set .snowImmune = false
set .jump = false
set this.propWindow = GetUnitDefaultPropWindow(slider)*bj_RADTODEG
set this.turnSpeed = GetUnitDefaultTurnSpeed(slider)
if UnitAddAbility(u,'Amrf') and UnitRemoveAbility(u,'Amrf')then
endif
call UnitAddAbility(u,'Aloc')
call ShowUnit(u,false)
call ShowUnit(u,true)
call UnitRemoveAbility(u,'Aloc')
call SetUnitPathing( u, false )
if (thistype.first == 0) then
call EnableTrigger(moveTrigger)
endif
call UnitAddAbility(u, CAM_UNLOCK)
set .pointToFlag = true
set showRange = false
set .flagPointer_blue = CreateUnit(.owner, 'fPoi', 0, 0, 270)
set .flagPointer_red = CreateUnit(.owner, 'fPoi', 0, 0, 270)
call SetUnitVertexColor(.flagPointer_blue, 255, 240, 0, 150)
call SetUnitVertexColor(.flagPointer_red, 255, 240, 0, 150)
if LOCAL_PLAYER != .owner then
call ShowUnit(.flagPointer_blue, false)
call ShowUnit(.flagPointer_red, false)
endif
call UnitAddAbility(.slider, FLAG_INDICATOR_OFF)
set .next = thistype.first
set thistype.first.prev = this
set thistype.first = this
set .prev = 0
return this
endmethod
method destroy takes nothing returns nothing
call .TextList.destroy()
call .RangeList.destroy()
set is[this] = false
call RemoveUnit(.flagPointer_blue)
call RemoveUnit(.flagPointer_red)
call RemoveUnit(.slider)
set .slider = null
set .flagPointer_blue = null
set .flagPointer_red = null
call DestroyEffect(.stunEffect)
set .stunEffect = null
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 DisableTrigger(moveTrigger)
endif
endmethod
private method stunMove takes nothing returns nothing
local real x1
local real y1
local real x2
local real y2
local real x3
local real y3
local real angle
if this.snowCount > 3 then
call ApplyPendingTextTag(this, Color[8] + "Too long in snow!|r", 16, 1.5, 2.5, 0, 100, GetRandomReal(90-15, 90+15))
call KillUnit(slider)
set this.snowCount = 0
return
endif
set this.snowCount = this.snowCount + 1
// Go forward -- if there's snow then go backward
set angle = GetUnitFacing(this.slider)*bj_DEGTORAD
set x1 = GetUnitX(this.slider) - 160*Cos(angle)
set y1 = GetUnitY(this.slider) - 160*Sin(angle)
if Terrain[GetTerrainType(x1, y1)].stun then
set x1 = GetUnitX(this.slider) + 160*Cos(angle)
set y1 = GetUnitY(this.slider) + 160*Sin(angle)
endif
// Go left and right from point from above
set x2 = x1 + 150*Cos(angle+bj_PI/2)
set y2 = y1 + 150*Sin(angle+bj_PI/2)
set x3 = x1 + 150*Cos(angle-bj_PI/2)
set y3 = y1 + 150*Sin(angle-bj_PI/2)
// If both are snow or both are not snow then move to first point above
if (Terrain[GetTerrainType(x2, y2)].stun and Terrain[GetTerrainType(x3, y3)].stun)/*
*/or not (Terrain[GetTerrainType(x2, y2)].stun or Terrain[GetTerrainType(x3, y3)].stun) then
// To interrupt current order so unit doesnt run in snow again
call SetUnitPosition(this.slider, x1, y1)
else
// go to the one that is not snow
if (Terrain[GetTerrainType(x2, y2)].stun) then
call SetUnitPosition(this.slider, x3, y3)
else
call SetUnitPosition(this.slider, x2, y2)
endif
endif
set stunEffect = AddSpecialEffectTarget("Abilities\\Spells\\Orc\\LightningShield\\LightningShieldTarget.mdl", this.slider, "chest large")
// Make slider moveable.
call SetUnitPropWindow(slider, propWindow )
call SetUnitTurnSpeed(slider, turnSpeed)
call SetUnitMoveSpeed(slider, 0)
endmethod
/*
* Sliding - Movement (periodic call)
*/
private static method onMove takes nothing returns nothing
local real angle
local real offset
local real x
local real y
local real x2
local real y2
local real z
local integer terrainType
local thistype this = thistype.first
local TextData element
local TextData temp
local RangeData rangeElement
local integer i = 0
loop
exitwhen this == 0
if enabled and UnitAlive(this.slider) and not .cata and not .roots then
set x = GetUnitX(slider)
set y = GetUnitY(slider)
set terrainType = GetTerrainType(x, y)
if this.stunned then
set this.stunnedTime = this.stunnedTime - INTERVAL
set this.stunned = this.stunnedTime > 0
if not (this.stunned) then
call DestroyEffect(this.stunEffect)
call SetUnitMoveSpeed(slider, GetUnitDefaultMoveSpeed(slider))
endif
// Check if slider is on a registered terrain type.
elseif (Terrain[terrainType] != 0) or jump then
if (Terrain[terrainType].kill) then
call KillUnit(slider)
else
if Terrain[terrainType].stun and not this.snowImmune then
set this.stunned = true
set this.stunnedTime = STUN_TIMEOUT
call this.stunMove()
else
set this.snowCount = 0
set angle = (GetUnitFacing(slider)*bj_DEGTORAD)
if((Terrain[terrainType] == 0) and jump) then
set offset = (defaultSpeed + bonusSpeed + DEFAULT_SPEED/TPS)
else
set offset = (defaultSpeed + bonusSpeed + Terrain[terrainType].speed/TPS)*Terrain[terrainType].factor
endif
// Heal/damage the slider.
call SetWidgetLife(slider,GetWidgetLife(slider) + Terrain[terrainType].lifeAddition/TPS)
set x = x + offset * Cos(angle)
set y = y + offset * Sin(angle)
// Sliding
static if (CHECK_PATHING) then
call SetUnitPosition(slider, x, y)
else
call SetUnitX(slider, x)
call SetUnitY(slider, y)
endif
// Check if terrain type is pulling.
if (Terrain[terrainType].pullSpeed != 0) then
static if (CHECK_PATHING) then
call SetUnitPosition(slider, x + (Terrain[terrainType].pullSpeed/TPS) * Cos(Terrain[terrainType].pullDirection*bj_DEGTORAD), y + (Terrain[terrainType].pullSpeed/TPS) * Sin(Terrain[terrainType].pullDirection*bj_DEGTORAD))
else
call SetUnitX(slider, x + (Terrain[terrainType].pullSpeed/TPS) * Cos(Terrain[terrainType].pullDirection*bj_DEGTORAD))
call SetUnitY(slider, y + (Terrain[terrainType].pullSpeed/TPS) * Sin(Terrain[terrainType].pullDirection*bj_DEGTORAD))
endif
endif
// Make slider unmoveable while sliding.
call SetUnitPropWindow(slider, 0)
call SetUnitTurnSpeed(slider, 0.00)
endif
endif
else
// Make slider moveable.
call SetUnitPropWindow(slider, propWindow )
call SetUnitTurnSpeed(slider, turnSpeed)
endif
if(.flag != 0)then
call .flag.updatePosition()
endif
if MagicWall.isInWallRange(.slider, 80) then
call KillUnit(.slider)
call ApplyPendingTextTag(this, Color[0] + "Arghh!|r", 6, 1.25, 2.25, 0, 100, GetRandomReal(90-15, 90+15))
call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Undead\\UDeathSmall\\UDeathSmall.mdl", .slider, "origin"))
endif
endif
if not .cata then
set x = GetUnitX(.slider)
set y = GetUnitY(.slider)
set z = GetUnitFlyHeight(.slider)
set element = .TextList.first
set i = 1
loop
// fuck you, List, for this shit
exitwhen 0 == element
set temp = element.next
if(element.t != null)then
call SetTextTagPos(element.t, x-element.x, y, element.z + z)
else
call element.remove()
endif
set element = temp
endloop
endif
if .pointToFlag then
set x = GetUnitX(.slider)
set y = GetUnitY(.slider)
set z = GetUnitFlyHeight(.slider)
if this == Flag(Flag.BLUE).holder then
set angle = GetUnitFacing(.slider)*bj_DEGTORAD
call SetUnitX(.flagPointer_blue, x + 70*Cos(angle))
call SetUnitY(.flagPointer_blue, y + 70*Sin(angle))
call SetUnitFlyHeight(.flagPointer_blue, z+150, 0)
else
set angle = Atan2(GetUnitY(Flag(Flag.BLUE).flag) - y , GetUnitX(Flag(Flag.BLUE).flag) - x)
call SetUnitX(.flagPointer_blue, x + 300*Cos(angle))
call SetUnitY(.flagPointer_blue, y + 300*Sin(angle))
call SetUnitFlyHeight(.flagPointer_blue, z, 0)
endif
if this == Flag(Flag.RED).holder then
set angle = GetUnitFacing(.slider)*bj_DEGTORAD
call SetUnitX(.flagPointer_red, x + 70*Cos(angle))
call SetUnitY(.flagPointer_red, y + 70*Sin(angle))
call SetUnitFlyHeight(.flagPointer_red, z+150, 0)
else
set angle = Atan2(GetUnitY(Flag(Flag.RED).flag) - y , GetUnitX(Flag(Flag.RED).flag) - x)
call SetUnitX(.flagPointer_red, x + 300*Cos(angle))
call SetUnitY(.flagPointer_red, y + 300*Sin(angle))
call SetUnitFlyHeight(.flagPointer_red, z, 0)
endif
endif
if (.showRange) then
if UnitAlive(.slider) then
set x = GetUnitX(.slider)
set y = GetUnitY(.slider)
set rangeElement = .RangeList.first
set .rangeTime = rangeTime + INTERVAL
if rangeTime > 4 then
if .rangeChange != 0 then
set .rangeChange = 0
set .rangeTime = 0
elseif .rangeChangePositive then
set .rangeChange = bj_PI/100
set .rangeChangePositive = not .rangeChangePositive
set .rangeTime = 0
else
set .rangeChange = -bj_PI/100
set .rangeChangePositive = not .rangeChangePositive
set .rangeTime = 0
endif
endif
loop
exitwhen 0 == rangeElement
set x2 = x + RangeData.OFFSET * Cos(rangeElement.angle)
set y2 = y + RangeData.OFFSET * Sin(rangeElement.angle)
if IsInBounds(x2, y2) then
call SetUnitX(rangeElement.u, x2)
call SetUnitY(rangeElement.u, y2)
endif
set rangeElement.angle = rangeElement.angle - .rangeChange
set rangeElement = rangeElement.next
endloop
else
set rangeElement = .RangeList.first
loop
exitwhen 0 == rangeElement
call KillUnit(rangeElement.u)
set rangeElement.u = null
set rangeElement = rangeElement.next
endloop
call .RangeList.destroy()
call UnitRemoveAbility(.slider, RANGE_OFF)
call UnitAddAbility(.slider, RANGE_ON)
set .showRange = false
endif
endif
set this = next
endloop
endmethod
/*
* Sliding - Steering
*/
private static method onTurn takes nothing returns boolean
local unit u = GetTriggerUnit()
local real x
local real y
local integer terrainType
local integer order = GetIssuedOrderId()
local boolean b = true
local thistype slider = thistype[u]
if (is[GetUnitUserData(u)] and slider.enabled) and not slider.cata then
set x = GetUnitX(u)
set y = GetUnitY(u)
set terrainType = GetTerrainType(x, y)
// Check if slider is on a registered terrain type.
if (Terrain[terrainType] != 0 and slider.steer) or slider.jump then
if( (order == SMART) and (Terrain[terrainType].allowSteer) or slider.stunned or slider.jump) then
// Let the slider turn.
call SetUnitFacing( u, (Atan2(GetOrderPointY() - y , GetOrderPointX() - x) * bj_RADTODEG) + Terrain[terrainType].angle)
elseif ((order != SMART) and (order != MOVE) and (order != PATROL) and (Terrain[terrainType].allowCast)) then
// The slider is casting an ability. Let him face wanted position, if allowed.
call SetUnitFacing( u, Atan2(GetOrderPointY() - y , GetOrderPointX() - x) * bj_RADTODEG)
set b = false
endif
if ((order == SMART) or (order == MOVE) or (order == PATROL) or (b)) then
call DisableTrigger( steerTrigger )
call PauseUnit (u,true)
call IssueImmediateOrderById(u, STOP) // That will abbort unit's order if unit is not casting.
call PauseUnit (u,false)
call EnableTrigger( steerTrigger )
endif
endif
endif
set u = null
return false
endmethod
method newText takes texttag text, real z returns TextData
local TextData element
set element = .TextList.enqueue()
set element.t = text
set element.z = z
return element
endmethod
// API - Start
method enable takes boolean b returns nothing
set enabled = b
endmethod
method isEnabled takes nothing returns boolean
return enabled
endmethod
method getDefaultSpeed takes nothing returns real
return defaultSpeed*TPS
endmethod
method getTempSpeed takes nothing returns real
return bonusSpeed*TPS
endmethod
/* Permanent Boost */
method setDefaultSpeed takes real s returns nothing
set defaultSpeed = s/TPS
endmethod
method addDefaultSpeed takes real s returns nothing
set defaultSpeed = defaultSpeed + s/TPS
endmethod
/* Temporary Boost */
private static method callback takes nothing returns nothing
local Acceleration this = GetTimerData(GetExpiredTimer())
set this.instance.bonusSpeed = this.instance.bonusSpeed - this.speedChange
call this.destroy()
endmethod
method addTempSpeed takes real speed, real duration returns nothing
local integer handleId
local Acceleration newData
if duration > 0 then
set speed = speed/TPS
set bonusSpeed = bonusSpeed + speed
set newData = Acceleration.create(this, speed)
set newData.tim = NewTimerEx(newData)
call TimerStart(newData.tim, duration, false, function thistype.callback)
else
debug call BJDebugMsg("Error - Sliding System - AddTempSpeed: Duration must be greater 0.")
endif
endmethod
// API - End
private static method onDeindex takes nothing returns boolean
if is[GetUnitUserData(GetIndexedUnit())] then
call thistype[GetIndexedUnit()].destroy()
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ( steerTrigger, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER )
call TriggerAddCondition(steerTrigger, Condition(function thistype.onTurn))
call TriggerRegisterTimerEvent(moveTrigger, INTERVAL, true)
call TriggerAddAction(moveTrigger, function thistype.onMove)
call DisableTrigger(moveTrigger)
call RegisterUnitIndexEvent(Condition(function thistype.onDeindex), UnitIndexer.DEINDEX)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct TerrainSettings extends array
private static method onInit takes nothing returns nothing
local integer TerrainType
set TerrainType = SLIDE_NORMAL
call Terrain.create(TerrainType)
set Terrain[TerrainType].allowSteer = true
set Terrain[TerrainType].factor = 1
set TerrainType = SLIDE_FAST
call Terrain.create(SLIDE_FAST)
set Terrain[TerrainType].allowSteer = true
set Terrain[TerrainType].factor = 2
set TerrainType = SLIDE_DARK
call Terrain.create(TerrainType)
set Terrain[TerrainType].factor = 1
set TerrainType = SLIDE_SNOW
call Terrain.create(TerrainType)
set Terrain[TerrainType].stun = true
set Terrain[TerrainType].allowSteer = true
set Terrain[TerrainType].factor = 1
endmethod
endstruct
//TESH.scrollpos=220
//TESH.alwaysfold=0
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//-=-=-= Terrain Type Constants by Darthfett =-=-=-=-=-
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//-=-=-=-= Thanks to Romek for the Raw Codes -=-=-=-=-
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
scope LORDAERONSUMMER
// Lordaeron Summer
globals
public constant integer DIRT = 'Ldrt'
public constant integer ROUGH_DIRT = 'Ldro'
public constant integer GRASSY_DIRT = 'Ldrg'
public constant integer ROCK = 'Lrok'
public constant integer GRASS = 'Lgrs'
public constant integer DARK_GRASS = 'Lgrd'
public constant integer DIRT_CLIFF = 'cLc2'
public constant integer GRASS_CLIFF = 'cLc1'
endglobals
endscope
scope LORDAERONFALL
// Lordaeron Fall
globals
public constant integer DIRT = 'Fdrt'
public constant integer ROUGH_DIRT = 'Fdro'
public constant integer GRASSY_DIRT = 'Fdrg'
public constant integer ROCK = 'Frok'
public constant integer GRASS = 'Fgrs'
public constant integer DARK_GRASS = 'Fgrd'
public constant integer DIRT_CLIFF = 'cFc2'
public constant integer GRASS_CLIFF = 'cFc1'
endglobals
endscope
scope LORDAERONWINTER
// Lordaeron Winter
globals
public constant integer DIRT = 'Wdrt'
public constant integer ROUGH_DIRT = 'Wdro'
public constant integer GRASSY_SNOW = 'Wsng'
public constant integer ROCK = 'Wrok'
public constant integer GRASS = 'Wgrs'
public constant integer SNOW = 'Wsnw'
public constant integer GRASS_CLIFF = 'cWc2'
public constant integer SNOW_CLIFF = 'cWc1'
endglobals
endscope
scope BARRENS
// Barrens
globals
public constant integer DIRT = 'Bdrt'
public constant integer ROUGH_DIRT = 'Bdrh'
public constant integer PEBBLES = 'Bdrr'
public constant integer GRASSY_DIRT = 'Bdrg'
public constant integer DESERT = 'Bdsr'
public constant integer DARK_DESERT = 'Bdsd'
public constant integer ROCK = 'Bflr'
public constant integer GRASS = 'Bgrr'
public constant integer DESERT_CLIFF = 'cBc2'
public constant integer GRASS_CLIFF = 'cBc1'
endglobals
endscope
scope ASHENVALE
// Ashenvale
globals
public constant integer DIRT = 'Adrt'
public constant integer ROUGH_DIRT = 'Adrd'
public constant integer GRASS = 'Agrs'
public constant integer ROCK = 'Arck'
public constant integer LUMPY_GRASS = 'Agrd'
public constant integer VINES = 'Avin'
public constant integer GRASSY_DIRT = 'Adrg'
public constant integer LEAVES = 'Alvd'
public constant integer DIRT_CLIFF = 'cAc2'
public constant integer GRASS_CLIFF = 'cAc1'
endglobals
endscope
scope FELWOOD
// Felwood
globals
public constant integer DIRT = 'Cdrt'
public constant integer ROUGH_DIRT = 'Cdrd'
public constant integer POISON = 'Cpos'
public constant integer ROCK = 'Crck'
public constant integer VINES = 'Cvin'
public constant integer GRASS = 'Cgrs'
public constant integer LEAVES = 'Clvg'
public constant integer DIRT_CLIFF = 'cCc2'
public constant integer GRASS_CLIFF = 'cCc1'
endglobals
endscope
scope NORTHREND
// Northrend
globals
public constant integer DIRT = 'Ndrt'
public constant integer DARK_DIRT = 'Ndrd'
public constant integer ROCK = 'Nrck'
public constant integer GRASS = 'Ngrs'
public constant integer ICE = 'Nice'
public constant integer SNOW = 'Nsnw'
public constant integer ROCKY_SNOW = 'Nsnr'
public constant integer DIRT_CLIFF = 'cNc2'
public constant integer SNOW_CLIFF = 'cNc1'
endglobals
endscope
scope CITYSCAPE
// Cityscape
globals
public constant integer DIRT = 'Ydrt'
public constant integer ROUGH_DIRT = 'Ydtr'
public constant integer BLACK_MARBLE = 'Yblm'
public constant integer BRICK = 'Ybtl'
public constant integer SQUARE_TILES = 'Ysqd'
public constant integer ROUND_TILES = 'Yrtl'
public constant integer GRASS = 'Ygsb'
public constant integer GRASS_TRIM = 'Yhdg'
public constant integer WHITE_MARBLE = 'Ywmb'
public constant integer DIRT_CLIFF = 'cYc2'
public constant integer SQUARE_TILES_CLIFF = 'cYc1'
endglobals
endscope
scope VILLAGE
// Village
globals
public constant integer DIRT = 'Vdrt'
public constant integer ROUGH_DIRT = 'Vdrr'
public constant integer CROPS = 'Vcrp'
public constant integer COBBLE_PATH = 'Vcbp'
public constant integer STONE_PATH = 'Vstp'
public constant integer SHORT_GRASS = 'Vgrs'
public constant integer ROCKS = 'Vrck'
public constant integer THICK_GRASS = 'Vgrt'
public constant integer DIRT_CLIFF = 'cVc2'
public constant integer GRASS_THICK_CLIFF = 'cVc1'
endglobals
endscope
scope VILLAGEFALL
// Village Fall
globals
public constant integer DIRT = 'Qdrt'
public constant integer ROUGH_DIRT = 'Qdrr'
public constant integer CROPS = 'Qcrp'
public constant integer COBBLE_PATH = 'Qcbp'
public constant integer STONE_PATH = 'Qstp'
public constant integer SHORT_GRASS = 'Qgrs'
public constant integer ROCKS = 'Qrck'
public constant integer THICK_GRASS = 'Qgrt'
public constant integer DIRT_CLIFF = 'cQc2'
public constant integer GRASS_THICK_CLIFF = 'cQc1'
endglobals
endscope
scope DALARAN
// Dalaran
globals
public constant integer DIRT = 'Xdrt'
public constant integer ROUGH_DIRT = 'Xdtr'
public constant integer BLACK_MARBLE = 'Xblm'
public constant integer BRICK_TILES = 'Xbtl'
public constant integer SQUARE_TILES = 'Xsqd'
public constant integer ROUND_TILES = 'Xrtl'
public constant integer GRASS = 'Xgsb'
public constant integer TRIM_GRASS = 'Xhdg'
public constant integer WHITE_MARBLE = 'Xwmb'
public constant integer DIRT_CLIFF = 'cXc2'
public constant integer SQUARE_TILES_CLIFF = 'cXc1'
endglobals
endscope
scope DUNGEON
// Dungeon
globals
public constant integer DIRT = 'Ddrt'
public constant integer BRICK = 'Dbrk'
public constant integer RED_STONES = 'Drds'
public constant integer LAVA_CRACKS = 'Dlvc'
public constant integer LAVA = 'Dlav'
public constant integer DARK_ROCKS = 'Ddkr'
public constant integer GREY_STONES = 'Dgrs'
public constant integer SQUARE_TILES = 'Dsqd'
public constant integer DIRT_CLIFF = 'cDc2'
public constant integer SQUARE_TILES_CLIFF = 'cDc1'
endglobals
endscope
scope UNDERGROUND
// Underground
globals
public constant integer DIRT = 'Gdrt'
public constant integer BRICK = 'Gbrk'
public constant integer RED_STONES = 'Grds'
public constant integer LAVA_CRACKS = 'Glvc'
public constant integer LAVA = 'Glav'
public constant integer DARK_ROCKS = 'Gdkr'
public constant integer GREY_STONES = 'Ggrs'
public constant integer SQUARE_TILES = 'Gsqd'
public constant integer DIRT_CLIFF = 'cGc2'
public constant integer SQUARE_TILES_CLIFF = 'cGc1'
endglobals
endscope
scope SUNKENRUINS
// Sunken Ruins
globals
public constant integer DIRT = 'Zdrt'
public constant integer ROUGH_DIRT = 'Zdtr'
public constant integer GRASSY_DIRT = 'Zdrg'
public constant integer SMALL_BRICKS = 'Zbks'
public constant integer SAND = 'Zsan'
public constant integer LARGE_BRICKS = 'Zbkl'
public constant integer ROUND_TILES = 'Ztil'
public constant integer GRASS = 'Zgrs'
public constant integer DARK_GRASS = 'Zvin'
public constant integer DIRT_CLIFF = 'cZc2'
public constant integer LARGE_BRICKS_CLIFF = 'cZc1'
endglobals
endscope
scope ICECROWNGLACIER
// Icecrown Glacier
globals
public constant integer DIRT = 'Idrt'
public constant integer ROUGH_DIRT = 'Idtr'
public constant integer DARK_ICE = 'Idki'
public constant integer BLACK_BRICKS = 'Ibkb'
public constant integer RUNE_BRICKS = 'Irbk'
public constant integer TILED_BRICKS = 'Itbk'
public constant integer ICE = 'Iice'
public constant integer BLACK_SQUARES = 'Ibsq'
public constant integer SNOW = 'Isnw'
public constant integer RUNE_BRICKS_CLIFF = 'cIc2'
public constant integer SNOW_CLIFF = 'cIc1'
endglobals
endscope
scope OUTLAND
// Outland
globals
public constant integer DIRT = 'Odrt'
public constant integer LIGHT_DIRT = 'Odtr'
public constant integer ROUGH_DIRT = 'Osmb'
public constant integer CRACKED_DIRT = 'Ofst'
public constant integer FLAT_STONES = 'Olgb'
public constant integer ROCK = 'Orok'
public constant integer LIGHT_FLAT_STONES = 'Ofsl'
public constant integer ABYSS = 'Oaby'
public constant integer ABYSS_CLIFF = 'cOc1'
public constant integer ROUGH_DIRT_CLIFF = 'cOc2'
endglobals
endscope
scope BLACKCITADEL
// Black Citadel
globals
public constant integer DIRT = 'Kdrt'
public constant integer LIGHT_DIRT = 'Kfsl'
public constant integer ROUGH_DIRT = 'Kdtr'
public constant integer FLAT_STONES = 'Kfst'
public constant integer SMALL_BRICKS = 'Ksmb'
public constant integer LARGE_BRICKS = 'Klgb'
public constant integer SQUARE_TILES = 'Ksqt'
public constant integer DARK_TILES = 'Kdkt'
public constant integer DIRT_CLIFF = 'cKc1'
public constant integer DARK_TILES_CLIFF = 'cKc2'
endglobals
endscope
scope DALARANRUINS
// Dalaran Ruins
globals
public constant integer DIRT = 'Jdrt'
public constant integer ROUGH_DIRT = 'Jdtr'
public constant integer BLACK_MARBLE = 'Jblm'
public constant integer BRICK_TILES = 'Jbtl'
public constant integer SQUARE_TILES = 'Jsqd'
public constant integer ROUND_TILES = 'Jrtl'
public constant integer GRASS = 'Jgsb'
public constant integer TRIM_GRASS = 'Jhdg'
public constant integer WHITE_MARBLE = 'Jwmb'
public constant integer DIRT_CLIFF = 'cJc2'
public constant integer SQUARE_TILES_CLIFF = 'cJc1'
endglobals
endscope
//TESH.scrollpos=99
//TESH.alwaysfold=0
library Missle requires WorldBounds
struct Missle extends array
static group g = CreateGroup()
static constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
static constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_COLD
real cos
real sin
real speed
unit missle
effect effect
unit caster
player owner
real time_current
real time_max
real distance_current
real distance_max
real damage
real collision
real aoe
integer aoeEffect
integer killCount
RSound sound_launch
RSound sound_explosion
private method unitFilter takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_HERO) and UnitAlive(u) and User[GetOwningPlayer(u)].team != User[.owner].team/*
*/ and not Slider[u].jump/*
*/ and not Slider[u].cata
endmethod
method onExplosion takes unit u returns nothing
local unit fog
local real x = GetUnitX(u)
local real y = GetUnitY(u)
if (u != null) then
call KillUnit(CreateUnit(.owner, 'blod', x, y, 0))
call UnitDamageTarget(.caster, u, .damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, null)
if(GetWidgetLife(u) <= .damage)then
set .killCount = .killCount + 1
if(.killCount == 2)then
call Sound[1].play(x, y, 0, 200)
elseif .killCount > 2 then
call Sound[2].play(x, y, 0, 200)
endif
endif
endif
if(.aoe > 0) then
if (u == null) then
call KillUnit(CreateUnit(.owner, .aoeEffect, GetUnitX(.missle), GetUnitY(.missle), 0))
else
call KillUnit(CreateUnit(.owner, .aoeEffect, GetUnitX(u), GetUnitY(u), 0))
endif
call GroupEnumUnitsInRange(g, x, y, .aoe, null)
loop
set fog = FirstOfGroup(g)
exitwhen fog == null
if (.unitFilter(fog) and u != fog) then
call UnitDamageTarget(.caster, fog, .damage, true, false, ATTACK_TYPE, DAMAGE_TYPE, null)
endif
call GroupRemoveUnit(g, fog)
endloop
endif
call KillUnit(.missle)
set .aoeEffect = 0
set .caster = null
set .missle = null
call .destroy()
endmethod
implement CTL
// Loop locals
local real x_origin
local real y_origin
local real x
local real y
local integer terrainType
local unit fog
local Slider s
implement CTLExpire
// Loop body
set .time_current = .time_current + INTERVAL
if(.time_current >= .time_max or not UnitAlive(.missle)) then
call .onExplosion(null)
else
set x_origin = GetUnitX(.missle)
set y_origin = GetUnitY(.missle)
set terrainType = GetTerrainType(x_origin, y_origin)
if Terrain.table.has(terrainType)then
set x = x_origin + (.speed/TPS)* Terrain[terrainType].factor * .cos
set y = y_origin + (.speed/TPS)* Terrain[terrainType].factor * .sin
else
set x = x_origin + (.speed/TPS) * .cos
set y = y_origin + (.speed/TPS) * .sin
endif
if IsInBounds(x, y) then
if(Wall.isInWall(x_origin, y_origin, x, y) or not IsInBounds(x, y)) then
call .onExplosion(null)
else
call SetUnitX(.missle, x)
call SetUnitY(.missle, y)
call GroupEnumUnitsInRange(g, x, y, .collision, null)
loop
set fog = FirstOfGroup(g)
exitwhen fog == null
if .unitFilter(fog) then
call .onExplosion(fog)
exitwhen true
endif
call GroupRemoveUnit(g, fog)
endloop
set s = Slider.first
loop
exitwhen s == 0
if ExplosiveEgg[s.slider].egg != null and IsUnitInRange(.missle, ExplosiveEgg[s.slider].egg, ExplosiveEgg.COLLISION) then
call ExplosiveEgg[s.slider].explode()
call .onExplosion(null)
exitwhen true
endif
set s = s.next
endloop
endif
else
call .onExplosion(null)
endif
endif
implement CTLEnd
public static method apply takes unit u, integer who returns thistype
local thistype this = create()
local real angle = GetUnitFacing(u)
set .caster = u
set .killCount = 0
set .owner = GetOwningPlayer(u)
set .cos = Cos(angle*bj_DEGTORAD)
set .sin = Sin(angle*bj_DEGTORAD)
set .missle = CreateUnit(.owner, who , GetUnitX(u)+40*.cos, GetUnitY(u)+40*.sin, angle)
call UnitAddAbility(.missle, 'Aloc')
call SetUnitPathing(.missle, false)
set .speed = 0
set .time_current = 0
set .time_max = 0
set .distance_current = 0
set .distance_max = 0
set .damage = 0
set .collision = 0
set .aoe = 0
return this
endmethod
endstruct
endlibrary
//TESH.scrollpos=30
//TESH.alwaysfold=0
// Normal missles for blue and red team
scope EnergyBall
globals
private constant real SPEED = 2.4*DEFAULT_SPEED
private constant real COLLISION = 80.
private constant real DURATION = 1.2
private constant real DAMAGE = 100.
private constant real SCALE = 2.8
endglobals
private struct EnegeryBall extends array
private static method orderFilter takes unit u, integer orderId returns boolean
return orderId == ORDER_ENERGY_BALL and GetUnitAbilityLevel(u, ENERGY_BALL) > 0
endmethod
private static method filter takes Slider s returns boolean
return not(Terrain.table.has(GetTerrainType(GetUnitX(s.slider), GetUnitY(s.slider))))/*
*/ or s.jump/*
*/ or s.roots/*
*/ or s.stunned
endmethod
private static method onCast takes nothing returns nothing
local Missle this
set Slider[GetTriggerUnit()].invisible = false
if (GetPlayerId(GetTriggerPlayer()) < 6) then
set this = Missle.apply(GetTriggerUnit(), MISSLE_BLUE)
else
set this = Missle.apply(GetTriggerUnit(), MISSLE_RED)
endif
call Sound[LAUNCH_ENERGYBALL].play(GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), 0, 200)
set this.speed = SPEED
set this.collision = COLLISION
set this.time_max = DURATION
set this.damage = DAMAGE
endmethod
private static method callback takes nothing returns nothing
call UnitAddAbility(Slider(GetTimerData(GetExpiredTimer())).slider, ENERGY_BALL)
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onOrder takes nothing returns nothing
local unit u = GetTriggerUnit()
if orderFilter(u, GetIssuedOrderId())then
if filter(Slider[u]) then
call ApplyErrorTextTag(Slider[u])
call UnitRemoveAbility(u, ENERGY_BALL)
call TimerStart(NewTimerEx(Slider[u]), 0, false, function thistype.callback)
endif
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(ENERGY_BALL, function thistype.onCast)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function thistype.onOrder)
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
// Fast sniper missles
scope SniperArrow
globals
private constant real SPEED = 3*DEFAULT_SPEED
private constant real COLLISION = 80.
private constant real DURATION = 1.2
private constant real DAMAGE = 200.
private constant real SCALE = 1.4
endglobals
private struct EnegeryBall extends array
private static method orderFilter takes unit u, integer orderId returns boolean
return orderId == ORDER_SNIPER_ARROW and GetUnitAbilityLevel(u, SNIPER_ARROW) > 0
endmethod
private static method filter takes Slider s returns boolean
return not(Terrain.table.has(GetTerrainType(GetUnitX(s.slider), GetUnitY(s.slider))))/*
*/ or s.jump/*
*/ or s.roots/*
*/ or s.stunned
endmethod
private static method callback takes nothing returns nothing
call UnitAddAbility(Slider(GetTimerData(GetExpiredTimer())).slider, SNIPER_ARROW)
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onCast takes nothing returns nothing
local unit u = GetTriggerUnit()
local Missle this = Missle.apply(u, MISSLE_SNIPER)
set Slider[u].invisible = false
call Sound[LAUNCH_SNIPERARROW].play(GetUnitX(u), GetUnitY(u), 0, 200)
set this.speed = SPEED
set this.collision = COLLISION
set this.time_max = DURATION
set this.damage = DAMAGE
set u = null
endmethod
private static method onOrder takes nothing returns nothing
local unit u = GetTriggerUnit()
if orderFilter(u, GetIssuedOrderId()) and filter(Slider[u])then
call ApplyErrorTextTag(Slider[u])
call UnitRemoveAbility(u, SNIPER_ARROW)
call TimerStart(NewTimerEx(Slider[u]), 0, false, function thistype.callback)
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(SNIPER_ARROW, function thistype.onCast)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function thistype.onOrder)
endmethod
endstruct
endscope
//TESH.scrollpos=36
//TESH.alwaysfold=0
// Fast and strong sniper missle with aoe
scope Rocket
globals
private constant real SPEED = 2.8*DEFAULT_SPEED
private constant real COLLISION = 105.
private constant real DURATION = 1
private constant real DAMAGE = 200.
private constant real AOE = 260
private constant real SCALE = 2.2
private constant integer AOE_EFFECT = ROCKET_EFFECT//"Objects\\Spawnmodels\\Human\\FragmentationShards\\FragBoomSpawn.mdl"
endglobals
private struct EnegeryBall extends array
private static method orderFilter takes unit u, integer orderId returns boolean
return orderId == ORDER_ROCKET and GetUnitAbilityLevel(u, ROCKET) > 0
endmethod
private static method filter takes Slider s returns boolean
return not(Terrain.table.has(GetTerrainType(GetUnitX(s.slider), GetUnitY(s.slider))))/*
*/ or s.jump/*
*/ or s.roots/*
*/ or s.stunned
endmethod
private static method onCast takes nothing returns nothing
local unit u = GetTriggerUnit()
local Missle this = Missle.apply(u, MISSLE_ROCKET)
set Slider[u].invisible = false
call Sound[LAUNCH_ROCKET].play(GetUnitX(u), GetUnitY(u), 0, 200)
set this.speed = SPEED
set this.collision = COLLISION
set this.time_max = DURATION
set this.damage = DAMAGE
set this.aoe = AOE
set this.aoeEffect = AOE_EFFECT
set u = null
endmethod
private static method onFinish takes nothing returns nothing
if (GetSpellAbilityId() == ROCKET and GetUnitState(GetTriggerUnit(), UNIT_STATE_MANA) < 1) then
call CurrentShootAbility.apply(GetTriggerUnit(), DefaultShootAbility[GetTriggerUnit()])
call SetUnitMaxState(GetTriggerUnit(), UNIT_STATE_MAX_MANA, 0)
endif
endmethod
private static method callback takes nothing returns nothing
call UnitAddAbility(Slider(GetTimerData(GetExpiredTimer())).slider, ROCKET)
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onOrder takes nothing returns nothing
local unit u = GetTriggerUnit()
if orderFilter(u, GetIssuedOrderId()) and filter(Slider[u])then
call ApplyErrorTextTag(Slider[u])
call UnitRemoveAbility(u, ROCKET)
call TimerStart(NewTimerEx(Slider[u]), 0, false, function thistype.callback)
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call RegisterSpellEffectEvent(ROCKET, function thistype.onCast)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function thistype.onOrder)
call TriggerAddAction(t, function thistype.onFinish)
call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_FINISH )
endmethod
endstruct
endscope
//TESH.scrollpos=30
//TESH.alwaysfold=0
scope Invisibility
struct Invisibility extends array
private static constant real DURATION = 4
real time
Slider slider
implement CTL
local Team t = User[.slider.owner].team
implement CTLExpire
// Loop body
set this.time = this.time + INTERVAL
if this.time >= DURATION or (not UnitAlive(this.slider.slider)) or not .slider.invisible then
call this.destroy()
call SetUnitVertexColor(.slider.slider, t.r, t.g, t.b, 255)
set slider.invisible = false
endif
implement CTLEnd
private static method orderFilter takes unit u, integer orderId returns boolean
return orderId == ORDER_INVISIBILITY and GetUnitAbilityLevel(u, INVISIBILITY) > 0
endmethod
private static method filter takes Slider s returns boolean
return /*
*/ s.stunned/*
*/ or s.roots
endmethod
private static method onCast takes nothing returns nothing
local thistype this = create()
local Team t = User[GetTriggerPlayer()].team
set .slider = Slider[GetTriggerUnit()]
set .slider.invisible = true
set .time = 0
if User[GetTriggerPlayer()].team != User[LOCAL_PLAYER].team then
call SetUnitVertexColor(.slider.slider, t.r, t.g, t.b, 0)
else
call SetUnitVertexColor(.slider.slider, t.r, t.g, t.b, 125)
endif
endmethod
private static method callback takes nothing returns nothing
call UnitAddAbility(Slider(GetTimerData(GetExpiredTimer())).slider, INVISIBILITY)
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onOrder takes nothing returns nothing
local unit u = GetTriggerUnit()
if orderFilter(u, GetIssuedOrderId()) and filter(Slider[u])then
call ApplyErrorTextTag(Slider[u])
call UnitRemoveAbility(u, INVISIBILITY)
call TimerStart(NewTimerEx(Slider[u]), 0, false, function thistype.callback)
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(INVISIBILITY, function thistype.onCast)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function thistype.onOrder)
endmethod
endstruct
endscope
//TESH.scrollpos=38
//TESH.alwaysfold=0
scope Jump
struct Jump extends array
private static constant real DURATION = 0.6
private static constant real SPEED_BOOST = DEFAULT_SPEED*0.8
private static constant real MAX_HEIGHT = 250
real time
real height
Slider slider
implement CTL
// Loop locals
implement CTLExpire
// Loop body
set this.time = this.time + INTERVAL
call SetUnitFlyHeight(this.slider.slider, ParabolaZ(MAX_HEIGHT, DURATION, time), 0)
if(this.time >= DURATION or not UnitAlive(this.slider.slider)) then
call this.destroy()
call SetUnitFlyHeight(this.slider.slider, 0, 0)
call this.slider.addDefaultSpeed(-SPEED_BOOST)
set this.slider.snowImmune = false
set this.slider.jump = false
endif
implement CTLEnd
private static method orderFilter takes unit u, integer orderId returns boolean
return orderId == ORDER_JUMP and GetUnitAbilityLevel(u, JUMP) > 0
endmethod
private static method filter takes Slider s returns boolean
return s.stunned or s.roots
endmethod
private static method onCast takes nothing returns nothing
local thistype this = create()
set .slider = Slider[GetTriggerUnit()]
set .time = 0
set .height = 0
call .slider.addDefaultSpeed(SPEED_BOOST)
set .slider.snowImmune = true
set .slider.jump = true
endmethod
private static method callback takes nothing returns nothing
call UnitAddAbility(Slider(GetTimerData(GetExpiredTimer())).slider, JUMP)
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onOrder takes nothing returns nothing
local unit u = GetTriggerUnit()
if orderFilter(u, GetIssuedOrderId()) then
if filter(Slider[u])then
call ApplyErrorTextTag(Slider[u])
call UnitRemoveAbility(u, JUMP)
call TimerStart(NewTimerEx(Slider[u]), 0, false, function thistype.callback)
elseif MagicWall.isInWallRange(u, 800) then
call ApplyPendingTextTag(Slider[u], Color[0] + "Wall Blocks|r", 10, 1.5, 2.5, 0, 100, GetRandomReal(90-15, 90+15))
call Sound[ERROR].play(GetUnitX(u), GetUnitY(u), 0, 200)
call UnitRemoveAbility(u, JUMP)
call TimerStart(NewTimerEx(Slider[u]), 0, false, function thistype.callback)
endif
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(JUMP, function thistype.onCast)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function thistype.onOrder)
endmethod
endstruct
endscope
//TESH.scrollpos=66
//TESH.alwaysfold=0
struct HolyRa extends array
private static constant real DURATION = 2.6
private static constant real SPEED = 2.5*DEFAULT_SPEED
unit u
real time
Team team
implement CTL
local Slider s
local real minimumRange
local unit aimUnit = null
local real x
local real y
local real angle
local real distance
local integer terrainType
local real offset
implement CTLExpire
// Loop body
set this.time = this.time + INTERVAL
if this.time >= DURATION or not UnitAlive(this.u) then
call this.destroy()
call KillUnit(this.u)
set this.u = null
else
set x = GetUnitX(.u)
set y = GetUnitY(.u)
// Get clostest dead slider
set s = Slider.first
loop
exitwhen s == 0
if User[s.owner].team == .team and not UnitAlive(s.slider) then
set distance = SquareRoot(((GetUnitX(s.slider) - x) * (GetUnitX(s.slider) - x)) + ((GetUnitY(s.slider) - y) * (GetUnitY(s.slider) - y)))
if null == aimUnit or minimumRange > distance then
set aimUnit = s.slider
set minimumRange = distance
endif
endif
set s = s.next
endloop
if(aimUnit != null) then
call SetUnitFacing(.u, Atan2(GetUnitY(aimUnit) - y, GetUnitX(aimUnit) - x)*bj_RADTODEG)
endif
set angle = GetUnitFacing(.u)*bj_DEGTORAD
set terrainType = GetTerrainType(x, y)
if Terrain[terrainType] == 0 then
set offset = SPEED/TPS
else
set offset = (SPEED + Terrain[terrainType].speed)/TPS*Terrain[terrainType].factor
endif
set x = x + offset*Cos(angle)
set y = y + offset*Sin(angle)
if IsInBounds(x, y) then
call SetUnitX(.u, x)
call SetUnitY(.u, y)
// Save all dead heroes in range
set s = Slider.first
loop
exitwhen s == 0
if User[s.owner].team == .team and not UnitAlive(s.slider) then
set distance = SquareRoot(((GetUnitX(s.slider) - x) * (GetUnitX(s.slider) - x)) + ((GetUnitY(s.slider) - y) * (GetUnitY(s.slider) - y)))
if Respawn.COLLISION > distance then
call Respawn[s.owner].revive(.u)
endif
endif
set s = s.next
endloop
else
call this.destroy()
call KillUnit(this.u)
set this.u = null
set aimUnit = null
endif
endif
set aimUnit = null
implement CTLEnd
private static method onCast takes nothing returns nothing
local thistype this = create()
local unit u = GetTriggerUnit()
local real angle = GetUnitFacing(u)
local real x = GetUnitX(u) + 50*Cos(angle)*bj_DEGTORAD
local real y = GetUnitY(u) + 50*Sin(angle)*bj_DEGTORAD
call Sound[LAUNCH_HOLYRA].play(GetUnitX(u), GetUnitY(u), 0, 200)
set .u = CreateUnit(GetTriggerPlayer(), MISSLE_HOLYRA, x, y, angle)
set .team = User[GetTriggerPlayer()].team
set .time = 0
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(HOLYRA, function thistype.onCast)
endmethod
endstruct
//TESH.scrollpos=37
//TESH.alwaysfold=0
struct Roots extends array
private static constant real DURATION = 1.5
private static constant real RANGE = 500.
Slider slider
unit u
real time
effect sfx
unit eff
implement CTL
implement CTLExpire
// Loop body
set this.time = this.time + INTERVAL
if this.time >= DURATION or not UnitAlive(u) then
call this.destroy()
set .slider.roots = false
call SetUnitMoveSpeed(u, GetUnitDefaultMoveSpeed(.u))
call KillUnit(.eff)
set u = null
set .eff = null
endif
implement CTLEnd
private static method onCast takes nothing returns nothing
local thistype this = 0
local Slider s = Slider.first
local unit u = GetTriggerUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local Team team = User[GetTriggerPlayer()].team
loop
exitwhen s == 0
if IsUnitInRange(s.slider, u, RANGE) and team != User[s.owner].team and UnitAlive(s.slider) then
set this = create()
set u = s.slider
set x = GetUnitX(u)
set y = GetUnitY(u)
call Sound[ROOTSOUND].play(x, y, 0, 200)
call SetUnitMoveSpeed(u, 0)
set .eff = CreateUnit(GetTriggerPlayer(), NET_EFFECT, x, y, GetUnitFacing(u))
set .u = u
set s.roots = true
set .slider = s
set .time = 0
exitwhen true
endif
set s = s.next
endloop
if this == 0 then
call Sound[ERROR].play(x, y, 0, 200)
call ApplyPendingTextTag(Slider[u], Color[12] + "No found|r", 8, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
endif
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(NET, function thistype.onCast)
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope DisplayRange initializer Init
globals
private constant integer AMOUNT = 8
private constant integer EFFECT = 'rang'
endglobals
private function onCast_on takes nothing returns nothing
local real angle = 0
local unit u = GetTriggerUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
local RangeData element = Slider[u].RangeList
local player p = GetTriggerPlayer()
local integer i = 1
loop
exitwhen i > AMOUNT
set element = Slider[u].RangeList.enqueue()
set element.angle = angle
set element.u = CreateUnit(p, EFFECT, x + RangeData.OFFSET*Cos(angle), y + RangeData.OFFSET*Sin(angle), 0)
if(LOCAL_PLAYER != p)then
call ShowUnit(element.u, false)
endif
set angle = angle + bj_PI*2/AMOUNT
set i = i + 1
endloop
call UnitRemoveAbility(u, RANGE_ON)
call UnitAddAbility(u, RANGE_OFF)
set Slider[u].showRange = true
call ApplyPendingTextTag(Slider[u], Color[12] + "Range on|r", 8, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
set u = null
endfunction
private function onCast_off takes nothing returns nothing
local unit u = GetTriggerUnit()
local RangeData rangeElement = Slider[u].RangeList.first
loop
exitwhen 0 == rangeElement
call KillUnit(rangeElement.u)
set rangeElement.u = null
set rangeElement = rangeElement.next
endloop
set Slider[u].showRange = false
call Slider[u].RangeList.clear()
call UnitRemoveAbility(u, RANGE_OFF)
call UnitAddAbility(u, RANGE_ON)
call ApplyPendingTextTag(Slider[u], Color[12] + "Range off|r", 9, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
set u = null
endfunction
private function Init takes nothing returns nothing
call RegisterSpellEffectEvent(RANGE_ON, function onCast_on)
call RegisterSpellEffectEvent(RANGE_OFF, function onCast_off)
endfunction
endscope
//TESH.scrollpos=18
//TESH.alwaysfold=0
scope FlagIndicator initializer Init
globals
constant integer FLAG_INDICATOR_ON = 'FLAG'
constant integer FLAG_INDICATOR_OFF = 'pOff'
endglobals
private function onCast_on takes nothing returns nothing
local unit u = GetTriggerUnit()
local player p = GetTriggerPlayer()
if(LOCAL_PLAYER == p)then
call ShowUnit(Slider[u].flagPointer_blue, true)
call ShowUnit(Slider[u].flagPointer_red, true)
endif
set Slider[u].pointToFlag = true
call UnitRemoveAbility(Slider[u].flagPointer_blue, 'Aloc')
call UnitRemoveAbility(Slider[u].flagPointer_red, 'Aloc')
call UnitAddAbility(Slider[u].flagPointer_blue, 'Aloc')
call UnitAddAbility(Slider[u].flagPointer_red, 'Aloc')
call UnitRemoveAbility(u, FLAG_INDICATOR_ON)
call UnitAddAbility(u, FLAG_INDICATOR_OFF)
call ApplyPendingTextTag(Slider[u], Color[12] + "Flags on|r", 8, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
set u = null
endfunction
private function onCast_off takes nothing returns nothing
local unit u = GetTriggerUnit()
local player p = GetTriggerPlayer()
if(LOCAL_PLAYER == p)then
call ShowUnit(Slider[u].flagPointer_blue, false)
call ShowUnit(Slider[u].flagPointer_red, false)
endif
set Slider[u].pointToFlag = false
call UnitRemoveAbility(u, FLAG_INDICATOR_OFF)
call UnitAddAbility(u, FLAG_INDICATOR_ON)
call ApplyPendingTextTag(Slider[u], Color[12] + "Flags off|r", 9, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
set u = null
endfunction
private function Init takes nothing returns nothing
call RegisterSpellEffectEvent(FLAG_INDICATOR_ON, function onCast_on)
call RegisterSpellEffectEvent(FLAG_INDICATOR_OFF, function onCast_off)
endfunction
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct ExplosiveEgg extends array
private static constant real DURATION = 3.
private static constant real INTERVAL = 0.05
static constant real COLLISION = 70.
private static constant real AOE = 260
private static constant real DAMAGE = 150
real time
unit egg
player owner
method destroy takes nothing returns nothing
set .egg = null
endmethod
private method unitFilter takes unit u returns boolean
return IsUnitType(u, UNIT_TYPE_HERO) and UnitAlive(u) and User[GetOwningPlayer(u)].team != User[.owner].team/*
*/ and not Slider[u].jump/*
*/ and not Slider[u].cata
endmethod
method explode takes nothing returns nothing
local real x = GetUnitX(.egg)
local real y = GetUnitY(.egg)
local unit fog
call KillUnit(CreateUnit(.owner, ROCKET_EFFECT, x, y, 0))
call GroupEnumUnitsInRange(G, x, y, AOE, null)
loop
set fog = FirstOfGroup(G)
exitwhen fog == null
if (.unitFilter(fog) and .egg != fog) then
call UnitDamageTarget(User[.owner].slider.slider, fog, DAMAGE, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_COLD, null)
endif
call GroupRemoveUnit(G, fog)
endloop
call KillUnit(.egg)
call .destroy()
endmethod
private static method callback takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local Slider s
local real range
set this.time = this.time + INTERVAL
if(this.time >= DURATION or not UnitAlive(this.egg)) then
call this.explode()
call ReleaseTimer(GetExpiredTimer())
else
set s = Slider.first
loop
exitwhen s == 0
set range = SquareRoot((GetUnitX(s.slider) - GetUnitX(.egg))*(GetUnitX(s.slider) - GetUnitX(.egg)) + (GetUnitY(s.slider) - GetUnitY(.egg))*(GetUnitY(s.slider) - GetUnitY(.egg)))
if range < COLLISION and unitFilter(s.slider) then
call ReleaseTimer(GetExpiredTimer())
call this.explode()
exitwhen true
endif
set s = s.next
endloop
endif
endmethod
static method operator [] takes unit u returns thistype
return thistype(GetUnitUserData(u))
endmethod
private static method onCast_egg takes nothing returns nothing
local thistype this = ExplosiveEgg[GetTriggerUnit()]
local unit u = GetTriggerUnit()
set .owner = GetTriggerPlayer()
set .egg = CreateUnit(.owner, 'eggU', GetUnitX(u), GetUnitY(u), GetUnitFacing(u))
set .time = 0
call SetUnitVertexColor(.egg, User[.owner].team.r, User[.owner].team.g, User[.owner].team.b, 255)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
set u = null
endmethod
private static method onCast_explosion takes nothing returns nothing
call thistype[GetTriggerUnit()].explode()
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(EXPLOSIVE_EGG, function thistype.onCast_egg)
call RegisterSpellEffectEvent(EXPLOSION, function thistype.onCast_explosion)
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct CamLock extends array
private static method onLock takes nothing returns nothing
local unit u = GetTriggerUnit()
call UnitRemoveAbility(u, CAM_LOCK)
call UnitAddAbility(u, CAM_UNLOCK)
if(LOCAL_PLAYER == GetTriggerPlayer())then
call SetCameraTargetController(u, 0, 0, false)
endif
call ApplyPendingTextTag(Slider[u], Color[12] + "Lock|r", 4, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
set u = null
endmethod
private static method onUnlock takes nothing returns nothing
local unit u = GetTriggerUnit()
call UnitRemoveAbility(u, CAM_UNLOCK)
call UnitAddAbility(u, CAM_LOCK)
if(LOCAL_PLAYER == GetTriggerPlayer())then
call PanCameraTo(GetUnitX(u), GetUnitY(u))
endif
call ApplyPendingTextTag(Slider[u], Color[12] + "Unlock|r", 6, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
set u = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterSpellEffectEvent(CAM_LOCK, function thistype.onLock)
call RegisterSpellEffectEvent(CAM_UNLOCK, function thistype.onUnlock)
endmethod
endstruct
//TESH.scrollpos=2
//TESH.alwaysfold=0
struct Wall extends array
static constant real WALL_WIDTH = 50.
private static integer counter = 0
real xMin
real yMin
real xMax
real yMax
// sometimes missles can be very fast so a simple check if x/y is inside rect is not enough
// since the rect is not very big. missle could just skip it within one tickrate
// so we take original x/y and x/y to move to, and check if this line crosses the rect
static method isInWall takes real x1, real y1, real x2, real y2 returns boolean
local thistype this = counter
local real xMin
local real xMax
local real yMin
local real yMax
if (x1 < x2)then
set xMin = x1
set xMax = x2
else
set xMin = x2
set xMax = x1
endif
if (y1 < y2)then
set yMin = y1
set yMax = y2
else
set yMin = y2
set yMax = y1
endif
loop
exitwhen this == 0
if (xMax > .xMin) and (xMin < .xMax) and (yMax > .yMin) and (yMin < .yMax) then
return true
endif
set this = this - 1
endloop
return false
endmethod
private static method onInit takes nothing returns nothing
local thistype this
// always define the length of the wall of the bottom or the left side
// Left base - start from bottom left
set counter = counter + 1
set this = counter
set .xMin = -11445
set .xMax = -11082
set .yMin = 7300
set .yMax = 7300 + WALL_WIDTH
set counter = counter + 1
set this = counter
set .xMin = -11082 - WALL_WIDTH
set .xMax = -11082
set .yMin = 7300
set .yMax = 7809
set counter = counter + 1
set this = counter
set .xMin = -11082 - WALL_WIDTH
set .xMax = -11082
set .yMin = 8258
set .yMax = 8760
set counter = counter + 1
set this = counter
set .xMin = -11454
set .xMax = -11082
set .yMin = 8786 - WALL_WIDTH
set .yMax = 8760
// Middle
set counter = counter + 1
set this = counter
set .xMin = -4849// -65
set .xMax = -4849 + WALL_WIDTH// + 65
set .yMin = 7816
set .yMax = 8325
set counter = counter + 1
set this = counter
set .xMin = -3634// - 65
set .xMax = -3634 + WALL_WIDTH// + 65
set .yMin = 7823
set .yMax = 8340
// Right base - start from bottom right
set counter = counter + 1
set this = counter
set .xMin = 2631
set .xMax = 3005
set .yMin = 7305
set .yMax = 7300 + WALL_WIDTH
set counter = counter + 1
set this = counter
set .xMin = 2631
set .xMax = 2631 + WALL_WIDTH
set .yMin = 7305
set .yMax = 7805
set counter = counter + 1
set this = counter
set .xMin = 2631
set .xMax = 2631 + WALL_WIDTH
set .yMin = 8259
set .yMax = 8761
set counter = counter + 1
set this = counter
set .xMin = 2631
set .xMax = 3005
set .yMin = 8761 - WALL_WIDTH
set .yMax = 8761
set counter = counter + 1
set this = counter
set .xMin = -12319
set .xMax = -12261
set .yMin = 7037
set .yMax = 9213
set counter = counter + 1
set this = counter
set .xMin = 3940
set .xMax = 3993
set .yMin = 7104
set .yMax = 9131
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct MagicWall extends array
private static integer counter = 0
real x1
real y1
real x2
real y2
static method isInWallRange takes unit u, real distance returns boolean
local thistype this = counter
local real x1 = GetUnitX(u)
local real y1 = GetUnitY(u)
local real angle = GetUnitFacing(u)*bj_DEGTORAD
local real x2 = x1 + distance*Cos(angle)
local real y2 = y1 + distance*Sin(angle)
loop
exitwhen this == 0
if DoLinesIntersect(x1, y1, x2, y2, .x1, .y1, .x2, .y2) then
return true
endif
set this = this - 1
endloop
return false
endmethod
private static method onInit takes nothing returns nothing
local thistype this
set counter = counter + 1
set this = counter
set .x1 = -12290
set .y1 = 6930
set .x2 = -12291
set .y2 = 9250
set counter = counter + 1
set this = counter
set .x1 = 3960
set .y1 = 6930
set .x2 = 3961
set .y2 = 9250
endmethod
endstruct
//TESH.scrollpos=1
//TESH.alwaysfold=0
scope WeatherTest initializer Init
globals
private WeatherEffect WE
private timer clock
endglobals
private function SwitchWeather takes nothing returns nothing
local integer rand = GetRandomInt(0, 5)
if(rand == 0)then
set WE.style = WeatherStyle.NorthrendBlizzard
elseif rand == 1 then
set WE.style = WeatherStyle.NorthrendSnowHeavy
elseif rand == 2 then
set WE.style = WeatherStyle.NorthrendSnowLight
elseif rand == 3 then
set WE.style = WeatherStyle.RaysOfLight
elseif rand == 4 then
set WE.style = WeatherStyle.RaysOfMoonlight
elseif rand == 5 then
set WE.style = WeatherStyle.LordaeronRainHeavy
endif
call TimerStart(clock, GetRandomReal(80, 150), false, function SwitchWeather)
endfunction
private function foo takes nothing returns nothing
set WE = WeatherEffect.create(bj_mapInitialPlayableArea, WeatherStyle.NorthrendBlizzard)
call WE.enable()
call TimerStart(clock, GetRandomReal(80, 150), false, function SwitchWeather)
endfunction
private function Init takes nothing returns nothing
set clock = NewTimer()
call TimerStart(clock, 0, false, function foo)
endfunction
endscope
//TESH.scrollpos=33
//TESH.alwaysfold=0
scope WeaponPickUp
// Config onInit
struct WeaponPickUp extends array
private static constant real INTERVAL = 0.075
real x
real y
unit dummy
real collision
real mana
real timeout
Weapon weaponlist
private method filter takes Slider s returns boolean
return SquareRoot((GetUnitX(s.slider)-.x) * (GetUnitX(s.slider)-.x) + (GetUnitY(s.slider)-.y) * (GetUnitY(s.slider)-.y)) < .collision/*
*/ and not s.jump/*
*/ and not s.cata
endmethod
private static method timeoutFinish takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
call ShowUnit(.dummy, true)
call UnitRemoveAbility(.dummy, 'Aloc')
call UnitAddAbility(.dummy, 'Aloc')
call SetUnitPathing(.dummy, false)
call TimerStart(t, .INTERVAL, true, function thistype.callback)
endmethod
private static method callback takes nothing returns nothing
local Slider s = Slider.first
local timer t = GetExpiredTimer()
local thistype this = GetTimerData(t)
local Weapon weapon
loop
exitwhen null == s
if(.filter(s))then
set weapon = .weaponlist.getRandomWeapon()
call ApplyStaticTextTag(s, Color[12] + "Weapon: |r" + GetObjectName(weapon.whichability), (7+StringLength(GetObjectName(weapon.whichability))), 3, 4, 120)
call SetUnitMaxState(s.slider, UNIT_STATE_MAX_MANA, weapon.mana)
call CurrentShootAbility.apply(s.slider, weapon.whichability)
call SetUnitState(s.slider, UNIT_STATE_MANA, weapon.mana)
call ShowUnit(.dummy, false)
call TimerStart(t, .timeout, false, function thistype.timeoutFinish)
endif
set s = s.next
endloop
endmethod
implement AllocT
static method create takes string modelpath, real scale, real x, real y, Weapon weaponlist, real collision, real mana, real timeout returns thistype
local thistype this = allocate()
set .x = x
set .y = y
set .collision = collision
set .mana = mana
set .timeout = timeout
set .weaponlist = weaponlist
set .dummy = GetRecycledDummy(x, y, 0, 90)
call UnitAddAbility(.dummy, 'Aloc')
call SetUnitPathing(.dummy, false)
call AddSpecialEffectTarget(modelpath, .dummy, "origin")
call SetUnitScale(.dummy, scale, 1, 1)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
return this
endmethod
// CONFIG
private static method init takes nothing returns nothing
// Rocket in center
call create(SECRET_ITEM_MODELPATH, SCALE_SECRET_ITEM, CENTER_X, CENTER_Y, Weapon.WEAPON_LIST_1, 105, 10, 45)
endmethod
implement InitTimer
endstruct
endscope
//TESH.scrollpos=69
//TESH.alwaysfold=0
struct Weapon extends array
implement List
integer whichability
real whichChance
integer mana
// weapon lists
// each list can have multiple weapons (abilities)
static thistype WEAPON_LIST_1
static thistype WEAPON_LIST_2
static thistype WEAPON_LIST_3
static thistype WEAPON_LIST_4
static thistype WEAPON_LIST_5
method getRandomWeapon takes nothing returns thistype
local thistype node
local real rand = GetRandomReal(0, 100)
local real currentLowestChance
local thistype array currentWeapon
local integer index = -1
set node = .first
set currentLowestChance = 101
loop
exitwhen node == 0
if (rand <= node.whichChance) then
if(node.whichChance < currentLowestChance and node.whichChance > 0)then
// A weapon with new lowest chance has qualified, empty array
set index = 0
set currentWeapon[index] = node
set currentLowestChance = node.whichChance
elseif (node.whichChance == currentLowestChance) then
// A weapon with same chance has qualified, add to array
set index = index + 1
set currentWeapon[index] = node
set currentLowestChance = node.whichChance
endif
endif
set node = node.next
endloop
// no weapon had qualified, just take the one now with highest chance
if(index == -1)then
set node = .first
set currentLowestChance = 0
loop
exitwhen node == 0
if(node.whichChance > currentLowestChance)then
set index = 0
set currentWeapon[index] = node
set currentLowestChance = node.whichChance
elseif (node.whichChance == currentLowestChance and currentLowestChance > 0) then
// A weapon with same chance has qualified, add to array
set index = index + 1
set currentWeapon[index] = node
set currentLowestChance = node.whichChance
endif
set node = node.next
endloop
endif
if (index > -1) and (currentLowestChance > 0) then
set index = GetRandomInt(0, index)
return currentWeapon[index]
endif
return 0
endmethod
private static method init takes nothing returns nothing
local thistype this
local thistype node
// All weapons from a list must give together 100 (%) for correct result.
set WEAPON_LIST_1 = create()
set this = WEAPON_LIST_1
set node = .push()
set node.whichability = ROCKET
set node.whichChance = 100.
set node.mana = 10
endmethod
implement Init
endstruct
//TESH.scrollpos=22
//TESH.alwaysfold=0
library TextHandler uses Default
// for charCount
globals
private real xRate = 100/13
endglobals
// if .t is set to null it means for sliding system the node can be removed
private function callback takes nothing returns nothing
local TextData element = GetTimerData(GetExpiredTimer())
set element.t = null
call ReleaseTimer(GetExpiredTimer())
endfunction
//Pending means it has x/y velocity.
// charCount is used so textags are a bit fixed to appear in middle above car, and not next to
function ApplyPendingTextTag takes Slider s, string text, integer charCount, real fp, real lt, real z, real speed, real angle returns texttag
local texttag t = CreateTextTag()
local real offset = speed*0.071/128
local real xVel = offset * Cos(angle*bj_DEGTORAD)
local real yVel = offset * Sin(angle*bj_DEGTORAD)
local TextData td
call SetTextTagText(t, text, .023)
call SetTextTagColor(t, 255, 255, 255, 255)
call SetTextTagVelocity(t,xVel, yVel)
call SetTextTagPermanent(t, false)
call SetTextTagFadepoint(t, fp)
call SetTextTagLifespan(t, lt)
set td = s.newText(t,z)
set td.x = charCount*xRate
call TimerStart(NewTimerEx(td), lt, false, function callback)
return t
endfunction
function ApplyStaticTextTag takes Slider s, string text, integer charCount, real fp, real lt, real z returns texttag
local texttag t = CreateTextTag()
local TextData td
call SetTextTagText(t, text, .023)
call SetTextTagColor(t, 255, 255, 255, 255)
call SetTextTagPermanent(t, false)
call SetTextTagFadepoint(t, fp)
call SetTextTagLifespan(t, lt)
set td = s.newText(t,z)
set td.x = charCount*xRate
call TimerStart(NewTimerEx(td), lt, false, function callback)
return t
endfunction
function ApplyErrorTextTag takes Slider s returns nothing
call ApplyPendingTextTag(s, Color[12] + "Error|r", 5, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
call Sound[ERROR].play(GetUnitX(s.slider), GetUnitY(s.slider), 0, 200)
endfunction
endlibrary
//TESH.scrollpos=48
//TESH.alwaysfold=0
library DialogSystem initializer Init uses GameHandler
globals
dialog dialog_car
dialog dialog_score
dialog dialog_pickmode
// 8 for cars
// 3 for score
// 2 for pick mode
private button array b[12]
private trigger trigger_car = CreateTrigger()
private trigger trigger_score = CreateTrigger()
private trigger trigger_pickmode = CreateTrigger()
endglobals
private function onClick_car takes nothing returns nothing
local integer i = LoadInteger(HASH, GetHandleId(GetClickedButton()), 0)
if i != 0 then
call NewSlider(GetTriggerPlayer(), i)
else
call NewRandomSlider(GetTriggerPlayer())
endif
endfunction
private function NewButton_car takes dialog d, integer unitType returns nothing
local integer counter = LoadInteger(HASH, GetHandleId(d), 0)
call SaveInteger(HASH, GetHandleId(d), 0, counter + 1)
set b[counter] = DialogAddButton(d, GetObjectName(unitType), 0)
call SaveInteger(HASH, GetHandleId(b[counter]), 0, unitType)
endfunction
private function onClick_score takes nothing returns nothing
call SetMaxScore(LoadInteger(HASH, GetHandleId(GetClickedButton()), 0))
call ScoreModeDialog_End()
endfunction
private function NewButton_score takes dialog d, string s returns nothing
local integer counter = LoadInteger(HASH, GetHandleId(d), 0)
call SaveInteger(HASH, GetHandleId(d), 0, counter + 1)
set b[counter] = DialogAddButton(d, s, 0)
call SaveInteger(HASH, GetHandleId(b[counter]), 0, S2I(s))
endfunction
private function onClick_pickmode takes nothing returns nothing
call SetPickMode(LoadStr(HASH, GetHandleId(GetClickedButton()), 0))
call PickModeDialog_End()
endfunction
private function NewButton_pickmode takes dialog d, string s returns nothing
local integer counter = LoadInteger(HASH, GetHandleId(d), 0)
call SaveInteger(HASH, GetHandleId(d), 0, counter + 1)
set b[counter] = DialogAddButton(d, s, 0)
call SaveStr(HASH, GetHandleId(b[counter]), 0, s)
endfunction
private function Setup takes nothing returns nothing
local integer i = 1
set dialog_car = DialogCreate()
call TriggerRegisterDialogEvent(trigger_car, dialog_car)
call TriggerAddAction(trigger_car, function onClick_car)
call DialogSetMessage(dialog_car, "Choose a vehicle")
loop
exitwhen i > Hero.counter
call NewButton_car(dialog_car, Hero(i).unittypeId)
set i = i + 1
endloop
call DialogAddButton(dialog_car, "<Random>", 0)
set dialog_score = DialogCreate()
call TriggerRegisterDialogEvent(trigger_score, dialog_score)
call TriggerAddAction(trigger_score, function onClick_score)
call DialogSetMessage(dialog_score, "Score Limit")
call NewButton_score(dialog_score, "1")
call NewButton_score(dialog_score, "3")
call NewButton_score(dialog_score, "5")
set dialog_pickmode = DialogCreate()
call TriggerRegisterDialogEvent(trigger_pickmode, dialog_pickmode)
call TriggerAddAction(trigger_pickmode, function onClick_pickmode)
call DialogSetMessage(dialog_pickmode, "Pick Mode")
call NewButton_pickmode(dialog_pickmode, "Pick")
call NewButton_pickmode(dialog_pickmode, "Random")
call ReleaseTimer(GetExpiredTimer())
endfunction
private function Init takes nothing returns nothing
call TimerStart(NewTimer(), 0, false, function Setup)
endfunction
endlibrary
//TESH.scrollpos=198
//TESH.alwaysfold=0
scope Catapult
// Config onInit
globals
private constant integer CATA_ID = 'cata'
private constant integer AIM_ID = 'n000'
private constant real SPEED = DEFAULT_SPEED*2.4
private constant real HEIGHT_MINIMUM = 400
private constant real RANGE = 130 // collision with cata
private constant real TIMEOUT = 0.1 // interval for collision checl
endglobals
struct CatapultShot extends array
static constant real TURN_TIME_MAX = 0.3
Catapult cata
Slider slider
real travel_current
real height
integer stage
real time
implement CTL
// Loop locals
local real x
local real y
local real z
implement CTLExpire
// Loop body
if (.stage == 1) then
set .time = .time + INTERVAL
call SetUnitFacing(slider.slider, cata.angle)
if .time >= TURN_TIME_MAX then
set .stage = 2
set this.cata.enabled = true
call SetUnitAnimation( this.cata.cata, "attack" )
endif
elseif (.stage == 2) then
set x = GetUnitX(this.slider.slider)
set y = GetUnitY(this.slider.slider)
set this.travel_current = this.travel_current + SPEED/TPS
call SetUnitFlyHeight(this.slider.slider, ParabolaZ(this.cata.height_max, this.cata.travel_max, this.travel_current), 0)
call SetUnitX(this.slider.slider, x + (SPEED/TPS) * .cata.cos)
call SetUnitY(this.slider.slider, y + (SPEED/TPS) * .cata.sin)
if(this.travel_current >= this.cata.travel_max or not UnitAlive(this.slider.slider)) then
call this.destroy()
call SetUnitFlyHeight(this.slider.slider, 0, 0)
set this.slider.cata = false
call SuspendUnit(this.slider.slider, false)
endif
endif
if(.slider.flag != 0)then
call .slider.flag.updatePosition()
endif
implement CTLEnd
static method apply takes Catapult c, Slider s returns nothing
local thistype this = create()
call SetUnitPosition(s.slider, c.x1, c.y1)
call SuspendUnit(s.slider, true)
set .cata = c
set .slider = s
set .travel_current = 0
set .time = 0
set .height = 0
set .stage = 1
set c.enabled = false
set s.cata = true
endmethod
endstruct
struct Catapult extends array
private static timer clock = CreateTimer()
private static trigger t = CreateTrigger()
real travel_max
boolean enabled
real height_max
real x1
real y1
real x2
real y2
real angle
real cos
real sin
unit cata
unit aim
private static method callback takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
local Slider slider = Slider.first
local real x
local real y
loop
exitwhen slider == 0
set x = GetUnitX(slider.slider)
set y = GetUnitY(slider.slider)
if this.enabled and slider.enabled and not slider.jump and not slider.cata and /*
*/ SquareRoot((x-x1)*(x-x1) + (y-y1)*(y-y1)) < RANGE then
call CatapultShot.apply(this, slider)
return
endif
set slider = slider.next
endloop
endmethod
implement AllocT
private static method create takes real x1, real y1, real x2, real y2 returns thistype
local thistype this = allocate()
set .angle = Atan2(y2 - y1, x2 - x1)*bj_RADTODEG
set .cos = Cos(.angle*bj_DEGTORAD)
set .sin = Sin(.angle*bj_DEGTORAD)
set .cata = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), CATA_ID, x1, y1, .angle)
call SetUnitPathing(.cata, false)
set .aim = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), AIM_ID, x2, y2, 0)
call SetUnitPathing(.aim, false)
set .x1 = x1
set .y1 = y1
set .x2 = x2
set .y2 = y2
set .travel_max = SquareRoot((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))
set .height_max = RMaxBJ(HEIGHT_MINIMUM, HEIGHT_MINIMUM + (.travel_max-1000)/150*10)
set .enabled = true
call TimerStart(NewTimerEx(this), TIMEOUT, true, function thistype.callback)
return this
endmethod
// x1 for cata
// y1 for cata
// x2 for aim
// y2 for aim
private static method onInit takes nothing returns nothing
local real x1
local real y1
local real x2
local real y2
// ==== Left Catas ====
// Base to top-left
set x1 = -11725
set y1 = 9040
set x2 = -14661
set y2 = 13635
call create(x1, y1, x2, y2)
// Base to bottom
set x1 = -11725
set y1 = 7125
set x2 = -10314
set y2 = 2073
call create(x1, y1, x2, y2)
// Top - down/right
set x1 = -13060
set y1 = 14611
set x2 = -8628
set y2 = 11867
call create(x1, y1, x2, y2)
// ==== Middle Catas ====
// Top Left to Top middle
set x1 = -6619
set y1 = 13044
set x2 = -5635
set y2 = 13046
call create(x1, y1, x2, y2)
// Top - to bottom
set x1 = -4420
set y1 = 11150
set x2 = -3000
set y2 = 4220
call create(x1, y1, x2, y2)
// Bottom - to top
set x1 = -4420
set y1 = 4900
set x2 = -5720
set y2 = 11890
call create(x1, y1, x2, y2)
// Right Bottom - to Middle Bottom
set x1 = -2025
set y1 = 2950
set x2 = -3085
set y2 = 2935
call create(x1, y1, x2, y2)
// ==== Right Catas ====
// Base to bottom
set x1 = 3160
set y1 = 7120
set x2 = 6590
set y2 = 2900
call create(x1, y1, x2, y2)
// bottom - middle/left
set x1 = 5243
set y1 = 1950
set x2 = 229
set y2 = 4700
call create(x1, y1, x2, y2)
// bottom - middle/left
set x1 = 3160
set y1 = 9040
set x2 = 1770
set y2 = 14335
call create(x1, y1, x2, y2)
endmethod
endstruct
endscope
//TESH.scrollpos=63
//TESH.alwaysfold=0
struct Teleport
real x_enter
real y_enter
real x_leave
real y_leave
unit e_unit
real angle
real range
integer block
boolean array blocked[11]
private static constant real INTERVAL = 0.075
private static constant real INTERVAL_TURN = 6
boolean turn_right
readonly static integer counter = 0
private static method enableMessage takes nothing returns nothing
local timer clock = GetExpiredTimer()
set thistype(LoadInteger(HASH, GetHandleId(clock), 0)).blocked[LoadInteger(HASH, GetHandleId(clock), 1)] = false
call ReleaseTimer(clock)
endmethod
method isUnitInRange takes unit u returns boolean
return IsUnitInRangeXY(u, .x_enter, .y_enter, .range) /*
*/ and not Slider[u].jump/*
*/ and not Slider[u].cata
endmethod
private static method callback takes nothing returns nothing
local Slider s = Slider.first
local timer t
local thistype this = GetTimerData(GetExpiredTimer())
loop
exitwhen s == null
if .isUnitInRange(s.slider)then
if User[s.owner].team != .block then
if(s.flag == 0)then
call SetUnitPosition(s.slider, x_leave, y_leave)
call SetUnitFacing(s.slider, .angle)
if GetUnitAbilityLevel(s.slider, CAM_LOCK) > 0 and s.owner == LOCAL_PLAYER then
call PanCameraToTimed(x_leave, y_leave, 0)
endif
elseif not .blocked[GetPlayerId(s.owner)] then
set t = NewTimer()
//call PrintTo(s.owner, Color[9] + "Not allowed to enter with flag.", 5)
call ApplyPendingTextTag(s, Color[0] + "Not allowed with flag|r", 20, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
call Sound[ERROR].play(GetUnitX(s.slider), GetUnitY(s.slider), 0, 200)
call SaveInteger(HASH, GetHandleId(t), 0, this)
call SaveInteger(HASH, GetHandleId(t), 1, GetPlayerId(s.owner))
set .blocked[GetPlayerId(s.owner)] = true
call TimerStart(t, 3, false, function thistype.enableMessage)
endif
elseif not .blocked[GetPlayerId(s.owner)] then
set t = NewTimer()
//call PrintTo(s.owner, Color[9] + "Not allowed to enter.", 5)
call ApplyPendingTextTag(s, Color[0] + "Not allowed|r", 11, 1, 2, 0, 100, GetRandomReal(90-15, 90+15))
call Sound[ERROR].play(GetUnitX(s.slider), GetUnitY(s.slider), 0, 200)
call SaveInteger(HASH, GetHandleId(t), 0, this)
call SaveInteger(HASH, GetHandleId(t), 1, GetPlayerId(s.owner))
set .blocked[GetPlayerId(s.owner)] = true
call TimerStart(t, 3, false, function thistype.enableMessage)
endif
endif
set s = s.next
endloop
endmethod
private static method callback_turn takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
if .turn_right then
call SetUnitFacingTimed(.e_unit, GetUnitFacing(.e_unit)+179, 2)
else
call SetUnitFacingTimed(.e_unit, GetUnitFacing(.e_unit)+181, 2)
endif
set .turn_right = not .turn_right
endmethod
private static method onInit takes nothing returns nothing
local thistype this
/*
LEFT SIDE
*/
// Spawn - Flag
set counter = counter + 1
set this = counter
set .x_enter = -12100
set .y_enter = 8150
set .x_leave = -15970+240
set .y_leave = 8230
set .angle = 0
set .range = 140
set .block = Team.RED
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Flag - Spawn
set counter = counter + 1
set this = counter
set .x_enter = -15970
set .y_enter = 8230
set .x_leave = -12100+240
set .y_leave = 8150
set .angle = 0
set .range = 140
set .block = Team.RED
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Spawn - Bottom
set counter = counter + 1
set this = counter
set .x_enter = -9973
set .y_enter = 7086
set .x_leave = -4547
set .y_leave = 1783
set .angle = 90
set .range = 110
set .block = 0
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Spawn - Top
set counter = counter + 1
set this = counter
set .x_enter = -9973
set .y_enter = 9054
set .x_leave = -4301
set .y_leave = 14242
set .angle = 270
set .range = 110
set .block = 0
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Left - Right
set counter = counter + 1
set this = counter
set .x_enter = -11526
set .y_enter = 4874
set .x_leave = 4370
set .y_leave = 13730
set .angle = 90
set .range = 110
set .block = 0
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
/*
RIGHT SIDE
*/
// Spawn - Flag
set counter = counter + 1
set this = counter
set .x_enter = 3765
set .y_enter = 8145
set .x_leave = 7636
set .y_leave = 8304
set .angle = 180
set .range = 160
set .block = Team.BLUE
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Flag - Spawn
set counter = counter + 1
set this = counter
set .x_enter = 7636+240
set .y_enter = 8230
set .x_leave = 3765-240
set .y_leave = 8145
set .angle = 180
set .range = 160
set .block = Team.BLUE
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Spawn - Bottom
set counter = counter + 1
set this = counter
set .x_enter = 1480
set .y_enter = 7200
set .x_leave = -4547
set .y_leave = 1783
set .angle = 90
set .range = 110
set .block = 0
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Spawn - Top
set counter = counter + 1
set this = counter
set .x_enter = 1480
set .y_enter = 9170
set .x_leave = -4301
set .y_leave = 14242
set .angle = 270
set .range = 110
set .block = 0
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
// Right - Left
set counter = counter + 1
set this = counter
set .x_enter = 3193
set .y_enter = 11276
set .x_leave = -12787
set .y_leave = 2372
set .angle = 270
set .range = 110
set .block = 0
set .e_unit = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), 'tele', x_enter, y_enter, 0)
call TimerStart(NewTimerEx(this), INTERVAL, true, function thistype.callback)
call TimerStart(NewTimerEx(this), INTERVAL_TURN, true, function thistype.callback_turn)
endmethod
endstruct
//TESH.scrollpos=62
//TESH.alwaysfold=0
struct Board extends array
static Multiboard Board
static integer array playerRow
static method update takes player p returns nothing
local integer row = playerRow[GetPlayerId(p)]
set Board[row][0].text = GetPlayerName(p) + "|r (" + I2S(KD[p].streak_current) + ")"
set Board[row][1].text = I2S(KD[p].kills)
set Board[row][2].text = I2S(KD[p].deaths)
set Board[row][3].text = R2S(KD[p].kd)
if User[p].slider != 0 then
set Board[row][0].icon = Hero.table.string[GetUnitTypeId(User[p].slider.slider)]
else
set Board[row][0].icon = "UI\\Minimap\\MinimapIconCreepLoc2.blp"
endif
endmethod
static method NewBoard takes nothing returns nothing
local integer i = 0
local integer currentRow
local player p
if Board != 0 then
call Board.destroy()
endif
set Board = Multiboard.create(PlayerTools.user_Amount + 6, 4)
set Board.title = "Stats Board"
call Board.setStyle(true, false)
call Board.column[0].setStyle(true, true)
call Board[0][0].setStyle(true, false)
call Board[1][0].setStyle(true, false)
call Board[Team.BLUE.count + 3][0].setStyle(true, false)
call Board[PlayerTools.user_Amount + 4][0].setStyle(true, false)
call Board[PlayerTools.user_Amount + 5][0].setStyle(true, false)
set Board.Board[PlayerTools.user_Amount + 5][0].text = "|cffffffccGametime:|r " + Gametime.toString()
set Board.Board[PlayerTools.user_Amount + 5][1].text = "|cffffffccESC to switch Boards|r"
set Board.column[0].width = 0.132
set Board.column[1].width = 0.03
set Board.column[2].width = 0.04
set Board.column[3].width = 0.035
set Board[PlayerTools.user_Amount + 5][0].width = 0.11
set Board[PlayerTools.user_Amount + 5][1].width = 0. //0.12
set Board[PlayerTools.user_Amount + 5][2].width = 0
set Board[PlayerTools.user_Amount + 5][3].width = 0
set Board[0][0].text = Color[13] + "Player (streak)"
set Board[0][1].text = Color[13] + "Kills"
set Board[0][2].text = Color[13] + "Deaths"
set Board[0][3].text = Color[13] + "KD"
set Board[1][0].text = Color[1] + "Blue Team"
call Board[1][0].setStyle(true, false)
set Board[Team.BLUE.count + 3][0].text = Color[0] + "Red Team"
set currentRow = 1
set i = 0
loop
exitwhen i > Team.BLUE.count
set currentRow = currentRow + 1
set p = Team.BLUE.user[i]
set playerRow[GetPlayerId(p)] = currentRow
call update(p)
set i = i + 1
endloop
set currentRow = Team[Team.BLUE].count + 3
set i = 0
loop
exitwhen i > Team.RED.count
set currentRow = currentRow + 1
set p = Team.RED.user[i]
set playerRow[GetPlayerId(p)] = currentRow
call update(p)
set i = i + 1
endloop
set Board.display = true
set Board.minimize = false
//set BoardSwitch.switch = true
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onInit takes nothing returns nothing
set Board = 0
call TimerStart(NewTimer(),1.8 ,false,function thistype.NewBoard)
endmethod
endstruct
//TESH.scrollpos=14
//TESH.alwaysfold=0
struct BoardLocal extends array
static Multiboard Board
static integer array playerRow
private static method load takes player p returns nothing
local integer kills
local integer deaths
local real kd
local integer streak
local integer scores
local integer row = playerRow[GetPlayerId(p)]
set kills = KD[p].kills_loaded
set deaths = KD[p].deaths_loaded
set streak = KD[p].streak_loaded
set scores = KD[p].score_loaded
if deaths > 0 then
set kd = I2R(kills/deaths)
else
set kd = I2R(kills)
endif
set Board[row][0].text = GetPlayerName(p)
set Board[row][1].text = I2S(scores)
set Board[row][2].text = I2S(streak)
set Board[row][3].text = I2S(kills)
set Board[row][4].text = I2S(deaths)
set Board[row][5].text = R2S(kd)
endmethod
static method NewBoard takes nothing returns nothing
local integer i = 0
local integer currentRow
local player p
set Board = Multiboard.create(PlayerTools.user_Amount + 4, 6)
set Board.title = "Stats Board (loaded)"
call Board.setStyle(true, false)
set Board.column[0].width = 0.11
set Board.column[1].width = 0.04
set Board.column[2].width = 0.04
set Board.column[3].width = 0.03
set Board.column[4].width = 0.04
set Board.column[5].width = 0.035
set Board[0][0].text = Color[13] + "Player"
set Board[0][1].text = Color[13] + "Scores"
set Board[0][2].text = Color[13] + "Streak"
set Board[0][3].text = Color[13] + "Kills"
set Board[0][4].text = Color[13] + "Deaths"
set Board[0][5].text = Color[13] + "KD"
set currentRow = 1
set i = 0
loop
exitwhen i > PlayerTools.user_Amount
set currentRow = currentRow + 1
set p = PlayerTools.user[i]
set playerRow[GetPlayerId(p)] = currentRow
call load(p)
if LOCAL_PLAYER == PlayerTools.user[i] then
if File.enabled and IS_GAME_ONLINE then
set Board.row.count = Board.row.count + 1
set Board[Board.row.count-1][0].width = 0.3
set Board[Board.row.count-1][0].text = "Status: |r" + Color[6] + "enabled"
else
if File.enabled then
set Board.row.count = Board.row.count + 2
set Board[Board.row.count-2][0].width = 0.3
set Board[Board.row.count-1][0].width = 0.3
set Board[Board.row.count-2][0].text = "Status: |r" + Color[6] + "enabled"
set Board[Board.row.count-1][0].text = Color[4] + "Warning: |r Saving data is not allowed in SinglePlayer mode."
else
set Board.row.count = Board.row.count + 4
set Board[Board.row.count-1][0].width = 0.3
set Board[Board.row.count-2][0].width = 0.3
set Board[Board.row.count-3][0].width = 0.3
set Board[Board.row.count-4][0].width = 0.3
set Board[Board.row.count-4][0].text = "Status: |r" + Color[0] + "disabled"
set Board[Board.row.count-3][0].text = Color[4] + "Warning: |r You need to enable LocalFiles to use Save/Load."
set Board[Board.row.count-2][0].text = "You can use following map to enable LocalFiles:"
set Board[Board.row.count-1][0].text = Color[13] + "www.epicwar.com/maps/263738"
endif
endif
endif
set i = i + 1
endloop
set Board.display = false
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(NewTimer(),3,false,function thistype.NewBoard)
endmethod
endstruct
//TESH.scrollpos=2
//TESH.alwaysfold=0
struct BoardSwitch extends array
static integer state = 0
static boolean switch = false
private static method onSwitch takes nothing returns nothing
/*
if switch and LOCAL_PLAYER == GetTriggerPlayer() then
set state = state + 1
if state == 1 then
set Board.Board.display = false
set BoardLocal.Board.display = true
elseif state == 2 then
set BoardLocal.Board.display = false
set Board.Board.display = true
set state = 0
endif
endif
*/
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
exitwhen i > 11
call TriggerRegisterPlayerEvent(t, Player(i), EVENT_PLAYER_END_CINEMATIC)
set i = i + 1
endloop
call TriggerAddAction(t, function thistype.onSwitch)
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct BoFData extends array
static constant string MAP_NAME = "Battle of Flags v2.0"
static constant string FILE_NAME = "Statistics"
static constant integer MAX_VALUE = 100000
static method LoadFinish takes nothing returns nothing
local SyncData data = GetSyncedData()
local player p = data.from
local string s = ""
local integer i = 0
local Savecode loadcode
set s = data.readString(0)
call data.destroy()
set loadcode = Savecode.create()
if not loadcode.Load(p, s, 1) then
if (s != "") then
call DisplayTextToPlayer(p, 0 , 0, "Your stats code is invalid: " + s)
endif
return
endif
// data needs to be decoded
// note that if you decode multiple bits of data, the given order will be reversed.
// the first encoded data will be the last data to decode
set KD[p].deaths_loaded = loadcode.Decode(MAX_VALUE)
set KD[p].kills_loaded = loadcode.Decode(MAX_VALUE)
set KD[p].streak_loaded = loadcode.Decode(MAX_VALUE)
set KD[p].score_loaded = loadcode.Decode(MAX_VALUE)
endmethod
static method Load takes player p returns boolean
local File f
local string line = ""
local string s = ""
local integer i = 0
local SyncData data
if (GetLocalPlayer() == p) then
set f = File.open(MAP_NAME, FILE_NAME, File.Flag.READ)
set s = f.read()
if (s == null or StringLength(s) <= 0) then
//call DisplayTextToPlayer(p, 0, 0, "File is empty or was not found.")
call f.close()
return false
else
// Loop and get all lines from file
loop
set line = f.read()
exitwhen null == line
set s = s + line
set i = i + 1
endloop
call f.close()
endif
endif
// Local data exists, so it must be synced now
set data = SyncData.create(p)
call data.addString(s, 64)
call data.addEventListener(function thistype.LoadFinish)
call data.start()
return true
endmethod
static method Save takes player p returns nothing
local File f
local string s
local Savecode savecode
local integer i = 0
// Open local file
if (GetLocalPlayer() == p) then
set f = File.open(MAP_NAME, FILE_NAME, File.Flag.WRITE)
endif
// encode all values
set savecode = Savecode.create()
call savecode.Encode(KD[p].score + KD[p].score_loaded, MAX_VALUE)
set i = IMaxBJ(KD[p].streak_max, KD[p].streak_loaded)
call savecode.Encode(i, MAX_VALUE)
call savecode.Encode(KD[p].kills + KD[p].kills_loaded, MAX_VALUE)
call savecode.Encode(KD[p].deaths + KD[p].deaths_loaded, MAX_VALUE)
// Give s the encoded data
set s = savecode.Save(p, 1)
// Insert s to local file
if (GetLocalPlayer() == p) then
call f.write(s)
call f.close()
endif
endmethod
// File.enabled can't be used onInit
private static method init takes nothing returns nothing
local integer i = 0
loop
call Load(Player(i))
set i = i + 1
exitwhen i > 11
endloop
call ReleaseTimer(GetExpiredTimer())
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(NewTimer(), 0., false, function thistype.init)
endmethod
endstruct
//TESH.scrollpos=51
//TESH.alwaysfold=0
library AbilityPreload
//===========================================================================
// Information:
//==============
//
// Preloading removes the noticeable delay the first time an ability
// is loaded in a game. If an ability was not already on a pre-placed unit
// or a unit that was created during initialization, preloading is needed
// to prevent a delay.
//
//===========================================================================
// AbilityPreload API:
//=====================
//
// AbilityPreload(abilityid) :
// Call this before any time has elapsed to preload a specific
// ability. If debug mode is enabled, you will see an error message
// if you call this after initialization, or if you try to preload
// an ability that does not exist. Will inline to a UnitAddAbility
// call if debug mode is disabled.
//
// AbilityRangePreload(start, end) :
// Same as AbilityPreload, but preloads a range of abilities.
// It will iterates between the two rawcode values and preload
// every ability along the way. It will not show an error message
// for non-existent abilities.
//
//===========================================================================
// Configuration:
//================
globals
private constant integer PreloadUnitRawcode = 'zsmc'
//This is the rawcode for "Sammy!". It is never used and has no model,
//which makes an ideal preloading unit. Change it if you want to.
endglobals
//===========================================================================
globals
private unit PreloadUnit
endglobals
function AbilityPreload takes integer abilityid returns nothing
static if DEBUG_MODE then
if GetUnitTypeId(PreloadUnit) == 0 then
call BJDebugMsg("AbilityPreload error: Can't preload an ability after initialization")
return
endif
endif
call UnitAddAbility(PreloadUnit, abilityid)
static if DEBUG_MODE then
if GetUnitAbilityLevel(PreloadUnit, abilityid) == 0 then
call BJDebugMsg("AbilityPreload error: Attempted to preload a non-existent ability")
endif
endif
endfunction
function AbilityRangePreload takes integer start, integer end returns nothing
local integer i = 1
static if DEBUG_MODE then
if GetUnitTypeId(PreloadUnit) == 0 then
call BJDebugMsg("AbilityPreload error: Can't preload an ability after initialization")
return
endif
endif
if start > end then
set i = -1
endif
loop
exitwhen start > end
call UnitAddAbility(PreloadUnit, start)
set start = start + i
endloop
endfunction
//===========================================================================
private struct Init extends array
private static method onInit takes nothing returns nothing
set PreloadUnit = CreateUnit(Player(15), PreloadUnitRawcode, 0., 0., 0.)
call UnitApplyTimedLife(PreloadUnit, 0, .001)
call ShowUnit(PreloadUnit, false)
call UnitAddAbility(PreloadUnit, 'Aloc')
endmethod
endstruct
endlibrary
//TESH.scrollpos=22
//TESH.alwaysfold=0
struct PlayerTools
static force user_Force
static integer user_Amount
static player array user
static method isPlayerUser takes player p returns boolean
return (GetPlayerController(p) == MAP_CONTROL_USER and GetPlayerSlotState(p) == PLAYER_SLOT_STATE_PLAYING)
endmethod
static method user_update takes nothing returns nothing
local player p
local integer i = 0
local trigger t = CreateTrigger()
set user_Amount = -1
loop
exitwhen i > 11
set p = Player(i)
if isPlayerUser(p)then
set user_Amount = user_Amount + 1
set user[user_Amount] = p
endif
set i = i + 1
endloop
endmethod
static method onLeave takes nothing returns nothing
call ForceRemovePlayer(user_Force, GetTriggerPlayer())
call thistype.user_update()
endmethod
static method onInit takes nothing returns nothing
local player p
local integer i = 0
local trigger t = CreateTrigger()
call TriggerAddAction(t, function thistype.onLeave)
set user_Force = CreateForce()
loop
exitwhen i > 11
set p = Player(i)
if isPlayerUser(p) then
call ForceAddPlayer(user_Force, p)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_LEAVE)
call TriggerRegisterPlayerEvent(t, p, EVENT_PLAYER_DEFEAT)
endif
set i = i + 1
endloop
call user_update()
endmethod
implement Init
endstruct
//TESH.scrollpos=177
//TESH.alwaysfold=0
library Multiboard /* v2.0.0.1
*************************************************************************************
*
* 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 == $ROW$
set mb = $TABLE$.multiboarditem[this]
call $CODE$
set this = this + 1
set $ROW$ = $ROW$ - 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=4
//TESH.alwaysfold=0
library AllocT /* v1.0.2.0
*************************************************************************************
*
* */uses/*
*
* */ ErrorMessage /* https://github.com/nestharus/JASS/tree/master/jass/Systems/ErrorMessage
* */ Table /* http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
*************************************************************************************
*
* Minimizes code generation and global variables while maintaining
* excellent performance.
*
* Uses hashtable instead of array, which drastically reduces performance
* but uncaps the instance limit. Should use with table fields instead of
* array fields.
*
* local thistype this = recycler[0]
*
* if (recycler[this] == 0) then
* set recycler[0] = this + 1
* else
* set recycler[0] = recycler[this]
* endif
*
************************************************************************************
*
* module AllocT
*
* static method allocate takes nothing returns thistype
* method deallocate takes nothing returns nothing
*
* readonly boolean isAllocated
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
************************************************************************************/
module AllocT
/*
* stack
*/
private static Table recycler
/*
* list of allocated memory
*/
debug private static Table allocatedNext
debug private static Table allocatedPrev
/*
* free memory counter
*/
debug private static integer usedMemory = 0
/*
* allocation
*/
static method allocate takes nothing returns thistype
local thistype this = recycler[0]
debug call ThrowError(this < 0, "AllocT", "allocate", "thistype", 0, "Overflow.")
if (recycler[this] == 0) then
set recycler[0] = this + 1
else
set recycler[0] = recycler[this]
endif
set recycler[this] = -1
debug set usedMemory = usedMemory + 1
debug set allocatedNext[this] = 0
debug set allocatedPrev[this] = allocatedPrev[0]
debug set allocatedNext[allocatedPrev[0]] = this
debug set allocatedPrev[0] = this
return this
endmethod
method deallocate takes nothing returns nothing
debug call ThrowError(recycler[this] != -1, "AllocT", "deallocate", "thistype", this, "Attempted To Deallocate Null Instance.")
set recycler[this] = recycler[0]
set recycler[0] = this
debug set usedMemory = usedMemory - 1
debug set allocatedNext[allocatedPrev[this]] = allocatedNext[this]
debug set allocatedPrev[allocatedNext[this]] = allocatedPrev[this]
endmethod
/*
* analysis
*/
method operator isAllocated takes nothing returns boolean
return recycler[this] == -1
endmethod
static if DEBUG_MODE then
static method calculateMemoryUsage takes nothing returns integer
return usedMemory
endmethod
static method getAllocatedMemoryAsString takes nothing returns string
local integer memoryCell = allocatedNext[0]
local string memoryRepresentation = null
loop
exitwhen memoryCell == 0
if (memoryRepresentation == null) then
set memoryRepresentation = I2S(memoryCell)
else
set memoryRepresentation = memoryRepresentation + ", " + I2S(memoryCell)
endif
set memoryCell = allocatedNext[memoryCell]
endloop
return memoryRepresentation
endmethod
endif
/*
* initialization
*/
private static method onInit takes nothing returns nothing
set recycler = Table.create()
debug set allocatedNext = Table.create()
debug set allocatedPrev = Table.create()
set recycler[0] = 1
endmethod
endmodule
endlibrary
//TESH.scrollpos=258
//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=0
//TESH.alwaysfold=0
library RapidSound requires optional TimerUtils
globals
// Actually, just leave this value
private constant real MIN_DELAY_FACTOR = 4.0
endglobals
/* v1.6
Description
¯¯¯¯¯¯¯¯¯¯¯
Allows you to play sounds rapidly and flawlessly without limit.
Remember one sound file can only have one RSound instance.
External Dependencies
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
(Optional)
TimerUtils by Vexorian
wc3c.net/showthread.php?t=101322
User API
¯¯¯¯¯¯¯¯
struct RSound
Instantiate an RapidSound instance
| static method create takes string fileName, boolean is3D, boolean autoStop, integer inRate, integer outRate returns thistype
autoStop => stop when sound is out of range
inRate => fade in rate
outRate => fade out rate
Play the sound at given coordinate
| method play takes real x, real y, real z, integer volume returns nothing
Stop sound
| method stop takes boolean fadeOut returns nothing
Destroy RapidSound instance
| method kill takes nothing returns nothing
Sound file duration (in second)
| method operator duration takes nothing returns real
Resource Link
¯¯¯¯¯¯¯¯¯¯¯¯¯
hiveworkshop.com/threads/snippet-rapidsound.258991/
*/
struct RSound
private static constant integer MAX_COUNT = 4
private static integer Counter = -1
private static string array StrLib
private static thistype array StrDex
private integer ct
private integer lib
private integer dex
private real dur
private sound array snd[thistype.MAX_COUNT]
private timer array tmr[thistype.MAX_COUNT]
method operator duration takes nothing returns real
return .dur*MIN_DELAY_FACTOR
endmethod
method kill takes nothing returns nothing
local integer i
set .ct = .ct - 1
if .ct == 0 then
set i = 0
loop
exitwhen i == MAX_COUNT
call StopSound(.snd[i], true, false)
static if LIBRARY_TimerUtils then
call ReleaseTimer(.tmr[i])
else
call DestroyTimer(.tmr[i])
endif
set .snd[i] = null
set .tmr[i] = null
set i = i + 1
endloop
set StrLib[.lib] = StrLib[Counter]
set StrDex[.lib] = StrDex[Counter]
set Counter = Counter - 1
call deallocate()
endif
endmethod
method stop takes boolean fadeOut returns nothing
local integer i = 0
loop
exitwhen i == MAX_COUNT
call StopSound(.snd[i], false, fadeOut)
set i = i + 1
endloop
endmethod
method play takes real x, real y, real z, integer volume returns nothing
set .dex = .dex + 1
if .dex == MAX_COUNT then
set .dex = 0
endif
if TimerGetRemaining(.tmr[.dex]) == 0 then
call StopSound(.snd[.dex], false, false)
call SetSoundPosition(.snd[.dex], x, y, z)
call SetSoundVolume(.snd[.dex], volume)
call StartSound(.snd[.dex])
call TimerStart(.tmr[.dex], .dur, false, null)
endif
endmethod
static method create takes string fileName, boolean is3D, boolean autoStop, integer inRate, integer outRate returns thistype
local thistype this
local integer i = 0
local boolean b = true
loop
exitwhen i > Counter
if fileName == StrLib[i] then
set b = false
exitwhen true
endif
set i = i + 1
endloop
if b then
set this = allocate()
set Counter = Counter + 1
set StrLib[Counter] = fileName
set StrDex[Counter] = this
set .ct = 1
set .dex = -1
set .lib = Counter
set .dur = I2R(GetSoundFileDuration(fileName))/(1000.*MIN_DELAY_FACTOR)
set i = 0
loop
exitwhen i == MAX_COUNT
set .snd[i] = CreateSound(fileName, false, is3D, autoStop, inRate, outRate, "")
static if LIBRARY_TimerUtils then
set .tmr[i] = NewTimer()
call TimerStart(.tmr[i], 0, false, null)
call PauseTimer(.tmr[i])
else
set .tmr[i] = CreateTimer()
endif
set i = i + 1
endloop
else
set this = StrDex[i]
set .ct = .ct + 1
endif
return this
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*****************************************************************************
*
* Weather v1.1.0.0
* by Bannar aka Spinnaker
*
* Defines Weather struct family, for better weathereffect management.
*
******************************************************************************
*
* Optional requirements:
*
* Table by Bribe
* hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
*
* Alloc - choose whatever you like
*
******************************************************************************
*
* Function:
*
* function GetRectWeather takes rect r, WeatherType wt returns WeatherEffect
* returns WeatherEffect instance (if exists) associated with rect r of type wt
*
******************************************************************************
*
* struct WeatherType:
*
* constant type Rain
* constant type Shield
* constant type DungeonFog
* constant type Snow
* constant type Wind
* constant type Ray
*
******************************************************************************
*
* struct WeatherStyle:
*
* Fields:
*
* | readonly integer effectId
* | static id of weathereffect style
* |
* | readonly WeatherType type
* | generic type of weathereffect
*
* constant style AshenvaleRainHeavy
* constant style AshenvaleRainLight
* constant style DalaranShield
* constant style DungeonBlueFogHeavy
* constant style DungeonBlueFogLight
* constant style DungeonGreenFogHeavy
* constant style DungeonGreenFogLight
* constant style DungeonRedFogHeavy
* constant style DungeonRedFogLight
* constant style DungeonWhiteFogHeavy
* constant style DungeonWhiteFogLight
* constant style LordaeronRainHeavy
* constant style LordaeronRainLight
* constant style NorthrendBlizzard
* constant style NorthrendSnowHeavy
* constant style NorthrendSnowLight
* constant style OutlandWindHeavy
* constant style OutlandWindLight
* constant style RaysOfLight
* constant style RaysOfMoonlight
* constant style WindHeavy
*
******************************************************************************
*
* struct WeatherEffect:
*
* Fields:
*
* | readonly weathereffect weather
* | actual weathereffect handle
* |
* | readonly rect where
* | area which weathereffect is associated with
* |
* | readonly boolean enabled
* | indicates whether weathereffect is visible or not
* |
* | method operator style takes nothing returns WeatherStyle
* | method operator style= takes WeatherStyle ws returns nothing
* | generic style of weathereffect
*
* Methods:
*
* | static method create takes rect r, WeatherStyle ws returns thistype
* | default ctor, creates new WeatherEffect given the rect and WeatherStyle
* |
* | method destroy takes nothing returns nothing
* | default dctor
* |
* | method enable takes nothing returns nothing
* | enables this weathereffect on associated rect
* |
* | method disable takes nothing returns nothing
* | disables this weathereffect on associated rect
*
*****************************************************************************/
library WeatherEffect uses optional Table, optional Alloc
struct WeatherType extends array
readonly static thistype Rain = 1
readonly static thistype Shield = 2
readonly static thistype DungeonFog = 3
readonly static thistype Snow = 4
readonly static thistype Wind = 5
readonly static thistype Ray = 6
endstruct
private module WeatherStyleInit
private static method onInit takes nothing returns nothing
set AshenvaleRainHeavy = create('RAhr', WeatherType.Rain)
set AshenvaleRainLight = create('RAlr', WeatherType.Rain)
set DalaranShield = create('MEds', WeatherType.Shield)
set DungeonBlueFogHeavy = create('FDbh', WeatherType.DungeonFog)
set DungeonBlueFogLight = create('FDbl', WeatherType.DungeonFog)
set DungeonGreenFogHeavy = create('FDgh', WeatherType.DungeonFog)
set DungeonGreenFogLight = create('FDgl', WeatherType.DungeonFog)
set DungeonRedFogHeavy = create('FDrh', WeatherType.DungeonFog)
set DungeonRedFogLight = create('FDrl', WeatherType.DungeonFog)
set DungeonWhiteFogHeavy = create('FDwh', WeatherType.DungeonFog)
set DungeonWhiteFogLight = create('FDwl', WeatherType.DungeonFog)
set LordaeronRainHeavy = create('RLhr', WeatherType.Rain)
set LordaeronRainLight = create('RLlr', WeatherType.Rain)
set NorthrendBlizzard = create('SNbs', WeatherType.Snow)
set NorthrendSnowHeavy = create('SNhs', WeatherType.Snow)
set NorthrendSnowLight = create('SNls', WeatherType.Snow)
set OutlandWindHeavy = create('WOcw', WeatherType.Wind)
set OutlandWindLight = create('WOlw', WeatherType.Wind)
set RaysOfLight = create('LRaa', WeatherType.Ray)
set RaysOfMoonlight = create('LRma', WeatherType.Ray)
set WindHeavy = create('WNcw', WeatherType.Wind)
endmethod
endmodule
struct WeatherStyle extends array
private static integer count = 1 // up to 21
readonly integer effectId
readonly WeatherType type
readonly static thistype AshenvaleRainHeavy
readonly static thistype AshenvaleRainLight
readonly static thistype DalaranShield
readonly static thistype DungeonBlueFogHeavy
readonly static thistype DungeonBlueFogLight
readonly static thistype DungeonGreenFogHeavy
readonly static thistype DungeonGreenFogLight
readonly static thistype DungeonRedFogHeavy
readonly static thistype DungeonRedFogLight
readonly static thistype DungeonWhiteFogHeavy
readonly static thistype DungeonWhiteFogLight
readonly static thistype LordaeronRainHeavy
readonly static thistype LordaeronRainLight
readonly static thistype NorthrendBlizzard
readonly static thistype NorthrendSnowHeavy
readonly static thistype NorthrendSnowLight
readonly static thistype OutlandWindHeavy
readonly static thistype OutlandWindLight
readonly static thistype RaysOfLight
readonly static thistype RaysOfMoonlight
readonly static thistype WindHeavy
private static method create takes integer id, WeatherType t returns thistype
local thistype this = count
set effectId = id
set type = t
set count = count + 1
return this
endmethod
implement WeatherStyleInit
endstruct
static if LIBRARY_Table then
private module WeatherBaseInit
private static method onInit takes nothing returns nothing
set table = TableArray[7]
endmethod
endmodule
endif
private struct WeatherBase extends array
static if LIBRARY_Table then
static TableArray table
implement WeatherBaseInit
else
static hashtable table = InitHashtable()
endif
endstruct
function GetRectWeather takes rect r, WeatherType wt returns WeatherEffect
static if LIBRARY_Table then
return WeatherBase.table[wt][GetHandleId(r)]
else
return LoadInteger(WeatherBase.table, wt, GetHandleId(r))
endif
endfunction
struct WeatherEffect extends array
readonly weathereffect weather
readonly rect where
readonly boolean enabled
private WeatherStyle wstyle
private method init takes WeatherStyle ws returns nothing // assumes all the checks already happened
if ( wstyle != 0 ) then
call RemoveWeatherEffect(weather)
endif
set weather = AddWeatherEffect(where, ws.effectId)
call EnableWeatherEffect(weather, enabled)
if ( ws.type != wstyle.type ) then
static if LIBRARY_Table then
call WeatherBase.table[wstyle.type].remove(GetHandleId(where))
set WeatherBase.table[ws.type][GetHandleId(where)] = this
else
call RemoveSavedInteger(WeatherBase.table, wstyle.type, GetHandleId(where))
call SaveInteger(WeatherBase.table, ws.type, GetHandleId(where), this)
endif
set wstyle = ws
endif
endmethod
method operator style takes nothing returns WeatherStyle
return wstyle
endmethod
method operator style= takes WeatherStyle ws returns nothing
local WeatherEffect we
if ( ws != wstyle ) then
set we = GetRectWeather(where, wstyle.type)
if ( we == 0 or we == this ) then
call init(ws) // initializes actual weathereffect
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "WeatherEffect::operator style= failed assigning new style. Area is already connected with WeatherEffect instance of type: " + I2S(ws.type) + ".")
endif
endif
endmethod
implement optional Alloc
static if not thistype.allocate.exists then
private static integer instances = 0
private thistype recycle
static method allocate takes nothing returns thistype
local thistype this = thistype(0).recycle
if (this == 0) then
set instances = instances + 1
set this = instances
else
set thistype(0).recycle = this.recycle
endif
return this
endmethod
method deallocate takes nothing returns nothing
set this.recycle = thistype(0).recycle
set thistype(0).recycle = this
endmethod
endif
static method create takes rect r, WeatherStyle ws returns thistype
local thistype this = GetRectWeather(r, ws.type)
if ( this == 0 ) then
set this = allocate()
set where = r
set enabled = false
call init(ws) // initializes actual weathereffect
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "WeatherEffect::create failed allocating new instance. Area is already connected with WeatherEffect instance of type: " + I2S(ws.type) + ".")
endif
return this
endmethod
method destroy takes nothing returns nothing
static if LIBRARY_Table then
call WeatherBase.table[wstyle.type].remove(GetHandleId(where))
else
call RemoveSavedInteger(WeatherBase.table, wstyle.type, GetHandleId(where))
endif
call RemoveWeatherEffect(weather)
set weather = null
set where = null
set wstyle = 0
call deallocate()
endmethod
method enable takes nothing returns nothing
set enabled = true
call EnableWeatherEffect(weather, enabled)
endmethod
method disable takes nothing returns nothing
set enabled = false
call EnableWeatherEffect(weather, enabled)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitMaxState initializer Initialize requires optional AbilityPreload, optional xepreload
//==============================================================================
// UnitMaxState v2.1
//==============================================================================
// Credits:
//------------------------------------------------------------------------------
// Written By:
// Earth-Fury
//
// Original System By:
// Blade.dk
//
// Intermittent Version By:
// Deaod
//
// With Thanks To:
// - weaaddar for BonusMod and thus inspiration
// - PitzerMike for the ObjectMerger
// - Vexorian for vJass and Jass Helper
// - PipeDream for Grimoire
// - SFilip for TESH
// - MindWorX for maintaining NewGen
//------------------------------------------------------------------------------
// If you use this library in your map, please at least give credit to Blade.dk.
// Without him, this library would not exist.
//==============================================================================
// Introduction:
//------------------------------------------------------------------------------
// UnitMaxState is a library which allows you to modify a unit's maximum life,
// or maximum mana. To achieve this, the library abuses a bug with the AIlf and
// AImz abilities, which is too complex to explain here.
//
// I do believe it was indeed Blade.dk who initially found this bug. If not,
// it's still his system I stole and rewrote. Further, let me thank Deaod for
// writing up his version of this system, which inspired both the reality of
// this rewrite, and the method abilities are handled within it.
//
//==============================================================================
// Requirements:
//------------------------------------------------------------------------------
// UnitMaxState is written in vJass and requires the NewGen editor, or
// Jass Helper with PitzerMike's Object Merger configured for it.
//
// UnitMaxState requires the latest version of Jass Helper.
//
// Preloading of abilities requires either AbilityPreload or xepreload. Neither
// are required for the library to function; however, having one or the other
// will remove the slight delay the first time a unit's max state is changed.
//
//==============================================================================
// Using UnitMaxState:
//------------------------------------------------------------------------------
// UnitMaxState comes with two useful functions:
//
// nothing SetUnitMaxState(unit <target>, unitstate <state>, real <value>)
// Changes <target>'s unitstate <state> to be equal to <value>.
//
// nothing AddUnitMaxState(unit <target>, unitstate <state>, real <value>)
// Adds <value> to <target>'s <state> unitstate. Note that you can use
// negative values with this function.
//
// Both of these functions accept unitstate's other than UNIT_STATE_MAX_LIFE and
// UNIT_STATE_MAX_MANA. There is a small performance penalty in using these over
// direct usage of SetUnitState.
//
// You must not use life/mana boosting upgrades in combination with this system.
//
// Attempting to set a unit's maximum life below 1, or mana below 0 will do
// nothing. A debug message will be output if the script is compiled in
// debug mode.
//==============================================================================
//==============================================================================
// Configuration:
//------------------------------------------------------------------------------
// The below textmacro call is an all-in-one configuration line.
//------------------------------------------------------------------------------
// The first parameter is a boolean.
//
// If true, the abilities used by this system will be created on save. This adds
// a slight delay to saving your map. You only ever have to create the abilities
// the first time this library is added to your map, or if you modify any of
// the other configuration options.
//
// Note that to make the ability creation permanent, you must save with ability
// creation enabled, close your map, and reopen it in the editor. You can then
// disable ability creation, as the abilities will be permanently in your map.
//------------------------------------------------------------------------------
// The second parameter is an integer.
//
// This is the number of abilities this system will use for adding/removing
// life/mana. Note that this system uses four sets of abilities, so the actual
// number of abilities generated and used will be the value you pass here,
// multiplied by 4.
//
// The higher this number, the faster large bonuses will be added. This number
// should never have to go above 13. Between 3 and 5 will work fine for most
// maps.
//------------------------------------------------------------------------------
// The fourth and fifth parameters are 3 character prefixes for rawcodes.
//
// The first one is for the life-modifying abilities, while the second is for
// the mana-modifying abilities.
//
// Please, make sure your map has no abilities whose rawcodes begin with either
// of these prefixes before saving! Otherwise, those abilities will be
// overwritten. You can change these to any 3 character combination, if your
// map does already contain abilities whose rawcodes begin with these prefixes.
//------------------------------------------------------------------------------
///! runtextmacro UnitMaxState_Configuration("true", "3", "ZxL", "ZxM")
//! runtextmacro UnitMaxState_Globals("true", "3", "ZxL", "ZxM")
//------------------------------------------------------------------------------
// End of configuration
//------------------------------------------------------------------------------
//! textmacro UnitMaxState_Configuration takes LOAD_ABILITIES, ABILITY_COUNT, LIFE_PREFIX, MANA_PREFIX
//*
//! externalblock extension=lua ObjectMerger $FILENAME$
//! i function CreateAbilities(baseAbility, rawcodePrefix, field, name, icon)
//! i k = 0
//! i for sign = -1, 1, 2 do
//! i signStr = "+"
//! i if sign < 0 then
//! i signStr = "-"
//! i end
//! i j = 0
//! i for i = 0, (abilityCount - 1) * 3, 3 do
//! i j = j + 1
//! i createobject(baseAbility, rawcodePrefix .. string.sub(Chars, k + 1, k + 1))
//! i makechange(current, "anam", "UnitMaxState - " .. name)
//! i makechange(current, "ansf", "(" .. signStr .. tostring(j) .. ")")
//! i makechange(current, "aart", "ReplaceableTextures\\CommandButtons\\" .. icon)
//! i makechange(current, "aite", 0)
//! i makechange(current, "alev", 4)
//! i makechange(current, field, 1, 0)
//! i makechange(current, field, 2, 2^(i + 0) * sign)
//! i makechange(current, field, 3, 2^(i + 1) * sign)
//! i makechange(current, field, 4, 2^(i + 2) * sign)
//! i k = k + 1
//! i end
//! i end
//! i end
//! i if $LOAD_ABILITIES$ then
//! i setobjecttype("abilities")
//! i abilityCount = $ABILITY_COUNT$
//! i Chars = "abcdefghijklmnopqrstuvwxyz"
//! i CreateAbilities("AIlf", "$LIFE_PREFIX$", "Ilif", "Life", "BTNHealthStone.blp")
//! i CreateAbilities("AImz", "$MANA_PREFIX$", "Iman", "Mana", "BTNManaStone.blp")
//! i end
//! endexternalblock
// */
//! endtextmacro
//! textmacro UnitMaxState_Globals takes LOAD_ABILITIES, ABILITY_COUNT, LIFE_PREFIX, MANA_PREFIX
globals
private constant integer RAWCODE_LIFE = '$LIFE_PREFIX$a'
private constant integer RAWCODE_MANA = '$MANA_PREFIX$a'
public constant integer ABILITY_COUNT = $ABILITY_COUNT$
endglobals
//! endtextmacro
globals
private constant boolean PRELOAD_ABILITIES = false
private integer array POWERS_OF_2
endglobals
private function ErrorMsg takes string s returns nothing
debug call BJDebugMsg("SetUnitMaxState: " + s)
endfunction
function SetUnitMaxState takes unit target, unitstate state, real targetValue returns nothing
local integer difference
local integer rawcode
local integer abilityId
local integer abilityLevel
local integer currentAbility
if state == UNIT_STATE_MAX_LIFE then
set rawcode = RAWCODE_LIFE
if targetValue < 1 then
call ErrorMsg("You can not set a unit's max life to below 1")
return
endif
elseif state == UNIT_STATE_MAX_MANA then
set rawcode = RAWCODE_MANA
if targetValue < 0 then
call ErrorMsg("You can not set a unit's max mana to below 0")
return
endif
else
call SetUnitState(target, state, targetValue)
return
endif
set difference = R2I(targetValue) - R2I(GetUnitState(target, state))
if difference < 0 then
set difference = -difference
set rawcode = rawcode + ABILITY_COUNT
endif
set abilityId = ABILITY_COUNT - 1
set abilityLevel = 4
set currentAbility = rawcode + abilityId
loop
exitwhen difference == 0
if difference >= POWERS_OF_2[abilityId * 3 + (abilityLevel - 2)] then
call UnitAddAbility(target, currentAbility)
call SetUnitAbilityLevel(target, currentAbility, abilityLevel)
call UnitRemoveAbility(target, currentAbility)
set difference = difference - POWERS_OF_2[abilityId * 3 + (abilityLevel - 2)]
else
set abilityLevel = abilityLevel - 1
if abilityLevel <= 1 then
set abilityId = abilityId - 1
set abilityLevel = 4
set currentAbility = rawcode + abilityId
endif
endif
endloop
endfunction
function AddUnitMaxState takes unit target, unitstate state, real additionalValue returns nothing
call SetUnitMaxState(target, state, GetUnitState(target, state) + additionalValue)
endfunction
//! textmacro UnitMaxState_Preload takes RAWCODE
set i = 0
loop
exitwhen i == ABILITY_COUNT * 2 - 1
static if LIBRARY_AbilityPreload then
call AbilityPreload($RAWCODE$ + i)
elseif LIBRARY_xepreload then
call XE_PreloadAbility($RAWCODE$ + i)
endif
set i = i + 1
endloop
//! endtextmacro
private function Initialize takes nothing returns nothing
local integer i
local integer k
set i = 1
set POWERS_OF_2[0] = 1
loop
exitwhen i == ABILITY_COUNT * 2 * 2 * 3 + 1
set POWERS_OF_2[i] = POWERS_OF_2[i - 1] * 2
set i = i + 1
endloop
static if DEBUG_MODE and PRELOAD_ABILITIES and not LIBRARY_AbilityPreload and not LIBRARY_xepreload then
call ErrorMsg("Ability preloading was enabled, but neither of the supported preload libraries are present")
elseif PRELOAD_ABILITIES then
//! runtextmacro UnitMaxState_Preload("RAWCODE_LIFE")
//! runtextmacro UnitMaxState_Preload("RAWCODE_MANA")
endif
endfunction
endlibrary
//TESH.scrollpos=124
//TESH.alwaysfold=0
library DummyRecycler
// DummyRecycler v1.22
// by Flux
//
// A system that recycles dummy units while considering their facing angle.
// It can be used as attachment units or as dummy caster.
//
// Why is recycling a unit important?
// Because creating a unit is is one of the slowest function in the game
// and it will always leave a permanent tiny bit of memory (0.04 KB).
//
// Features:
//
// -- Dummy Sharing
// When a Dummy List gets low on unit count, it will borrow Dummy Units
// from the Dummy List with the highest unit count. The transfer is not
// instant because the shared Dummy Unit has to turn to the appropriate
// angle of its new Dummy List before it can be recycled.
// See BORROW_REQUEST.
//
// -- Self-balancing recycling algorithm
// Recycled Dummy Units will be thrown to the List having the least number
// of Dummy Units.
//
// -- Recycling least used
// Allows recycling a Dummy from the Dummy List with the highest
// unit count. It is useful when the facing angle of the Dummy Unit
// does not matter.
// See GetRecycledDummyAnyAngle.
//
// -- Self-adaptation
// When there are no free Dummy Units from a Dummy List, it will end up creating
// a new unit instead but that unit will be permanently added as a Dummy
// Unit to be recycled increasing the overall total Dummy Unit count.
//
// -- Count control
// Allows limiting the overall number of Dummy Units.
// See MAX_DUMMY_COUNT.
//
// -- Delayed Recycle
// Allows recycling Dummy Units after some delay to allocate time for the
// death animation of Special Effects to be seen.
// See DummyAddRecycleTimer.
//
//
//--------------------
// CREDITS
//--------------------
// Bribe - for the MissileRecycler (vJASS) where I got this concept from
// http://www.hiveworkshop.com/forums/jass-resources-412/system-missilerecycler-206086/
// - for the optional Table
// http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/
// Vexorian - for the Attachable and Pitch Animation Model (dummy.mdx)
// http://www.wc3c.net/showthread.php?t=101150
// Maker and IcemanBo - for the unit permanent 0.04 KB memory leak of units.
// http://www.hiveworkshop.com/forums/trigger-gui-editor-tutorials-279/memory-leaks-263410/
// Nestharus - for the data structure
// http://www.hiveworkshop.com/forums/2809461-post7.html
// - for the optional WorldBounds
// http://githubusercontent.com/nestharus/JASS/master/jass/Systems/WorldBounds/script.j
//
// ******************************************************************
// ***************************** API: *******************************
// ******************************************************************
//
// function GetRecycledDummy takes real x, real y, real z, real facing returns unit
// - Retrieve an unused Dummy Unit from the List.
// - The equivalent of CreateUnit
// - To use as a Dummy Caster, follow it with PauseUnit(dummy, false)
//
// function GetRecycledDummyAnyAngle takes real x, real y, real z returns unit
// - Use this function if the facing angle of the Dummy doesn't matter to you.
// - It will return a unit from the list having the highest number of unused Dummy Units.
// - To use as a Dummy Caster, follow it with PauseUnit(dummy, false)
//
// function RecycleDummy takes unit u returns nothing
// - Recycle the Dummy unit for it to be used again later.
// - The equivalent of RemoveUnit.
//
// function DummyAddRecycleTimer takes unit u, real time returns nothing
// - Recycle the Dummy unit after a certain time.
// - Use this to allocate time for the the death animation of an effect attached to the
// Dummy Unit to finish..
// - The equivalent of UnitApplyTimedLife.
// =============================================================== //
// ====================== CONFIGURATION ========================== //
// =============================================================== //
globals
//The rawcode of the Dummy Unit
private constant integer DUMMY_ID = 'dumy'
//The owner of the Dummy Unit
private constant player OWNER = Player(14)
//The number of indexed angle. The higher the value the:
// - Lesser the turning time for the Dummy Units.
// - Higher the total number of Dummy Units created at Map Initialization.
// Recommended Value: 10 (Max difference of 18 degrees)
private constant integer ANGLES_COUNT = 10
//The number of Dummy units per ANGLES_COUNT. The higher the value the:
// - Higher the number of units that can be recycled per angle, when
// no more units are in queue, the system will resort to use CreateUnit.
// - Higher the total number of Dummy Units created at Map Initialization.
// Recommended Value: 3 to 5 (for less overhead in Map Loading Screen)
private constant integer STORED_UNIT_COUNT = 3
//The maximum number of Dummy units that can exist. When the system resort
//to using CreateUnit, the unit will be permanently added to the Dummy
//List. To avoid spamming Dummy Units and having too much free Dummy
//Units to allocate, the maximum number of Dummy Units is capped.
// Recommended Value: 80 to 120
private constant integer MAX_DUMMY_COUNT = 100
//When a certain angle have less than BORROW_REQUEST units in its list,
//it will start to borrow Dummy Units from the list with the highest
//Dummy Unit count.
// Recommended Value: Half of maximum STORED_UNIT_COUNT
private constant integer BORROW_REQUEST = 5
//It will only return a Dummy if the current dummy is close
//to it's appropriate facing angle. This is to avoid returning
//a Dummy which is still turning to face it's list angle.
private constant real ANGLE_TOLERANCE = 10.0
//An additional option to automatically hide recycled dummy units in the
//corner of the map camera bounds
private constant boolean HIDE_ON_MAP_CORNER = true
endglobals
//Every time a new dummy unit is retrieved, it will apply this resets
//If it is redundant/you dont need it, remove it.
//! textmacro DUMMY_UNIT_RESET
//call SetUnitScale(bj_lastCreatedUnit, 1, 0, 0)
//call SetUnitAnimationByIndex(bj_lastCreatedUnit, 90)
//! endtextmacro
// =============================================================== //
// ==================== END CONFIGURATION ======================== //
// =============================================================== //
globals
private integer dummyCount = ANGLES_COUNT*STORED_UNIT_COUNT
private real array angle
private integer array count
private integer array countHead
private integer array countNext
private integer array countPrev
private integer array next
private integer array prev
private unit array dummy
private integer upper
private integer lower
private integer lastInstance
private constant real FACING_OFFSET = 180.0/ANGLES_COUNT
endglobals
static if HIDE_ON_MAP_CORNER and not LIBRARY_WorldBounds then
private struct Bounds extends array
readonly static real x
readonly static real y
private static method onInit takes nothing returns nothing
local rect map = GetWorldBounds()
set thistype.x = GetRectMaxX(map)
set thistype.y = GetRectMaxY(map)
call RemoveRect(map)
set map = null
endmethod
endstruct
endif
private struct S extends array
static if LIBRARY_Table then
static Table tb
else
static hashtable hash = InitHashtable()
endif
private static method onInit takes nothing returns nothing
local real add = 360.0/ANGLES_COUNT
local real a = 0
local integer this = ANGLES_COUNT
local integer head = 0
local integer cHead = JASS_MAX_ARRAY_SIZE - 1 //avoid allocation collision
local integer i = R2I(MAX_DUMMY_COUNT/ANGLES_COUNT + 0.5)
set upper = STORED_UNIT_COUNT
set lower = STORED_UNIT_COUNT
static if LIBRARY_Table then
set tb = Table.create()
endif
//Initialize countHeads
loop
exitwhen i < 0
set countNext[cHead] = cHead
set countPrev[cHead] = cHead
set countHead[i] = cHead
set cHead = cHead - 1
set i = i - 1
endloop
set cHead = countHead[STORED_UNIT_COUNT] //All heads will be inserted here initially
//Create the Dummy units
loop
exitwhen a >= 360
//Initialize head
set next[head] = head
set prev[head] = head
set count[head] = STORED_UNIT_COUNT
set angle[head] = a
//Insert head in the Count List
set countNext[head] = cHead
set countPrev[head] = countPrev[cHead]
set countNext[countPrev[head]] = head
set countPrev[countNext[head]] = head
set i = 0
loop
exitwhen i >= STORED_UNIT_COUNT
//Queued Linked List
set next[this] = head
set prev[this] = prev[head]
set next[prev[this]] = this
set prev[next[this]] = this
static if HIDE_ON_MAP_CORNER then
static if LIBRARY_WorldBounds then
set dummy[this] = CreateUnit(OWNER, DUMMY_ID, WorldBounds.maxX, WorldBounds.maxY, a)
else
set dummy[this] = CreateUnit(OWNER, DUMMY_ID, Bounds.x, Bounds.y, a)
endif
else
set dummy[this] = CreateUnit(OWNER, DUMMY_ID, 0, 0, a)
endif
call PauseUnit(dummy[this], true)
static if LIBRARY_Table then
set tb[GetHandleId(dummy[this])] = this
else
call SaveInteger(hash, GetHandleId(dummy[this]), 0, this)
endif
set this = this + 1
set i = i + 1
endloop
set head = head + 1
set a = a + add
endloop
set lastInstance = this
endmethod
endstruct
private function GetHead takes integer facing returns integer
if facing < 0 or facing >= 360 then
set facing = facing - (facing/360)*360
if facing < 0 then
set facing = facing + 360
endif
endif
return R2I((facing*ANGLES_COUNT/360.0))
endfunction
function GetRecycledDummy takes real x, real y, real z, real facing returns unit
local integer head = GetHead(R2I(facing + FACING_OFFSET))
local integer this = next[head]
local integer cHead
//If there are Dummy Units in the Queue List already facing close to the appropriate angle
if this != head and RAbsBJ(GetUnitFacing(dummy[this]) - angle[head]) <= ANGLE_TOLERANCE then
//Remove from the Queue List
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]
//For double free protection
set next[this] = -1
//Unit Properties
set bj_lastCreatedUnit = dummy[this]
call PauseUnit(bj_lastCreatedUnit, true)
call SetUnitX(bj_lastCreatedUnit, x)
call SetUnitY(bj_lastCreatedUnit, y)
call SetUnitFacing(bj_lastCreatedUnit, facing)
call SetUnitVertexColor(bj_lastCreatedUnit, 255, 255, 255, 255)
call SetUnitFlyHeight(bj_lastCreatedUnit, z, 0)
//! runtextmacro DUMMY_UNIT_RESET()
//Update Count and Bounds
set count[head] = count[head] - 1
//------------------------------------------------
// Unit Sharing
//------------------------------------------------
if count[head] < BORROW_REQUEST and count[countNext[countHead[upper]]] > count[head] then
set count[head] = count[head] + 1
set this = next[countNext[countHead[upper]]]
call SetUnitFacing(dummy[this], angle[head])
//Remove
set next[prev[this]] = next[this]
set prev[next[this]] = prev[this]
//Add to the Current List
set next[this] = head
set prev[this] = prev[head]
set next[prev[this]] = this
set prev[next[this]] = this
set head = countNext[countHead[upper]]
set count[head] = count[head] - 1
endif
//---------------------------
//Update Count Lists
//---------------------------
//Remove from the current Count List
set countNext[countPrev[head]] = countNext[head]
set countPrev[countNext[head]] = countPrev[head]
//Add to the new Count List
set cHead = countHead[count[head]]
set countNext[head] = cHead
set countPrev[head] = countPrev[cHead]
set countNext[countPrev[head]] = head
set countPrev[countNext[head]] = head
//---------------------------
// Update Bounds
//---------------------------
set cHead = countHead[upper]
if countNext[cHead] == cHead then
set upper = upper - 1
endif
if count[head] < lower then
set lower = count[head]
endif
else
set bj_lastCreatedUnit = CreateUnit(OWNER, DUMMY_ID, x, y, facing)
call PauseUnit(bj_lastCreatedUnit, true)
call SetUnitFlyHeight(bj_lastCreatedUnit, z, 0)
if dummyCount < MAX_DUMMY_COUNT then
set this = lastInstance
//For double free protection
set next[this] = -1
set dummy[this] = bj_lastCreatedUnit
static if LIBRARY_Table then
set S.tb[GetHandleId(bj_lastCreatedUnit)] = this
else
call SaveInteger(S.hash, GetHandleId(bj_lastCreatedUnit), 0, this)
endif
set lastInstance = lastInstance + 1
endif
set dummyCount = dummyCount + 1
endif
return bj_lastCreatedUnit
endfunction
function RecycleDummy takes unit u returns nothing
static if LIBRARY_Table then
local integer this = S.tb[GetHandleId(u)]
else
local integer this = LoadInteger(S.hash, GetHandleId(u), 0)
endif
local integer head
local integer cHead
//If the unit is a legit Dummy Unit
if this > 0 and next[this] == -1 then
//Find where to insert based on the list having the least number of units
set head = countNext[countHead[lower]]
set next[this] = head
set prev[this] = prev[head]
set next[prev[this]] = this
set prev[next[this]] = this
//Update Status
call SetUnitFacing(u, angle[head])
call PauseUnit(u, true)
call SetUnitOwner(u, OWNER, false)
static if HIDE_ON_MAP_CORNER then
static if LIBRARY_WorldBounds then
call SetUnitX(u, WorldBounds.maxX)
call SetUnitY(u, WorldBounds.maxY)
else
call SetUnitX(u, Bounds.x)
call SetUnitY(u, Bounds.y)
endif
else
call SetUnitVertexColor(u, 0, 0, 0, 0)
endif
set count[head] = count[head] + 1
//---------------------------
// Update Count Lists
//---------------------------
//Remove
set countNext[countPrev[head]] = countNext[head]
set countPrev[countNext[head]] = countPrev[head]
//Add to the new Count List
set cHead = countHead[count[head]]
set countNext[head] = cHead
set countPrev[head] = countPrev[cHead]
set countNext[countPrev[head]] = head
set countPrev[countNext[head]] = head
//---------------------------
// Update Bounds
//---------------------------
set cHead = countHead[lower]
if countNext[cHead] == cHead then
set lower = lower + 1
endif
if count[head] > upper then
set upper = count[head]
endif
elseif this == 0 then
call RemoveUnit(u)
debug elseif next[this] != -1 then
debug call BJDebugMsg("|cffffcc00[DummyRecycler]:|r Attempted to recycle a pending/free Dummy Unit.")
endif
endfunction
private function Expires takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer id = GetHandleId(t)
static if LIBRARY_Table then
call RecycleDummy(S.tb.unit[id])
call S.tb.remove(id)
else
call RecycleDummy(LoadUnitHandle(S.hash, id, 0))
call FlushChildHashtable(S.hash, id)
endif
call DestroyTimer(t)
set t = null
endfunction
function DummyAddRecycleTimer takes unit u, real time returns nothing
local timer t = CreateTimer()
static if LIBRARY_Table then
set S.tb.unit[GetHandleId(t)] = u
else
call SaveUnitHandle(S.hash, GetHandleId(t), 0, u)
endif
call TimerStart(t, time, false, function Expires)
set t = null
endfunction
function GetRecycledDummyAnyAngle takes real x, real y, real z returns unit
return GetRecycledDummy(x, y, z, angle[countNext[countHead[upper]]])
endfunction
// runtextmacro DUMMY_DEBUG_TOOLS()
endlibrary
//TESH.scrollpos=132
//TESH.alwaysfold=0
library CTL /* v1.2.0.1
*************************************************************************************
*
* CTL or Constant Timer Loop provides a loop for constant merged timers of timeout .03125
*
* Similar to T32 but pauses timer when no structs have instances and removes structs
* from timer trigger when those structs have no instances.
*
* This can also create new timers after destroying a previous timer and generates less
* code in the module. It also generates no triggers so long as the module is implemented
* at the top of the struct.
*
************************************************************************************
*
* module CTL
*
* Allows creation/destruction of timers in a struct. Provides instancing of those timers.
*
* - static method create takes nothing returns thistype
* - method destroy takes nothing returns nothing
*
* CTL (optional)
* local variables, code before running any timers
* CTLExpire (not optional)
* timer code
* CTLNull (optional)
* null any locals, runs after all timers
* CTLEnd (not optional)
*
* module CT32
*
* Converts struct into a timer group. Allows the timer group to be started and stopped.
* Instancing and looping through active timers is up to the user.
*
* - static method start takes nothing returns nothing
* - static method stop takes nothing returns nothing
*
* CT32 (not optional)
* timer code
* CT32End (not optional)
*
* struct TimerGroup32 extends array
*
* Allows for the creation of timer groups. Timer instancing and looping is entirely up
* to the user.
*
* - static method create takes code func returns thistype
* - method destroy takes nothing returns nothing
* - method start takes nothing returns nothing
* - method stop takes nothing returns nothing
*
************************************************************************************/
globals
private integer tgc = 0 //timer group count
private integer array tgr //timer group recycler
private integer ic=0 //instance count
private integer tc=0 //timer count
private integer array rf //root first
private integer array n //next
private integer array p //previous
private integer array th //timer head
private integer array ns //next stack
private trigger t=CreateTrigger()
private timer m=CreateTimer()
private triggercondition array ct
private conditionfunc array rc
private boolean array e32 //enabled
private integer array i32r //ct32 recycler
private integer i32cr = 0 //ct32 count recycler
private boolean array ir32 //is recycling
private boolean array id32 //is destroying
endglobals
private function E takes nothing returns nothing
local integer i=ns[0]
set ns[0]=0
loop
exitwhen 0==i
if (0==p[i]) then
if (0==n[i]) then
call TriggerRemoveCondition(t,ct[th[i]])
set ct[th[i]]=null
set tc=tc-1
set rf[th[i]]=0
else
set rf[th[i]]=n[i]
set p[n[i]]=0
endif
else
set p[n[i]]=p[i]
set n[p[i]]=n[i]
endif
set n[i]=n[0]
set n[0]=i
set i=ns[i]
endloop
loop
exitwhen 0 == i32cr
set i32cr = i32cr - 1
set i = i32r[i32cr]
if (not e32[i]) then
call TriggerRemoveCondition(t,ct[i])
set ct[i] = null
if (id32[i]) then
set tgr[i] = tgr[0]
set tgr[0] = i
set id32[i] = false
set e32[i] = false
set ir32[i] = false
endif
endif
endloop
if (0==tc) then
call PauseTimer(m)
else
call TriggerEvaluate(t)
endif
endfunction
private function CT takes integer r returns integer
local integer i
local integer f
if (0==n[0]) then
set i=ic+1
set ic=i
else
set i=n[0]
set n[0]=n[i]
endif
set th[i]=r
set ns[i]=-1
set f=rf[r]
if (0==f) then
set n[i]=0
set p[i]=0
set rf[r]=i
set ct[r]=TriggerAddCondition(t,rc[r])
//set ct[r] = null
if (0==tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc=tc+1
else
set n[i]=f
set p[i]=0
set p[f]=i
set rf[r]=i
endif
return i
endfunction
private function DT takes integer t returns nothing
debug if (0>ns[t]) then
set ns[t]=ns[0]
set ns[0]=t
debug else
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,"TIMER LOOP ERROR: ATTEMPT TO DESTROY NULL TIMER")
debug endif
endfunction
private function A takes code c returns integer
local integer i = tgr[0]
if (0 == i) then
set i = tgc + 1
set tgc = i
else
set tgr[0] = tgr[i]
endif
set rc[i]=Condition(c)
return i
endfunction
private function A32 takes integer i returns nothing
if (not e32[i]) then
if (not ir32[i] and not id32[i]) then
set ct[i] = TriggerAddCondition(t, rc[i])
endif
if (0 == tc) then
call TimerStart(m,.031250000,true,function E)
endif
set tc = tc + 1
set e32[i] = true
endif
endfunction
private function SR32 takes integer i returns nothing
if (e32[i]) then
if (not ir32[i] and not id32[i]) then
set i32r[i32cr] = i
set i32cr = i32cr + 1
set ir32[i] = true
endif
set e32[i] = false
set tc = tc - 1
endif
endfunction
private function DT32 takes integer i returns nothing
if (not id32[i]) then
if (not ir32[i]) then
set ir32[i] = true
set tc = tc - 1
set i32r[i32cr] = i
set i32cr = i32cr + 1
set e32[i] = false
endif
set id32[i] = true
endif
endfunction
private keyword r
private keyword e
module CTL
static integer rctl32
static method create takes nothing returns thistype
return CT(rctl32)
endmethod
method destroy takes nothing returns nothing
call DT(this)
endmethod
static method ectl32 takes nothing returns boolean
local thistype this=rf[rctl32]
endmodule
module CTLExpire
implement CTL
loop
exitwhen 0==this
endmodule
module CTLNull
set this=n[this]
endloop
endmodule
module CTLEnd
implement CTLNull
return false
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
module CT32
static integer rctl32
static method ectl32 takes nothing returns boolean
endmodule
module CT32End
return false
endmethod
static method start takes nothing returns nothing
call A32(rctl32)
endmethod
static method stop takes nothing returns nothing
call SR32(rctl32)
endmethod
private static method onInit takes nothing returns nothing
set rctl32 = A(function thistype.ectl32)
endmethod
endmodule
struct TimerGroup32 extends array
static method create takes code c returns thistype
return A(c)
endmethod
method destroy takes nothing returns nothing
call DT32(this)
endmethod
method start takes nothing returns nothing
call A32(this)
endmethod
method stop takes nothing returns nothing
call SR32(this)
endmethod
endstruct
endlibrary
//TESH.scrollpos=9
//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=9
//TESH.alwaysfold=0
library WorldBounds
//struct WorldBounds extends array
//static readonly rect world
// same as GetWorldBounds()
//static readonly region worldRegion
// contains world for triggers
//static readonly real maxX
//static readonly real maxY
//static readonly real minX
//static readonly real minY
//static readonly real centerX
//static readonly real centerY
private module WorldBoundInit
private static method onInit takes nothing returns nothing
set world=GetWorldBounds()
set maxX=GetRectMaxX(world)
set maxY=GetRectMaxY(world)
set minX=GetRectMinX(world)
set minY=GetRectMinY(world)
set centerX=(maxX+minX)/2
set centerY=(minY+maxY)/2
set worldRegion=CreateRegion()
call RegionAddRect(worldRegion,world)
endmethod
endmodule
struct WorldBounds extends array
readonly static real maxX
readonly static real maxY
readonly static real minX
readonly static real minY
readonly static real centerX
readonly static real centerY
readonly static rect world
readonly static region worldRegion
implement WorldBoundInit
endstruct
function IsInBounds takes real x, real y returns boolean
return x < WorldBounds.maxX and x > WorldBounds.minX and y < WorldBounds.maxY and y > WorldBounds.minY
endfunction
endlibrary
//TESH.scrollpos=18
//TESH.alwaysfold=0
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.1.0.1
* 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 either
* return a boolean (false) or nothing. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
* - Don't destroy a trigger unless you really know what you're doing.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent takes playerunitevent whichEvent, code whichFunction returns nothing
* - Registers code that will execute when an event fires.
* - function RegisterPlayerUnitEventForPlayer takes playerunitevent whichEvent, code whichFunction, player whichPlayer returns nothing
* - Registers code that will execute when an event fires for a certain player.
* - function GetPlayerUnitEventTrigger takes playerunitevent whichEvent returns trigger
* - Returns the trigger corresponding to ALL functions of a playerunitevent.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code 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], Filter(c))
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 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], Filter(c))
endfunction
function GetPlayerUnitEventTrigger takes playerunitevent p returns trigger
return t[GetHandleId(p)]
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library TimerUtils initializer init
//*********************************************************************
//* TimerUtils (red+blue+orange flavors for 1.24b+) 2.0
//* ----------
//*
//* To implement it , create a custom text trigger called TimerUtils
//* and paste the contents of this script there.
//*
//* To copy from a map to another, copy the trigger holding this
//* library to your map.
//*
//* (requires vJass) More scripts: htt://www.wc3c.net
//*
//* For your timer needs:
//* * Attaching
//* * Recycling (with double-free protection)
//*
//* set t=NewTimer() : Get a timer (alternative to CreateTimer)
//* set t=NewTimerEx(x) : Get a timer (alternative to CreateTimer), call
//* Initialize timer data as x, instead of 0.
//*
//* ReleaseTimer(t) : Relese a timer (alt to DestroyTimer)
//* SetTimerData(t,2) : Attach value 2 to timer
//* GetTimerData(t) : Get the timer's value.
//* You can assume a timer's value is 0
//* after NewTimer.
//*
//* Multi-flavor:
//* Set USE_HASH_TABLE to true if you don't want to complicate your life.
//*
//* If you like speed and giberish try learning about the other flavors.
//*
//********************************************************************
//================================================================
globals
//How to tweak timer utils:
// USE_HASH_TABLE = true (new blue)
// * SAFEST
// * SLOWEST (though hash tables are kind of fast)
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = true (orange)
// * kinda safe (except there is a limit in the number of timers)
// * ALMOST FAST
//
// USE_HASH_TABLE = false, USE_FLEXIBLE_OFFSET = false (red)
// * THE FASTEST (though is only faster than the previous method
// after using the optimizer on the map)
// * THE LEAST SAFE ( you may have to tweak OFSSET manually for it to
// work)
//
private constant boolean USE_HASH_TABLE = true
private constant boolean USE_FLEXIBLE_OFFSET = false
private constant integer OFFSET = 0x100000
private integer VOFFSET = OFFSET
//Timers to preload at map init:
private constant integer QUANTITY = 256
//Changing this to something big will allow you to keep recycling
// timers even when there are already AN INCREDIBLE AMOUNT of timers in
// the stack. But it will make things far slower so that's probably a bad idea...
private constant integer ARRAY_SIZE = 8190
endglobals
//==================================================================================================
globals
private integer array data[ARRAY_SIZE]
private hashtable ht
endglobals
//It is dependent on jasshelper's recent inlining optimization in order to perform correctly.
function SetTimerData takes timer t, integer value returns nothing
static if(USE_HASH_TABLE) then
// new blue
call SaveInteger(ht,0,GetHandleId(t), value)
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-VOFFSET]=value
else
// new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
set data[GetHandleId(t)-OFFSET]=value
endif
endfunction
function GetTimerData takes timer t returns integer
static if(USE_HASH_TABLE) then
// new blue
return LoadInteger(ht,0,GetHandleId(t) )
elseif (USE_FLEXIBLE_OFFSET) then
// orange
static if (DEBUG_MODE) then
if(GetHandleId(t)-VOFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-VOFFSET]
else
// new red
static if (DEBUG_MODE) then
if(GetHandleId(t)-OFFSET<0) then
call BJDebugMsg("SetTimerData: Wrong handle id, only use SetTimerData on timers created by NewTimer")
endif
endif
return data[GetHandleId(t)-OFFSET]
endif
endfunction
//==========================================================================================
globals
private timer array tT[ARRAY_SIZE]
private integer tN = 0
private constant integer HELD=0x28829022
//use a totally random number here, the more improbable someone uses it, the better.
private boolean didinit = false
endglobals
private keyword init
//==========================================================================================
// I needed to decide between duplicating code ignoring the "Once and only once" rule
// and using the ugly textmacros. I guess textmacros won.
//
//! textmacro TIMERUTIS_PRIVATE_NewTimerCommon takes VALUE
// On second thought, no.
//! endtextmacro
function NewTimerEx takes integer value returns timer
if (tN==0) then
if (not didinit) then
//This extra if shouldn't represent a major performance drawback
//because QUANTITY rule is not supposed to be broken every day.
call init.evaluate()
set tN = tN - 1
else
//If this happens then the QUANTITY rule has already been broken, try to fix the
// issue, else fail.
debug call BJDebugMsg("NewTimer: Warning, Exceeding TimerUtils_QUANTITY, make sure all timers are getting recycled correctly")
set tT[0]=CreateTimer()
static if( not USE_HASH_TABLE) then
debug call BJDebugMsg("In case of errors, please increase it accordingly, or set TimerUtils_USE_HASH_TABLE to true")
static if( USE_FLEXIBLE_OFFSET) then
if (GetHandleId(tT[0])-VOFFSET<0) or (GetHandleId(tT[0])-VOFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
else
if (GetHandleId(tT[0])-OFFSET<0) or (GetHandleId(tT[0])-OFFSET>=ARRAY_SIZE) then
//all right, couldn't fix it
call BJDebugMsg("NewTimer: Unable to allocate a timer, you should probably set TimerUtils_USE_HASH_TABLE to true or fix timer leaks.")
return null
endif
endif
endif
endif
else
set tN=tN-1
endif
call SetTimerData(tT[tN],value)
return tT[tN]
endfunction
function NewTimer takes nothing returns timer
return NewTimerEx(0)
endfunction
//==========================================================================================
function ReleaseTimer takes timer t returns nothing
if(t==null) then
debug call BJDebugMsg("Warning: attempt to release a null timer")
return
endif
if (tN==ARRAY_SIZE) then
debug call BJDebugMsg("Warning: Timer stack is full, destroying timer!!")
//stack is full, the map already has much more troubles than the chance of bug
call DestroyTimer(t)
else
call PauseTimer(t)
if(GetTimerData(t)==HELD) then
debug call BJDebugMsg("Warning: ReleaseTimer: Double free!")
return
endif
call SetTimerData(t,HELD)
set tT[tN]=t
set tN=tN+1
endif
endfunction
private function init takes nothing returns nothing
local integer i=0
local integer o=-1
local boolean oops = false
if ( didinit ) then
return
else
set didinit = true
endif
static if( USE_HASH_TABLE ) then
set ht = InitHashtable()
loop
exitwhen(i==QUANTITY)
set tT[i]=CreateTimer()
call SetTimerData(tT[i], HELD)
set i=i+1
endloop
set tN = QUANTITY
else
loop
set i=0
loop
exitwhen (i==QUANTITY)
set tT[i] = CreateTimer()
if(i==0) then
set VOFFSET = GetHandleId(tT[i])
static if(USE_FLEXIBLE_OFFSET) then
set o=VOFFSET
else
set o=OFFSET
endif
endif
if (GetHandleId(tT[i])-o>=ARRAY_SIZE) then
exitwhen true
endif
if (GetHandleId(tT[i])-o>=0) then
set i=i+1
endif
endloop
set tN = i
exitwhen(tN == QUANTITY)
set oops = true
exitwhen not USE_FLEXIBLE_OFFSET
debug call BJDebugMsg("TimerUtils_init: Failed a initialization attempt, will try again")
endloop
if(oops) then
static if ( USE_FLEXIBLE_OFFSET) then
debug call BJDebugMsg("The problem has been fixed.")
//If this message doesn't appear then there is so much
//handle id fragmentation that it was impossible to preload
//so many timers and the thread crashed! Therefore this
//debug message is useful.
elseif(DEBUG_MODE) then
call BJDebugMsg("There were problems and the new timer limit is "+I2S(i))
call BJDebugMsg("This is a rare ocurrence, if the timer limit is too low:")
call BJDebugMsg("a) Change USE_FLEXIBLE_OFFSET to true (reduces performance a little)")
call BJDebugMsg("b) or try changing OFFSET to "+I2S(VOFFSET) )
endif
endif
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library UnitIndexer /* v4.0.2.6
*************************************************************************************
*
* 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 UnitIndexStructMethods
* static method operator [] takes unit u returns thistype
* - Return GetUnitUserData(u)
*
* readonly unit unit
* - The indexed unit of the struct
*
************************************************************************************
*
* module UnitIndexStruct extends UnitIndexStructMethods
*
* - 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.
*
* 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 UnitIndexStructMethods
*
* - 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,'Adef',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
method operator unit takes nothing returns unit
return e[this]
endmethod
static method operator [] takes unit whichUnit returns thistype
return GetUnitUserData(whichUnit)
endmethod
endstruct
struct UnitIndexer extends array
readonly static Event INDEX
readonly static Event DEINDEX
static boolean enabled=true
private static method onEnter takes nothing returns boolean
local unit Q=GetFilterUnit()
local integer i
local integer d=o
if (enabled and 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,'Adef')
call UnitMakeAbilityPermanent(Q,true,'Adef')
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,'Adef') 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,'Adef')
endfunction
module UnitIndexStructMethods
static method operator [] takes unit u returns thistype
return GetUnitUserData(u)
endmethod
method operator unit takes nothing returns unit
return e[this]
endmethod
endmodule
module UnitIndexStruct
implement UnitIndexStructMethods
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=36
//TESH.alwaysfold=0
//============================================================================
// SpellEffectEvent
// - Version 1.1.0.0
//
// API
// ---
// RegisterSpellEffectEvent(integer abil, code onCast)
//
// Requires
// --------
// RegisterPlayerUnitEvent: hiveworkshop.com/forums/showthread.php?t=203338
//
// Optional
// --------
// Table: hiveworkshop.com/forums/showthread.php?t=188084
//
library SpellEffectEvent requires RegisterPlayerUnitEvent, optional Table
//============================================================================
private module M
static if LIBRARY_Table then
static Table tb
else
static hashtable ht = InitHashtable()
endif
static method onCast takes nothing returns nothing
static if LIBRARY_Table then
call TriggerEvaluate(.tb.trigger[GetSpellAbilityId()])
else
call TriggerEvaluate(LoadTriggerHandle(.ht, 0, GetSpellAbilityId()))
endif
endmethod
private static method onInit takes nothing returns nothing
static if LIBRARY_Table then
set .tb = Table.create()
endif
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function thistype.onCast)
endmethod
endmodule
//============================================================================
private struct S extends array
implement M
endstruct
//============================================================================
function RegisterSpellEffectEvent takes integer abil, code onCast returns nothing
static if LIBRARY_Table then
if not S.tb.handle.has(abil) then
set S.tb.trigger[abil] = CreateTrigger()
endif
call TriggerAddCondition(S.tb.trigger[abil], Filter(onCast))
else
if not HaveSavedHandle(S.ht, 0, abil) then
call SaveTriggerHandle(S.ht, 0, abil, CreateTrigger())
endif
call TriggerAddCondition(LoadTriggerHandle(S.ht, 0, abil), Filter(onCast))
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library isGameOnline initializer INIT
globals
boolean IS_GAME_ONLINE = false
//TRUE = Game is online, no cheats possible.
//FALSE = Game is offline, cheats possible.
//If your map have some sort of secrets, you can cover them in offline games
endglobals
private function INIT takes nothing returns nothing
if GetExpiredTimer() != null then
set IS_GAME_ONLINE = not IsNoDefeatCheat()
call Cheat("StrengthAndHonor")
call DestroyTimer(GetExpiredTimer())
call ClearTextMessages()
return
endif
call Cheat("StrengthAndHonor")
call TimerStart(CreateTimer(),1.0,false,function INIT)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Init /* v1.0.0.0
************************************************************************************
*
* module Init
*
* interface private static method init takes nothing returns nothing
* - Runs at map init
*
*************************************************************************************
*
* module InitTimer
*
* interface private static method init takes nothing returns nothing
* - Runs after a one-shot timer with a period of 0
*
************************************************************************************/
module Init
static if thistype.init.exists then
private static method onInit takes nothing returns nothing
call init()
endmethod
endif
endmodule
module InitTimer
static if thistype.init.exists then
private static method initex takes nothing returns nothing
call DestroyTimer(GetExpiredTimer())
call init()
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), 0, false, function thistype.initex)
endmethod
endif
endmodule
endlibrary
//TESH.scrollpos=24
//TESH.alwaysfold=0
// modified to create the .bat file inside the warcraft folder
library FileIO /* v2.0.0.1
*************************************************************************************
*
* Used read/write data to/from files
*
************************************************************************************
*
* struct File extends array
*
* Description
* -----------------------
*
* This is used to read data from files and write data to files
*
* Creators/Destructors
* -----------------------
*
* static method open takes string mapName, string fileName, integer flag returns File
* - Used to open a file. Pass read/write flag in to open file for reading or writing.
*
* method close takes nothing returns nothing
*
* Fields
* -----------------------
*
* readonly boolean enabled
* - This is a local value. It is true if the player can read files, false if the player can't read files.
* readonly string localFileScriptName
* - This contains the name and path to a bat file that is automatically created
* - on the player's computer in the event that they can't read files. Output this filename
* - and tell them to run the script so that they can read files.
*
* integer Flag.READ
* integer Flag.WRITE
* - These are the read/write flags. Pass these into File.open
*
* Methods
* -----------------------
*
* method read takes nothing returns string
* - Reads next line from file. Returns null when there are no more lines.
*
* method write takes string data returns nothing
* - Writes line to file. The only limit is wc3 max string size.
*
************************************************************************************/
//Tests if the player can read files
private module LocalFileTestInit
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(),0,false,function thistype.init)
endmethod
endmodule
private struct LocalFileTest extends array
private static constant string FLAG_FOLDER = "Flag"
private static constant string FLAG_FILE = "flag"
readonly static boolean success = false
private static method testForLocalEnabled takes nothing returns nothing
local string playerName = GetPlayerName(GetLocalPlayer())
call Preloader(FLAG_FOLDER + "\\" + FLAG_FILE)
set success = GetPlayerName(GetLocalPlayer()) != playerName
call SetPlayerName(GetLocalPlayer(), playerName)
endmethod
private static method writeLocalFileTest takes nothing returns nothing
call PreloadGenClear()
call PreloadGenStart()
call Preload("\")\r\n\tcall SetPlayerName(GetLocalPlayer(), \"FLAG TEST LOCAL CHECK\")\r\n//")
call Preload("\" )\r\nendfunction\r\nfunction AAA takes nothing returns nothing \r\n//")
call PreloadGenEnd(FLAG_FOLDER + "\\" + FLAG_FILE)
endmethod
private static method writeEnableLocalRegistry takes nothing returns nothing
call PreloadGenClear()
call PreloadGenStart()
call Preload("\")\r\necho Set Reg = CreateObject(\"wscript.shell\") > download.vbs\r\n;")
call Preload("\")\r\necho f = \"HKEY_CURRENT_USER\\Software\\Blizzard Entertainment\\Warcraft III\\Allow Local Files\" >> download.vbs\r\n;")
call Preload("\")\r\necho f = Replace(f,\"\\\",Chr(92)) >> download.vbs\r\n;") //"
call Preload("\")\r\necho Reg.RegWrite f, 1, \"REG_DWORD\" >> download.vbs\r\n;")
call Preload("\")\r\nstart download.vbs\r\n;")
call PreloadGenEnd("!! AllowLocalFiles\\" + File.localFileScriptName) // modified
endmethod
private static method init takes nothing returns nothing
call DestroyTimer(GetExpiredTimer())
call writeLocalFileTest()
call testForLocalEnabled()
if (not success) then
call writeEnableLocalRegistry()
endif
endmethod
implement LocalFileTestInit
endstruct
private struct FlagG extends array
static constant integer READ = 1
static constant integer WRITE = 2
endstruct
private module FileInit
private static method onInit takes nothing returns nothing
call init()
endmethod
endmodule
struct File extends array
private static constant string SAVE_GAME_FOLDER = "GameData" //don't change this for the player's convenience
private static constant integer MAX_LINE_LENGTH = 209 //max amount of data per line
private static hashtable stringTable //stores lines from file, 16 lines per file
private static integer instanceCount = 0
private static integer array recycler
private string mapName
private string fileName
private string data //data buffer
private integer fileIndex //current file index, -2147483648 to 2147483647
private integer dataIndex //current data index for file, 0-15
private integer flag //read/write flag
private static string array extra0 //extra 0s on string lengths to make digits = 4
static method operator Flag takes nothing returns FlagG
return 0
endmethod
static method operator enabled takes nothing returns boolean
return LocalFileTest.success
endmethod
static method operator localFileScriptName takes nothing returns string
return "AllowLocalFiles.bat" // modified
endmethod
static method open takes string mapName, string fileName, integer flag returns File
local thistype this = recycler[0]
if (0 == this) then
set this = instanceCount + 1
set instanceCount = this
else
set recycler[0] = recycler[this]
endif
set fileIndex = -2147483648
set this.mapName = mapName
set this.fileName = fileName
set this.flag = flag
if (flag == Flag.READ) then
//if reading, go to previous file index so that the reader can auto load up the file
set fileIndex = fileIndex - 1
set dataIndex = 16
elseif (flag == Flag.WRITE) then
//open file for writing
call PreloadGenClear()
call PreloadGenStart()
endif
return this
endmethod
//loads file and returns lines out of file
private static string array pname
private method loadline takes nothing returns nothing
local integer i
//if there are no more lines in the file, load next file
if (16 == dataIndex) then
set dataIndex = 0
set fileIndex = fileIndex + 1
//store current player names
set i = 15
loop
set pname[i] = GetPlayerName(Player(i))
exitwhen 0 == i
set i = i - 1
endloop
//load file (sets the player names to lines in file)
call Preloader(SAVE_GAME_FOLDER + "\\" + mapName + "\\" + fileName + I2S(fileIndex))
//flush file buffer
call FlushChildHashtable(stringTable, this)
//load lines from file to file buffer and return player names to normal
set i = 15
loop
if (pname[i] != GetPlayerName(Player(i))) then
call SaveStr(stringTable, this, i, SubString(GetPlayerName(Player(i)), 1, StringLength(GetPlayerName(Player(i)))))
call SetPlayerName(Player(i), pname[i])
endif
exitwhen 0 == i
set i = i - 1
endloop
endif
//add next line of file to data
set this.data = this.data + LoadStr(stringTable, this, dataIndex)
set dataIndex = dataIndex + 1
endmethod
method read takes nothing returns string
local integer length
local string data = ""
debug if (flag != Flag.READ) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60000,"FILE IO ERROR: ATTEMPT TO READ TO FILE OPEN FOR WRITING")
debug return null
debug endif
//if there is no data at the moment, get next line from file
if (StringLength(this.data) < 4) then
call loadline()
//if there is no next line, return null
if (StringLength(this.data) < 4) then
return null
endif
endif
//get the length of the data (# of characters that make it up)
set length = S2I(SubString(this.data, 0, 4))
set this.data = SubString(this.data, 4, StringLength(this.data))
loop
if (length > StringLength(this.data)) then
//if the length is greater than the data currently in the buffer, dump the
//entire buffer to the data being returned and get the next line
set length = length - StringLength(this.data)
set data = data + this.data
set this.data = ""
call loadline()
else
//if the length is less than the data in the buffer, dump that data
//from the buffer
set data = data + SubString(this.data, 0, length)
set this.data = SubString(this.data, length, StringLength(this.data))
set length = 0
return data
endif
endloop
return null
endmethod
method write takes string data returns nothing
local integer length = StringLength(data)
local integer digits = 0
local boolean done = false
debug if (flag != Flag.WRITE) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60000,"FILE IO ERROR: ATTEMPT TO WRITE TO FILE OPEN FOR READING")
debug return
debug endif
//first, retrieve the # of digits for the length
loop
set digits = digits + 1
set length = length/10
exitwhen 0 == length
endloop
//add the extra digits to and length to buffer
set this.data = this.data + extra0[digits] + I2S(StringLength(data))
loop
if (StringLength(data) > 400) then
//if the length of the data is greater than 400, throw first 400 chars into buffer
set this.data = this.data + SubString(data, 0, 400)
set data = SubString(data, 400, StringLength(data))
else
//if the length isn't greater than 400, throw it all into the buffer
set this.data = this.data + data
set data = ""
set done = true
endif
loop
//throw the data into file in sets of MAX_LINE_LENGTH chars until there is not
//enough data in the buffer to completely fill a line
exitwhen StringLength(this.data) < MAX_LINE_LENGTH
call Preload("\")\r\n\tcall SetPlayerName(Player("+I2S(dataIndex)+"), \" "+SubString(this.data, 0, MAX_LINE_LENGTH)+"\")\r\n//")
set this.data = SubString(this.data, MAX_LINE_LENGTH, StringLength(this.data))
set dataIndex = dataIndex + 1
if (dataIndex == 16) then
//start a new file
set dataIndex = 0
call Preload( "\" )\r\nendfunction\r\nfunction AAA takes nothing returns nothing \r\n//")
call PreloadGenEnd(SAVE_GAME_FOLDER + "\\" + mapName + "\\" + fileName + I2S(fileIndex))
set fileIndex = fileIndex + 1
call PreloadGenClear()
call PreloadGenStart()
endif
endloop
exitwhen done
endloop
endmethod
method close takes nothing returns nothing
if (flag == Flag.READ) then
//flush the read buffer
call FlushChildHashtable(stringTable, this)
elseif (flag == Flag.WRITE) then
//write remaining of data to file and close it out
call Preload("\")\r\n\tcall SetPlayerName(Player("+I2S(dataIndex)+"), \" "+data+"\")\r\n//")
call Preload( "\" )\r\nendfunction\r\nfunction AAA takes nothing returns nothing \r\n//")
call PreloadGenEnd(SAVE_GAME_FOLDER + "\\" + mapName + "\\" + fileName + I2S(fileIndex))
endif
//deallocate and reset
set recycler[this] = recycler[0]
set recycler[0] = this
set dataIndex = 0
set data = ""
endmethod
private static method init takes nothing returns nothing
set extra0[1] = "000"
set extra0[2] = "00"
set extra0[3] = "0"
set extra0[4] = ""
set stringTable = InitHashtable()
endmethod
implement FileInit
endstruct
endlibrary
//TESH.scrollpos=66
//TESH.alwaysfold=0
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library Sync requires SyncInteger, optional PlayerUtils
/***************************************************************
*
* v1.0.8, by TriggerHappy
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*
* This library allows you to quickly synchronize async data to
* all players in the map by using the game cache.
*
* Full Documentation: -http://www.hiveworkshop.com/forums/pastebin.php?id=p4f84s
*
* _________________________________________________________________________
* 1. Installation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Copy the script to your map and save it (requires JassHelper *or* JNGP)
* _________________________________________________________________________
* 2. API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* struct SyncData
*
* method create takes player from returns SyncData
* method start takes nothing returns nothing
* method refresh takes nothing returns nothing
* method destroy takes nothing returns nothing
*
* method addInt takes integer i returns nothing
* method addReal takes integer i returns nothing
* method addString takes string s, integer len returns nothing
* method addBool takes booleanflag returns nothing
*
* method readInt takes integer index returns integer
* method readReal takes integer index returns integer
* method readString takes integer index returns string
* method readBool takes integer index returns boolean
*
* method hasInt takes nothing returns boolean
* method hasReal takes nothing returns boolean
* method hasString takes nothing returns boolean
* method hasBool takes nothing returns boolean
*
* method addEventListener takes code func returns nothing
*
* ---------
*
* readonly player from
*
* readonly real timeStarted
* readonly real timeFinished
* readonly real timeElapsed
*
* readonly integer intCount
* readonly integer boolCount
* readonly integer strCount
* readonly integer realCount
* readonly integer playersDone
*
* readonly boolean buffering
*
* readonly static integer last
* readonly static player LocalPlayer
* readonly static boolean Initialized
*
* function GetSyncedData takes nothing returns SyncData
*
***************************************************************/
globals
// characters that can be synced (ascii)
private constant string ALPHABET = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~`"
// safe characters for use in game cache keys
// (case sensitive)
private constant string SAFE_KEYS = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`{|}~`"
// how fast the buffer updates
private constant real UPDATE_PERIOD = 0.0325
// automatically recycle indices when the syncing player leaves
private constant boolean AUTO_DESTROY_ON_LEAVE = true
// we use this with SyncInteger to let the library know
// that we are syncing gc data
private constant integer IDENTIFIER = 5
// size of the alphabet
private constant integer ALPHABET_BASE = StringLength(ALPHABET)
// stop reading the buffer when reaching this char
private constant string TERM_CHAR = "`"
// maximum number of strings *per instance*
private constant integer MAX_STRINGS = 8192
// filenames for gc
private constant string CACHE_FILE = "i.w3v"
private constant string CACHE_FILE_STR = "s.w3v"
// event id for JASS API
constant integer EVENT_SYNC_CACHE = 3
endglobals
//**************************************************************
function GetSyncedData takes nothing returns SyncData
return SyncData(SyncData.last)
endfunction
public function I2Char takes string alphabet, integer i returns string
return SubString(alphabet, i, i + 1)
endfunction
public function Char2I takes string alphabet, string c returns integer
local integer i = 0
local string s
local integer l = StringLength(alphabet)
loop
set s = I2Char(alphabet, i)
exitwhen i == l
if (s == c) then
return i
endif
set i = i + 1
endloop
return 0
endfunction
public function ConvertBase takes string alphabet, integer i returns string
local integer b
local string s = ""
local integer l = StringLength(alphabet)
if i < l then
return I2Char(alphabet, i)
endif
loop
exitwhen i <= 0
set b = i - ( i / l ) * l
set s = I2Char(alphabet, b) + s
set i = i / l
endloop
return s
endfunction
public function PopulateString takes string s, integer makeLen returns string
local integer i = 0
local integer l = StringLength(s)
if (l == makeLen) then
return s
endif
set l = makeLen-l
loop
exitwhen i > l
set s = s + TERM_CHAR
set i = i + 1
endloop
return s
endfunction
//**************************************************************
globals
// string table keys
private constant integer KEY_STR_POS = (0*MAX_STRINGS)
private constant integer KEY_STR_LEN = (1*MAX_STRINGS)
// pending data storage space
private constant integer KEY_DATA = (2*MAX_STRINGS)
endglobals
struct SyncData
readonly player from
readonly real timeStarted
readonly real timeFinished
readonly real timeElapsed
readonly integer intCount
readonly integer boolCount
readonly integer strCount
readonly integer realCount
readonly integer playersDone
readonly boolean buffering
private integer strBufferLen
private trigger eventTrig
private string mkey
private static hashtable Table
private static gamecache array Cache
private static integer array PendingCount
private static timer Elapsed
private static timer BufferTimer
private static integer Running = 0
readonly static integer last = 0
readonly static player LocalPlayer
readonly static boolean Initialized = false
private thistype next
private thistype prev
private method resetVars takes nothing returns nothing
set this.intCount = 0
set this.strCount = 0
set this.boolCount = 0
set this.realCount = 0
set this.playersDone = 0
set this.strBufferLen = 0
set this.timeStarted = 0
set this.timeFinished = 0
set this.buffering = false
endmethod
static method create takes player from returns thistype
local thistype this
if (GetPlayerController(from) != MAP_CONTROL_USER) then
return 0
endif
// has to be playing because of GetLocalPlayer
if (GetPlayerSlotState(from) != PLAYER_SLOT_STATE_PLAYING) then
return 0
endif
set this = thistype.allocate()
set this.from = from
set this.mkey = ConvertBase(SAFE_KEYS, this-1)
call this.resetVars()
set thistype(0).next.prev = this
set this.next = thistype(0).next
set thistype(0).next = this
set this.prev = 0
return this
endmethod
method refresh takes nothing returns nothing
local integer i = 0
local integer p = 0
loop
static if (LIBRARY_PlayerUtils) then
exitwhen i > User.AmountPlaying
set p = User.fromPlaying(i).id
else
exitwhen i == bj_MAX_PLAYER_SLOTS
set p = i
endif
call SaveInteger(Table, this, KEY_STR_POS + p, 0)
call SaveInteger(Table, this, KEY_STR_LEN + p, 0)
call SaveBoolean(Table, p, this, false) // waiting
call SaveBoolean(Table, 16+p, this, false) // playerdone
set i = i + 1
endloop
call FlushStoredMission(Cache[0], this.mkey)
call FlushStoredMission(Cache[1], this.mkey)
call this.resetVars()
endmethod
method destroy takes nothing returns nothing
if (this.eventTrig != null) then
call DestroyTrigger(this.eventTrig)
set this.eventTrig=null
endif
call this.refresh()
set this.next.prev = this.prev
set this.prev.next = this.next
call this.deallocate()
endmethod
method start takes nothing returns nothing
set this.timeStarted = TimerGetElapsed(Elapsed)
set this.playersDone = 1
set this.buffering = true
if (Running==0) then
call TimerStart(BufferTimer, UPDATE_PERIOD, true, function thistype.readBuffer)
endif
set Running=Running+1
endmethod
method addInt takes integer i returns nothing
local string position=ConvertBase(SAFE_KEYS, intCount)
if (LocalPlayer == this.from) then
call StoreInteger(Cache[0], this.mkey, position, i)
call SyncStoredInteger(Cache[0], this.mkey, position)
endif
set intCount=intCount+1
endmethod
method addReal takes real i returns nothing
local string position=ConvertBase(SAFE_KEYS, realCount)
if (LocalPlayer == this.from) then
call StoreReal(Cache[0], this.mkey, position, i)
call SyncStoredReal(Cache[0], this.mkey, position)
endif
set realCount=realCount+1
endmethod
method addBool takes boolean flag returns nothing
local string position=ConvertBase(SAFE_KEYS, boolCount)
if (LocalPlayer == this.from) then
call StoreBoolean(Cache[0], this.mkey, position, flag)
call SyncStoredBoolean(Cache[0], this.mkey, position)
endif
set boolCount=boolCount+1
endmethod
// SyncStoredString doesn't work
method addString takes string s, integer l returns nothing
local string position
local integer i = 0
local integer strPos = 0
local integer strLen = 0
if (StringLength(s) < l) then
set s = PopulateString(s, l)
endif
// store the string position in the table
if (strCount == 0) then
call SaveInteger(Table, this, KEY_STR_POS, 0)
else
set strLen = LoadInteger(Table, this, KEY_STR_LEN + (strCount-1)) + 1
set strPos = LoadInteger(Table, this, KEY_STR_POS + (strCount-1)) + strLen
call SaveInteger(Table, this, KEY_STR_POS + strCount, strPos)
endif
// convert each character in the string to an integer
loop
exitwhen i > l
set position = ConvertBase(SAFE_KEYS, strPos + i)
if (LocalPlayer == this.from) then
call StoreInteger(Cache[1], this.mkey, position, Char2I(ALPHABET, SubString(s, i, i + 1)))
call SyncStoredInteger(Cache[1], this.mkey, position)
endif
set i = i + 1
endloop
set strBufferLen = strBufferLen + l
call SaveInteger(Table, this, KEY_STR_LEN+strCount, l) // store the length as well
set strCount=strCount+1
endmethod
method readInt takes integer index returns integer
return GetStoredInteger(Cache[0], this.mkey, ConvertBase(SAFE_KEYS, index))
endmethod
method readReal takes integer index returns real
return GetStoredReal(Cache[0], this.mkey, ConvertBase(SAFE_KEYS, index))
endmethod
method readBool takes integer index returns boolean
return GetStoredBoolean(Cache[0], this.mkey, ConvertBase(SAFE_KEYS, index))
endmethod
method readString takes integer index returns string
local string s = ""
local string c
local integer i = 0
local integer strLen = LoadInteger(Table, this, KEY_STR_LEN+index)
local integer strPos
if (strLen == 0) then
return ""
endif
set strPos = LoadInteger(Table, this, KEY_STR_POS+index)
loop
exitwhen i > strLen
set c = I2Char(ALPHABET, GetStoredInteger(Cache[1], this.mkey, ConvertBase(SAFE_KEYS, strPos + i)))
if (c == TERM_CHAR) then
return s
endif
set s = s + c
set i = i + 1
endloop
return s
endmethod
method hasInt takes integer index returns boolean
return HaveStoredInteger(Cache[0], this.mkey, ConvertBase(SAFE_KEYS, index))
endmethod
method hasReal takes integer index returns boolean
return HaveStoredReal(Cache[0], this.mkey, ConvertBase(SAFE_KEYS, index))
endmethod
method hasBool takes integer index returns boolean
return HaveStoredBoolean(Cache[0], this.mkey, ConvertBase(SAFE_KEYS, index))
endmethod
method hasString takes integer index returns boolean
return (readString(index) != "")
endmethod
method addEventListener takes code func returns nothing
if (this.eventTrig == null) then
set this.eventTrig = CreateTrigger()
endif
call TriggerAddCondition(this.eventTrig, Filter(func))
endmethod
static method readBuffer takes nothing returns nothing
local boolean b = true
local integer i = 0
local integer p
local thistype data = thistype(0).next
loop
exitwhen data == 0
// find the nearest instance that is still buffering
loop
exitwhen data.buffering or data == 0
set data=data.next
endloop
// if none are found, exit
if (not data.buffering) then
return
endif
// if the player has left, destroy the instance
static if (AUTO_DESTROY_ON_LEAVE) then
if (GetPlayerSlotState(data.from) != PLAYER_SLOT_STATE_PLAYING) then
call data.destroy()
endif
endif
set b = true
// make sure all integers have been synced
if (data.intCount > 0 and not data.hasInt(data.intCount-1)) then
set b = false
endif
// make sure all reals have been synced
if (data.realCount > 0 and not data.hasReal(data.realCount-1)) then
set b = false
endif
// check strings too
if (data.strCount > 0 and not data.hasString(data.strCount-1)) then
set b = false
endif
// and booleans
if (data.boolCount > 0 and not data.hasBool(data.boolCount-1)) then
set b = false
endif
// if everything has been synced
if (b) then
set i = 0
loop
static if (LIBRARY_PlayerUtils) then
exitwhen i == User.AmountPlaying
set p = User.fromPlaying(i).id
set b = User.fromPlaying(i).isPlaying
else
exitwhen i == bj_MAX_PLAYER_SLOTS
set p = i
set b = (GetPlayerController(Player(p)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(p)) == PLAYER_SLOT_STATE_PLAYING)
endif
if (b and not LoadBoolean(Table, p, data)) then
set PendingCount[p]=PendingCount[p]+1
call SaveBoolean(Table, p, data, true)
// notify everyone that the player has recieved the message
call SyncInteger(p, IDENTIFIER)
call SaveInteger(Table, KEY_DATA + p, PendingCount[p], data)
endif
set i = i + 1
endloop
endif
set data = data.next
endloop
endmethod
static method updateStatus takes nothing returns boolean
local integer i = GetSyncedInteger()
local integer p = GetSyncedPlayerId()
local boolean b = true
local boolean c = true
local thistype data
if (i==IDENTIFIER and PendingCount[p] > 0)then
set data = thistype(LoadInteger(Table, KEY_DATA + p, PendingCount[p]))
call SaveInteger(Table, KEY_DATA + p, PendingCount[p], 0)
set PendingCount[p] = PendingCount[p]-1
set data.playersDone = data.playersDone + 1
call SaveBoolean(Table, 16+p, data, true)
set i = 0
// check if everyone has received the data
loop
static if (LIBRARY_PlayerUtils) then
exitwhen i == User.AmountPlaying
set p = User.fromPlaying(i).id
set c = User.fromPlaying(i).isPlaying
else
exitwhen i == bj_MAX_PLAYER_SLOTS
set p = i
set c = (GetPlayerController(Player(p)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(p)) == PLAYER_SLOT_STATE_PLAYING)
endif
if (c and not LoadBoolean(Table, 16+p, data)) then
set b = false // someone hasn't
endif
set i = i + 1
endloop
// if everyone has recieved the data
if (b) then
set Running=Running-1
if (Running == 0) then
call PauseTimer(BufferTimer)
endif
set data.buffering = false
set i = 0
set data.timeFinished = TimerGetElapsed(Elapsed)
set data.timeElapsed = data.timeFinished - data.timeStarted
loop
static if (LIBRARY_PlayerUtils) then
exitwhen i == User.AmountPlaying
set p = User.fromPlaying(i).id
else
exitwhen i == bj_MAX_PLAYER_SLOTS
set p = i
endif
call SaveBoolean(Table, p, data, false)
set i = i + 1
endloop
// fire events
if (data.eventTrig != null) then
set last = data
call TriggerEvaluate(data.eventTrig)
endif
call SyncInteger_FireEvents(EVENT_SYNC_CACHE)
endif
endif
return false
endmethod
static method onInit takes nothing returns nothing
set Table=InitHashtable()
set Cache[0]=InitGameCache(CACHE_FILE)
set Cache[1]=InitGameCache(CACHE_FILE_STR)
set Elapsed=CreateTimer()
set BufferTimer=CreateTimer()
static if (LIBRARY_PlayerUtils) then
set LocalPlayer=User.Local
else
set LocalPlayer=GetLocalPlayer()
endif
call OnSyncInteger(function thistype.updateStatus)
call TimerStart(Elapsed, 604800, false, null)
set Initialized = true
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Savecode requires BigNum
//library Savecode requires BigNum
//Colorize colors
constant function uppercolor takes nothing returns string
return "|cffff0000"
endfunction
constant function lowercolor takes nothing returns string
return "|cff00ff00"
endfunction
constant function numcolor takes nothing returns string
return "|cff0000ff"
endfunction
private function player_charset takes nothing returns string
return "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
endfunction
private function player_charsetlen takes nothing returns integer
return StringLength(player_charset())
endfunction
private function charset takes nothing returns string
return "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// return "0123456789"
endfunction
private function charsetlen takes nothing returns integer
return StringLength(charset())
endfunction
private function BASE takes nothing returns integer
return charsetlen()
endfunction
private constant function HASHN takes nothing returns integer
return 5000 //1./HASHN() is the probability of a random code being valid
endfunction
private constant function MAXINT takes nothing returns integer
return 2147483647
endfunction
private function player_chartoi takes string c returns integer
local integer i = 0
local string cs = player_charset()
local integer len = player_charsetlen()
loop
exitwhen i>=len or c == SubString(cs,i,i+1)
set i = i + 1
endloop
return i
endfunction
private function chartoi takes string c returns integer
local integer i = 0
local string cs = charset()
local integer len = charsetlen()
loop
exitwhen i>=len or c == SubString(cs,i,i+1)
set i = i + 1
endloop
return i
endfunction
private function itochar takes integer i returns string
return SubString(charset(),i,i+1)
endfunction
//You probably want to use a different char set for this
//Also, use a hash that doesn't suck so much
private function scommhash takes string s returns integer
local integer array count
local integer i = 0
local integer len = StringLength(s)
local integer x
set s = StringCase(s,true)
loop
exitwhen i >= len
set x = player_chartoi(SubString(s,i,i+1))
set count[x] = count[x] + 1
set i = i + 1
endloop
set i = 0
set len = player_charsetlen()
set x = 0
loop
exitwhen i>= len
set x = count[i]*count[i]*i+count[i]*x+x+199
// call BJDebugMsg(I2S(x)+" "+I2S(count[i]))
// call TriggerSleepAction(0.)
set i = i + 1
endloop
if x < 0 then
set x = -x
endif
return x
endfunction
private function modb takes integer x returns integer
if x >= BASE() then
return x - BASE()
elseif x < 0 then
return x + BASE()
else
return x
endif
endfunction
struct Savecode
real digits //logarithmic approximation
BigNum bignum
static method create takes nothing returns Savecode
local Savecode sc = Savecode.allocate()
set sc.digits = 0.
set sc.bignum = BigNum.create(BASE())
return sc
endmethod
method onDestroy takes nothing returns nothing
call .bignum.destroy()
endmethod
method Encode takes integer val, integer max returns nothing
set .digits = .digits + log(max+1,BASE())
call .bignum.MulSmall(max+1)
call .bignum.AddSmall(val)
endmethod
method Decode takes integer max returns integer
return .bignum.DivSmall(max+1)
endmethod
method IsEmpty takes nothing returns boolean
return .bignum.IsZero()
endmethod
method Length takes nothing returns real
return .digits
endmethod
method Clean takes nothing returns nothing
call .bignum.Clean()
endmethod
//These functions get too intimate with BigNum_l
method Pad takes nothing returns nothing
local BigNum_l cur = .bignum.list
local BigNum_l prev
local integer maxlen = R2I(1.0 + .Length())
loop
exitwhen cur == 0
set prev = cur
set cur = cur.next
set maxlen = maxlen - 1
endloop
loop
exitwhen maxlen <= 0
set prev.next = BigNum_l.create()
set prev = prev.next
set maxlen = maxlen - 1
endloop
endmethod
method ToString takes nothing returns string
local BigNum_l cur = .bignum.list
local string s = ""
loop
exitwhen cur == 0
set s = itochar(cur.leaf) + s
set cur = cur.next
endloop
return s
endmethod
method FromString takes string s returns nothing
local integer i = StringLength(s)-1
local BigNum_l cur = BigNum_l.create()
set .bignum.list = cur
loop
set cur.leaf = chartoi(SubString(s,i,i+1))
exitwhen i <= 0
set cur.next = BigNum_l.create()
set cur = cur.next
set i = i - 1
endloop
endmethod
method Hash takes nothing returns integer
local integer hash = 0
local integer x
local BigNum_l cur = .bignum.list
loop
exitwhen cur == 0
set x = cur.leaf
set hash = ModuloInteger(hash+79*hash/(x+1) + 293*x/(1+hash - (hash/BASE())*BASE()) + 479,HASHN())
set cur = cur.next
endloop
return hash
endmethod
//this is not cryptographic which is fine for this application
//sign = 1 is forward
//sign = -1 is backward
method Obfuscate takes integer key, integer sign returns nothing
local integer seed = GetRandomInt(0,MAXINT())
local integer advance
local integer x
local BigNum_l cur = .bignum.list
if sign == -1 then
call SetRandomSeed(.bignum.LastDigit())
set cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,BASE()-1))
set x = cur.leaf
endif
call SetRandomSeed(key)
loop
exitwhen cur == 0
if sign == -1 then
set advance = cur.leaf
endif
set cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,BASE()-1))
if sign == 1 then
set advance = cur.leaf
endif
set advance = advance + GetRandomInt(0,BASE()-1)
call SetRandomSeed(advance)
set x = cur.leaf
set cur = cur.next
endloop
if sign == 1 then
call SetRandomSeed(x)
set .bignum.list.leaf = modb(.bignum.list.leaf + sign*GetRandomInt(0,BASE()-1))
endif
call SetRandomSeed(seed)
endmethod
method Dump takes nothing returns nothing
local BigNum_l cur = .bignum.list
local string s = ""
set s = "max: "+R2S(.digits)
loop
exitwhen cur == 0
set s = I2S(cur.leaf)+" "+s
set cur = cur.next
endloop
call BJDebugMsg(s)
endmethod
method Save takes player p, integer loadtype returns string
local integer key = scommhash(GetPlayerName(p))+loadtype*73
local string s
local integer hash
call .Clean()
set hash = .Hash()
call .Encode(hash,HASHN())
call .Clean()
/////////////////////// Save code information. Comment out next two lines in implementation
//call BJDebugMsg("Expected length: " +I2S(R2I(1.0+.Length())))
//call BJDebugMsg("Room left in last char: "+R2S(1.-ModuloReal((.Length()),1)))
///////////////////////
call .Pad()
call .Obfuscate(key,1)
return .ToString()
endmethod
method Load takes player p, string s, integer loadtype returns boolean
local integer ikey = scommhash(GetPlayerName(p))+loadtype*73
local integer inputhash
call .FromString(s)
call .Obfuscate(ikey,-1)
set inputhash = .Decode(HASHN())
call .Clean()
return inputhash == .Hash()
endmethod
endstruct
private function isupper takes string c returns boolean
return c == StringCase(c,true)
endfunction
private function ischar takes string c returns boolean
return S2I(c) == 0 and c!= "0"
endfunction
private function chartype takes string c returns integer
if(ischar(c)) then
if isupper(c) then
return 0
else
return 1
endif
else
return 2
endif
endfunction
private function testchar takes string c returns nothing
if(ischar(c)) then
if isupper(c) then
call BJDebugMsg(c+" isupper")
else
call BJDebugMsg(c+" islower")
endif
else
call BJDebugMsg(c+ " isnumber")
endif
endfunction
public function colorize takes string s returns string
local string out = ""
local integer i = 0
local integer len = StringLength(s)
local integer ctype
local string c
loop
exitwhen i >= len
set c = SubString(s,i,i+1)
set ctype = chartype(c)
if ctype == 0 then
set out = out + uppercolor()+c+"|r"
elseif ctype == 1 then
set out = out + lowercolor()+c+"|r"
else
set out = out + numcolor()+c+"|r"
endif
set i = i + 1
endloop
return out
endfunction
private function prop_Savecode takes nothing returns boolean
local string s
local Savecode loadcode
//--- Data you want to save ---
local integer medal1 = 10
local integer medal2 = 3
local integer medalmax = 13
local integer XP = 1337
local integer XPmax = 1000000
local Savecode savecode = Savecode.create()
call SetPlayerName(Player(0),"yomp")
call SetPlayerName(Player(1),"fruitcup")
call savecode.Encode(medal1,medalmax)
call savecode.Encode(medal2,medalmax)
call savecode.Encode(XP,XPmax)
//--- Savecode_save generates the savecode for a specific player ---
set s = savecode.Save(Player(0),1)
call savecode.destroy()
// call BJDebugMsg("Savecode: " + Savecode_colorize(s))
//--- User writes down code, inputs again ---
set loadcode = Savecode.create()
if loadcode.Load(Player(0),s,1) then
// call BJDebugMsg("load ok")
else
call BJDebugMsg("load failed")
return false
endif
//Must decode in reverse order of encodes
// load object : max value that data can take
if XP != loadcode.Decode(XPmax) then
return false
elseif medal2 != loadcode.Decode(medalmax) then
return false
elseif medal1 != loadcode.Decode(medalmax) then
return false
endif
call loadcode.destroy()
return true
endfunction
endlibrary
//===========================================================================
function InitTrig_Savecode takes nothing returns nothing
endfunction
//TESH.scrollpos=120
//TESH.alwaysfold=0
library Trigger /* v1.1.0.2
************************************************************************************
*
* */ uses /*
*
* */ ErrorMessage /*
* */ BooleanExpression /*
* */ NxListT /*
* */ UniqueNxListT /*
* */ Init /*
* */ AllocT /*
*
************************************************************************************
*
* struct Trigger extends array
*
* Fields
* -------------------------
*
* readonly trigger trigger
* - use to register events, nothing else
* - keep in mind that triggers referencing this trigger won't fire when events fire
* - this trigger will fire when triggers referencing this trigger are fired
*
* boolean enabled
*
* Methods
* -------------------------
*
* static method create takes boolean reversed returns Trigger
* - when reverse is true, the entire expression is run in reverse
*
* method destroy takes nothing returns nothing
*
* method register takes boolexpr expression returns TriggerCondition
*
* method reference takes Trigger trig returns TriggerReference
* - like register, but for triggers instead
*
* method fire takes nothing returns nothing
*
* method clear takes nothing returns nothing
* - clears expressions
* method clearReferences takes nothing returns nothing
* - clears trigger references
* method clearBackReferences takes nothing returns nothing
* - removes references for all triggers referencing this trigger
* method clearEvents takes nothing returns nothing
* - clears events
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
************************************************************************************
*
* struct TriggerReference extends array
*
* Methods
* -------------------------
*
* method destroy takes nothing returns nothing
*
* method replace takes Trigger trigger returns nothing
*
************************************************************************************
*
* struct TriggerCondition extends array
*
* Methods
* -------------------------
*
* method destroy takes nothing returns nothing
*
* method replace takes boolexpr expr returns nothing
*
************************************************************************************/
private struct TriggerMemory extends array
//! runtextmacro CREATE_TABLE_FIELD("public", "trigger", "trig", "trigger")
//! runtextmacro CREATE_TABLE_FIELD("public", "triggercondition", "tc", "triggercondition")
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "expression", "BooleanExpression") //the trigger's expression
//! runtextmacro CREATE_TABLE_FIELD("public", "boolean", "enabled", "boolean")
method updateTrigger takes nothing returns nothing
if (tc != null) then
call TriggerRemoveCondition(trig, tc)
endif
if (enabled and expression.expression != null) then
set tc = TriggerAddCondition(trig, expression.expression)
else
call tc_clear()
endif
endmethod
private static method init takes nothing returns nothing
//! runtextmacro INITIALIZE_TABLE_FIELD("trig")
//! runtextmacro INITIALIZE_TABLE_FIELD("tc")
//! runtextmacro INITIALIZE_TABLE_FIELD("expression")
//! runtextmacro INITIALIZE_TABLE_FIELD("enabled")
endmethod
implement Init
endstruct
private struct TriggerAllocator extends array
implement AllocT
endstruct
private keyword TriggerReferencedList
private struct TriggerReferenceListData extends array
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "trig", "TriggerMemory") //the referenced trigger
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "ref", "TriggerReferencedList") //the TriggerReferencedList data for that trigger (relationship in 2 places)
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "expr", "BooleanExpression")
implement NxListT
private static method init takes nothing returns nothing
//! runtextmacro INITIALIZE_TABLE_FIELD("trig")
//! runtextmacro INITIALIZE_TABLE_FIELD("ref")
//! runtextmacro INITIALIZE_TABLE_FIELD("expr")
endmethod
implement Init
endstruct
/*
* List of triggers referencing current trigger
*/
private struct TriggerReferencedList extends array
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "trig", "TriggerMemory") //the trigger referencing this trigger
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "ref", "TriggerReferenceListData") //the ref
implement NxListT
method updateExpression takes nothing returns nothing
local thistype node
local boolexpr expr
/*
* Retrieve the expression of the referenced trigger
*/
if (TriggerMemory(this).enabled) then
set expr = TriggerMemory(this).expression.expression
else
set expr = null
endif
/*
* Iterate over all triggers referencing this trigger
*/
set node = first
loop
exitwhen node == 0
/*
* Replace expression and then update the target trigger
*/
call node.ref.expr.replace(expr)
call node.trig.updateTrigger()
call TriggerReferencedList(node.trig).updateExpression()
set node = node.next
endloop
set expr = null
endmethod
method purge takes nothing returns nothing
local thistype node = first
loop
exitwhen node == 0
/*
* Unregister the expression from the referencing trigger
* Update that trigger
*/
call node.ref.expr.unregister()
call node.trig.updateTrigger()
call node.ref.remove()
call TriggerReferencedList(node.trig).updateExpression()
set node = node.next
endloop
call destroy()
endmethod
method clearReferences takes nothing returns nothing
local thistype node = first
loop
exitwhen node == 0
/*
* Unregister the expression from the referencing trigger
* Update that trigger
*/
call node.ref.expr.unregister()
call node.trig.updateTrigger()
call node.ref.remove()
call TriggerReferencedList(node.trig).updateExpression()
set node = node.next
endloop
call clear()
endmethod
private static method init takes nothing returns nothing
//! runtextmacro INITIALIZE_TABLE_FIELD("trig")
//! runtextmacro INITIALIZE_TABLE_FIELD("ref")
endmethod
implement Init
endstruct
/*
* List of triggers current trigger references
*/
private struct TriggerReferenceList extends array
method add takes TriggerReferencedList trig returns thistype
local TriggerReferenceListData node = TriggerReferenceListData(this).enqueue()
/*
* Register the trigger as a reference
*/
set node.trig = trig
set node.ref = TriggerReferencedList(trig).enqueue()
set node.ref.trig = this
set node.ref.ref = node
/*
* Add the reference's expression
*
* Add even if null to ensure correct order
*/
if (TriggerMemory(trig).enabled) then
set node.expr = TriggerMemory(this).expression.register(TriggerMemory(trig).expression.expression)
else
set node.expr = TriggerMemory(this).expression.register(null)
endif
call TriggerMemory(this).updateTrigger()
/*
* Update the expressions of triggers referencing this trigger
*/
call TriggerReferencedList(this).updateExpression()
/*
* Return the reference
*/
return node
endmethod
method erase takes nothing returns nothing
local TriggerReferenceListData node = this //the node
set this = node.ref.trig //this trigger
call node.expr.unregister()
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
call node.ref.remove()
call node.remove()
endmethod
method replace takes TriggerMemory trig returns nothing
local TriggerReferenceListData node = this
set this = node.list
call node.ref.remove()
set node.trig = trig
set node.ref = TriggerReferencedList(trig).enqueue()
set node.ref.trig = this
set node.ref.ref = node
if (trig.enabled) then
call node.expr.replace(trig.expression.expression)
else
call node.expr.replace(null)
endif
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
endmethod
/*
* Purges all references
*/
method purge takes nothing returns nothing
local TriggerReferenceListData node = TriggerReferenceListData(this).first
loop
exitwhen node == 0
/*
* Removes the reference from the referenced list
* (triggers no longer referenced by this)
*/
call node.ref.remove()
set node = node.next
endloop
/*
* Destroy all references by triggers referencing this
*/
call TriggerReferencedList(this).purge()
call TriggerReferenceListData(this).destroy()
endmethod
method clearReferences takes nothing returns nothing
local TriggerReferenceListData node = TriggerReferenceListData(this).first
loop
exitwhen node == 0
/*
* Removes the reference from the referenced list
* (triggers no longer referenced by this)
*/
call node.ref.remove()
/*
* unregisters code
*/
call node.expr.unregister()
set node = node.next
endloop
call TriggerReferenceListData(this).clear()
endmethod
endstruct
private struct TriggerReferenceData extends array
static if DEBUG_MODE then
//! runtextmacro CREATE_TABLE_FIELD("private", "boolean", "isTriggerReference", "boolean")
endif
static method create takes TriggerReferenceList origin, TriggerMemory ref returns thistype
local thistype this = origin.add(ref)
debug set isTriggerReference = true
return this
endmethod
method destroy takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "destroy", "TriggerReferenceData", this, "Attempted To Destroy Null TriggerReferenceData.")
debug call ThrowError(not isTriggerReference, "Trigger", "destroy", "TriggerReferenceData", this, "Attempted To Destroy Invalid TriggerReferenceData.")
debug set isTriggerReference = false
call TriggerReferenceList(this).erase()
endmethod
method replace takes Trigger trig returns nothing
debug call ThrowError(this == 0, "Trigger", "destroy", "TriggerReferenceData", this, "Attempted To Destroy Null TriggerReferenceData.")
debug call ThrowError(not isTriggerReference, "Trigger", "destroy", "TriggerReferenceData", this, "Attempted To Destroy Invalid TriggerReferenceData.")
call TriggerReferenceList(this).replace(trig)
endmethod
private static method init takes nothing returns nothing
static if DEBUG_MODE then
//! runtextmacro INITIALIZE_TABLE_FIELD("isTriggerReference")
endif
endmethod
implement Init
endstruct
private struct TriggerConditionDataCollection extends array
implement UniqueNxListT
endstruct
private struct TriggerConditionData extends array
static if DEBUG_MODE then
//! runtextmacro CREATE_TABLE_FIELD("private", "boolean", "isCondition", "boolean")
endif
//! runtextmacro CREATE_TABLE_FIELD("private", "integer", "trig", "TriggerMemory")
private static method updateTrigger takes TriggerMemory trig returns nothing
call trig.updateTrigger()
call TriggerReferencedList(trig).updateExpression()
endmethod
static method create takes TriggerMemory trig, boolexpr expression returns thistype
local thistype this = trig.expression.register(expression)
set this.trig = trig
debug set isCondition = true
call TriggerConditionDataCollection(trig).enqueue(this)
call updateTrigger(trig)
return this
endmethod
method destroy takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "destroy", "TriggerConditionData", this, "Attempted To Destroy Null TriggerConditionData.")
debug call ThrowError(not isCondition, "Trigger", "destroy", "TriggerConditionData", this, "Attempted To Destroy Invalid TriggerConditionData.")
call BooleanExpression(this).unregister()
call TriggerConditionDataCollection(this).remove()
debug set isCondition = false
/*
* Update the expression
*/
call updateTrigger(trig)
endmethod
method replace takes boolexpr expr returns nothing
debug call ThrowError(this == 0, "Trigger", "destroy", "TriggerConditionData", this, "Attempted To Destroy Null TriggerConditionData.")
debug call ThrowError(not isCondition, "Trigger", "destroy", "TriggerConditionData", this, "Attempted To Destroy Invalid TriggerConditionData.")
call BooleanExpression(this).replace(expr)
call updateTrigger(trig)
endmethod
private static method init takes nothing returns nothing
static if DEBUG_MODE then
//! runtextmacro INITIALIZE_TABLE_FIELD("isCondition")
endif
//! runtextmacro INITIALIZE_TABLE_FIELD("trig")
endmethod
implement Init
endstruct
struct TriggerReference extends array
method destroy takes nothing returns nothing
call TriggerReferenceData(this).destroy()
endmethod
method replace takes Trigger trig returns nothing
call TriggerReferenceData(this).replace(trig)
endmethod
endstruct
struct TriggerCondition extends array
method destroy takes nothing returns nothing
call TriggerConditionData(this).destroy()
endmethod
method replace takes boolexpr expr returns nothing
call TriggerConditionData(this).replace(expr)
endmethod
endstruct
struct Trigger extends array
static if DEBUG_MODE then
//! runtextmacro CREATE_TABLE_FIELD("private", "boolean", "isTrigger", "boolean")
endif
static method create takes boolean reversed returns thistype
local thistype this = TriggerAllocator.allocate()
debug set isTrigger = true
set TriggerMemory(this).enabled = true
call TriggerReferencedList(this).clear()
call TriggerReferenceListData(this).clear()
call TriggerConditionDataCollection(this).clear()
set TriggerMemory(this).expression = BooleanExpression.create(reversed)
set TriggerMemory(this).trig = CreateTrigger()
return this
endmethod
static if DEBUG_MODE then
method destroy takes nothing returns nothing
call destroy_p()
endmethod
private method destroy_p takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "destroy", "Trigger", this, "Attempted To Destroy Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "destroy", "Trigger", this, "Attempted To Destroy Invalid Trigger.")
debug set isTrigger = false
call TriggerReferenceList(this).purge()
call TriggerConditionDataCollection(this).destroy()
if (TriggerMemory(this).tc != null) then
call TriggerRemoveCondition(TriggerMemory(this).trig, TriggerMemory(this).tc)
endif
call TriggerMemory(this).tc_clear()
call DestroyTrigger(TriggerMemory(this).trig)
call TriggerMemory(this).trig_clear()
call TriggerMemory(this).expression.destroy()
call TriggerAllocator(this).deallocate()
endmethod
else
method destroy takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "destroy", "Trigger", this, "Attempted To Destroy Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "destroy", "Trigger", this, "Attempted To Destroy Invalid Trigger.")
debug set isTrigger = false
call TriggerReferenceList(this).purge()
call TriggerConditionDataCollection(this).destroy()
if (TriggerMemory(this).tc != null) then
call TriggerRemoveCondition(TriggerMemory(this).trig, TriggerMemory(this).tc)
endif
call TriggerMemory(this).tc_clear()
call DestroyTrigger(TriggerMemory(this).trig)
call TriggerMemory(this).trig_clear()
call TriggerMemory(this).expression.destroy()
call TriggerAllocator(this).deallocate()
endmethod
endif
static if DEBUG_MODE then
method register takes boolexpr expression returns TriggerCondition
return register_p(expression)
endmethod
private method register_p takes boolexpr expression returns TriggerCondition
debug call ThrowError(this == 0, "Trigger", "register", "Trigger", this, "Attempted To Register To Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "register", "Trigger", this, "Attempted To Register To Invalid Trigger.")
/*
* Register the expression
*/
return TriggerConditionData.create(this, expression)
endmethod
else
method register takes boolexpr expression returns TriggerCondition
debug call ThrowError(this == 0, "Trigger", "register", "Trigger", this, "Attempted To Register To Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "register", "Trigger", this, "Attempted To Register To Invalid Trigger.")
/*
* Register the expression
*/
return TriggerConditionData.create(this, expression)
endmethod
endif
static if DEBUG_MODE then
method clear takes nothing returns nothing
call clear_p()
endmethod
private method clear_p takes nothing returns nothing
local TriggerConditionDataCollection node = TriggerConditionDataCollection(this).first
debug call ThrowError(this == 0, "Trigger", "clear", "Trigger", this, "Attempted To Clear Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clear", "Trigger", this, "Attempted To Clear Invalid Trigger.")
loop
exitwhen node == 0
call BooleanExpression(node).unregister()
set node = node.next
endloop
call TriggerConditionDataCollection(this).clear()
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
endmethod
else
method clear takes nothing returns nothing
local TriggerConditionDataCollection node = TriggerConditionDataCollection(this).first
debug call ThrowError(this == 0, "Trigger", "clear", "Trigger", this, "Attempted To Clear Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clear", "Trigger", this, "Attempted To Clear Invalid Trigger.")
loop
exitwhen node == 0
call BooleanExpression(node).unregister()
set node = node.next
endloop
call TriggerConditionDataCollection(this).clear()
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
endmethod
endif
static if DEBUG_MODE then
method clearReferences takes nothing returns nothing
call clearReferences_p()
endmethod
private method clearReferences_p takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear References Of Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear References Of Invalid Trigger.")
call TriggerReferenceList(this).clearReferences()
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
endmethod
else
method clearReferences takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear References Of Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear References Of Invalid Trigger.")
call TriggerReferenceList(this).clearReferences()
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
endmethod
endif
static if DEBUG_MODE then
method clearBackReferences takes nothing returns nothing
call clearBackReferences_p()
endmethod
private method clearBackReferences_p takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear Back References Of Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear Back References Of Invalid Trigger.")
call TriggerReferencedList(this).clearReferences()
endmethod
else
method clearBackReferences takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear Back References Of Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clearReferences", "Trigger", this, "Attempted To Clear Back References Of Invalid Trigger.")
call TriggerReferencedList(this).clearReferences()
endmethod
endif
static if DEBUG_MODE then
method reference takes thistype trig returns TriggerReference
return reference_p(trig)
endmethod
private method reference_p takes thistype trig returns TriggerReference
debug call ThrowError(this == 0, "Trigger", "reference", "Trigger", this, "Attempted To Make Null Trigger Reference Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "reference", "Trigger", this, "Attempted To Make Invalid Trigger Reference Trigger.")
debug call ThrowError(trig == 0, "Trigger", "reference", "Trigger", this, "Attempted To Reference Null Trigger (" + I2S(trig) + ").")
debug call ThrowError(not trig.isTrigger, "Trigger", "reference", "Trigger", this, "Attempted To Reference Invalid Trigger (" + I2S(trig) + ").")
return TriggerReferenceData.create(this, trig)
endmethod
else
method reference takes thistype trig returns TriggerReference
debug call ThrowError(this == 0, "Trigger", "reference", "Trigger", this, "Attempted To Make Null Trigger Reference Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "reference", "Trigger", this, "Attempted To Make Invalid Trigger Reference Trigger.")
debug call ThrowError(trig == 0, "Trigger", "reference", "Trigger", this, "Attempted To Reference Null Trigger (" + I2S(trig) + ").")
debug call ThrowError(not trig.isTrigger, "Trigger", "reference", "Trigger", this, "Attempted To Reference Invalid Trigger (" + I2S(trig) + ").")
return TriggerReferenceData.create(this, trig)
endmethod
endif
static if DEBUG_MODE then
method clearEvents takes nothing returns nothing
call clearEvents_p()
endmethod
private method clearEvents_p takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "clearEvents", "Trigger", this, "Attempted To Clear Events Of Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clearEvents", "Trigger", this, "Attempted To Clear Events Of Invalid Trigger.")
if (TriggerMemory(this).tc != null) then
call TriggerRemoveCondition(TriggerMemory(this).trig, TriggerMemory(this).tc)
endif
call DestroyTrigger(TriggerMemory(this).trig)
set TriggerMemory(this).trig = CreateTrigger()
if (TriggerMemory(this).enabled) then
set TriggerMemory(this).tc = TriggerAddCondition(TriggerMemory(this).trig, TriggerMemory(this).expression.expression)
else
call TriggerMemory(this).tc_clear()
endif
endmethod
else
method clearEvents takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "clearEvents", "Trigger", this, "Attempted To Clear Events Of Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "clearEvents", "Trigger", this, "Attempted To Clear Events Of Invalid Trigger.")
if (TriggerMemory(this).tc != null) then
call TriggerRemoveCondition(TriggerMemory(this).trig, TriggerMemory(this).tc)
endif
call DestroyTrigger(TriggerMemory(this).trig)
set TriggerMemory(this).trig = CreateTrigger()
if (TriggerMemory(this).enabled) then
set TriggerMemory(this).tc = TriggerAddCondition(TriggerMemory(this).trig, TriggerMemory(this).expression.expression)
else
call TriggerMemory(this).tc_clear()
endif
endmethod
endif
method fire takes nothing returns nothing
debug call ThrowError(this == 0, "Trigger", "fire", "Trigger", this, "Attempted To Fire Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "fire", "Trigger", this, "Attempted To Fire Invalid Trigger.")
call TriggerEvaluate(TriggerMemory(this).trig)
endmethod
method operator trigger takes nothing returns trigger
debug call ThrowError(this == 0, "Trigger", "trigger", "Trigger", this, "Attempted To Read Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "trigger", "Trigger", this, "Attempted To Read Invalid Trigger.")
return TriggerMemory(this).trig
endmethod
method operator enabled takes nothing returns boolean
debug call ThrowError(this == 0, "Trigger", "enabled", "Trigger", this, "Attempted To Read Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "enabled", "Trigger", this, "Attempted To Read Invalid Trigger.")
return TriggerMemory(this).enabled
endmethod
static if DEBUG_MODE then
method operator enabled= takes boolean enable returns nothing
set enabled_p = enable
endmethod
private method operator enabled_p= takes boolean enable returns nothing
debug call ThrowError(this == 0, "Trigger", "enabled=", "Trigger", this, "Attempted To Set Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "enabled=", "Trigger", this, "Attempted To Set Invalid Trigger.")
debug call ThrowWarning(TriggerMemory(this).enabled == enable, "Trigger", "enabled=", "Trigger", this, "Setting Enabled To Its Value.")
set TriggerMemory(this).enabled = enable
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
endmethod
else
method operator enabled= takes boolean enable returns nothing
debug call ThrowError(this == 0, "Trigger", "enabled=", "Trigger", this, "Attempted To Set Null Trigger.")
debug call ThrowError(not isTrigger, "Trigger", "enabled=", "Trigger", this, "Attempted To Set Invalid Trigger.")
debug call ThrowWarning(TriggerMemory(this).enabled == enable, "Trigger", "enabled=", "Trigger", this, "Setting Enabled To Its Value.")
set TriggerMemory(this).enabled = enable
call TriggerMemory(this).updateTrigger()
call TriggerReferencedList(this).updateExpression()
endmethod
endif
static if DEBUG_MODE then
static method calculateMemoryUsage takes nothing returns integer
return /*
*/ TriggerAllocator.calculateMemoryUsage() + /*
*/ TriggerConditionDataCollection.calculateMemoryUsage() + /*
*/ TriggerReferenceListData.calculateMemoryUsage() + /*
*/ TriggerReferencedList.calculateMemoryUsage() + /*
*/ BooleanExpression.calculateMemoryUsage()
endmethod
static method getAllocatedMemoryAsString takes nothing returns string
return /*
*/ "(Trigger)[" + TriggerAllocator.getAllocatedMemoryAsString() + "], " + /*
*/ "(Trigger TriggerConditionDataCollection)[" + TriggerConditionDataCollection.getAllocatedMemoryAsString() + "], " + /*
*/ "(Trigger Reference)[" + TriggerReferenceListData.getAllocatedMemoryAsString() + "], " + /*
*/ "(Trigger Reference Back)[" + TriggerReferencedList.getAllocatedMemoryAsString() + "], " + /*
*/ "(Boolean Expression (all))[" + BooleanExpression.getAllocatedMemoryAsString() + "]"
endmethod
endif
private static method init takes nothing returns nothing
static if DEBUG_MODE then
//! runtextmacro INITIALIZE_TABLE_FIELD("isTrigger")
endif
endmethod
implement Init
endstruct
endlibrary
//TESH.scrollpos=6
//TESH.alwaysfold=0
//Thanks to anitarf and Vexorian @ wc3c.net for this library, it makes things easier.
// Edited by Maker
library IsTerrainWalkable initializer Init
globals
// this value is how far from a point the item may end up for the point to be considered pathable
private constant real MAX_RANGE=1.
// the following two variables are set to the position of the item after each pathing check
// that way, if a point isn't pathable, these will be the coordinates of the nearest point that is
public real X=0.
public real Y=0.
private rect r
private item check
private item array hidden
private integer hiddenMax=0
endglobals
private function Init takes nothing returns nothing
set check=CreateItem('ciri',0,0)
call SetItemVisible(check,false)
set r=Rect(0.0,0.0,128.0,128.0)
endfunction
private function HideBothersomeItem takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
set hidden[hiddenMax]=GetEnumItem()
call SetItemVisible(hidden[hiddenMax],false)
set hiddenMax=hiddenMax+1
endif
endfunction
function IsTerrainWalkable takes real x, real y returns boolean
// first, hide any items in the area so they don't get in the way of our item
call MoveRectTo(r,x,y)
call EnumItemsInRect(r,null,function HideBothersomeItem)
// try to move the check item and get it's coordinates
call SetItemPosition(check,x,y)//this unhides the item...
set X=GetItemX(check)-x
set Y=GetItemY(check)-y
call SetItemVisible(check,false)//...so we must hide it again
// before returning, unhide any items that got hidden at the start
loop
exitwhen hiddenMax<=0
set hiddenMax=hiddenMax-1
call SetItemVisible(hidden[hiddenMax],true)
set hidden[hiddenMax]=null
endloop
// return pathability status
return X*X+Y*Y<MAX_RANGE
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library BigNum
//prefer algebraic approach because of real subtraction issues
function log takes real y, real base returns real
local real x
local real factor = 1.0
local real logy = 0.0
local real sign = 1.0
if(y < 0.) then
return 0.0
endif
if(y < 1.) then
set y = 1.0/y
set sign = -1.0
endif
//Chop out powers of the base
loop
exitwhen y < 1.0001 //decrease this ( bounded below by 1) to improve precision
if(y > base) then
set y = y / base
set logy = logy + factor
else
set base = SquareRoot(base) //If you use just one base a lot, precompute its squareroots
set factor = factor / 2.
endif
endloop
return sign*logy
endfunction
struct BigNum_l
integer leaf
BigNum_l next
debug static integer nalloc = 0
static method create takes nothing returns BigNum_l
local BigNum_l bl = BigNum_l.allocate()
set bl.next = 0
set bl.leaf = 0
debug set BigNum_l.nalloc = BigNum_l.nalloc + 1
return bl
endmethod
method onDestroy takes nothing returns nothing
debug set BigNum_l.nalloc = BigNum_l.nalloc - 1
endmethod
//true: want destroy
method Clean takes nothing returns boolean
if .next == 0 and .leaf == 0 then
return true
elseif .next != 0 and .next.Clean() then
call .next.destroy()
set .next = 0
return .leaf == 0
else
return false
endif
endmethod
method DivSmall takes integer base, integer denom returns integer
local integer quotient
local integer remainder = 0
local integer num
if .next != 0 then
set remainder = .next.DivSmall(base,denom)
endif
set num = .leaf + remainder*base
set quotient = num/denom
set remainder = num - quotient*denom
set .leaf = quotient
return remainder
endmethod
endstruct
struct BigNum
BigNum_l list
integer base
static method create takes integer base returns BigNum
local BigNum b = BigNum.allocate()
set b.list = 0
set b.base = base
return b
endmethod
method onDestroy takes nothing returns nothing
local BigNum_l cur = .list
local BigNum_l next
loop
exitwhen cur == 0
set next = cur.next
call cur.destroy()
set cur = next
endloop
endmethod
method IsZero takes nothing returns boolean
local BigNum_l cur = .list
loop
exitwhen cur == 0
if cur.leaf != 0 then
return false
endif
set cur = cur.next
endloop
return true
endmethod
method Dump takes nothing returns nothing
local BigNum_l cur = .list
local string s = ""
loop
exitwhen cur == 0
set s = I2S(cur.leaf)+" "+s
set cur = cur.next
endloop
call BJDebugMsg(s)
endmethod
method Clean takes nothing returns nothing
local BigNum_l cur = .list
call cur.Clean()
endmethod
//fails if bignum is null
//BASE() + carry must be less than MAXINT()
method AddSmall takes integer carry returns nothing
local BigNum_l next
local BigNum_l cur = .list
local integer sum
if cur == 0 then
set cur = BigNum_l.create()
set .list = cur
endif
loop
exitwhen carry == 0
set sum = cur.leaf + carry
set carry = sum / .base
set sum = sum - carry*.base
set cur.leaf = sum
if cur.next == 0 then
set cur.next = BigNum_l.create()
endif
set cur = cur.next
endloop
endmethod
//x*BASE() must be less than MAXINT()
method MulSmall takes integer x returns nothing
local BigNum_l cur = .list
local integer product
local integer remainder
local integer carry = 0
loop
exitwhen cur == 0 and carry == 0
set product = x * cur.leaf + carry
set carry = product/.base
set remainder = product - carry*.base
set cur.leaf = remainder
if cur.next == 0 and carry != 0 then
set cur.next = BigNum_l.create()
endif
set cur = cur.next
endloop
endmethod
//Returns remainder
method DivSmall takes integer denom returns integer
return .list.DivSmall(.base,denom)
endmethod
method LastDigit takes nothing returns integer
local BigNum_l cur = .list
local BigNum_l next
loop
set next = cur.next
exitwhen next == 0
set cur = next
endloop
return cur.leaf
endmethod
endstruct
private function prop_Allocator1 takes nothing returns boolean
local BigNum b1
local BigNum b2
set b1 = BigNum.create(37)
call b1.destroy()
set b2 = BigNum.create(37)
call b2.destroy()
return b1 == b2
endfunction
private function prop_Allocator2 takes nothing returns boolean
local BigNum b1
local boolean b = false
set b1 = BigNum.create(37)
call b1.AddSmall(17)
call b1.MulSmall(19)
debug if BigNum_l.nalloc < 1 then
debug return false
debug endif
call b1.destroy()
debug set b = BigNum_l.nalloc == 0
return b
endfunction
private function prop_Arith takes nothing returns boolean
local BigNum b1
set b1 = BigNum.create(37)
call b1.AddSmall(73)
call b1.MulSmall(39)
call b1.AddSmall(17)
//n = 2864
if b1.DivSmall(100) != 64 then
return false
elseif b1.DivSmall(7) != 0 then
return false
elseif b1.IsZero() then
return false
elseif b1.DivSmall(3) != 1 then
return false
elseif b1.DivSmall(3) != 1 then
return false
elseif not b1.IsZero() then
return false
endif
return true
endfunction
endlibrary
//===========================================================================
function InitTrig_BigNum takes nothing returns nothing
endfunction
//TESH.scrollpos=0
//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 module Initializer
private static method onInit takes nothing returns nothing
set uc = Table.create()
endmethod
endmodule
private struct init extends array
implement Initializer
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Event
globals
private real q=0
endglobals
struct Event extends array
readonly static thistype last = 0
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 GetHandleId(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
local thistype p = thistype.last
set thistype.last = this
set q=0
set q=this
call TriggerEvaluate(e[this])
set thistype.last = p
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
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
//TESH.scrollpos=-1
//TESH.alwaysfold=0
library SyncInteger initializer Init uses optional UnitDex, optional GroupUtils
/***************************************************************
*
* v1.0.7a, by TriggerHappy
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
*
* This library allows you to send integers to all other players.
*
* _________________________________________________________________________
* 1. Installation
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* Copy the script to your map and save it (requires JassHelper *or* JNGP)
* _________________________________________________________________________
* 2. How it works
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* 1. Creates 12 dummy units and assigns 10 of them an integer from 0-9.
* The 11th dummy is used to signal when the sequence of numbers is over.
* The 12h signifies a negative number.
*
* 2. Breaks down the number you want to sync to one or more base 10 integers,
* then selects each unit assoicated with that integer.
*
* 4. The selection event fires for all players when the selection has been sycned
*
* 5. The ID of the selected unit is one of the base 10 numbers. The current
* total (starts at 0) is multiplied by 10 and the latest synced integer is
* added to that. The process will repeat until it selects the 11th dummy,
* and the total is our result.
* _________________________________________________________________________
* 3. Proper Usage
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* - Avoid the SyncSelections native. It may cause the
* thread to hang or make some units un-able to move.
*
* - Dummies must be select-able (no locust)
*
* - Run the script in debug mode while testing
* _________________________________________________________________________
* 4. Function API
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* function SyncInteger takes integer playerId, integer number returns boolean
*
* function GetSyncedInteger takes nothing returns integer
* function GetSyncedPlayer takes nothing returns player
* function GetSyncedPlayerId takes nothing returns integer
* function IsPlayerSyncing takes player p returns boolean
* function IsSyncEnabled takes nothing returns boolean
* function SyncIntegerToggle takes boolean flag returns nothing
* function SyncIntegerEnable takes nothing returns nothing
* function SyncIntegerDisable takes nothing returns nothing
*
* function OnSyncInteger takes code func returns triggercondition
* function RemoveSyncEvent takes triggercondition action returns nothing
* function TriggerRegisterSyncEvent takes trigger t, integer eventtype returns nothing
*
* function SyncInitialize takes nothing returns nothing
* function SyncTerminate takes boolean destroyEvent returns nothing
*
* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
* -http://www.hiveworkshop.com/forums/submissions-414/syncinteger-syncstring-278674/
*
*/
globals
// calls SyncInitialize automatically
private constant boolean AUTO_INIT = true
// owner of the dummy units
private constant player DUMMY_PLAYER = Player(PLAYER_NEUTRAL_PASSIVE)
// dummy can *not* have locust (must be selectabe)
// basically anything should work (like 'hfoo')
private constant integer DUMMY_ID = 'hfoo' // XE_DUMMY_UNITID
// dummy ghost ability
private constant integer DUMMY_ABILITY = 'Aeth'
// debug mode
private constant boolean ALLOW_DEBUGGING = true
// higher == more dummies but faster
private constant integer BASE = 10
// don't need to change this
private constant integer DUMMY_COUNT = BASE+2
// endconfig
constant integer EVENT_SYNC_INTEGER = 1
private trigger OnSelectTrigger = CreateTrigger()
private trigger EventTrig = CreateTrigger()
private real FireEvent = 0
private group SelectionGroup
private integer array SyncData
private integer LastPlayer
private integer LastSync
private unit array SyncIntegerDummy
private integer array Power
endglobals
function GetSyncedInteger takes nothing returns integer
return LastSync
endfunction
function GetSyncedPlayer takes nothing returns player
return Player(LastPlayer)
endfunction
function GetSyncedPlayerId takes nothing returns integer
return LastPlayer
endfunction
function IsPlayerSyncing takes player p returns boolean
return (SyncData[GetPlayerId(p)] != -1)
endfunction
function IsPlayerIdSyncing takes integer pid returns boolean
return (SyncData[pid] != -1)
endfunction
function IsSyncEnabled takes nothing returns boolean
return IsTriggerEnabled(OnSelectTrigger)
endfunction
function SyncIntegerEnable takes nothing returns nothing
call EnableTrigger(OnSelectTrigger)
endfunction
function SyncIntegerDisable takes nothing returns nothing
call DisableTrigger(OnSelectTrigger)
endfunction
function SyncIntegerToggle takes boolean flag returns nothing
if (flag) then
call EnableTrigger(OnSelectTrigger)
else
call DisableTrigger(OnSelectTrigger)
endif
endfunction
function OnSyncInteger takes code func returns triggercondition
return TriggerAddCondition(EventTrig, Filter(func))
endfunction
function RemoveSyncEvent takes triggercondition action returns nothing
call TriggerRemoveCondition(EventTrig, action)
endfunction
function TriggerRegisterSyncEvent takes trigger t, integer eventtype returns nothing
call TriggerRegisterVariableEvent(t, SCOPE_PREFIX + "FireEvent", EQUAL, eventtype)
endfunction
function SyncInteger takes integer playerId, integer number returns boolean
local integer x = number
local integer i = 0
local integer d = BASE
local integer n = 0
local player p
local unit u
static if (ALLOW_DEBUGGING and DEBUG_MODE) then
if (OnSelectTrigger == null) then
call BJDebugMsg(SCOPE_PREFIX + "SyncInteger: OnSelectTrigger is destroyed")
endif
if (not IsSyncEnabled()) then
call BJDebugMsg(SCOPE_PREFIX + "SyncInteger: OnSelectTrigger is disabled")
endif
endif
if (not IsSyncEnabled()) then
return false
endif
if (number < 0) then
set d = DUMMY_COUNT-1
set number = number * -1
endif
set p = Player(playerId)
loop
set x = x/(BASE)
exitwhen x==0
set i=i+1
endloop
// de-select one unit in case the players selection is full
call GroupEnumUnitsSelected(SelectionGroup, p, null)
set u = FirstOfGroup(SelectionGroup)
if (GetLocalPlayer() == p) then
call SelectUnit(u, false)
endif
loop
set n = Power[i]
set x = number/n
if (GetLocalPlayer() == p) then
call SelectUnit(SyncIntegerDummy[x], true)
call SelectUnit(SyncIntegerDummy[x], false)
endif
set number = number-x*n
exitwhen i == 0
set i = i - 1
endloop
if (GetLocalPlayer() == p) then
call SelectUnit(SyncIntegerDummy[d], true)
call SelectUnit(SyncIntegerDummy[d], false)
call SelectUnit(u, true)
endif
set u = null
return true
endfunction
//this cleans up all dummies and triggers created by the system
function SyncTerminate takes boolean destroyEvents returns nothing
local integer i = 0
if (destroyEvents) then
call DestroyTrigger(OnSelectTrigger)
call DestroyTrigger(EventTrig)
static if (LIBRARY_SyncString) then
call DestroyTrigger(SyncString_EventTrig)
endif
else
call SyncIntegerDisable()
endif
static if (LIBRARY_UnitDex) then
set UnitDex.Enabled = false
endif
loop
exitwhen i >= DUMMY_COUNT
call RemoveUnit(SyncIntegerDummy[i])
set SyncIntegerDummy[i] = null
set i = i + 1
endloop
static if (LIBRARY_UnitDex) then
set UnitDex.Enabled = true
endif
endfunction
function SyncInitialize takes nothing returns nothing
local integer i = 0
static if (ALLOW_DEBUGGING and DEBUG_MODE) then
if (OnSelectTrigger == null) then
call BJDebugMsg(SCOPE_PREFIX + "SyncInitialize: OnSelectTrigger is null and has no events attached to it")
endif
endif
static if (LIBRARY_UnitDex) then
set UnitDex.Enabled = false
endif
loop
exitwhen i >= DUMMY_COUNT
set SyncIntegerDummy[i]=CreateUnit(DUMMY_PLAYER, DUMMY_ID, 1000000, 1000000, i)
static if (ALLOW_DEBUGGING and DEBUG_MODE) then
if (i == 0) then // display once
if (SyncIntegerDummy[i] == null) then
call BJDebugMsg(SCOPE_PREFIX + "SyncInitialize: Dummy unit is null (check DUMMY_ID)")
endif
if (GetUnitAbilityLevel(SyncIntegerDummy[i], 'Aloc') > 0) then
call BJDebugMsg(SCOPE_PREFIX + "SyncInitialize: Dummy units must be selectable (detected locust)")
call UnitRemoveAbility(SyncIntegerDummy[i], 'Aloc')
endif
endif
endif
call SetUnitUserData(SyncIntegerDummy[i], i)
call UnitAddAbility(SyncIntegerDummy[i], DUMMY_ABILITY)
call PauseUnit(SyncIntegerDummy[i], true)
set i = i + 1
endloop
static if (LIBRARY_UnitDex) then
set UnitDex.Enabled = true
endif
if (GetExpiredTimer() != null) then
call DestroyTimer(GetExpiredTimer())
endif
endfunction
private function OnSelect takes nothing returns boolean
local unit u = GetTriggerUnit()
local player p = GetTriggerPlayer()
local integer id = GetPlayerId(p)
local integer index = GetUnitUserData(u)
local boolean isNeg = (SyncIntegerDummy[DUMMY_COUNT-1] == u)
if (SyncIntegerDummy[index] != u) then
set u = null
return false
endif
static if (ALLOW_DEBUGGING and DEBUG_MODE) then
if (OnSelectTrigger == null) then
call BJDebugMsg(SCOPE_PREFIX + "SyncInteger: OnSelectTrigger is null")
endif
endif
if (isNeg) then
set SyncData[id] = SyncData[id]*-1
endif
if (isNeg or SyncIntegerDummy[DUMMY_COUNT-2] == u) then
set LastPlayer = id
set LastSync = SyncData[id]
set SyncData[id] = -1
// run "events"
set FireEvent = EVENT_SYNC_INTEGER
call TriggerEvaluate(EventTrig)
set FireEvent = 0
else
if (SyncData[id]==-1)then
set SyncData[id]=0
endif
set SyncData[id] = SyncData[id] * BASE + index
endif
set u = null
return false
endfunction
public function FireEvents takes real eventtype returns nothing
set FireEvent = eventtype
set FireEvent = 0
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local integer i = 0
local integer j
loop
call TriggerRegisterPlayerUnitEvent(OnSelectTrigger, Player(i), EVENT_PLAYER_UNIT_SELECTED, null)
set SyncData[i] = -1
set i = i + 1
exitwhen i==bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(OnSelectTrigger, Filter(function OnSelect))
static if (AUTO_INIT) then
call TimerStart(CreateTimer(), 0, false, function SyncInitialize)
endif
static if (LIBRARY_GroupUtils) then
set SelectionGroup=ENUM_GROUP
else
set SelectionGroup=CreateGroup()
endif
// fix for innacuracy of real numbers
set i=0
set j=1
loop
exitwhen i==32
set Power[i]=j
set j = j * BASE
set i=i+1
endloop
endfunction
static if (ALLOW_DEBUGGING and DEBUG_MODE) then
private function SyncSelectionsHook takes nothing returns nothing
call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, SCOPE_PREFIX + "SyncSelectionsHook: Detected SyncSelections (can cause issues)")
endfunction
hook SyncSelections SyncSelectionsHook
endif
endlibrary
//TESH.scrollpos=48
//TESH.alwaysfold=0
library ListT /* v1.0.1.0
************************************************************************************
*
* */ uses /*
*
* */ ErrorMessage /*
*
************************************************************************************
*
* module ListT
*
* Description
* -------------------------
*
* NA
*
* Fields
* -------------------------
*
* debug readonly boolean isList
* debug readonly boolean isElement
*
* 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
*
************************************************************************************/
private keyword isNode
private keyword isCollection
private keyword pp_list
private keyword pp_next
private keyword pp_prev
private keyword pp_first
private keyword pp_last
module ListT
private static thistype collectionCount = 0
private static thistype nodeCount = 0
debug private static Table p_isNode
debug method operator isNode takes nothing returns boolean
debug return p_isNode.boolean[this]
debug endmethod
debug method operator isNode= takes boolean value returns nothing
debug set p_isNode.boolean[this] = value
debug endmethod
debug private static Table p_isCollection
debug method operator isCollection takes nothing returns boolean
debug return p_isCollection.boolean[this]
debug endmethod
debug method operator isCollection= takes boolean value returns nothing
debug set p_isCollection.boolean[this] = value
debug endmethod
debug method operator isList takes nothing returns boolean
debug return isCollection
debug endmethod
debug method operator isElement takes nothing returns boolean
debug return isNode
debug endmethod
private static Table p_list
method operator pp_list takes nothing returns thistype
return p_list[this]
endmethod
method operator pp_list= takes thistype value returns nothing
set p_list[this] = value
endmethod
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 pp_list
endmethod
private static Table p_next
method operator pp_next takes nothing returns thistype
return p_next[this]
endmethod
method operator pp_next= takes thistype value returns nothing
set p_next[this] = value
endmethod
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 pp_next
endmethod
private static Table p_prev
method operator pp_prev takes nothing returns thistype
return p_prev[this]
endmethod
method operator pp_prev= takes thistype value returns nothing
set p_prev[this] = value
endmethod
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 pp_prev
endmethod
private static Table p_first
method operator pp_first takes nothing returns thistype
return p_first[this]
endmethod
method operator pp_first= takes thistype value returns nothing
set p_first[this] = value
endmethod
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 pp_first
endmethod
private static Table p_last
method operator pp_last takes nothing returns thistype
return p_last[this]
endmethod
method operator pp_last= takes thistype value returns nothing
set p_last[this] = value
endmethod
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 pp_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).pp_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).pp_first = pp_first
endif
return this
endmethod
private static method allocateNode takes nothing returns thistype
local thistype this = thistype(0).pp_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).pp_next = pp_next
endif
return this
endmethod
static method create takes nothing returns thistype
local thistype this = allocateCollection()
debug set isCollection = true
set pp_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.pp_list = this
if (pp_first == 0) then
set pp_first = node
set pp_last = node
set node.pp_next = 0
else
set pp_first.pp_prev = node
set node.pp_next = pp_first
set pp_first = node
endif
set node.pp_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.pp_list = this
if (pp_first == 0) then
set pp_first = node
set pp_last = node
set node.pp_prev = 0
else
set pp_last.pp_next = node
set node.pp_prev = pp_last
set pp_last = node
endif
set node.pp_next = 0
return node
endmethod
method pop takes nothing returns nothing
local thistype node = pp_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 pp_first.pp_list = 0
set pp_first = pp_first.pp_next
if (pp_first == 0) then
set pp_last = 0
else
set pp_first.pp_prev = 0
endif
set node.pp_next = thistype(0).pp_next
set thistype(0).pp_next = node
endmethod
method dequeue takes nothing returns nothing
local thistype node = pp_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 pp_last.pp_list = 0
set pp_last = pp_last.pp_prev
if (pp_last == 0) then
set pp_first = 0
else
set pp_last.pp_next = 0
endif
set node.pp_next = thistype(0).pp_next
set thistype(0).pp_next = node
endmethod
method remove takes nothing returns nothing
local thistype node = this
set this = node.pp_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.pp_list = 0
if (0 == node.pp_prev) then
set pp_first = node.pp_next
else
set node.pp_prev.pp_next = node.pp_next
endif
if (0 == node.pp_next) then
set pp_last = node.pp_prev
else
set node.pp_next.pp_prev = node.pp_prev
endif
set node.pp_next = thistype(0).pp_next
set thistype(0).pp_next = node
endmethod
method clear takes nothing returns nothing
debug local thistype node = pp_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.pp_next
endloop
endif
if (pp_first == 0) then
return
endif
set pp_last.pp_next = thistype(0).pp_next
set thistype(0).pp_next = pp_first
set pp_first = 0
set pp_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 (pp_first != 0) then
set pp_last.pp_next = thistype(0).pp_next
set thistype(0).pp_next = pp_first
set pp_last = 0
endif
endif
set pp_first = thistype(0).pp_first
set thistype(0).pp_first = this
endmethod
private static method onInit takes nothing returns nothing
static if DEBUG_MODE then
set p_isNode = Table.create()
set p_isCollection = Table.create()
endif
set p_list = Table.create()
set p_next = Table.create()
set p_prev = Table.create()
set p_first = Table.create()
set p_last = Table.create()
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=397
//TESH.alwaysfold=0
library BooleanExpression /* v1.2.0.0
************************************************************************************
*
* */ uses /*
*
* */ ErrorMessage /*
* */ ListT /*
* */ Table /*
* */ Init /*
* */ TableField /*
*
************************************************************************************
*
* struct BooleanExpression extends array
*
* Description
* -------------------------
*
* Creates a single boolean expression via Or's
*
* Provides a slight speed boost
*
* Allows the for the safe usage of TriggerRemoveCondition given that the only boolexpr on the trigger
* is the one from this struct
*
* To put multiple boolean expressions on to one trigger, combine them with Or. Be sure to destroy later.
*
* Alternatively, they can be wrapped with another BooleanExpression, but this will add overhead. Only use
* if more than three are planned to be on one trigger.
*
* Fields
* -------------------------
*
* readonly boolexpr expression
*
* Examples: call booleanExpression.register(myCode)
* call TriggerRemoveCondition(thisTrigger, theOneCondition)
* set theOneCondition = TriggerAddCondition(thisTrigger, booleanExpression.expression)
*
* boolean reversed
* - if this is true, the expression will run in reverse
*
* Methods
* -------------------------
*
* static method create takes boolean reversed returns BooleanExpression
* - if reversed is true, the expression will run in reverse
*
* method destroy takes nothing returns nothing
* - only use .destroy with BooleanExpression from .create, not .register
*
* method register takes boolexpr expression returns BooleanExpression
* - the returned BooleanExpression is a subtype to be used with
* - .unregister and .replace
* method unregister takes nothing returns nothing
* - unregisters a BooleanExpression
* - only use BooleanExpression from .register, not .create
*
* method replace takes boolexpr expression returns nothing
* - replaces the boolexpr inside of the registered expression
* - useful for updating expressions without breaking order
* - null expressions take no space and have no overhead, so use them
* - only use BooleanExpression from .register, not .create
*
* method clear takes nothing returns nothing
* - only use .clear with BooleanExpression from .create, not .register
*
* debug static method calculateMemoryUsage takes nothing returns integer
* - calculates how many instances are currently active
* debug static method getAllocatedMemoryAsString takes nothing returns string
* - returns a list of all active instances as a string
*
************************************************************************************/
private struct List extends array
//! runtextmacro CREATE_TABLE_FIELD("public", "boolean", "reversed", "boolean")
implement ListT
private static method init takes nothing returns nothing
//! runtextmacro INITIALIZE_TABLE_FIELD("reversed")
endmethod
implement Init
endstruct
private struct TreeNode extends array
/*
* Tree Fields
*/
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "root", "thistype")
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "left", "thistype")
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "right", "thistype")
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "height", "integer")
/*
* Standard Fields
*/
//! runtextmacro CREATE_TABLE_FIELD("public", "boolexpr", "expression", "boolexpr")
//! runtextmacro CREATE_TABLE_FIELD("public", "boolean", "canDestroy", "boolean")
///! runtextmacro CREATE_TABLE_FIELD("public", "integer", "list", "ListExpression")
public method operator isData takes nothing returns boolean
return height == 1
endmethod
public method operator isNode takes nothing returns boolean
return height != 1
endmethod
public method join takes nothing returns nothing
if (canDestroy) then
call DestroyBoolExpr(expression)
endif
if (left.expression == null) then
set canDestroy = false
if (right.expression == null) then
call expression_clear()
else
set expression = right.expression
endif
elseif (right.expression == null) then
set canDestroy = false
set expression = left.expression
elseif (List(this).list.reversed) then
set canDestroy = true
set expression = Or(right.expression, left.expression)
else
set canDestroy = true
set expression = Or(left.expression, right.expression)
endif
endmethod
public method rebuild takes nothing returns nothing
if (isNode) then
call left.rebuild()
call right.rebuild()
call join()
endif
endmethod
public method replace takes boolexpr expression returns nothing
if (this.expression == expression) then
return
endif
if (expression == null) then
call this.expression_clear()
else
set this.expression = expression
endif
loop
set this = root
exitwhen this == 0
call join()
endloop
endmethod
public static method create takes List parent returns thistype
local thistype this = parent.enqueue()
set canDestroy = false
set height = 1
return this
endmethod
public static method createData takes List parent returns thistype
local thistype this = parent.push()
set canDestroy = false
return this
endmethod
method clean takes nothing returns nothing
if (canDestroy) then
call DestroyBoolExpr(expression)
endif
call expression_clear()
endmethod
method destroy takes nothing returns nothing
call clean()
call List(this).remove()
endmethod
public method operator sibling takes nothing returns thistype
if (root != 0) then
if (root.left == this) then
return root.right
else
return root.left
endif
endif
return 0
endmethod
method updateHeight takes nothing returns nothing
if (left.height > right.height) then
set height = left.height + 1
else
set height = right.height + 1
endif
endmethod
method operator factor takes nothing returns integer
return left.height - right.height
endmethod
method setRoot takes thistype newNode returns nothing
local thistype root = this.root
if (root != 0) then
if (this == root.left) then
set root.left = newNode
else
set root.right = newNode
endif
endif
set newNode.root = root
endmethod
method rotateRight takes nothing returns thistype
local thistype newRoot = left
call setRoot(newRoot)
set root = newRoot
set left = newRoot.right
set left.root = this
set newRoot.right = this
call updateHeight()
call newRoot.updateHeight()
call join()
call newRoot.join()
return newRoot
endmethod
method rotateLeft takes nothing returns thistype
local thistype newRoot = right
call setRoot(newRoot)
set root = newRoot
set right = newRoot.left
set right.root = this
set newRoot.left = this
call updateHeight()
call newRoot.updateHeight()
call join()
call newRoot.join()
return newRoot
endmethod
method balance takes nothing returns thistype
local integer factor
local thistype node
loop
call updateHeight()
set factor = this.factor
if (factor > 1) then
if (left.factor < 0) then
call left.rotateLeft()
endif
set this = rotateRight()
exitwhen true
elseif (factor < -1) then
if (right.factor > 0) then
call right.rotateRight()
endif
set this = rotateLeft()
exitwhen true
else
call join()
endif
set this = root
exitwhen this == 0
endloop
if (this != 0) then
set node = root
loop
exitwhen node == 0
call node.updateHeight()
call node.join()
set node = node.root
endloop
endif
return this
endmethod
private static method init takes nothing returns nothing
//! runtextmacro INITIALIZE_TABLE_FIELD("root")
//! runtextmacro INITIALIZE_TABLE_FIELD("left")
//! runtextmacro INITIALIZE_TABLE_FIELD("right")
//! runtextmacro INITIALIZE_TABLE_FIELD("height")
//! runtextmacro INITIALIZE_TABLE_FIELD("expression")
//! runtextmacro INITIALIZE_TABLE_FIELD("canDestroy")
endmethod
implement Init
endstruct
private struct Tree extends array
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "root", "TreeNode")
public static method create takes boolean reversed returns thistype
local thistype this = List.create()
set List(this).reversed = reversed
return this
endmethod
method clear takes nothing returns nothing
local List node = List(this).first
loop
exitwhen node == 0
call TreeNode(node).clean()
set node = node.next
endloop
call List(this).clear()
call root_clear()
endmethod
method destroy takes nothing returns nothing
call clear()
call List(this).destroy()
endmethod
method operator reversed takes nothing returns boolean
return List(this).reversed
endmethod
method operator reversed= takes boolean b returns nothing
if (b == reversed) then
return
endif
set List(this).reversed = b
if (root != 0) then
call root.rebuild()
endif
endmethod
method updateRoot takes TreeNode node returns nothing
if (node != 0 and node.root == 0) then
set this.root = node
endif
endmethod
method insert takes boolexpr expression returns TreeNode
local TreeNode sibling = List(this).last
local TreeNode node = TreeNode.create(this)
local TreeNode root = 0
local TreeNode grandroot = 0
if (expression != null) then
set node.expression = expression
endif
if (sibling != 0) then
set root = TreeNode.createData(this)
set grandroot = sibling.root
set root.left = sibling
set root.right = node
set node.root = root
set sibling.root = root
set root.height = 2
set root.root = grandroot
call root.join()
if (grandroot != 0) then
set grandroot.right = root
call updateRoot(grandroot.balance())
else
set this.root = root
endif
else
set this.root = node
call node.root_clear()
endif
call node.left_clear()
call node.right_clear()
return node
endmethod
method delete takes TreeNode node returns nothing
local TreeNode sibling = node.sibling
local TreeNode root = node.root
local TreeNode grandroot
if (root != 0) then
set grandroot = root.root
endif
if (sibling != 0) then
if (sibling.isData) then
set sibling.root = grandroot
if (grandroot != 0) then
if (grandroot.left == root) then
set grandroot.left = sibling
else
set grandroot.right = sibling
endif
call updateRoot(grandroot.balance())
else
set this.root = sibling
endif
call root.destroy()
else
set root.left = sibling.left
set root.right = sibling.right
call root.updateHeight()
call root.join()
if (sibling.left != 0) then
set sibling.left.root = root
endif
if (sibling.right != 0) then
set sibling.right.root = root
endif
call sibling.destroy()
if (grandroot != 0) then
call updateRoot(grandroot.balance())
endif
endif
else
set this.root = 0
endif
call node.destroy()
endmethod
private static method init takes nothing returns nothing
//! runtextmacro INITIALIZE_TABLE_FIELD("root")
endmethod
implement Init
endstruct
struct BooleanExpression extends array
method operator expression takes nothing returns boolexpr
debug call ThrowError(not List(this).isList, "BooleanExpression", "expression", "BooleanExpression", this, "Attempted To Read Null Boolean Expression.")
if (Tree(this).root != 0) then
return Tree(this).root.expression
endif
return null
endmethod
method operator reversed takes nothing returns boolean
debug call ThrowError(not List(this).isList, "BooleanExpression", "reversed", "BooleanExpression", this, "Attempted To Read Null Boolean Expression.")
return Tree(this).reversed
endmethod
method operator reversed= takes boolean b returns nothing
debug call ThrowError(not List(this).isList, "BooleanExpression", "reversed", "BooleanExpression", this, "Attempted To Set Null Boolean Expression.")
set Tree(this).reversed = b
endmethod
static method create takes boolean reversed returns thistype
return Tree.create(reversed)
endmethod
method destroy takes nothing returns nothing
debug call ThrowError(not List(this).isList, "BooleanExpression", "reversed", "BooleanExpression", this, "Attempted To Destroy Null Boolean Expression.")
call Tree(this).destroy()
endmethod
method register takes boolexpr expression returns BooleanExpression
return Tree(this).insert(expression)
endmethod
method unregister takes nothing returns nothing
debug call ThrowError(not TreeNode(this).isData, "BooleanExpression", "unregister", "BooleanExpression", this, "Attempted To Unregister Null Boolean Expression.")
call Tree(List(this).list).delete(this)
endmethod
method replace takes boolexpr expression returns nothing
debug call ThrowError(not TreeNode(this).isData, "BooleanExpression", "replace", "BooleanExpression", this, "Attempted To Replace Null Boolean Expression.")
call TreeNode(this).replace(expression)
endmethod
method clear takes nothing returns nothing
debug call ThrowError(not List(this).isList, "BooleanExpression", "clear", "BooleanExpression", this, "Attempted To Clear Null Boolean Expression.")
call Tree(this).clear()
endmethod
private static string indentation = " "
static method printEx takes TreeNode node, string indent, boolean height returns nothing
if (node != 0) then
call printEx(node.right, indent + indentation, height)
if (height) then
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60000, indent + I2S(node.height))
else
call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60000, indent + I2S(node))
endif
call printEx(node.left, indent + indentation, height)
endif
endmethod
method print takes boolean height returns nothing
call printEx(Tree(this).root, "", height)
call DisplayTimedTextFromPlayer(GetLocalPlayer(), 0, 0, 60000, "------------------------------------")
endmethod
debug static method calculateMemoryUsage takes nothing returns integer
debug return List.calculateMemoryUsage()
debug endmethod
debug static method getAllocatedMemoryAsString takes nothing returns string
debug return List.getAllocatedMemoryAsString()
debug endmethod
endstruct
endlibrary
//TESH.scrollpos=36
//TESH.alwaysfold=0
library TableField /* v1.0.0.1
************************************************************************************
*
* */ uses /*
*
* */ Table /*
* */ Init /*
*
************************************************************************************
*
* //! textmacro CREATE_TABLE_FIELD takes ACCESS_MODIFIER, TYPE, NAME, RETURN_TYPE
* - creates a table field surrounded by method operators
*
* //! textmacro INITIALIZE_TABLE_FIELD takes NAME
* - initializes table field
* - used in onInit
*
* //! textmacro CREATE_TABLE_FIELD_ARRAY takes TYPE, NAME, RETURN_TYPE
* - creates a struct that acts as an array
* - not used in a struct
*
* //! textmacro USE_TABLE_FIELD_ARRAY takes ACCESS_MODIFIER, NAME
* - creates a field of a struct array
* - used in a struct
*
************************************************************************************/
//! textmacro CREATE_TABLE_FIELD takes ACCESS_MODIFIER, TYPE, NAME, RETURN_TYPE
private static Table t$NAME$
$ACCESS_MODIFIER$ method operator $NAME$ takes nothing returns $RETURN_TYPE$
return t$NAME$.$TYPE$[this]
endmethod
$ACCESS_MODIFIER$ method operator $NAME$= takes $RETURN_TYPE$ value returns nothing
set t$NAME$.$TYPE$[this] = value
endmethod
$ACCESS_MODIFIER$ method $NAME$_clear takes nothing returns nothing
call t$NAME$.$TYPE$.remove(this)
endmethod
//! endtextmacro
//! textmacro CREATE_TABLE_FIELD_ARRAY takes TYPE, NAME, RETURN_TYPE
private struct T$NAME$ extends array
private static Table table
method operator [] takes integer index returns $RETURN_TYPE$
return table.$TYPE$[index]
endmethod
method operator []= takes integer index, $RETURN_TYPE$ value returns nothing
set table.$TYPE$[index] = value
endmethod
static method remove takes integer index returns nothing
call table.$TYPE$.remove(index)
endmethod
static method clear takes nothing returns nothing
call table.flush()
endmethod
private static method init takes nothing returns nothing
set table = Table.create()
endmethod
implement Init
endstruct
//! endtextmacro
//! textmacro USE_TABLE_FIELD_ARRAY takes ACCESS_MODIFIER, NAME
$ACCESS_MODIFIER$ static T$NAME$ $NAME$ = 0
//! endtextmacro
//! textmacro INITIALIZE_TABLE_FIELD takes NAME
set t$NAME$ = Table.create()
//! endtextmacro
endlibrary
library UniqueNxListT /* v1.0.0.1
************************************************************************************
*
* */ uses /*
*
* */ ErrorMessage /*
* */ TableField /*
*
************************************************************************************
*
* module UniqueNxListT
*
* Description
* -------------------------
*
* Node Properties:
*
* Unique
* Allocated
* Not 0
*
* Fields
* -------------------------
*
* readonly static integer sentinel
*
* readonly thistype list
*
* readonly thistype first
* readonly thistype last
*
* readonly thistype next
* readonly thistype prev
*
* Methods
* -------------------------
*
* method destroy takes nothing returns nothing
* - May only destroy lists
*
* method push takes thistype node returns nothing
* method enqueue takes thistype node returns nothing
*
* method pop takes nothing returns nothing
* method dequeue takes nothing returns nothing
*
* method remove takes nothing returns nothing
*
* method clear takes nothing returns nothing
* - Initializes list, use instead of create
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
************************************************************************************/
private keyword isNode
private keyword isCollection
private keyword p_list
private keyword p_next
private keyword p_prev
private keyword p_first
private keyword p_last
module UniqueNxListT
static if DEBUG_MODE then
//! runtextmacro CREATE_TABLE_FIELD("public", "boolean", "isNode", "boolean")
//! runtextmacro CREATE_TABLE_FIELD("public", "boolean", "isCollection", "boolean")
endif
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_list", "thistype")
method operator list takes nothing returns thistype
debug call ThrowError(this == 0, "UniqueNxListT", "list", "thistype", this, "Attempted To Read Null Node.")
debug call ThrowError(not isNode, "UniqueNxListT", "list", "thistype", this, "Attempted To Read Invalid Node.")
return p_list
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_next", "thistype")
method operator next takes nothing returns thistype
debug call ThrowError(this == 0, "UniqueNxListT", "next", "thistype", this, "Attempted To Go Out Of Bounds.")
debug call ThrowError(not isNode, "UniqueNxListT", "next", "thistype", this, "Attempted To Read Invalid Node.")
return p_next
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_prev", "thistype")
method operator prev takes nothing returns thistype
debug call ThrowError(this == 0, "UniqueNxListT", "prev", "thistype", this, "Attempted To Go Out Of Bounds.")
debug call ThrowError(not isNode, "UniqueNxListT", "prev", "thistype", this, "Attempted To Read Invalid Node.")
return p_prev
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_first", "thistype")
method operator first takes nothing returns thistype
debug call ThrowError(this == 0, "UniqueNxListT", "first", "thistype", this, "Attempted To Read Null List.")
debug call ThrowError(not isCollection, "UniqueNxListT", "first", "thistype", this, "Attempted To Read Invalid List.")
return p_first
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_last", "thistype")
method operator last takes nothing returns thistype
debug call ThrowError(this == 0, "UniqueNxListT", "last", "thistype", this, "Attempted To Read Null List.")
debug call ThrowError(not isCollection, "UniqueNxListT", "last", "thistype", this, "Attempted To Read Invalid List.")
return p_last
endmethod
static method operator sentinel takes nothing returns integer
return 0
endmethod
method push takes thistype node returns nothing
debug call ThrowError(this == 0, "UniqueNxListT", "push", "thistype", this, "Attempted To Push (" + I2S(node) + ") On To Null List.")
debug call ThrowError(not isCollection, "UniqueNxListT", "push", "thistype", this, "Attempted To Push (" + I2S(node) + ") On To Invalid List.")
debug call ThrowError(node == 0, "UniqueNxListT", "push", "thistype", this, "Attempted To Push Null Node.")
debug call ThrowError(node.isNode, "UniqueNxListT", "push", "thistype", this, "Attempted To Push Owned Node (" + I2S(node) + ").")
debug set node.isNode = true
set node.p_list = this
if (p_first == 0) then
set p_first = node
set p_last = node
set node.p_next = 0
else
set p_first.p_prev = node
set node.p_next = p_first
set p_first = node
endif
set node.p_prev = 0
endmethod
method enqueue takes thistype node returns nothing
debug call ThrowError(this == 0, "UniqueNxListT", "enqueue", "thistype", this, "Attempted To Enqueue (" + I2S(node) + ") On To Null List.")
debug call ThrowError(not isCollection, "UniqueNxListT", "enqueue", "thistype", this, "Attempted To Enqueue (" + I2S(node) + ") On To Invalid List.")
debug call ThrowError(node == 0, "UniqueNxListT", "enqueue", "thistype", this, "Attempted To Enqueue Null Node.")
debug call ThrowError(node.isNode, "UniqueNxListT", "enqueue", "thistype", this, "Attempted To Enqueue Owned Node (" + I2S(node) + ").")
debug set node.isNode = true
set node.p_list = this
if (p_first == 0) then
set p_first = node
set p_last = node
set node.p_prev = 0
else
set p_last.p_next = node
set node.p_prev = p_last
set p_last = node
endif
set node.p_next = 0
endmethod
method pop takes nothing returns nothing
debug call ThrowError(this == 0, "UniqueNxListT", "pop", "thistype", this, "Attempted To Pop Null List.")
debug call ThrowError(not isCollection, "UniqueNxListT", "pop", "thistype", this, "Attempted To Pop Invalid List.")
debug call ThrowError(p_first == 0, "UniqueNxListT", "pop", "thistype", this, "Attempted To Pop Empty List.")
debug set p_first.isNode = false
set p_first.p_list = 0
set p_first = p_first.p_next
if (p_first == 0) then
set p_last = 0
else
set p_first.p_prev = 0
endif
endmethod
method dequeue takes nothing returns nothing
debug call ThrowError(this == 0, "UniqueNxListT", "dequeue", "thistype", this, "Attempted To Dequeue Null List.")
debug call ThrowError(not isCollection, "UniqueNxListT", "dequeue", "thistype", this, "Attempted To Dequeue Invalid List.")
debug call ThrowError(p_last == 0, "UniqueNxListT", "dequeue", "thistype", this, "Attempted To Dequeue Empty List.")
debug set p_last.isNode = false
set p_last.p_list = 0
set p_last = p_last.p_prev
if (p_last == 0) then
set p_first = 0
else
set p_last.p_next = 0
endif
endmethod
method remove takes nothing returns nothing
local thistype node = this
set this = node.p_list
debug call ThrowError(node == 0, "UniqueNxListT", "remove", "thistype", this, "Attempted To Remove Null Node.")
debug call ThrowError(not node.isNode, "UniqueNxListT", "remove", "thistype", this, "Attempted To Remove Invalid Node (" + I2S(node) + ").")
debug set node.isNode = false
set node.p_list = 0
if (0 == node.p_prev) then
set p_first = node.p_next
else
set node.p_prev.p_next = node.p_next
endif
if (0 == node.p_next) then
set p_last = node.p_prev
else
set node.p_next.p_prev = node.p_prev
endif
endmethod
method clear takes nothing returns nothing
debug local thistype node = p_first
debug call ThrowError(this == 0, "UniqueNxListT", "clear", "thistype", this, "Attempted To Clear Null List.")
debug if (not isCollection) then
debug set isCollection = true
debug set p_first = 0
debug set p_last = 0
debug return
debug endif
static if DEBUG_MODE then
loop
exitwhen node == 0
set node.isNode = false
set node = node.p_next
endloop
endif
if (p_first == 0) then
return
endif
set p_first = 0
set p_last = 0
endmethod
method destroy takes nothing returns nothing
debug call ThrowError(this == 0, "UniqueNxListT", "destroy", "thistype", this, "Attempted To Destroy Null List.")
debug call ThrowError(not isCollection, "UniqueNxListT", "destroy", "thistype", this, "Attempted To Destroy Invalid List.")
call clear()
debug set isCollection = false
endmethod
private static method onInit takes nothing returns nothing
static if DEBUG_MODE then
//! runtextmacro INITIALIZE_TABLE_FIELD("isNode")
//! runtextmacro INITIALIZE_TABLE_FIELD("isCollection")
endif
//! runtextmacro INITIALIZE_TABLE_FIELD("p_list")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_next")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_prev")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_first")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_last")
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
set memory = memory + checkRegion2(start, end)
set start = end + 1
else
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
library NxListT /* v1.0.0.1
************************************************************************************
*
* */ uses /*
*
* */ ErrorMessage /*
* */ TableField /*
*
************************************************************************************
*
* module NxListT
*
* Description
* -------------------------
*
* NA
*
* Fields
* -------------------------
*
* readonly static integer sentinel
*
* readonly thistype list
*
* readonly thistype first
* readonly thistype last
*
* readonly thistype next
* readonly thistype prev
*
* Methods
* -------------------------
*
* 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
* - Initializes list, use instead of create
*
* debug static method calculateMemoryUsage takes nothing returns integer
* debug static method getAllocatedMemoryAsString takes nothing returns string
*
************************************************************************************/
private keyword isNode
private keyword isCollection
private keyword p_list
private keyword p_next
private keyword p_prev
private keyword p_first
private keyword p_last
module NxListT
private static thistype nodeCount = 0
static if DEBUG_MODE then
//! runtextmacro CREATE_TABLE_FIELD("public", "boolean", "isNode", "boolean")
//! runtextmacro CREATE_TABLE_FIELD("public", "boolean", "isCollection", "boolean")
endif
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_list", "thistype")
method operator list takes nothing returns thistype
debug call ThrowError(this == 0, "NxList", "list", "thistype", this, "Attempted To Read Null Node.")
debug call ThrowError(not isNode, "NxList", "list", "thistype", this, "Attempted To Read Invalid Node.")
return p_list
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_next", "thistype")
method operator next takes nothing returns thistype
debug call ThrowError(this == 0, "NxList", "next", "thistype", this, "Attempted To Go Out Of Bounds.")
debug call ThrowError(not isNode, "NxList", "next", "thistype", this, "Attempted To Read Invalid Node.")
return p_next
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_prev", "thistype")
method operator prev takes nothing returns thistype
debug call ThrowError(this == 0, "NxList", "prev", "thistype", this, "Attempted To Go Out Of Bounds.")
debug call ThrowError(not isNode, "NxList", "prev", "thistype", this, "Attempted To Read Invalid Node.")
return p_prev
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_first", "thistype")
method operator first takes nothing returns thistype
debug call ThrowError(this == 0, "NxList", "first", "thistype", this, "Attempted To Read Null List.")
debug call ThrowError(not isCollection, "NxList", "first", "thistype", this, "Attempted To Read Invalid List.")
return p_first
endmethod
//! runtextmacro CREATE_TABLE_FIELD("public", "integer", "p_last", "thistype")
method operator last takes nothing returns thistype
debug call ThrowError(this == 0, "NxList", "last", "thistype", this, "Attempted To Read Null List.")
debug call ThrowError(not isCollection, "NxList", "last", "thistype", this, "Attempted To Read Invalid List.")
return p_last
endmethod
static method operator sentinel takes nothing returns integer
return 0
endmethod
private static method allocateNode takes nothing returns thistype
local thistype this = thistype(0).p_next
if (0 == this) then
set this = nodeCount + 1
set nodeCount = this
else
set thistype(0).p_next = p_next
endif
return this
endmethod
method push takes nothing returns thistype
local thistype node = allocateNode()
debug call ThrowError(this == 0, "NxList", "push", "thistype", this, "Attempted To Push On To Null List.")
debug call ThrowError(not isCollection, "NxList", "push", "thistype", this, "Attempted To Push On To Invalid List.")
debug set node.isNode = true
set node.p_list = this
if (p_first == 0) then
set p_first = node
set p_last = node
set node.p_next = 0
else
set p_first.p_prev = node
set node.p_next = p_first
set p_first = node
endif
set node.p_prev = 0
return node
endmethod
method enqueue takes nothing returns thistype
local thistype node = allocateNode()
debug call ThrowError(this == 0, "NxList", "enqueue", "thistype", this, "Attempted To Enqueue On To Null List.")
debug call ThrowError(not isCollection, "NxList", "enqueue", "thistype", this, "Attempted To Enqueue On To Invalid List.")
debug set node.isNode = true
set node.p_list = this
if (p_first == 0) then
set p_first = node
set p_last = node
set node.p_prev = 0
else
set p_last.p_next = node
set node.p_prev = p_last
set p_last = node
endif
set node.p_next = 0
return node
endmethod
method pop takes nothing returns nothing
local thistype node = p_first
debug call ThrowError(this == 0, "NxList", "pop", "thistype", this, "Attempted To Pop Null List.")
debug call ThrowError(not isCollection, "NxList", "pop", "thistype", this, "Attempted To Pop Invalid List.")
debug call ThrowError(node == 0, "NxList", "pop", "thistype", this, "Attempted To Pop Empty List.")
debug set node.isNode = false
set p_first.p_list = 0
set p_first = p_first.p_next
if (p_first == 0) then
set p_last = 0
else
set p_first.p_prev = 0
endif
set node.p_next = thistype(0).p_next
set thistype(0).p_next = node
endmethod
method dequeue takes nothing returns nothing
local thistype node = p_last
debug call ThrowError(this == 0, "NxList", "dequeue", "thistype", this, "Attempted To Dequeue Null List.")
debug call ThrowError(not isCollection, "NxList", "dequeue", "thistype", this, "Attempted To Dequeue Invalid List.")
debug call ThrowError(node == 0, "NxList", "dequeue", "thistype", this, "Attempted To Dequeue Empty List.")
debug set node.isNode = false
set p_last.p_list = 0
set p_last = p_last.p_prev
if (p_last == 0) then
set p_first = 0
else
set p_last.p_next = 0
endif
set node.p_next = thistype(0).p_next
set thistype(0).p_next = node
endmethod
method remove takes nothing returns nothing
local thistype node = this
set this = node.p_list
debug call ThrowError(node == 0, "NxList", "remove", "thistype", this, "Attempted To Remove Null Node.")
debug call ThrowError(not node.isNode, "NxList", "remove", "thistype", this, "Attempted To Remove Invalid Node (" + I2S(node) + ").")
debug set node.isNode = false
set node.p_list = 0
if (0 == node.p_prev) then
set p_first = node.p_next
else
set node.p_prev.p_next = node.p_next
endif
if (0 == node.p_next) then
set p_last = node.p_prev
else
set node.p_next.p_prev = node.p_prev
endif
set node.p_next = thistype(0).p_next
set thistype(0).p_next = node
endmethod
method clear takes nothing returns nothing
debug local thistype node = p_first
debug call ThrowError(this == 0, "NxList", "clear", "thistype", this, "Attempted To Clear Null List.")
debug if (not isCollection) then
debug set isCollection = true
debug set p_first = 0
debug set p_last = 0
debug return
debug endif
static if DEBUG_MODE then
loop
exitwhen node == 0
set node.isNode = false
set node = node.p_next
endloop
endif
if (p_first == 0) then
return
endif
set p_last.p_next = thistype(0).p_next
set thistype(0).p_next = p_first
set p_first = 0
set p_last = 0
endmethod
method destroy takes nothing returns nothing
debug call ThrowError(this == 0, "NxList", "destroy", "thistype", this, "Attempted To Destroy Null List.")
debug call ThrowError(not isCollection, "NxList", "destroy", "thistype", this, "Attempted To Destroy Invalid List.")
call clear()
debug set isCollection = false
endmethod
private static method onInit takes nothing returns nothing
static if DEBUG_MODE then
//! runtextmacro INITIALIZE_TABLE_FIELD("isNode")
//! runtextmacro INITIALIZE_TABLE_FIELD("isCollection")
endif
//! runtextmacro INITIALIZE_TABLE_FIELD("p_list")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_next")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_prev")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_first")
//! runtextmacro INITIALIZE_TABLE_FIELD("p_last")
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
set memory = memory + checkRegion2(start, end)
set start = end + 1
else
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=0
//TESH.alwaysfold=0
library Colors
globals
string array Color
endglobals
private struct color extends array
private static method init takes nothing returns nothing
set Color[0] = "|CFFFF0303"
set Color[1] = "|CFF0042FF"
set Color[2] = "|c001CE6B9" /*********** Colors **********/
set Color[3] = "|CFF540081" /** **/
set Color[4] = "|CFFFFFF01" /** Color 0-11 = player **/
set Color[5] = "|CFFFE8A0E" /** **/
set Color[6] = "|CFF20C000" /** [12] = gold **/
set Color[7] = "|CFFE55BB0" /** **/
set Color[8] = "|c00959697" /** [13] = white **/
set Color[9] = "|CFF7EBFF1" /** **/
set Color[10] = "|CFF106246" /********************************/
set Color[11] = "|CFF4E2A04"
set Color[12] = "|c00ffcc00"
set Color[13] = "|cffffffcc"
endmethod
implement Init
endstruct
endlibrary
//TESH.scrollpos=33
//TESH.alwaysfold=0
library Cam initializer CamInit uses Print
globals
constant real ZOOM_START = 2950.
constant real ZOOM_MIN = 500.
constant real ZOOM_MAX = 4500.
constant real ZOOM_TIMEOUT = 0.1
constant real ZOOM_TIME = 0.1
constant integer MAX_PLAYERS = 11
real array zoom
endglobals
function SetDistance takes nothing returns nothing
local integer i = 0
local player p
loop
set p = Player(i)
if GetLocalPlayer() == p then
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, zoom[i], ZOOM_TIME)
endif
set i = i + 1
exitwhen i > MAX_PLAYERS
endloop
endfunction
function Zoom takes nothing returns boolean
local string chat = GetEventPlayerChatString()
local player p = GetTriggerPlayer()
local real r = S2R(SubString(chat, 6, StringLength(chat)))
local string s = null
if r == 0 and chat != "-zoom 0" and chat != "zoom0" then
call PrintTo(p, "|c00ffcc00Current Zoom: |r" + R2S(zoom[GetPlayerId(p)]), 8)
else
if r < ZOOM_MIN or r == 0 then
set r = ZOOM_MIN
set s = "|c00ffcc00Min-"
elseif r > ZOOM_MAX then
set r = ZOOM_MAX
set s = "|c00ffcc00Max-"
endif
set zoom[GetPlayerId(p)] = r
if GetLocalPlayer() == p then
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, r, ZOOM_TIME)
endif
set s = s + "|c00ffcc00Zoom: |r" + R2S(r)
call PrintTo(p, s, 8)
endif
return false
endfunction
function CamInit takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
local timer tim = CreateTimer()
call TriggerAddCondition( t, Filter(function Zoom ))
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, ZOOM_START, 0.00)
call TimerStart(tim, ZOOM_TIMEOUT, true, function SetDistance)
loop
set zoom[i] = ZOOM_START
call TriggerRegisterPlayerChatEvent( t, Player(i), "-zoom", false )
set i = i + 1
exitwhen i > MAX_PLAYERS
endloop
set tim = null
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Clear initializer ClearInit
function ClearScreen takes nothing returns nothing
if GetLocalPlayer() == GetTriggerPlayer() then
call ClearTextMessages()
endif
endfunction
function ClearInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerChatEvent(t, Player(i), "-clear", true )
call TriggerRegisterPlayerChatEvent(t, Player(i), "-c", true )
set i = i + 1
exitwhen i > 11
endloop
call TriggerAddAction( t, function ClearScreen )
endfunction
endscope
//TESH.scrollpos=54
//TESH.alwaysfold=0
library TileDefinition
/* TileDefinition v1.1a
-----------------------
Link:
[url]http://www.hiveworkshop.com/forums/submissions-414/snippet-tiledefinition-259347/[/url]
**
**
** Information
** _____________
**
** TileDefinition gives geographical information about the location of a terrain tile.
**
**
** API
** _______
**
**
** Functions:
** -----------
**
** 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 GetTileRect takes real x, real y returns rect
** Returns a rect, that covers the terrain tile of given coorinates.
**
** function GetTileCenterLoc takes real x, real y returns location
** Returns the centre of the terrain tile of given coorinates.
**
** 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.
**
**
***********************************************************************************************************/
/*
* GetTileDistance evaluates how many tiles the given
* cooridnate is away from reference tile. (located at 0/0)
*/
private function GetTileDistance takes real a returns integer
if (a >= 0) then
return R2I((a + 64)/128)
else
return R2I((a - 64)/128)
endif
endfunction
function GetTileMax takes real a returns real
local integer aCount = GetTileDistance(a)
if (aCount == 0) then
return 64.
elseif (aCount > 0) then
return (aCount + 1.)*128. - 64.
else
return (aCount)* 128. + 64.
endif
endfunction
function GetTileMin takes real a returns real
local integer aCount = GetTileDistance(a)
if (aCount == 0) then
return -64.
elseif (aCount > 0) then
return (aCount)*128. - 64.
else
return (aCount - 1.)* 128. + 64.
endif
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 ((GetTileDistance(x1) == (GetTileDistance(x2)) and (GetTileDistance(y1) == (GetTileDistance(y2)))))
endfunction
function GetTileRect takes real x, real y returns rect
return Rect(GetTileMin(x), GetTileMin(y), GetTileMax(x), GetTileMax(y))
endfunction
function GetTileCenterCooridnate takes real a returns real
if (a >= 0) then
return GetTileMin(a) + 64.
else
return GetTileMin(a) - 64.
endif
endfunction
function GetTileCenterLoc takes real x, real y returns location
return Location(GetTileCenterCooridnate(x), GetTileCenterCooridnate(y))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library SuspendUnit /* v1.1 By IcemanBo (credits to Maker for this method)
Alternative for the PauseUnit() function without known side effects.
A paused unit will be completly unuseable until unpaused.
Unit's current order will be forgetten.
API
¯¯¯¯¯¯
function SuspendUnit(unit, boolean) returns nothing
function IsUnitSuspended(unit) returns boolean
Instructions:
¯¯¯¯¯¯¯¯¯¯¯¯¯¯
After copying the library save the map and restart the editor.
When done, then comment out the next line:*/
///! external ObjectMerger w3a ANcl paus Ncl6 1 "defend" anam "Channel Pause" acat "" atat "" aher 0 alev 1 Ncl1 1 10000 aani "stand" aeat "" |
globals
private constant integer PAUSE = 'paus'
private constant integer DEFEND = 852055
endglobals
function SuspendUnit takes unit u, boolean b returns nothing
if (b) then
call UnitAddAbility(u, PAUSE)
call IssueImmediateOrderById(u, DEFEND)
else
call UnitRemoveAbility(u, PAUSE)
endif
endfunction
function IsUnitSuspended takes unit u returns boolean
return (GetUnitAbilityLevel(u, PAUSE) > 0)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library Print
function Print takes string text, real duration returns nothing
local integer i = 0
loop
call DisplayTimedTextToPlayer(Player(i), 0, 0, duration, text)
set i = i + 1
exitwhen i > 11
endloop
endfunction
function PrintTo takes player p, string text, real duration returns nothing
call DisplayTimedTextToPlayer(p, 0, 0, duration, text)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library QuickSort
/*
Allows to sort an array of integer/real.
Binds an extra integer (index)
to the filled value to allow keeping track of it.
Complexity:
Best: O(n*log (n))
Average: O(n log n) .
Worst: O(n^2)
// For bigger unsorted arrays it gets unlikely to get the worst case.
// In tests it could sort arrays with size of ~650 until OP limit was hit.
Usage
¯¯¯¯¯¯¯
*/
//! novjass
// Fill these arrays:
real array QuickSortValue[]
integer array QuickSortIndex[] // Requierement, not optional.
// Ascending:
boolean QuickSortAscending
// just set it to true or false
// Start:
function QuickSort takes integer left, integer right returns nothing
// left is index where it starts
// right is index where it ends
//==============================================================//
//! endnovjass
globals
real array QuickSortValue
integer array QuickSortIndex
boolean QuickSortAscending = false
endglobals
/*
Get median of three values.
if (i < j)then
if(j<k) then
return j
elseif (k<pivot) then
return = k
else
return i
endif
elseif (k<j) then
return j
elseif (k<i) then
return k
else
return i
endif
*/
private function Partition takes integer left, integer right returns integer
local real pivot = QuickSortValue[left]
local integer l = left
local integer r = right
local real tempR
local integer tempI
loop
exitwhen l > r
if (QuickSortAscending and QuickSortValue[l] > pivot) or (not QuickSortAscending and QuickSortValue[l] < pivot) then
set tempR = QuickSortValue[l]
set QuickSortValue[l] = QuickSortValue[r]
set QuickSortValue[r] = tempR
set tempI = QuickSortIndex[l]
set QuickSortIndex[l] = QuickSortIndex[r]
set QuickSortIndex[r] = tempI
set r = r - 1
else
set l = l + 1
endif
endloop
set tempR = QuickSortValue[left]
set QuickSortValue[left] = QuickSortValue[r]
set QuickSortValue[r] = tempR
set tempI = QuickSortIndex[left]
set QuickSortIndex[left] = QuickSortIndex[r]
set QuickSortIndex[r] = tempI
return r
endfunction
function QuickSort takes integer left, integer right returns nothing
local integer i
if (left < right) then
set i = Partition(left, right)
call QuickSort(left, i - 1)
call QuickSort(i + 1, right)
endif
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
struct Gametime extends array
readonly static integer seconds
readonly static integer minutes
private static method callback takes nothing returns nothing
set seconds = seconds + 1
if ModuloInteger(seconds, 60) == 0 then
set minutes = minutes + 1
endif
set Board.Board[PlayerTools.user_Amount + 5][0].text = "|cffffffccGametime:|r " + Gametime.toString()
endmethod
static method toString takes nothing returns string
local string s = ""
set s = I2S(minutes) + ": "
if ModuloInteger(seconds, 60) < 10 then
set s = s + "0" + I2S(ModuloInteger(seconds, 60))
else
set s = s+ I2S(ModuloInteger(seconds, 60))
endif
return s
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(NewTimer(), 1, true, function thistype.callback)
set seconds = 0
set minutes = 0
endmethod
endstruct
//TESH.scrollpos=0
//TESH.alwaysfold=0
library LineIntersect
// if points are oredered counterclockwise
function ccw takes real x1, real y1, real x2, real y2, real x3, real y3 returns boolean
return (y3 - y1)*(x2 - x1) > (y2 - y1)*(x3 - x1)
endfunction
// if ACD xor BCD is ccw we have intersection
function DoLinesIntersect takes real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4 returns boolean
return ccw(x1, y1, x3, y3, x4, y4) != ccw(x2, y2, x3, y3, x4, y4) and ccw(x1, y1, x2, y2, x3, y3) != ccw(x1, y1, x2, y2, x4, y4)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library ParabolicMovement
function ParabolaZ takes real h, real d, real x returns real
return (4 * h / d) * (d - x) * (x / d)
endfunction
endlibrary