Name | Type | is_array | initial_value |
LevitationVars | hashtable | No |
//TESH.scrollpos=6
//TESH.alwaysfold=0
//===============================================
// System Configuration
//===============================================
//-----------------------------------------------
// Dummy Fly Ability for ground units
//
// This ability is needed to make ground units appear
// flying.
//-----------------------------------------------
constant function LS_DUMMY_FLY_ABILITY takes nothing returns integer
return 'A000'
endfunction
constant function MaxCollision takes nothing returns real
return 32.
endfunction
//-----------------------------------------------
// Pointer to the system hashtable
//
// Example: hashtable "udg_LevitationVars".
// Replace with desired global hashtable here.
//-----------------------------------------------
function LS_DATABASE takes nothing returns hashtable
return udg_LevitationVars
endfunction
function CreateLeviSystemTable takes nothing returns nothing
set udg_LevitationVars = InitHashtable()
endfunction
//-----------------------------------------------
// Static keys
//
// Must be UNIQUE integers and not overlap
// with other table PARENT keys.
//-----------------------------------------------
// parent keys
constant function LS_TRIGGER_KEY takes nothing returns integer
return 1
endfunction
constant function LS_REGION_KEY takes nothing returns integer
return 2
endfunction
constant function LS_REGION_E_TRIGGER_KEY takes nothing returns integer
return 3
endfunction
constant function LS_REGION_L_TRIGGER_KEY takes nothing returns integer
return 4
endfunction
constant function LS_REGION_RECT_KEY takes nothing returns integer
return 5
endfunction
constant function LS_UNIT_KEY takes nothing returns integer
return 6
endfunction
constant function LS_ELEVATION_SPEED_KEY takes nothing returns integer
return 7
endfunction
constant function LS_UTIL_VARIABLES_KEY takes nothing returns integer
return 8
endfunction
// child keys
constant function LS_GROUP_VAR_KEY takes nothing returns integer
return 1
endfunction
constant function LS_LOCATION_VAR_KEY takes nothing returns integer
return 2
endfunction
// constant dummy
constant function LS_TRUE takes nothing returns boolean
return true
endfunction
//===============================================
// System Core components
//===============================================
//-----------------------------------------------
// DB interface
//
// Do not modify or use without full understanding of the
// system's operations.
//-----------------------------------------------
// -- binds a region with 2 triggers
function LSSetRegion takes rect r,trigger t, trigger t2 returns nothing
call SaveRectHandle(LS_DATABASE(),GetHandleId(t),LS_REGION_KEY(),r)
call SaveTriggerHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_E_TRIGGER_KEY(),t)
call SaveTriggerHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_L_TRIGGER_KEY(),t2)
endfunction
// -- returns an elevation region controlled by the trigger
function LSGetRegion takes trigger t returns rect
return LoadRectHandle(LS_DATABASE(),GetHandleId(t),LS_REGION_KEY())
endfunction
// -- getters for elevation triggers attached to region
function LSGetEnterTriggerOfRegion takes rect r returns trigger
return LoadTriggerHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_E_TRIGGER_KEY())
endfunction
function LSGetLeaveTriggerOfRegion takes rect r returns trigger
return LoadTriggerHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_L_TRIGGER_KEY())
endfunction
// -- region elevation height accessors
function LSSetRegionHeightByTrigger takes trigger t, real h returns nothing
call SaveReal(LS_DATABASE(),GetHandleId(t),LS_TRIGGER_KEY(),h)
endfunction
function LSGetRegionHeightByTrigger takes trigger t returns real
return LoadReal(LS_DATABASE(),GetHandleId(t),LS_TRIGGER_KEY())
endfunction
function LSSetRegionHeight takes rect r, real h returns nothing
call LSSetRegionHeightByTrigger(LSGetEnterTriggerOfRegion(r),h)
endfunction
function LSGetRegionHeight takes rect r returns real
return LSGetRegionHeightByTrigger(LSGetEnterTriggerOfRegion(r))
endfunction
// -- region elevation speed accessors
function LSGetRegionElevationSpeedByTrigger takes trigger t returns real
return LoadReal(LS_DATABASE(),GetHandleId(t),LS_ELEVATION_SPEED_KEY())
endfunction
function LSSetRegionElevationSpeedByTrigger takes trigger t, real s returns nothing
call SaveReal(LS_DATABASE(),GetHandleId(t),LS_ELEVATION_SPEED_KEY(),s)
endfunction
function LSGetRegionRisingElevationSpeed takes rect r returns real
return LSGetRegionElevationSpeedByTrigger(LSGetEnterTriggerOfRegion(r))
endfunction
function LSSetRegionRisingElevationSpeed takes rect r, real s returns nothing
call LSSetRegionElevationSpeedByTrigger(LSGetEnterTriggerOfRegion(r),s)
endfunction
function LSGetRegionFallingElevationSpeed takes rect r returns real
return LSGetRegionElevationSpeedByTrigger(LSGetLeaveTriggerOfRegion(r))
endfunction
function LSSetRegionFallingElevationSpeed takes rect r, real s returns nothing
call LSSetRegionElevationSpeedByTrigger(LSGetLeaveTriggerOfRegion(r),s)
endfunction
// -- dummy region creation
function LSCreateRegionFromRect takes rect r,region r1 returns nothing
call RegionAddRect(r1,r)
call SaveRegionHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_RECT_KEY(),r1)
endfunction
function LSGetRegionFromRect takes rect r returns region
return LoadRegionHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_RECT_KEY())
endfunction
// -- cleanups
function LSFlushTriggerData takes trigger t returns nothing
call SaveReal(LS_DATABASE(),GetHandleId(t),LS_TRIGGER_KEY(),0)
call SaveRectHandle(LS_DATABASE(),GetHandleId(t),LS_REGION_KEY(),null)
call FlushChildHashtable(LS_DATABASE(),GetHandleId(t))
endfunction
function LSFlushRegionData takes rect r returns nothing
call SaveTriggerHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_E_TRIGGER_KEY(),null)
call SaveTriggerHandle(LS_DATABASE(),GetHandleId(r),LS_REGION_L_TRIGGER_KEY(),null)
call FlushChildHashtable(LS_DATABASE(),GetHandleId(r))
endfunction
// group recycle
function LSGroup takes nothing returns group
return LoadGroupHandle(LS_DATABASE(),LS_UTIL_VARIABLES_KEY(),LS_GROUP_VAR_KEY())
endfunction
//-----------------------------------------------
// Setting unit heights
//
// Those methods are used by the system, do not
// modify without full knowledge of the system's
// operations.
//
// Can probably apply those methods outside the
// system as well.
//-----------------------------------------------
//-----------------------------------------
// Height modification for single units
//-----------------------------------------
function LSResetUnitHeight takes unit u returns nothing
if not IsUnitType(u, UNIT_TYPE_FLYING) then
call UnitAddAbility(u, LS_DUMMY_FLY_ABILITY())
call UnitRemoveAbility(u, LS_DUMMY_FLY_ABILITY())
endif
call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u),0)
endfunction
function LSSetUnitHeight takes unit u, real h returns nothing
if not IsUnitType(u, UNIT_TYPE_FLYING) then
call UnitAddAbility(u, LS_DUMMY_FLY_ABILITY())
call UnitRemoveAbility(u, LS_DUMMY_FLY_ABILITY())
endif
call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u)+h,0)
endfunction
function LSResetUnitHeightTimed takes unit u, real speed returns nothing
if not IsUnitType(u, UNIT_TYPE_FLYING) then
call UnitAddAbility(u, LS_DUMMY_FLY_ABILITY())
call UnitRemoveAbility(u, LS_DUMMY_FLY_ABILITY())
endif
call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u),speed)
endfunction
function LSSetUnitHeightTimed takes unit u, real h, real speed returns nothing
if not IsUnitType(u, UNIT_TYPE_FLYING) then
call UnitAddAbility(u, LS_DUMMY_FLY_ABILITY())
call UnitRemoveAbility(u, LS_DUMMY_FLY_ABILITY())
endif
call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u)+h,speed)
endfunction
//-----------------------------------------
// Height modification for all units in rect
//-----------------------------------------
function LS_RESETHEIGHTENUM takes nothing returns nothing
call LSResetUnitHeight(GetEnumUnit())
endfunction
function LSResetAllUnitsHeight takes rect r returns nothing
local group g = LSGroup()
local conditionfunc LSAlwaysTrue = Condition(function LS_TRUE)
local rect copyr = Rect(GetRectMinX(r)-MaxCollision(),GetRectMinY(r)-MaxCollision(),GetRectMaxX(r)+MaxCollision(),GetRectMaxY(r)+MaxCollision())
call GroupEnumUnitsInRect(g,copyr,LSAlwaysTrue )
call ForGroup( g, function LS_RESETHEIGHTENUM )
call DestroyBoolExpr(LSAlwaysTrue)
call RemoveRect(copyr)
set LSAlwaysTrue = null
set g = null
set copyr = null
endfunction
function LS_SETHEIGHTENUM takes nothing returns nothing
call LSSetUnitHeight(GetEnumUnit(),bj_enumDestructableRadius)
endfunction
function LSSetAllUnitsHeight takes rect r, real h returns nothing
local group g = LSGroup()
local conditionfunc LSAlwaysTrue = Condition(function LS_TRUE)
local rect copyr = Rect(GetRectMinX(r)-MaxCollision(),GetRectMinY(r)-MaxCollision(),GetRectMaxX(r)+MaxCollision(),GetRectMaxY(r)+MaxCollision())
set bj_enumDestructableRadius = h
call GroupEnumUnitsInRect(g,copyr, LSAlwaysTrue )
call ForGroup( g, function LS_SETHEIGHTENUM )
call DestroyBoolExpr(LSAlwaysTrue)
call RemoveRect(copyr)
set LSAlwaysTrue = null
set g = null
set copyr = null
endfunction
//-----------------------------------------------
// TriggerActions for region entry/leave
//
// Used by the triggers responsible for elevation.
//-----------------------------------------------
function Unit_Enteres_LS_Region_Actions takes nothing returns nothing
call LSSetUnitHeightTimed(GetTriggerUnit(),LSGetRegionHeightByTrigger(GetTriggeringTrigger()),LSGetRegionElevationSpeedByTrigger(GetTriggeringTrigger()))
endfunction
function Unit_Leaves_LS_Region_Actions takes nothing returns nothing
call LSResetUnitHeightTimed(GetTriggerUnit(),LSGetRegionElevationSpeedByTrigger(GetTriggeringTrigger()))
endfunction
//===============================================
// System Front End Interface
//===============================================
//
// create/add/remove/destroy/enable/disable
// levitation regions
//
// Warning: must call LSAddRegion() or LSCreateRegion()
// before doing any other operations.
//
// Parameters:
//
// Region r - the region that is to be used for levitation.
// Real h - the levitation height of a region.
//
// Real x1,y1,x2,y2 - used for creating regions.
//
//-----------------------------------------------
// Toggle unit enters levitation region event on or off
function LSToggleRegionEnterEvent takes rect r, boolean b returns nothing
local trigger t = LSGetEnterTriggerOfRegion(r)
if (b) then
call EnableTrigger(t)
call LSSetAllUnitsHeight(r,LSGetRegionHeightByTrigger(t))
else
call DisableTrigger(t)
endif
set t = null
endfunction
// Toggle unit leaves levitation region event on or off
function LSToggleRegionLeaveEvent takes rect r, boolean b returns nothing
local trigger t = LSGetLeaveTriggerOfRegion(r)
if (b) then
call EnableTrigger(t)
else
call DisableTrigger(t)
endif
set t = null
endfunction
// Turn levitation region on
function LSEnableRegion takes rect r returns nothing
call EnableTrigger(LSGetEnterTriggerOfRegion(r))
call EnableTrigger(LSGetLeaveTriggerOfRegion(r))
call LSSetAllUnitsHeight(r,LSGetRegionHeight(r))
endfunction
// Turn levitation region off
function LSDisableRegion takes rect r returns nothing
call DisableTrigger(LSGetEnterTriggerOfRegion(r))
call DisableTrigger(LSGetLeaveTriggerOfRegion(r))
call LSResetAllUnitsHeight(r)
endfunction
function LSRegionIsOn takes rect r returns boolean
return IsTriggerEnabled(LSGetEnterTriggerOfRegion(r)) or IsTriggerEnabled(LSGetLeaveTriggerOfRegion(r))
endfunction
function LSRegionEnterTriggerIsOn takes rect r returns boolean
return IsTriggerEnabled(LSGetEnterTriggerOfRegion(r))
endfunction
function LSRegionLeaveTriggerIsOn takes rect r returns boolean
return IsTriggerEnabled(LSGetLeaveTriggerOfRegion(r))
endfunction
//--------------------------------------
// Set levitation region levitation height
function LSSetHeight takes rect r, real h returns nothing
call LSDisableRegion(r)
call LSSetRegionHeightByTrigger(LSGetEnterTriggerOfRegion(r),h)
call LSSetRegionHeightByTrigger(LSGetLeaveTriggerOfRegion(r),h)
call LSEnableRegion(r)
endfunction
function LSGetHeight takes rect r returns real
return LSGetRegionHeight(r)
endfunction
function LSSetRisingSpeed takes rect r, real s returns nothing
call LSSetRegionRisingElevationSpeed(r,s)
endfunction
function LSSetFallingSpeed takes rect r, real s returns nothing
call LSSetRegionFallingElevationSpeed(r,s)
endfunction
function LSGetRisingSpeed takes rect r returns real
return LSGetRegionRisingElevationSpeed(r)
endfunction
function LSGetFallingSpeed takes rect r returns real
return LSGetRegionFallingElevationSpeed(r)
endfunction
// destroys a levitation region (does not actually destroy the
// region itself)
function LSDestroyRegion takes rect r returns nothing
local trigger t = LSGetEnterTriggerOfRegion(r)
local trigger t2 = LSGetLeaveTriggerOfRegion(r)
local region r1 = LSGetRegionFromRect(r)
call LSFlushTriggerData(t)
call LSFlushTriggerData(t2)
call LSFlushRegionData(r)
call DisableTrigger(t)
call DisableTrigger(t2)
call DestroyTrigger(t)
call DestroyTrigger(t2)
call RemoveRegion(r1)
call LSResetAllUnitsHeight(r)
set r1 = null
set t = null
set t2 = null
endfunction
// adds and enables region for levitation
function LSAddRegion takes rect r, real h returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local region r1 = CreateRegion()
// events here
call LSCreateRegionFromRect(r,r1) // also defines r1 from r
call TriggerRegisterEnterRegion(t1,r1,null)
call TriggerRegisterLeaveRegion(t2,r1,null)
// conditions here
// trigger actions here
call TriggerAddAction( t1, function Unit_Enteres_LS_Region_Actions )
call TriggerAddAction( t2, function Unit_Leaves_LS_Region_Actions )
call LSSetRegion(r,t1,t2)
call LSSetRegionHeightByTrigger(t1,h)
call LSSetRegionHeightByTrigger(t2,h)
call LSSetRegionElevationSpeedByTrigger(t1,0)
call LSSetRegionElevationSpeedByTrigger(t2,0)
call LSEnableRegion(r)
set r1 = null
set t1 = null
set t2 = null
endfunction
//creates a region for levitation
function LSCreateRegion takes real x1, real y1,real x2, real y2, real h returns rect
set bj_isUnitGroupInRectRect = Rect(x1, y1, x2, y2)
call LSAddRegion(bj_isUnitGroupInRectRect,h)
return bj_isUnitGroupInRectRect
endfunction
//===========================================================================
function InitTrig_ElevationSystem_JassGui takes nothing returns nothing
local group g = CreateGroup()
call CreateLeviSystemTable()
call SaveGroupHandle(LS_DATABASE(),LS_UTIL_VARIABLES_KEY(),LS_GROUP_VAR_KEY(),g)
set g = null
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope ElevationSystem initializer ElevationSystemInit
function ElevationSystemInit takes nothing returns nothing
call ElevationRegionMemoryManager.initStack()
endfunction
function db takes string s returns nothing
call BJDebugMsg(s)
endfunction
// -----------------------------------------------
// Constants for designer/mapper configuration
// -----------------------------------------------
struct ElevationSystemConstants
// dummy ability for flying
static integer FlyAbility = 'Amrf'
// hashtable used by the LS memory manager.
// merging with existing table:
// hashtable LSHashtable = your_hashtable_variable
static hashtable Hashtable = InitHashtable()
// group used to save some memory by recycling.
// merging with existing recycle group:
// group LSDummyGroup = your_group_variable
// Do not destroy this value.
static group DummyGroup = CreateGroup()
// this is the a value for determening
// if a unit is inside a rect ( partial
// containing does not count) so this value
// extends the rect in the 'insiderect'
// calculation. if this value is too small, then
// a glitch is possible when resetting/setting a region's
// height. (a unit will have it's height shifted
// but it won't be considered completly inside the
// region for setting/resetting heights )
// I recommend a value of 32.
static real MaxUnitCollision = 32
static real HeightEnum = 0
static method ALWAYS_TRUE takes nothing returns boolean
return true
endmethod
endstruct
// -----------------------------------------------
// The ElevationRegion Class
// -----------------------------------------------
struct ElevationRegion
public boolean overlap
private real Height
private real EntrySpeed
private real LeaveSpeed
private region ElevationArea
private ElevationRegionRectList RectList
private trigger EntryTrigger
private trigger LeaveTrigger
private boolean locked
// -----------------------------------------------------------------
// Constructors/Destructors
// -----------------------------------------------------------------
// constructor requires a base region
static method create takes rect targetRect, real h returns ElevationRegion
local ElevationRegion e = ElevationRegion.new()
call e.addRect(targetRect)
call e.setHeight(h)
return e
endmethod
// constructor without a base region
static method new takes nothing returns ElevationRegion
local ElevationRegion e = ElevationRegion.allocate()
call ElevationRegionMemoryManager.allocTriggers(e) // assigns trigger values
call e.lock()
call e.createRectList()
call e.setHeight(0)
call e.setEntrySpeed(0)
call e.setLeaveSpeed(0)
call e.setOverlap(true)
return e
endmethod
// destructors
private method DestroyElevationRegion takes nothing returns nothing
local integer i = 0
local rect r
loop
exitwhen i > .RectList.size
set r = .RectList.get(i)
if(r!=null) then
call RegionClearRect(.ElevationArea,r)
endif
set i = i + 1
endloop
call ElevationRegionActionManager.updateElevationRegion(this)
call ElevationRegionMemoryManager.freeTriggers(this) // frees up the triggers
call .setHeight(0)
call .RectList.destroy()
set .ElevationArea = null
set .EntryTrigger = null
set .LeaveTrigger = null
set r = null
endmethod
method onDestroy takes nothing returns nothing
call .DestroyElevationRegion()
endmethod
// ----------------------------------------------------------
// accessors (could prolly have a nice macro here)
// ----------------------------------------------------------
method setEntrySpeed takes real s returns nothing
set .EntrySpeed = s
endmethod
method getEntrySpeed takes nothing returns real
return .EntrySpeed
endmethod
method setLeaveSpeed takes real s returns nothing
set .LeaveSpeed = s
endmethod
method getLeaveSpeed takes nothing returns real
return .LeaveSpeed
endmethod
method setHeight takes real h returns nothing
set .Height = h
call ElevationRegionActionManager.updateElevationRegion(this)
endmethod
method getHeight takes nothing returns real
return .Height
endmethod
method lock takes nothing returns nothing
set .locked = true
endmethod
method setRegion takes region r returns nothing
set .ElevationArea = r
endmethod
method getRegion takes nothing returns region
return .ElevationArea
endmethod
method setEntryTrigger takes trigger t returns nothing
if(.locked == false) then
set .EntryTrigger = t
endif
endmethod
method getEntryTrigger takes nothing returns trigger
return .EntryTrigger
endmethod
method setLeaveTrigger takes trigger t returns nothing
if(.locked == false) then
set .LeaveTrigger = t
endif
endmethod
method getLeaveTrigger takes nothing returns trigger
return .LeaveTrigger
endmethod
// -----------------------------------------------------------------
// overlap boolean
// -----------------------------------------------------------------
method setOverlap takes boolean b returns nothing
set .overlap = b
endmethod
// -----------------------------------------------------------------
// composite region list
// -----------------------------------------------------------------
method createRectList takes nothing returns nothing
set .RectList = ElevationRegionRectList.create()
endmethod
method getRectList takes nothing returns ElevationRegionRectList
return .RectList
endmethod
method addRect takes rect r returns nothing
if(r!=null) then
call .RectList.add(r)
call RegionAddRect(.ElevationArea,r)
call ElevationRegionActionManager.updateElevationRegion(this)
endif
endmethod
method removeRect takes rect r returns nothing
if(r!=null) then
call .RectList.remove(r)
call RegionClearRect(.ElevationArea,r)
call ElevationRegionActionManager.ResetAllUnitsHeight(r)
call ElevationRegionActionManager.updateElevationRegion(this)
endif
endmethod
// -----------------------------------------------------
// Controlling the triggers
// ------------------------------------------------------
// enable/disable entry/leave events for a ElevationRegion
method setEntryEvent takes boolean b returns nothing
if(b) then
call EnableTrigger(.EntryTrigger)
else
call DisableTrigger(.EntryTrigger)
endif
endmethod
method setLeaveEvent takes boolean b returns nothing
if(b) then
call EnableTrigger(.LeaveTrigger)
else
call DisableTrigger(.LeaveTrigger)
endif
endmethod
// enable/disable entire elevation region
method enable takes nothing returns nothing
call .setEntryEvent(true)
call .setLeaveEvent(true)
call ElevationRegionActionManager.updateElevationRegion(this)
endmethod
method disable takes nothing returns nothing
call .setEntryEvent(false)
call .setLeaveEvent(false)
call ElevationRegionActionManager.updateElevationRegion(this)
endmethod
// get boolean values if the region is active or not
method isEntryOn takes nothing returns boolean
return IsTriggerEnabled(.EntryTrigger)
endmethod
method isLeaveOn takes nothing returns boolean
return IsTriggerEnabled(.LeaveTrigger)
endmethod
method isRegionActive takes nothing returns boolean
return .isLeaveOn() or .isEntryOn()
endmethod
// ----------------------------------------------------
// --- String representation ---
method toString takes nothing returns string
return "H:"+ R2S(.Height) + " SE:" + R2S(.EntrySpeed) + " SL:" + R2S(.LeaveSpeed)
endmethod
endstruct
// ---- End of ElevationRegion Class ----
// ------------------------------------------------------------
// This static object is responsible for all the actions that can
// be performed by the ElevationRegion objects
// ------------------------------------------------------------
struct ElevationRegionActionManager
static method updateElevationRegion takes ElevationRegion er returns nothing
local integer i = 0
local rect r
local boolean enabled = er.isEntryOn()
local ElevationRegionRectList rl = er.getRectList()
loop
exitwhen i > rl.size
set r = rl.get(i)
if(r!= null) then
if(enabled) then
call ElevationRegionActionManager.SetAllUnitsHeight(r,er.getHeight())
else
call ElevationRegionActionManager.ResetAllUnitsHeight(r)
endif
endif
set i = i + 1
endloop
set r = null
endmethod
static method EnterTriggerAction takes nothing returns nothing
local ElevationRegion e = ElevationRegionMemoryManager.LoadER(GetTriggeringRegion())
local ElevationRegionList el
local unit u = GetTriggerUnit()
if(e.overlap) then
set el = ElevationRegionMemoryManager.LoadERList(u)
if( el != 0 ) then // there is a list of regions for the triggering unit
call el.add(e)
if(e.getHeight() > ElevationRegionMemoryManager.LoadCurrentUnitHeight(u)) then
// go up
call ElevationRegionActionManager.SetUnitHeight(u,e.getHeight(),e.getEntrySpeed())
call ElevationRegionMemoryManager.SaveCurrentUnitHeight(u,e.getHeight())
endif
else // there is no list, create it
set el = ElevationRegionList.create()
call el.add(e)
call ElevationRegionMemoryManager.SaveERList(u,el)
call ElevationRegionActionManager.SetUnitHeight(u,e.getHeight(),e.getEntrySpeed())
call ElevationRegionMemoryManager.SaveCurrentUnitHeight(u,e.getHeight())
endif
else
call ElevationRegionActionManager.SetUnitHeight(u,e.getHeight(),e.getEntrySpeed())
endif
set u = null
endmethod
static method LeaveTriggerAction takes nothing returns nothing
local ElevationRegion e = ElevationRegionMemoryManager.LoadER(GetTriggeringRegion())
local ElevationRegionList el
local ElevationRegion e0
local unit u = GetTriggerUnit()
if(e.overlap) then
set el = ElevationRegionMemoryManager.LoadERList(u)
if( el != 0 and el.isEmpty() == false) then
call el.remove(e)
if(e.getHeight()== ElevationRegionMemoryManager.LoadCurrentUnitHeight(u)) then
// go down the highest last region
set e0 = el.getmax()
call ElevationRegionActionManager.SetUnitHeight(u,e0.getHeight(),e.getLeaveSpeed())
call ElevationRegionMemoryManager.SaveCurrentUnitHeight(u,e0.getHeight())
endif
else
if(el!=0) then
call el.destroy()
endif
call ElevationRegionMemoryManager.SaveERList(u,0)
call ElevationRegionMemoryManager.SaveCurrentUnitHeight(u,0)
call ElevationRegionMemoryManager.FlushVars(u)
call ElevationRegionActionManager.ResetUnitHeight(u,e.getLeaveSpeed())
endif
else
call ElevationRegionActionManager.ResetUnitHeight(u,e.getLeaveSpeed())
endif
set u = null
endmethod
// interaction with outside objects - units
static method SetUnitHeight takes unit u, real h, real s returns nothing
if (not IsUnitType(u, UNIT_TYPE_FLYING)) then
call UnitAddAbility(u, ElevationSystemConstants.FlyAbility)
call UnitRemoveAbility(u, ElevationSystemConstants.FlyAbility)
endif
call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u)+h,s)
endmethod
static method ResetUnitHeight takes unit u, real s returns nothing
if (not IsUnitType(u, UNIT_TYPE_FLYING)) then
call UnitAddAbility(u, ElevationSystemConstants.FlyAbility)
call UnitRemoveAbility(u, ElevationSystemConstants.FlyAbility)
endif
call SetUnitFlyHeight(u,GetUnitDefaultFlyHeight(u),s)
endmethod
static method SetHeightEnum takes nothing returns nothing
call ElevationRegionActionManager.SetUnitHeight(GetEnumUnit(),ElevationSystemConstants.HeightEnum,0)
endmethod
static method SetAllUnitsHeight takes rect r, real h returns nothing
local conditionfunc alwaystrue = Condition(function ElevationSystemConstants.ALWAYS_TRUE)
local rect copyr = Rect(GetRectMinX(r)-ElevationSystemConstants.MaxUnitCollision,GetRectMinY(r)-ElevationSystemConstants.MaxUnitCollision,GetRectMaxX(r)+ElevationSystemConstants.MaxUnitCollision,GetRectMaxY(r)+ElevationSystemConstants.MaxUnitCollision)
set ElevationSystemConstants.HeightEnum = h
call GroupEnumUnitsInRect(ElevationSystemConstants.DummyGroup,copyr, alwaystrue )
call ForGroup( ElevationSystemConstants.DummyGroup, function ElevationRegionActionManager.SetHeightEnum )
call DestroyBoolExpr(alwaystrue)
call RemoveRect(copyr)
set copyr = null
set alwaystrue = null
endmethod
static method ResetAllUnitsHeight takes rect r returns nothing
call ElevationRegionActionManager.SetAllUnitsHeight(r,0)
endmethod
endstruct
// ---- End of ElevationRegionActionManager Class ----
// --------------------------------------------------------------------
// This static object is responsible for managing custom memory allocations
// for the many ElevationRegion Objects.
// ---------------------------------------------------------------------
struct ElevationRegionMemoryManager
// =================================================================
// This object binds ElevationRegion objects to outside data storage
// entities so that they can interface with units via trigger actions.
// This entire class basically creates a "GetTriggeringElevationRegion()"
// function for the trigger actions to use.
// =================================================================
//------------------------------------------------------------------
// level 1 - global level (accessors for the hastable and other memory instances)
// -----------------------------------------------------------------
static integer ElevationRegionSlot = 1
static integer ElevationRegionListSlot = 2
static integer ElevationRegionUnitSlot = 3
static TriggerStack triggerstack
static RegionStack regionstack
static method LoadERList takes handle h returns ElevationRegionList
return LoadInteger(ElevationSystemConstants.Hashtable,GetHandleId(h),ElevationRegionMemoryManager.ElevationRegionListSlot)
endmethod
static method SaveERList takes handle h, ElevationRegionList erlist returns nothing
call SaveInteger(ElevationSystemConstants.Hashtable,GetHandleId(h),ElevationRegionMemoryManager.ElevationRegionListSlot,erlist)
endmethod
static method LoadCurrentUnitHeight takes handle h returns real
return LoadReal(ElevationSystemConstants.Hashtable,GetHandleId(h),ElevationRegionMemoryManager.ElevationRegionUnitSlot)
endmethod
static method SaveCurrentUnitHeight takes handle h, real val returns nothing
call SaveReal(ElevationSystemConstants.Hashtable,GetHandleId(h),ElevationRegionMemoryManager.ElevationRegionUnitSlot,val)
endmethod
static method LoadER takes handle h returns ElevationRegion
return LoadInteger(ElevationSystemConstants.Hashtable,GetHandleId(h),ElevationRegionMemoryManager.ElevationRegionSlot)
endmethod
static method SaveER takes handle h, ElevationRegion e returns nothing
call SaveInteger(ElevationSystemConstants.Hashtable,GetHandleId(h),ElevationRegionMemoryManager.ElevationRegionSlot,e)
endmethod
static method FlushVars takes handle h returns nothing
call FlushChildHashtable(ElevationSystemConstants.Hashtable,GetHandleId(h))
endmethod
static method initStack takes nothing returns nothing
set ElevationRegionMemoryManager.triggerstack = TriggerStack.create()
set ElevationRegionMemoryManager.regionstack = RegionStack.create()
endmethod
static method getTriggerStackSize takes nothing returns integer
return ElevationRegionMemoryManager.triggerstack.size
endmethod
static method allocateTrigger takes nothing returns trigger
if(ElevationRegionMemoryManager.triggerstack.size >0) then
return ElevationRegionMemoryManager.triggerstack.pop()
else
return CreateTrigger()
endif
endmethod
static method allocateRegion takes nothing returns region
if(ElevationRegionMemoryManager.regionstack.size >0) then
return ElevationRegionMemoryManager.regionstack.pop()
else
return CreateRegion()
endif
endmethod
static method freeTrigger takes trigger t returns nothing
call ElevationRegionMemoryManager.triggerstack.push(t)
endmethod
static method freeRegion takes region r returns nothing
call ElevationRegionMemoryManager.regionstack.push(r)
endmethod
// -----------------------------------------------------------------
// level 2 - class level (keys are the e.elevationRegion handle Ids)
// -----------------------------------------------------------------
static method BindElevationRegion takes ElevationRegion e returns nothing
call ElevationRegionMemoryManager.SaveER(e.getRegion(),e)
endmethod
static method UnbindElevationRegion takes ElevationRegion e returns nothing
call ElevationRegionMemoryManager.SaveER(e.getRegion(),0)
call ElevationRegionMemoryManager.FlushVars(e.getRegion())
endmethod
// -----------------------------------------------------------------
// level 3 - object level (trigger actions in the object)
// -----------------------------------------------------------------
static method allocTriggers takes ElevationRegion e returns nothing
local boolean newTriggers = ElevationRegionMemoryManager.getTriggerStackSize() <= 0
call e.setEntryTrigger(ElevationRegionMemoryManager.allocateTrigger())
call e.setLeaveTrigger(ElevationRegionMemoryManager.allocateTrigger())
call e.setRegion (ElevationRegionMemoryManager.allocateRegion())
// old triggers already have a region event, a region, and the actions needed.
if(newTriggers) then
call TriggerRegisterEnterRegion(e.getEntryTrigger(),e.getRegion(),null)
call TriggerRegisterLeaveRegion(e.getLeaveTrigger(),e.getRegion(),null)
call TriggerAddAction( e.getEntryTrigger(), function ElevationRegionActionManager.EnterTriggerAction )
call TriggerAddAction( e.getLeaveTrigger(), function ElevationRegionActionManager.LeaveTriggerAction )
endif
call ElevationRegionMemoryManager.BindElevationRegion(e)
endmethod
static method freeTriggers takes ElevationRegion e returns nothing
call ElevationRegionMemoryManager.freeRegion(e.getRegion())
call ElevationRegionMemoryManager.freeTrigger(e.getLeaveTrigger())
call ElevationRegionMemoryManager.freeTrigger(e.getEntryTrigger())
call ElevationRegionMemoryManager.UnbindElevationRegion(e)
endmethod
endstruct
// ---- End of ElevationRegionMemoryManager Class ----
// -----------------------------------------------
// Utilities Needed by the ElevationRegion memory
// Manager.
// -----------------------------------------------
struct TriggerStackNode
public trigger value = null
public TriggerStackNode next
public TriggerStackNode prev
method onDestroy takes nothing returns nothing
set .value = null
endmethod
endstruct
struct TriggerStack
public TriggerStackNode first
public TriggerStackNode current
public integer size
method push takes trigger t returns nothing
local TriggerStackNode next = TriggerStackNode.create()
set next.value = t
set next.prev = .current
set .current.next = next
set .current = next
set .size = .size + 1
endmethod
method pop takes nothing returns trigger
local trigger t = null
if(.size>0 ) then
set t = .current.value
set .current = .current.prev
call .current.next.destroy()
set .size = .size - 1
endif
return t
endmethod
static method create takes nothing returns TriggerStack
local TriggerStack stack = TriggerStack.allocate()
set stack.first = TriggerStackNode.create()
set stack.size = 0
set stack.current = stack.first
return stack
endmethod
endstruct
struct RegionStackNode
public region value = null
public RegionStackNode next
public RegionStackNode prev
method onDestroy takes nothing returns nothing
set .value = null
endmethod
endstruct
struct RegionStack
public RegionStackNode first
public RegionStackNode current
public integer size
method push takes region r returns nothing
local RegionStackNode next = RegionStackNode.create()
set next.value = r
set next.prev = .current
set .current.next = next
set .current = next
set .size = .size + 1
endmethod
method pop takes nothing returns region
local region r = null
if(.size>0 ) then
set r = .current.value
set .current = .current.prev
call .current.next.destroy()
set .size = .size - 1
endif
return r
endmethod
static method create takes nothing returns RegionStack
local RegionStack stack = RegionStack.allocate()
set stack.first = RegionStackNode.create()
set stack.size = 0
set stack.current = stack.first
return stack
endmethod
endstruct
// -----------------------------------------------
// Utilities Needed by the ElevationRegion Class.
// -----------------------------------------------
struct ElevationRegionListNode
// could probably use a nice interface here
// and generalize the linked list class so it
// can be used for other stuff.
// but meh, didnt feel like writing a complete
// linked list implementation for vJass
//(im aware somebody might of done it already,
// but im too lazy/stubborn).
// Instead, I wrote 2 custom made ones.
public ElevationRegion value
public ElevationRegionListNode next
endstruct
struct ElevationRegionList
public ElevationRegionListNode current
public ElevationRegionListNode first
public integer size
method add takes ElevationRegion e returns nothing
set .current.next = ElevationRegionListNode.create()
set .current.next.value = e
set .current = .current.next
set .size = .size + 1
endmethod
method remove takes ElevationRegion e returns nothing
local integer i = 0
local ElevationRegionListNode curr = .first
local ElevationRegionListNode prev
loop
exitwhen i> .size
set prev = curr
set curr = curr.next
if( curr.value == e) then
if(curr == .current) then
set .current = prev
endif
set prev.next = curr.next
set curr.value = 0
call curr.destroy()
set .size = .size - 1
return
endif
set i = i + 1
endloop
endmethod
method getmax takes nothing returns ElevationRegion
local integer i = 1
local ElevationRegionListNode node
local ElevationRegion max
if(.size <=0) then
return 0
endif
set node = .first.next
set max = .first.next.value
loop
exitwhen i> .size
if(max.getHeight() < node.value.getHeight()) then
set max = node.value
endif
set node = node.next
set i = i + 1
endloop
return max
endmethod
method isEmpty takes nothing returns boolean
return .size <=0
endmethod
static method create takes nothing returns ElevationRegionList
local ElevationRegionList elist = ElevationRegionList.allocate()
set elist.first = ElevationRegionListNode.create()
set elist.current = elist.first
set elist.first.value = 0
set elist.first.next = 0
set elist.size = 0
return elist
endmethod
method onDestroy takes nothing returns nothing
// deallocate all the nodes
local ElevationRegionListNode node = .first
local ElevationRegionListNode next
local integer i = 0
loop
exitwhen i < .size
set next = node.next
call node.destroy()
set node = next
set i = i + 1
endloop
endmethod
endstruct
struct ElevationRegionRectListNode
public rect value = null
public ElevationRegionRectListNode next
method onDestroy takes nothing returns nothing
set .value = null
endmethod
endstruct
struct ElevationRegionRectList
public ElevationRegionRectListNode current
public ElevationRegionRectListNode first
public integer size // the current size of valid elements
method add takes rect e returns nothing
set .current.next = ElevationRegionRectListNode.create()
set .current.next.value = e
set .current = .current.next
set .size = .size + 1
endmethod
method remove takes rect e returns nothing
local integer i = 0
local ElevationRegionRectListNode curr = .first
local ElevationRegionRectListNode prev
loop
exitwhen i> .size
set prev = curr
set curr = curr.next
if( curr.value == e) then
if(curr == .current) then
set .current = prev
endif
set prev.next = curr.next
call curr.destroy()
set .size = .size - 1
return
endif
set i = i + 1
endloop
endmethod
method get takes integer i returns rect
local integer j = 0
local ElevationRegionRectListNode curr = .first
loop
exitwhen j > i
set curr = curr.next
set j = j + 1
endloop
return curr.value
endmethod
method isEmpty takes nothing returns boolean
return .size <=0
endmethod
static method create takes nothing returns ElevationRegionRectList
local ElevationRegionRectList elist = ElevationRegionRectList.allocate()
set elist.first = ElevationRegionRectListNode.create()
set elist.current = elist.first
set elist.first.next = 0
set elist.size = 0
return elist
endmethod
method onDestroy takes nothing returns nothing
// deallocate all the nodes
local ElevationRegionRectListNode node = .first
local ElevationRegionRectListNode next
local integer i = 0
loop
exitwhen i < .size
set next = node.next
call node.destroy()
set node = next
set i = i + 1
endloop
endmethod
endstruct
endscope
//TESH.scrollpos=0
//TESH.alwaysfold=0
//===========================================================================
function InitTrig_LS_Regions_Jass takes nothing returns nothing
local rect r
// set r = Rect(GetRectMinX(targetRect),GetRectMinY(targetRect),GetRectMaxX(targetRect),GetRectMaxY(targetRect))
// static examples, regions defined by region palatte
// define height on 2nd parameter
call LSAddRegion(gg_rct_R1,40)
call LSAddRegion(gg_rct_R2,70)
call LSAddRegion(gg_rct_R3,90)
call LSAddRegion(gg_rct_R4,120)
call LSAddRegion(gg_rct_R5,135)
call LSAddRegion(gg_rct_R6,120)
//call LSAddRegion(gg_rct_RTower,390)
// call LSSetRisingSpeed(gg_rct_RTower,300)
// call LSSetFallingSpeed(gg_rct_RTower,0)
// disable those events for optimization
// and potential bug fixing with region
// overlap, only have the leave event
// handler where unit leaves the levitation area
// and steps on a regular terrain
// WARNING: if there are air units, then doing this
// will not reset their flying height if they leave
// a "middle" region
//call LSToggleRegionLeaveEvent(gg_rct_R2,false)
//call LSToggleRegionLeaveEvent(gg_rct_R3,false)
//call LSToggleRegionLeaveEvent(gg_rct_R4,false)
//call LSToggleRegionLeaveEvent(gg_rct_R5,false)
//call LSToggleRegionLeaveEvent(gg_rct_R6,false)
//dynamic example, regions defined by triggers
//set r = LSCreateRegion(0,0,300,300,400)
set r = null
endfunction
//TESH.scrollpos=0
//TESH.alwaysfold=0
//===========================================================================
function InitTrig_LS_Regions_vJass takes nothing returns nothing
local ElevationRegion e
local ElevationRegion e1
local integer i = 0
// basic test, same as the jass version
//set e = ElevationRegion.create(gg_rct_R1,40)
//set e = ElevationRegion.create(gg_rct_R2,70)
// set e = ElevationRegion.create(gg_rct_R3,90)
// set e = ElevationRegion.create(gg_rct_R4,120)
// set e = ElevationRegion.create(gg_rct_R5,135)
// set e = ElevationRegion.create(gg_rct_R6,120)
// set e = ElevationRegion.create(gg_rct_RTower,390)
// call e.setElevationEntrySpeed(300)
// call e.setElevationLeaveSpeed(0) // 0 = instant
// e.destroy() will not touch the original rect used to create the region
// call e.setLeaveEvent(true)
// call e.setEntryEvent(true)
// overlap test
set e = ElevationRegion.create(gg_rct_VR1,200)
set e = ElevationRegion.create(gg_rct_VR2,400)
set e = ElevationRegion.create(gg_rct_VR3,300)
set e = ElevationRegion.create(gg_rct_VR4,700)
// composite region test
set e = ElevationRegion.create(gg_rct_RR1,300)
call e.addRect(gg_rct_RR2)
call e.removeRect(gg_rct_RR2)
call e.addRect(gg_rct_RR2)
call e.addRect(gg_rct_RR4)
call e.addRect(gg_rct_RR3)
call e.removeRect(gg_rct_RR3)
// trigger recycling test
loop
exitwhen i > 20
set e = ElevationRegion.new()
set e1 = ElevationRegion.new()
call e.addRect(gg_rct_RR5)
call e.destroy()
call e1.destroy()
set i = i + 1
endloop
// new() test
set e = ElevationRegion.new()
call e.addRect(gg_rct_RR5)
call e.setHeight(300)
set e1 = ElevationRegion.new()
call e1.addRect(gg_rct_RR6)
call e1.setHeight(300)
endfunction