//TESH.scrollpos=0
//TESH.alwaysfold=0
Name | Type | is_array | initial_value |
//TESH.scrollpos=6
//TESH.alwaysfold=0
library CaptureBuildingSystem requires T32, PlayerColorUtils
// Captureable Building System by The_Witcher
//
// What is the Captureable Building System?
// The Captureable Building System is based on the system which is used in the
// popular online game League of Legends (Dominion Mode):
// -When you right click a capturable building, your hero will charge and
// release a beam which captures the building over time.
// -If the building was already captured by someone else, you will neutralize
// it before taking it for yourself.
// -If you are interrupted by an attack, or because you gave an order, while capturing,
// your unit will stop.
// -If your building was under attack but couldn't be neutralized, it will regenerate.
//
//
// Requirements:
// -T32 by Jesus4Lyf
// -PlayerColor Utils by The_Witcher
// -simpleBar by The_Witcher
// -Jass NewGen Pack and the newest Jasshelper
// -Minor Jass knowledge
//
//
// Methods & Functions:
// capturableBuilding.create( unit, points )
// CreateCapturableBuilding( unit, points ) <- simple Jass wrapper
// makes the given unit capturable, while the "points" value represents the "points to capture"
//
// set capturableBuilding.onCapture = yourFunc
// will fire the given function when the building is fully captured
// the given function MUST look like this:
// yourfunc takes capturableBuilding captured returns nothing
//
//
// Members:
// real points
// real maxPoints
// player owner
//
// you can edit those meber's values using
// set capturableBuilding.<yourMember> = <yourValue>
//
//
// How to import:
// - Copy the T32, the Simple Bars and the PlayerColorUtils triggers into your map.
// - Copy this trigger into your map.
// - Copy the Capture Building Dummy ability into your map.
// - Adjust the values of the ability and the globals below.
//
//============================ Setup ========================================
globals
//If true, only heroes can capture buildings
constant boolean HEROES_ONLY = true
//If true, a bar will indicate the captureing progress
constant boolean SHOW_BARS = true
//If >0, every capturable building will be in a visible circle for all player, with the given radius
constant real VISIBILITY_RADIUS = 800
//The points a building regenerates if it could'nt be fully captured
constant real REGENERATION_PER_SECOND = 1
//The points every hero capture per second
constant real POINTS_PER_SECOND = 5
//The time in seconds a hero charges before capturing
constant real CAPTURE_DELAY = 2
//If true, every building will be paused while being captured (= no attack)
constant boolean PAUSE_WHILE_CAPTUREING = true
//The rawcode of the dummy ability (press Ctrl + D in the object editor)
constant integer CAPTURE_ABILITY = 'A000'
//The order id of the dummy ability
constant string CAPTURE_ABILITY_ORDER = "channel"
//The lightning effect, symbolising the capture process
constant string LIGHTNING_EFFECT = "FORK"
//The effect indicating that the charging time is over
constant string BEGIN_CAPTURE_EFFECT = "Abilities\\Spells\\NightElf\\BattleRoar\\RoarCaster.mdl"
//The effect indicating that a building is captured
constant string FINISH_CAPTURE_EFFECT = "Abilities\\Spells\\Other\\Charm\\CharmTarget.mdl"
//The length of the building points bar
constant integer BAR_LENGTH = 50
//The size of the building points bar
constant real BAR_SIZE = 8
//The owning player of neutral buildings (only change if needed!)
constant player BUILDING_OWNER = Player(PLAYER_NEUTRAL_PASSIVE)
endglobals
//==============================================================================
//========================= System Code ========================================
//==============================================================================
function CreateCapturableBuilding takes unit u, real pts returns capturableBuilding
return capturableBuilding.create(u, pts)
endfunction
public function interface onCaptureFunc takes capturableBuilding captured returns nothing
private struct captureUnitData
unit u
real time
lightning light
capturableBuilding toCapture
endstruct
struct capturableBuilding
private static hashtable h
private static location loc
private static group dmgGroup
private static capturableBuilding temp
private static trigger onDamageTrig
private player owningPlayer
private player taker
readonly unit u
private group g
private texttag info
private real pts
private real maxPts
private simpleBar bar
onCaptureFunc onCapture = 0
private static method endCaptureForUnit takes unit u returns nothing
local captureUnitData dat = LoadInteger(.h, GetHandleId(u), 1)
call GroupRemoveUnit(dat.toCapture.g,u)
call UnitRemoveAbility(u, CAPTURE_ABILITY)
call SaveInteger(.h, GetHandleId(u), 1, 0)
if dat.light != null then
call DestroyLightning(dat.light)
endif
call dat.destroy()
set u = null
endmethod
private static method periodEnum takes nothing returns nothing
local unit u = GetEnumUnit()
local captureUnitData dat = LoadInteger(.h, GetHandleId(u), 1)
if (GetUnitCurrentOrder(u) != OrderId(CAPTURE_ABILITY_ORDER)) or ((IsUnitAlly(u, temp.owningPlayer) and temp.owningPlayer != BUILDING_OWNER)) then
call .endCaptureForUnit(u)
else
if dat.time > 0 then
set dat.time = dat.time - T32_PERIOD
call SetLightningColor(dat.light, GetLightningColorR(dat.light), GetLightningColorG(dat.light), GetLightningColorB(dat.light), (1 - dat.time / CAPTURE_DELAY) * 0.6)
if dat.time <= 0 then
call DestroyEffect(AddSpecialEffect(BEGIN_CAPTURE_EFFECT, GetUnitX(u), GetUnitY(u)))
call SetLightningColor(dat.light, GetLightningColorR(dat.light), GetLightningColorG(dat.light), GetLightningColorB(dat.light), 1)
endif
elseif temp.owningPlayer == BUILDING_OWNER and temp.taker == temp.owningPlayer then
set temp.taker = GetOwningPlayer(u)
set temp.bar.colorFull = GetPlayerColorString(temp.taker)
else
if IsUnitAlly(u, temp.taker) then
set temp.pts = temp.pts + POINTS_PER_SECOND / T32_FPS
else
set temp.pts = temp.pts - POINTS_PER_SECOND / T32_FPS
endif
endif
if temp.pts < 0 then
set temp.pts = 0
set temp.owningPlayer = BUILDING_OWNER
set temp.taker = GetOwningPlayer(u)
set temp.bar.colorFull = GetPlayerColorString(temp.taker)
call SetUnitColor(temp.u, GetPlayerColor(BUILDING_OWNER))
endif
endif
set u = null
endmethod
private static method endCapture takes nothing returns nothing
call .endCaptureForUnit(GetEnumUnit())
endmethod
private method periodic takes nothing returns nothing
set .temp = this
if FirstOfGroup(.g) != null then
call ForGroup(.g, function capturableBuilding.periodEnum)
elseif .pts < .maxPts and .owningPlayer != BUILDING_OWNER then
set .pts = .pts + REGENERATION_PER_SECOND / T32_FPS
if .pts > .maxPts then
set .pts = .maxPts
endif
endif
set .bar.progress = .pts/.maxPts
if .pts > .maxPts then
if .onCapture != 0 then
call onCapture.execute(this)
endif
call DestroyEffect(AddSpecialEffect(FINISH_CAPTURE_EFFECT,GetUnitX(.u),GetUnitY(.u)))
call .stopPeriodic()
set .pts = .maxPts
call ForGroup(.g, function capturableBuilding.endCapture)
call GroupClear(.g)
set .owningPlayer = .taker
call SetUnitColor(.u, GetPlayerColor(.taker))
endif
if (IsUnitType(.u, UNIT_TYPE_DEAD) or GetUnitTypeId(.u) == 0 ) then
call .stopPeriodic()
call .destroy()
endif
if FirstOfGroup(.g) == null and PAUSE_WHILE_CAPTUREING and IsUnitPaused(.u) then
call PauseUnit(.u,false)
endif
endmethod
implement T32xs
static method create takes unit u, real pts returns capturableBuilding
local capturableBuilding this = capturableBuilding.allocate()
local integer i = 0
set .u = u
if VISIBILITY_RADIUS > 0 then
loop
call FogModifierStart(CreateFogModifierRadius(Player(i), FOG_OF_WAR_VISIBLE, GetUnitX(u), GetUnitY(u), VISIBILITY_RADIUS, true, false))
set i = i + 1
exitwhen i == 12
endloop
endif
call SetUnitOwner(u, BUILDING_OWNER, true)
set .owningPlayer = BUILDING_OWNER
set .taker = owningPlayer
set .g = CreateGroup()
set .bar = 0
if SHOW_BARS then
set .bar = simpleBar.create(GetUnitX(u) - BAR_LENGTH * BAR_SIZE* 0.23, GetUnitY(u), 0, 0, BAR_SIZE, BAR_LENGTH, "","|cff949596")
endif
set .pts = 0
set .maxPts = pts
call SaveInteger(.h, GetHandleId(u), 0, this)
return this
endmethod
private static method initTaking takes nothing returns boolean
local unit u = GetOrderTargetUnit()
local unit o = GetOrderedUnit()
local capturableBuilding this = LoadInteger(.h, GetHandleId(u), 0)
local captureUnitData dat
if u != null and this != 0 and GetIssuedOrderId() != OrderId(CAPTURE_ABILITY_ORDER) then
if IsUnitType(o, UNIT_TYPE_HERO) or not HEROES_ONLY then
set dat = captureUnitData.create()
set dat.toCapture = this
set dat.u = o
set dat.time = CAPTURE_DELAY+ 0.01
set dat.light = null
call SaveInteger(.h, GetHandleId(o), 1, dat)
call UnitAddAbility(o, CAPTURE_ABILITY)
call IssueTargetOrder(o, CAPTURE_ABILITY_ORDER, .u)
endif
endif
set u = null
set o = null
return false
endmethod
private static method startTaking takes nothing returns boolean
local unit t = GetSpellTargetUnit()
local capturableBuilding this = LoadInteger(.h, GetHandleId(t), 0)
local unit u = GetTriggerUnit()
local captureUnitData dat = LoadInteger(.h, GetHandleId(u), 1)
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
local real uz
local real tx = GetUnitX(t)
local real ty = GetUnitY(t)
local real tz
local player p = GetOwningPlayer(u)
if GetSpellAbilityId() == CAPTURE_ABILITY then
call .startPeriodic()
if PAUSE_WHILE_CAPTUREING and not IsUnitPaused(t) then
call PauseUnit(t,true)
endif
call GroupAddUnit(.g, u)
call MoveLocation(.loc, ux, uy)
set uz = GetLocationZ(.loc)
call MoveLocation(.loc, tx, ty)
set tz = GetLocationZ(.loc)
set dat.light = AddLightningEx(LIGHTNING_EFFECT, false, ux, uy, uz + 50, tx, ty, tz + 150)
call SetLightningColor(dat.light, GetPlayerColorRedPercent(p), GetPlayerColorGreenPercent(p), GetPlayerColorBluePercent(p), 0)
if not IsUnitInGroup(u,.dmgGroup) then
call TriggerRegisterUnitEvent(onDamageTrig, u, EVENT_UNIT_DAMAGED)
call GroupAddUnit(.dmgGroup,u)
endif
endif
set u = null
return false
endmethod
private static method abortTaking takes nothing returns boolean
local unit u = GetTriggerUnit()
local captureUnitData dat = LoadInteger(.h, GetHandleId(u), 1)
local capturableBuilding this = dat.toCapture
if dat != 0 then
call .endCaptureForUnit(u)
endif
return false
endmethod
method operator owner= takes player p returns nothing
set .owningPlayer = p
set .taker = p
call SetUnitColor(.u, GetPlayerColor(p))
endmethod
method operator owner takes nothing returns player
return .owningPlayer
endmethod
method operator points= takes real r returns nothing
set .pts = r
if .pts > .maxPts then
set .pts = .maxPts
endif
set .bar.progress = .pts/.maxPts
call .bar.refresh()
endmethod
method operator points takes nothing returns real
return .pts
endmethod
method operator maxPoints= takes real r returns nothing
set .maxPts = r
if .pts > .maxPts then
set .pts = .maxPts
endif
set .bar.progress = .pts/.maxPts
call .bar.refresh()
endmethod
method operator maxPoints takes nothing returns real
return .maxPts
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger t2 = CreateTrigger()
local integer i = 0
loop
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, null)
call TriggerRegisterPlayerUnitEvent(t2, Player(i), EVENT_PLAYER_UNIT_SPELL_CHANNEL, null)
set i = i + 1
exitwhen i == 12
endloop
call TriggerAddCondition(t, Condition(function capturableBuilding.initTaking))
call TriggerAddCondition(t2, Condition(function capturableBuilding.startTaking))
set onDamageTrig = CreateTrigger()
call TriggerAddCondition(onDamageTrig, Condition(function capturableBuilding.abortTaking))
set .loc = Location(0, 0)
set .dmgGroup = CreateGroup()
set .h = InitHashtable()
endmethod
endstruct
endlibrary
//TESH.scrollpos=124
//TESH.alwaysfold=0
library SimpleBars
// SimpleBars library by The_Witcher
//
// Nothing special, just a small library to create a texttag bar
// which indicates a certain percentage using colored |
//
//
// Methods:
// method createDefault takes real x, real y, real z, real p returns simpleBar
// { position values } percentage
// this will create a bar using the default values for color, length and size
//
// method create takes real x, real y, real z, real p, real s, integer l, string colorFull, string colorEmpty returns simpleBar
// { position values } percentage size length bar color empty color
// this will create a bar with all the values passed in the parameters
//
// method refresh takes nothing returns nothing
// this method has to be called whenever you want to refresh the bar
//
// IMPORTANT: whenever you assign a new value to the members, the bar will auto-refresh!
//
//
// Members:
// real size
// integer length
// string colorFull
// string colorEmpty
// real x
// real y
// real z
// real progress
//
//all these default values are used by the createSimple function
globals
public constant integer DEFAULT_LENGTH = 40
public constant real DEFAULT_SIZE = 8
public constant string DEFAULT_FULL_COLOR = "|cff000000"
public constant string DEFAULT_EMPTY_COLOR = "|cffFFFFFF"
endglobals
//==============================================================================
//========================= System Code ========================================
//==============================================================================
struct simpleBar
readonly texttag t
private real p
private integer l
private real s
private real X
private real Y
private real Z
private string fullColor
private string emptyColor
//! textmacro newReadMember takes NAME, VAR, TYPE
method operator $NAME$ takes nothing returns $TYPE$
return .$VAR$
endmethod
//! endtextmacro
//! textmacro newMember takes NAME, VAR, TYPE
method operator $NAME$ takes nothing returns $TYPE$
return .$VAR$
endmethod
method operator $NAME$= takes $TYPE$ v returns nothing
set .$VAR$ = v
call .refresh()
endmethod
//! endtextmacro
//! runtextmacro newMember("size","s","real")
//! runtextmacro newMember("length","l","integer")
//! runtextmacro newMember("colorFull","fullColor","string")
//! runtextmacro newMember("colorEmpty","emptyColor","string")
//! runtextmacro newReadMember("x","X","real")
//! runtextmacro newReadMember("y","Y","real")
//! runtextmacro newReadMember("z","Z","real")
method operator x= takes real v returns nothing
set .X = v
call SetTextTagPos(.t,.X,.Y,.Z)
endmethod
method operator y= takes real v returns nothing
set .Y = v
call SetTextTagPos(.t,.X,.Y,.Z)
endmethod
method operator z= takes real v returns nothing
set .Z = v
call SetTextTagPos(.t,.X,.Y,.Z)
endmethod
method operator progress takes nothing returns real
return .p
endmethod
method operator progress= takes real p returns nothing
if p < 0 then
set p = 0
elseif p > 1 then
set p = 1
endif
set .p = p
call .refresh()
endmethod
static method create takes real x, real y, real z, real p, real s, integer l, string colorFull, string colorEmpty returns simpleBar
local simpleBar this = simpleBar.allocate()
set .t = CreateTextTag()
set .s = s
set .l = l
set .x = x
set .y = y
set .z = z
set .fullColor = colorFull
set .emptyColor = colorEmpty
call SetTextTagPos(.t, x, y, z)
call .refresh()
return this
endmethod
static method createDefault takes real x, real y, real z, real p returns simpleBar
local simpleBar this = simpleBar.allocate()
set .t = CreateTextTag()
set .s = DEFAULT_SIZE
set .l = DEFAULT_LENGTH
set .fullColor = DEFAULT_FULL_COLOR
set .emptyColor = DEFAULT_EMPTY_COLOR
set .x = x
set .y = y
set .z = z
call SetTextTagPos(.t, x, y, z)
call .refresh()
return this
endmethod
method refresh takes nothing returns nothing
local string result
local integer i = 0
local integer percentage = R2I( .p * .l)
set result = "[ " + .fullColor
loop
exitwhen i >= percentage
set result = result + "||"
set i = i + 1
endloop
set result = result + "|r" + .emptyColor
set percentage = .l - percentage
set i = 0
loop
exitwhen i >= percentage
set result = result + "||"
set i = i + 1
endloop
call SetTextTagText(.t, result + "|r ]", .s * 0.0023 )
endmethod
private method onDestroy takes nothing returns nothing
call DestroyTextTag(.t)
endmethod
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
library PlayerColorUtils
// PlayerColor Utils by The_Witcher
//
// Just a bunch of functions for easier player <-> color string handling
//
// Feel free to use!
//
// Functions:
// function GetPlayerColorString takes player p returns string
// function GetPlayerColorStringById takes integer i returns string
//
// function GetPlayerColorRed takes player p returns integer
// function GetPlayerColorGreen takes player p returns integer
// function GetPlayerColorBlue takes player p returns integer
//
// function GetPlayerColorRedPercent takes player p returns integer
// function GetPlayerColorGreenPercent takes player p returns integer
// function GetPlayerColorBluePercent takes player p returns integer
//
// function ColorStringGetRed takes string s returns integer
// function ColorStringGetGreen takes string s returns integer
// function ColorStringGetBlue takes string s returns integer
//
// Variables:
// public string array colors
//
//==============================================================================
//========================= System Code ========================================
//==============================================================================
globals
public string array colors[12]
endglobals
private function ColorStringGetColor takes string s returns integer
local string charMapL = "0123456789abcdef"
local string charMapU = "0123456789ABCDEF"
local string c1 = SubString(s, 0, 1)
local string c2 = SubString(s, 1, 2)
local integer x = 0
local integer y = 0
loop
exitwhen x == 15 or SubString(charMapL, x, x + 1) == c1 or SubString(charMapU, x, x + 1) == c1
set x = x + 1
endloop
loop
exitwhen y == 15 or SubString(charMapL, y, y + 1) == c2 or SubString(charMapU, y, y + 1) == c2
set y = y + 1
endloop
return x * 16 + y
endfunction
// Get the red, green and blue values from a color string
function ColorStringGetRed takes string s returns integer
return ColorStringGetColor(SubString(s, 4, 6))
endfunction
function ColorStringGetGreen takes string s returns integer
return ColorStringGetColor(SubString(s, 6, 8))
endfunction
function ColorStringGetBlue takes string s returns integer
return ColorStringGetColor(SubString(s, 8, 10))
endfunction
// Get the color string for a specific player
function GetPlayerColorString takes player p returns string
return colors[GetPlayerId(p)]
endfunction
function GetPlayerColorStringById takes integer i returns string
if i < 0 or i > 11 then
return "|cffFFFFFF"
endif
return colors[i]
endfunction
// Get the red, green and blue values from a playercolor
function GetPlayerColorRed takes player p returns integer
return ColorStringGetColor(SubString(colors[GetPlayerId(p)], 4, 6))
endfunction
function GetPlayerColorGreen takes player p returns integer
return ColorStringGetColor(SubString(colors[GetPlayerId(p)], 6, 8))
endfunction
function GetPlayerColorBlue takes player p returns integer
return ColorStringGetColor(SubString(colors[GetPlayerId(p)], 8, 10))
endfunction
// Get the red, green and blue values from a playercolor in percent
function GetPlayerColorRedPercent takes player p returns real
return ColorStringGetColor(SubString(colors[GetPlayerId(p)], 4, 6)) / 255.0
endfunction
function GetPlayerColorGreenPercent takes player p returns real
return ColorStringGetColor(SubString(colors[GetPlayerId(p)], 6, 8)) / 255.0
endfunction
function GetPlayerColorBluePercent takes player p returns real
return ColorStringGetColor(SubString(colors[GetPlayerId(p)], 8, 10)) / 255.0
endfunction
private module Init
private static method onInit takes nothing returns nothing
set colors[0] = "|cffFF0202"
set colors[1] = "|cff0041FF"
set colors[2] = "|cff1BE5B8"
set colors[3] = "|cff530080"
set colors[4] = "|cffFFFC00"
set colors[5] = "|cffFE890D"
set colors[6] = "|cff1FBF00"
set colors[7] = "|cffE45AAF"
set colors[8] = "|cff949596"
set colors[9] = "|cff7DBEF1"
set colors[10] = "|cff0F6145"
set colors[11] = "|cff4D2903"
endmethod
endmodule
private struct init extends array
implement Init
endstruct
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~ Timer32 ~~ By Jesus4Lyf ~~ Version 1.06 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Timer32?
// - Timer32 implements a fully optimised timer loop for a struct.
// - Instances can be added to the loop, which will call .periodic every
// PERIOD until .stopPeriodic() is called.
//
// =Pros=
// - Efficient.
// - Simple.
//
// =Cons=
// - Only allows one period.
// - The called method must be named ".periodic".
//
// Methods:
// - struct.startPeriodic()
// - struct.stopPeriodic()
//
// - private method periodic takes nothing returns nothing
//
// This must be defined in structs that implement Periodic Module.
// It will be executed by the module every PERIOD until .stopPeriodic() is called.
// Put "implement T32x" BELOW this method.
//
// Modules:
// - T32x
// Has no safety on .stopPeriodic or .startPeriodic (except debug messages
// to warn).
//
// - T32xs
// Has safety on .stopPeriodic and .startPeriodic so if they are called
// multiple times, or while otherwise are already stopped/started respectively,
// no error will occur, the call will be ignored.
//
// - T32
// The original, old version of the T32 module. This remains for backwards
// compatability, and is deprecated. The periodic method must return a boolean,
// false to continue running or true to stop.
//
// Details:
// - Uses one timer.
//
// - Do not, within a .periodic method, follow a .stopPeriodic call with a
// .startPeriodic call.
//
// How to import:
// - Create a trigger named T32.
// - Convert it to custom text and replace the whole trigger text with this.
//
// Thanks:
// - Infinitegde for finding a bug in the debug message that actually altered
// system operation (when in debug mode).
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library T32 initializer OnInit
globals
public constant real PERIOD=0.03125
public constant integer FPS=R2I(1/PERIOD)
public integer Tick=0 // very useful.
//==============================================================================
private trigger Trig=CreateTrigger()
endglobals
//==============================================================================
// The standard T32 module, T32x.
//
module T32x
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
method stopPeriodic takes nothing returns nothing
debug if this.prev==0 and thistype(0).next!=this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had stopPeriodic called while not running!")
debug endif
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The standard T32 module with added safety checks on .startPeriodic() and
// .stopPeriodic(), T32xs.
//
module T32xs
private thistype next
private thistype prev
private boolean runningPeriodic
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
call this.periodic()
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
if not this.runningPeriodic then
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
set this.runningPeriodic=true
endif
endmethod
method stopPeriodic takes nothing returns nothing
if this.runningPeriodic then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
set this.runningPeriodic=false
endif
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// The original T32 module, for backwards compatability only.
//
module T32 // deprecated.
private thistype next
private thistype prev
private static method PeriodicLoop takes nothing returns boolean
local thistype this=thistype(0).next
loop
exitwhen this==0
if this.periodic() then
// This is some real magic.
set this.prev.next=this.next
set this.next.prev=this.prev
// This will even work for the starting element.
debug set this.prev=0
endif
set this=this.next
endloop
return false
endmethod
method startPeriodic takes nothing returns nothing
debug if this.prev!=0 or thistype(0).next==this then
debug call BJDebugMsg("T32 ERROR: Struct #"+I2S(this)+" had startPeriodic called while already running!")
debug endif
set thistype(0).next.prev=this
set this.next=thistype(0).next
set thistype(0).next=this
set this.prev=thistype(0)
endmethod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(Trig,Condition(function thistype.PeriodicLoop))
endmethod
endmodule
//==============================================================================
// System Core.
//
private function OnExpire takes nothing returns nothing
set Tick=Tick+1
call TriggerEvaluate(Trig)
endfunction
private function OnInit takes nothing returns nothing
call TimerStart(CreateTimer(),PERIOD,true,function OnExpire)
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope TestMap initializer Step1
globals
private capturableBuilding testBuilding
private unit tower
private unit enemyHero
private unit friendlyHero
private boolean check = false
endglobals
private function Step6 takes capturableBuilding captured returns nothing
call TriggerSleepAction(2)
call CustomVictoryBJ( Player(0), true, true )
endfunction
private function Step5 takes nothing returns nothing
if GetUnitCurrentOrder(friendlyHero) == OrderId(CAPTURE_ABILITY_ORDER) then
set check = true
endif
if check and GetUnitCurrentOrder(friendlyHero) != OrderId(CAPTURE_ABILITY_ORDER) then
call DestroyTimer(GetExpiredTimer())
set testBuilding.points = 10
set testBuilding.maxPoints = 30
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl",GetUnitX(testBuilding.u),GetUnitY(testBuilding.u)))
call DisplayTimedTextToForce( GetPlayersAll(), 6.00, "Great, you understood the system!\nNow capture this tower to exit this demo.\nI hope you have great use for it ;)\n The_Witcher" )
set testBuilding.onCapture = Step6
endif
endfunction
private function Step4 takes nothing returns nothing
call EnableUserControl(false)
call SetUnitInvulnerable(enemyHero,true)
call SetUnitInvulnerable(friendlyHero,true)
call DisplayTimedTextToForce( GetPlayersAll(), 8.00, "Nice!\nGot it?\nYou can interrupt the process by attacking or\nabort it manually by giving another order.\nTry that now!" )
call TriggerSleepAction(3)
call IssuePointOrder(enemyHero,"move",1000,800)
call SetUnitInvulnerable(friendlyHero,false)
call UnitAddAbility(enemyHero,'Aloc')
set testBuilding.owner = Player(1)
set testBuilding.maxPoints = 5000
set testBuilding.points = 5000
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl",GetUnitX(testBuilding.u),GetUnitY(testBuilding.u)))
call IssueTargetOrder(friendlyHero, "attack", tower)
call TriggerSleepAction(3)
call TimerStart(CreateTimer(),0.05,true, function Step5)
call EnableUserControl(true)
endfunction
private function Step3 takes capturableBuilding captured returns nothing
local trigger t = CreateTrigger()
call TriggerAddAction(t, function Step4)
call TriggerRegisterUnitEvent(t, enemyHero, EVENT_UNIT_DAMAGED)
call DisplayTimedTextToForce( GetPlayersAll(), 6.00, "Okay you saw it:\nHe had to take your influence away\nbefore he could capture it himself." )
call TriggerSleepAction(6)
call DisplayTimedTextToForce( GetPlayersAll(), 4.00, "Well now he tries to capture your tower again!\nTry stopping him by attacking." )
set captured.owner = Player(0)
set captured.maxPoints = 5000
set captured.points = 5000
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\Resurrect\\ResurrectTarget.mdl",GetUnitX(testBuilding.u),GetUnitY(testBuilding.u)))
call PauseUnit(friendlyHero, false)
call IssueTargetOrder(enemyHero, "attack", tower)
endfunction
private function Step2 takes capturableBuilding captured returns nothing
set captured.onCapture = Step3
call PauseUnit(friendlyHero, true)
call DisplayTimedTextToForce( GetPlayersAll(), 5.00, "Great!\nNow lets watch the enemy Hero.\nHe tries to take over your tower." )
call IssueTargetOrder(enemyHero, "attack", tower)
endfunction
private function Step1 takes nothing returns nothing
set tower = gg_unit_hwtw_0002
set enemyHero = gg_unit_Ulic_0004
set friendlyHero = gg_unit_Hpal_0001
set testBuilding = capturableBuilding.create(tower, 30)
set testBuilding.onCapture = Step2
call DisplayTimedTextToForce( GetPlayersAll(), 10.00, "Welcome to this short demonstration of\nThe_Witcher's Capture Buildings System.\nYou might know this style from the popular game\nLeague of Legends (Dominion Mode)\n\nNow try to capture this tower by right clicking on it..." )
endfunction
endscope