function PolledWaitModified takes real duration returns nothing
local timer t
local real timeRemaining
if (duration > 0) then
set t = CreateTimer()
call TimerStart(t, duration, false, null)
loop
set timeRemaining = TimerGetRemaining(t)
exitwhen timeRemaining <= 0
// If we have a bit of time left, skip past 10% of the remaining
// duration instead of checking every interval, to minimize the
// polling on long waits.
if (timeRemaining > bj_POLLED_WAIT_SKIP_THRESHOLD) then
call TriggerSleepAction(0.1 * timeRemaining)
else
call TriggerSleepAction(bj_POLLED_WAIT_INTERVAL)
endif
endloop
call DestroyTimer(t)
endif
endfunction
function MultiboardSetItemValueBJModified takes multiboard mb, integer col, integer row, string val returns nothing
local integer curRow = 0
local integer curCol = 0
local integer numRows = MultiboardGetRowCount(mb)
local integer numCols = MultiboardGetColumnCount(mb)
local multiboarditem mbitem = null
// Loop over rows, using 1-based index
loop
set curRow = curRow + 1
exitwhen curRow > numRows
// Apply setting to the requested row, or all rows (if row is 0)
if (row == 0 or row == curRow) then
// Loop over columns, using 1-based index
set curCol = 0
loop
set curCol = curCol + 1
exitwhen curCol > numCols
// Apply setting to the requested column, or all columns (if col is 0)
if (col == 0 or col == curCol) then
set mbitem = MultiboardGetItem(mb, curRow - 1, curCol - 1)
call MultiboardSetItemValue(mbitem, val)
call MultiboardReleaseItem(mbitem)
endif
endloop
endif
endloop
endfunction
Name | Type | is_array | initial_value |
Ab_HiddenTrap_UG | group | No | |
CapturedPlayerHero | boolean | Yes | |
CapturePoint_UG | group | No | |
CinematicTempUnit | unit | No | |
cpLoopIndex | integer | Yes | |
cpProgress1 | real | Yes | |
cpVAR_AreaRadiusCapture | real | Yes | |
cpVAR_CaptureRate | integer | No | |
cpVAR_CaptureReqSecs | real | Yes | |
cpVAR_FloatOffset | real | No | |
cpVAR_SystemStyle1 | integer | Yes | |
cpVAR_UnitCapture | unit | Yes | |
Creep_FacingAngle | real | Yes | |
Creep_Loop | integer | No | |
Creep_Position | location | Yes | |
Defender_Count | integer | No | |
Defender_Force | force | No | |
Demon_Count | integer | No | |
Demon_Force | force | No | |
EventRegions | rect | Yes | |
FollowSystem_UG | group | No | |
GameEnd | boolean | No | |
GDD__Integers | integer | Yes | |
GDD__LeftMapGroup | group | No | |
GDD__TriggerArray | trigger | Yes | |
GDD__UnitArray | unit | Yes | |
GDD_Damage | real | No | |
GDD_DamagedUnit | unit | No | |
GDD_DamageSource | unit | No | |
GDD_Event | real | No | |
GhostCreepsGroup | group | No | |
GraveyardAreaCheck | boolean | Yes | |
Hashtable | hashtable | No | |
HornOfCenariusGaurdiansCount | integer | No | |
ItemGrantsAbility_AbilityID | integer | Yes | |
ItemGrantsAbility_Total | integer | No | |
ItemGrantsAbility_Type | itemcode | Yes | |
ItemMoonkeys_Count | integer | No | |
LimitDruids | integer | Yes | |
LimitGoblinZeppelin | integer | Yes | |
Loc | location | Yes | |
MinionsAreaCaptured | boolean | Yes | |
MinionsAreaSpawn | location | Yes | |
MinionsGroup | group | Yes | |
MinionsMaxSpawner | integer | No | |
MinionsNumber | integer | Yes | |
MinionsNumberMax | integer | Yes | |
MinionsOwner | player | Yes | |
MinionsUnitType1 | unitcode | Yes | |
MinionsUnitType2 | unitcode | Yes | |
MultiBoard | multiboard | No | |
MultiBoard_Players | integer | No | |
Multiboard_Spots | integer | Yes | |
NPCs_Group | group | No | |
Player | player | No | |
Player_Hero | unit | Yes | |
Player_Tech_Req_Unit | unit | Yes | |
PlayerColors | string | Yes | |
QuestDiscovered | boolean | Yes | |
QuestFinished | boolean | Yes | |
QuestGiverEffect | effect | Yes | |
SpecialUnits | unit | Yes | |
TempGroup | group | No | |
TempPlayer | player | Yes | |
TempUnit | unit | Yes | |
Text_Duration | real | No | |
TextSize_dmg | real | No | |
TextSize_spells | real | No | |
Timer | timer | No | |
Timer_Window | timerdialog | No | |
VaultRandomizer | integer | No | |
WithinRangeWanted_Filter | boolexpr | No |
// GUI-Friendly Damage Detection -- v1.2.1 -- by Weep
// http:// www.thehelper.net/forums/showthread.php?t=137957
//
// Requires: only this trigger and its variables.
//
// -- What? --
// This snippet provides a leak-free, GUI-friendly implementation of an "any unit takes
// damage" event. It requires no JASS knowledge to use.
//
// It uses the Game - Value Of Real Variable event as its method of activating other
// triggers, and passes the event responses through a few globals.
//
// -- Why? --
// The traditional GUI method of setting up a trigger than runs when any unit is damaged
// leaks trigger events. This snippet is easy to implement and removes the need to do
// you own GUI damage detection setup.
//
// -- How To Implement --
// 0. Before you copy triggers that use GDD into a new map, you need to copy over GDD
// with its GDD Variable Creator trigger, or there will be a problem: the variables
// won't be automatically created correctly.
//
// 1. Be sure "Automatically create unknown variables while pasting trigger data" is
// enabled in the World Editor general preferences.
// 2. Copy this trigger category ("GDD") and paste it into your map.
// (Alternately: create the variables listed in the globals block below, create a
// trigger named "GUI Friendly Damage Detection", and paste in this entire text.)
// 3. Create your damage triggers using Game - Value Of Real Variable as the event,
// select GDD_Event as the variable, and leave the rest of the settings to the default
// "becomes Equal to 0.00".
// The event responses are the following variables:
// GDD_Damage is the amount of damage, replacing Event Response - Damage Taken.
// GDD_DamagedUnit is the damaged unit, replacing Event Response - Triggering Unit.
// Triggering Unit can still be used, if you need to use waits.
// Read the -- Notes -- section below for more info.
// GDD_DamageSource is the damaging unit, replacing Event Response - Damage Source.
//
// -- Notes --
// GDD's event response variables are not wait-safe; you can't use them after a wait in
// a trigger. If you need to use waits, Triggering Unit (a.k.a. GetTriggerUnit()) can
// be used in place of GDD_DamageSource. There is no usable wait-safe equivalent to
// Event Damage or Damage Source; you'll need to save the values yourself.
//
// Don't write any values to the variables used as the event responses, or it will mess
// up any other triggers using this snippet for their triggering. Only use their values.
//
// This uses arrays, so can detect damage for a maximum of 8190 units at a time, and
// cleans up data at a rate of 33.33 per second, by default. This should be enough for
// most maps, but if you want to change the rate, change the value returned in the
// GDD_RecycleRate function at the top of the code, below.
//
// By default, GDD will not register units that have Locust at the moment of their
// entering the game, and will not recognize when they take damage (which can only
// happen if the Locust ability is later removed from the unit.) To allow a unit to have
// Locust yet still cause GDD damage events if Locust is removed, you can either design
// the unit to not have Locust by default and add it via triggers after creation, or
// edit the GDD_Filter function at the top of the code, below.
//
// -- Credits --
// Captain Griffin on wc3c.net for the research and concept of GroupRefresh.
//
// Credit in your map not needed, but please include this README.
//
// -- Version History --
// 1.2.1: Minor code cleaning. Added configuration functions. Updated documentation.
// 1.2.0: Made this snippet work properly with recursive damage.
// 1.1.1: Added a check in order to not index units with the Locust ability (dummy units).
// If you wish to check for damage taken by a unit that is unselectable, do not
// give the unit-type Locust in the object editor; instead, add the Locust ability
// 'Aloc' via a trigger after its creation, then remove it.
// 1.1.0: Added a check in case a unit gets moved out of the map and back.
// 1.0.0: First release.
//===================================================================
// Configurables.
function GDD_RecycleRate takes nothing returns real //The rate at which the system checks units to see if they've been removed from the game
return 0.03
endfunction
function GDD_Filter takes unit u returns boolean //The condition a unit has to pass to have it registered for damage detection
return GetUnitAbilityLevel(u, 'Aloc') == 0 //By default, the system ignores Locust units, because they normally can't take damage anyway
endfunction
//===================================================================
// This is just for reference.
// If you use JassHelper, you could uncomment this section instead of creating the variables in the trigger editor.
// globals
// real udg_GDD_Event = 0.
// real udg_GDD_Damage = 0.
// unit udg_GDD_DamagedUnit
// unit udg_GDD_DamageSource
// trigger array udg_GDD__TriggerArray
// integer array udg_GDD__Integers
// unit array udg_GDD__UnitArray
// group udg_GDD__LeftMapGroup = CreateGroup()
// endglobals
//===================================================================
// System code follows. Don't touch!
function GDD_Event takes nothing returns boolean
local unit damagedcache = udg_GDD_DamagedUnit
local unit damagingcache = udg_GDD_DamageSource
local real damagecache = udg_GDD_Damage
set udg_GDD_DamagedUnit = GetTriggerUnit()
set udg_GDD_DamageSource = GetEventDamageSource()
set udg_GDD_Damage = GetEventDamage()
set udg_GDD_Event = 1.
set udg_GDD_Event = 0.
set udg_GDD_DamagedUnit = damagedcache
set udg_GDD_DamageSource = damagingcache
set udg_GDD_Damage = damagecache
set damagedcache = null
set damagingcache = null
return false
endfunction
function GDD_AddDetection takes nothing returns boolean
// if(udg_GDD__Integers[0] > 8190) then
// call BJDebugMsg("GDD: Too many damage events! Decrease number of units present in the map or increase recycle rate.")
// ***Recycle rate is specified in the GDD_RecycleRate function at the top of the code. Smaller is faster.***
// return
// endif
if(IsUnitInGroup(GetFilterUnit(), udg_GDD__LeftMapGroup)) then
call GroupRemoveUnit(udg_GDD__LeftMapGroup, GetFilterUnit())
elseif(GDD_Filter(GetFilterUnit())) then
set udg_GDD__Integers[0] = udg_GDD__Integers[0]+1
set udg_GDD__UnitArray[udg_GDD__Integers[0]] = GetFilterUnit()
set udg_GDD__TriggerArray[udg_GDD__Integers[0]] = CreateTrigger()
call TriggerRegisterUnitEvent(udg_GDD__TriggerArray[udg_GDD__Integers[0]], udg_GDD__UnitArray[udg_GDD__Integers[0]], EVENT_UNIT_DAMAGED)
call TriggerAddCondition(udg_GDD__TriggerArray[udg_GDD__Integers[0]], Condition(function GDD_Event))
endif
return false
endfunction
function GDD_PreplacedDetection takes nothing returns nothing
local group g = CreateGroup()
local integer i = 0
loop
call GroupEnumUnitsOfPlayer(g, Player(i), Condition(function GDD_AddDetection))
set i = i+1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call DestroyGroup(g)
set g = null
endfunction
function GDD_GroupRefresh takes nothing returns nothing
// Based on GroupRefresh by Captain Griffen on wc3c.net
if (bj_slotControlUsed[5063] == true) then
call GroupClear(udg_GDD__LeftMapGroup)
set bj_slotControlUsed[5063] = false
endif
call GroupAddUnit(udg_GDD__LeftMapGroup, GetEnumUnit())
endfunction
function GDD_Recycle takes nothing returns nothing
if(udg_GDD__Integers[0] <= 0) then
return
elseif(udg_GDD__Integers[1] <= 0) then
set udg_GDD__Integers[1] = udg_GDD__Integers[0]
endif
if(GetUnitTypeId(udg_GDD__UnitArray[udg_GDD__Integers[1]]) == 0) then
call DestroyTrigger(udg_GDD__TriggerArray[udg_GDD__Integers[1]])
set udg_GDD__TriggerArray[udg_GDD__Integers[1]] = null
set udg_GDD__TriggerArray[udg_GDD__Integers[1]] = udg_GDD__TriggerArray[udg_GDD__Integers[0]]
set udg_GDD__UnitArray[udg_GDD__Integers[1]] = udg_GDD__UnitArray[udg_GDD__Integers[0]]
set udg_GDD__UnitArray[udg_GDD__Integers[0]] = null
set udg_GDD__Integers[0] = udg_GDD__Integers[0]-1
endif
set udg_GDD__Integers[1] = udg_GDD__Integers[1]-1
endfunction
function GDD_LeaveMap takes nothing returns boolean
local boolean cached = bj_slotControlUsed[5063]
if(udg_GDD__Integers[2] < 64) then
set udg_GDD__Integers[2] = udg_GDD__Integers[2]+1
else
set bj_slotControlUsed[5063] = true
call ForGroup(udg_GDD__LeftMapGroup, function GDD_GroupRefresh)
set udg_GDD__Integers[2] = 0
endif
call GroupAddUnit(udg_GDD__LeftMapGroup, GetFilterUnit())
set bj_slotControlUsed[5063] = cached
return false
endfunction
// ===========================================================================
function InitTrig_GUI_Friendly_Damage_Detection takes nothing returns nothing
local region r = CreateRegion()
call RegionAddRect(r, GetWorldBounds())
call TriggerRegisterEnterRegion(CreateTrigger(), r, Condition(function GDD_AddDetection))
call TriggerRegisterLeaveRegion(CreateTrigger(), r, Condition(function GDD_LeaveMap))
call GDD_PreplacedDetection()
call TimerStart(CreateTimer(), GDD_RecycleRate(), true, function GDD_Recycle)
set r = null
endfunction
library AdvancedCameraSystem initializer Init
// Advanced Camera System by The_Witcher
//
// This is a very advanced advanced camera system which adjusts the camera
// distance to the target so the camera isn't looking through houses/trees/...
// and the cameras angle of attack so the view isn't blocked because of hills...
//
// useful for RPGs and that stuff
//
// To bind the camera to a unit for a player use
// SetCameraUnit( unit, player )
//
// if you want to have your normal camera again use
// ReleaseCameraUnit( player )
//
// in case you want to know which unit is bound to the camera for player xy use
// GetCameraUnit( player )
//
// to change the AngleOfAttack of a player ingame use
// SetCamDefaultAngleOfAttack( Player, NewValue )
//
// to change the maximal camera target distance of a player ingame use
// SetCamMaxDistance( Player, NewValue )
//
// to change the maximal distance behind the target, the z-offset is checked (for z-angle), of a player ingame use
// SetCamMaxZCheckDistance( Player, NewValue )
//
// SETUP PART
globals
// The max. distance the camera can have to the target
private real DEFAULT_MAX_DISTANCE = 1000
// The max. distance the zOffset behind the unit is checked (for zAngle)
private real DEFAULT_MAX_Z_CHECK_DISTANCE = 500
// the camera angle of attack correction after the zAngle calculation
private real DEFAULT_ANGLE_OF_ATTACK = -25
// the timer interval (0.01 is best but can lagg in huge maps with many of these short intervals)
private constant real INTERVAL = 0.03
// the time the camera will need to adjust
private constant real DELAY = 0.05
// the standart z of the camera
private constant real NORMAL_HEIGHT = 100
// the accuracy increases if the value gets smaller
private constant real ACCURACY = 50
// the secondary accruracy when the camera reaches a barricade (just leave at this amount)
private constant real EXTREME_ACCURACY = 10
endglobals
// SETUP END
// don't modify the code below!
globals
private item ite
private real array Aoa[15]
private real array Dist[15]
private real array CheckDist[15]
private unit array CamUnit[15]
private timer tim = CreateTimer()
private location loc = Location(0,0)
private integer active = 0
private hashtable h = InitHashtable()
endglobals
private function IsCoordPathable takes real x, real y returns boolean
call SetItemVisible(ite,true)
call SetItemPosition(ite,x,y)
set x = GetItemX( ite) - x
set y = GetItemY( ite) - y
call SetItemVisible(ite,false)
if x < 1 and x > -1 and y < 1 and y > -1 then
return true
endif
return false
endfunction
private function HideAllItems takes nothing returns nothing
if IsItemVisible(GetEnumItem()) then
call SaveInteger(h,GetHandleId(GetEnumItem()),0,1)
endif
call SetItemVisible(GetEnumItem(),false)
endfunction
private function ShowAllItems takes nothing returns nothing
if LoadInteger(h,GetHandleId(GetEnumItem()),0) == 1 then
call SetItemVisible(GetEnumItem(),true)
call FlushChildHashtable(h,GetHandleId(GetEnumItem()))
endif
endfunction
private function Actions takes nothing returns nothing
local real x
local real y
local real angle
local real rz
local real z
local integer i = 0
local integer Check
local real CheckDistance
local real DistanceDone
local rect rec
loop
exitwhen i >= bj_MAX_PLAYERS
if CamUnit[i] != null then
set DistanceDone = 0
set rz = 0
set x = GetUnitX(CamUnit[i])
set y = GetUnitY(CamUnit[i])
set Check = 1
set angle = (GetUnitFacing(CamUnit[i]) - 180)*bj_DEGTORAD
set CheckDistance = ACCURACY
set z = DEFAULT_ANGLE_OF_ATTACK
if not IsUnitType(CamUnit[i], UNIT_TYPE_FLYING) then
loop
set x = x + CheckDistance * Cos(angle)
set y = y + CheckDistance * Sin(angle)
set DistanceDone = DistanceDone + CheckDistance
call MoveLocation(loc,x,y)
set z = GetLocationZ(loc)
if RAbsBJ(z) > RAbsBJ(rz) and DistanceDone <= CheckDist[i] then
set rz = z
endif
if not IsCoordPathable(x,y)then
set rec = Rect(x-ACCURACY,y-ACCURACY,x+ACCURACY,y+ACCURACY)
call EnumItemsInRect(rec,null, function HideAllItems)
if not IsCoordPathable(x,y)then
set Check = 0
endif
call RemoveRect(rec)
endif
if Check == 0 and CheckDistance == ACCURACY then
set DistanceDone = DistanceDone - CheckDistance
set x = x - CheckDistance * Cos(angle)
set y = y - CheckDistance * Sin(angle)
set Check = 1
set CheckDistance = EXTREME_ACCURACY
endif
exitwhen (Check == 0 and CheckDistance == EXTREME_ACCURACY) or DistanceDone > Dist[i]
endloop
else
set DistanceDone = Dist[i]
endif
call MoveLocation(loc,GetUnitX(CamUnit[i]),GetUnitY(CamUnit[i]))
set x = GetLocationZ(loc)
loop
exitwhen x - rz < 180
set x = x - 180
endloop
set z = Atan2(x-rz,200) * bj_RADTODEG + Aoa[i]
if IsUnitType(CamUnit[i], UNIT_TYPE_FLYING) then
set z = Aoa[i]
endif
if GetLocalPlayer() == Player(i) then
call CameraSetSmoothingFactor(1)
call SetCameraField(CAMERA_FIELD_TARGET_DISTANCE, DistanceDone, DELAY)
call SetCameraField(CAMERA_FIELD_ANGLE_OF_ATTACK, z, DELAY)
call SetCameraField(CAMERA_FIELD_ZOFFSET,GetCameraField(CAMERA_FIELD_ZOFFSET)+x+GetUnitFlyHeight(CamUnit[i])+NORMAL_HEIGHT-GetCameraTargetPositionZ(),DELAY)
call SetCameraField(CAMERA_FIELD_ROTATION, angle*bj_RADTODEG+180, DELAY)
call SetCameraTargetController(CamUnit[i],0,0,false)
endif
endif
set i = i + 1
endloop
call EnumItemsInRect(bj_mapInitialPlayableArea,null, function ShowAllItems)
set rec = null
endfunction
function ReleaseCameraUnit takes player p returns nothing
if CamUnit[GetPlayerId(p)] != null then
set CamUnit[GetPlayerId(p)] = null
call ResetToGameCameraForPlayer(p,0)
if GetLocalPlayer() == p then
call CameraSetSmoothingFactor(0)
endif
set active = active - 1
if active == 0 then
call PauseTimer(tim)
endif
endif
endfunction
function SetCameraUnit takes unit u, player owner returns nothing
if CamUnit[GetPlayerId(owner)] != null then
call ReleaseCameraUnit(owner)
endif
set CamUnit[GetPlayerId(owner)] = u
set active = active + 1
if active == 1 then
call TimerStart(tim,INTERVAL,true,function Actions)
endif
endfunction
function SetCamDefaultAngleOfAttack takes player p, real a returns nothing
set Aoa[GetPlayerId(p)] = a
endfunction
function SetCamMaxDistance takes player p, real d returns nothing
set Dist[GetPlayerId(p)] = d
endfunction
function SetCamMaxZCheckDistance takes player p, real d returns nothing
set CheckDist[GetPlayerId(p)] = d
endfunction
function GetCameraUnit takes player pl returns unit
return CamUnit[GetPlayerId(pl)]
endfunction
private function Init takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= bj_MAX_PLAYERS
set CamUnit[i] = null
set Aoa[i] = DEFAULT_ANGLE_OF_ATTACK
set Dist[i] = DEFAULT_MAX_DISTANCE
set CheckDist[i] = DEFAULT_MAX_Z_CHECK_DISTANCE
set i = i + 1
endloop
set ite = CreateItem( 'wolg', 0,0 )
call SetItemVisible(ite,false)
endfunction
endlibrary
library KeyboardSystem initializer Init
// Keyboard System by The_Witcher
// This System helps you to get rid of all the triggers
// you would need for creating an effective arrow key
// system.
// This system has aditionally the power to add a key twice press event to a trigger
// you just need to adjust this little variable:
globals
// this is the time the player has to "double press" a key
// if a key is pressed twice in this time the registered triggers are executed
private constant real DELAY = 0.2
endglobals
// Use this function to see which keys are hold down:
//
// IsKeyDown( key, pl) returns boolean
// string player
//
// key can be KEY_LEFT, KEY_RIGHT, KEY_UP or KEY_DOWN
// pl is the player who is checked
// if the function returns true the key is hold down by player pl
//
// And this 2 functions to register a double press event to a trigger
//
// TriggerRegisterKeyDoublePressEvent(t, key)
//
// TriggerRegisterPlayerKeyDoublePressEvent(t, key, pl)
//
// TriggerRegisterKeyDoubleInterruptEvent(t, key)
//
// TriggerRegisterPlayerKeyDoubleInterruptEvent(t, key, pl)
//
// t is the trigger you want to register that event to
// key is the pressed key (again can be KEY_LEFT, KEY_RIGHT, KEY_UP or KEY_DOWN)
// pl is in the second function the player who has to press
// the keys to fire the trigger
// the first function fires the trigger regardless of which player pressed the key
//
//
//--------------Don't edit anything below---------------------------
globals
private timer array time[13]
private trigger array TRIGGERS
private trigger array TRIGGERS2
private integer total = 0
private integer total2 = 0
private integer array PLAYER
private integer array PLAYER2
private string array KEY
private string array KEY2
constant string KEY_LEFT = "left"
constant string KEY_RIGHT = "right"
constant string KEY_UP = "up"
constant string KEY_DOWN = "down"
private hashtable h = InitHashtable()
endglobals
function IsKeyDown takes string key, player pl returns boolean
return LoadBoolean(h,GetPlayerId(pl),StringHash(key))
endfunction
function TriggerRegisterKeyDoublePressEvent takes trigger t, string key returns nothing
set TRIGGERS[total] = t
set KEY[total] = key
set PLAYER[total] = 100
set total = total + 1
endfunction
function TriggerRegisterPlayerKeyDoublePressEvent takes trigger t, string key, player pl returns nothing
set TRIGGERS[total] = t
set KEY[total] = key
set PLAYER[total] = GetPlayerId(pl)
set total = total + 1
endfunction
function TriggerRegisterKeyDoubleInterruptEvent takes trigger t, string key returns nothing
set TRIGGERS2[total2] = t
set KEY2[total2] = key
set PLAYER2[total2] = 100
set total2 = total2 + 1
endfunction
function TriggerRegisterPlayerKeyDoubleInterruptEvent takes trigger t, string key, player pl returns nothing
set TRIGGERS2[total2] = t
set KEY2[total2] = key
set PLAYER2[total2] = GetPlayerId(pl)
set total2 = total2 + 1
endfunction
//! textmacro TriggerActions takes NAME, VarTrue, VarFalse
private function $NAME$press takes nothing returns nothing
local integer i = GetPlayerId(GetTriggerPlayer())
local integer x = 0
call SaveBoolean(h,i,StringHash("$VarTrue$"),true)
call SaveBoolean(h,i,StringHash("$VarFalse$"),false)
if LoadStr(h,i,StringHash("LastKey")) != "$VarTrue$" then
call TimerStart(time[i],0,false,null)
endif
if TimerGetRemaining(time[i]) > 0 and LoadStr(h,i,StringHash("LastKey")) == "$VarTrue$" then
call SaveInteger(h,i,StringHash("Debug"),0)
call SaveBoolean(h,i,StringHash("$VarTrue$Double"),true)
loop
exitwhen x >= total
if TriggerEvaluate(TRIGGERS[x]) and KEY[x] == "$VarTrue$" and (PLAYER[x] == 100 or PLAYER[x] == i) then
call TriggerExecute(TRIGGERS[x])
endif
set x = x + 1
endloop
endif
if LoadInteger(h,i,StringHash("Debug")) == 1 then
call TimerStart(time[i],DELAY,false,null)
else
call SaveInteger(h,i,StringHash("Debug"),1)
endif
call SaveStr(h,i,StringHash("LastKey"),"$VarTrue$")
endfunction
private function $NAME$release takes nothing returns nothing
local integer i = GetPlayerId(GetTriggerPlayer())
local integer x = 0
call SaveBoolean(h,i,StringHash("$VarTrue$"),false)
if LoadBoolean(h,i,StringHash("$VarTrue$Double")) then
call SaveBoolean(h,i,StringHash("$VarTrue$Double"),false)
loop
exitwhen x >= total2
if TriggerEvaluate(TRIGGERS2[x]) and KEY2[x] == "$VarTrue$" and (PLAYER2[x] == 100 or PLAYER2[x] == i) then
call TriggerExecute(TRIGGERS2[x])
endif
set x = x + 1
endloop
endif
endfunction
//! endtextmacro
//! runtextmacro TriggerActions("LEFT","left","right")
//! runtextmacro TriggerActions("RIGHT","right","left")
//! runtextmacro TriggerActions("UP","up","down")
//! runtextmacro TriggerActions("DOWN","down","up")
//! textmacro Initiate takes NAME
set i = 0
set t = CreateTrigger()
set tt = CreateTrigger()
call TriggerAddAction(t,function $NAME$press)
call TriggerAddAction(tt,function $NAME$release)
loop
exitwhen i > 12
call TriggerRegisterPlayerEvent(t,Player(i),EVENT_PLAYER_ARROW_$NAME$_DOWN)
call TriggerRegisterPlayerEvent(tt,Player(i),EVENT_PLAYER_ARROW_$NAME$_UP)
set i = i + 1
endloop
//! endtextmacro
private function Init takes nothing returns nothing
local trigger t
local trigger tt
local integer i
//! runtextmacro Initiate("LEFT")
//! runtextmacro Initiate("RIGHT")
//! runtextmacro Initiate("UP")
//! runtextmacro Initiate("DOWN")
set i = 0
loop
exitwhen i > 12
set time[i] = CreateTimer()
set i = i + 1
endloop
endfunction
endlibrary
library ArrowKeyMovement initializer Init requires KeyboardSystem, ArrowKeyMovementPlugins
// Arrow key movement by The_Witcher
// this system allows each player to control 1 unit
// with his arrow keys even if he doesn't own the unit!
// It features turning on the left and right arrow, walking foreward
// by pressing the up arrow and walking backwards by pressing the down arrow...
//
// You can improve this system with plugins but you need vJass knowledge for that!
//
// --> The TurnRate of a unit inside the object editor STILL influences the turn rate from this system <--
//
// Included functions:
//
// SetMovementUnit ( whichunit, forWhichPlayer, walkAnimationIndex )
// unit player integer
// this gives the player the arrow key movement control over the unit
// while the unit moves the animation of the given index is played
// (just try around to find the index... start at 0 and increase
// by 1 until you find the walk index of that unit)
//
//
// ReleaseMovementUnit ( fromWhichPlayer )
// player
// this function removes the control from a player
//
//
// GetMovementUnit ( fromWhichPlayer ) returns unit
// player
// I think its self explaining...
//
//
// SetMovementUnitAnimation ( fromWhichPlayer, animation )
// player integer
// this function allows ingame changing of the played animation of a unit
// ------- SETUP PART ---------
globals
// the timer interval... increase if laggy
private constant real INTERVAL = 0.04
// the facing change in degrees each interval (must be a positive value)
private constant real DEFAULT_VIEW_CHANGE = 4
// when you move backwards you move slower than normal...
private constant real BACKWARDS_MOVING_FACTOR = 0.7
// if the unit turns it will turn faster the longer it does...
// some people may need that but then it should be 1.02 (1.0 means disabled)
private constant real TURN_ACCELERATION = 1
// (can only be 1 or -1) if you walk backwards you have 2 ways of turning
// 1. way: pressing left will make the char turn left
// 2. way: pressing left will make the char turn so he moves to the left
private constant integer REVERSED_BACKWARDS_MOVING = 1
endglobals
// whenever this function returns false for a unit it won't be moved even if the player
// presses the keys! change to create your own "No Movement" conditions
private function MoveConditions takes unit u returns boolean
return not IsUnitType(u,UNIT_TYPE_SLEEPING) and not IsUnitType(u,UNIT_TYPE_STUNNED) and not (IsUnitType(u,UNIT_TYPE_DEAD) or GetUnitTypeId(u) == 0 )
endfunction
// --------- don't modify anything below this line ------------
struct ArrowKeyMovement
private static ArrowKeyMovement array all [12] // = bj_MAX_PLAYERS
private static timer tim
integer walking
unit u
integer animation
real SpeedFactor
real ViewChange
real SpecialDirection
boolean SpecialDirectionActive
static method operator [] takes player p returns ArrowKeyMovement
local integer i = GetPlayerId(p)
if .all[i] == 0 then
set .all[i] = ArrowKeyMovement.create()
set .all[i].SpeedFactor = 1
set .all[i].SpecialDirection = 0
set .all[i].SpecialDirectionActive = false
set .all[i].ViewChange = DEFAULT_VIEW_CHANGE
endif
return .all[i]
endmethod
private static method Walking takes nothing returns nothing
local integer i = 0
local real x
local real y
local real X
local real Y
local boolean boolX
local boolean boolY
local boolean left
local boolean right
local boolean up
local boolean down
local ArrowKeyMovement mov
loop
exitwhen i >= 12 // = bj_MAX_PLAYERS
set mov = .all[i]
if mov.u != null and MoveConditions(mov.u) then
// special movement <-- plugins
if mov.SpecialDirectionActive then
if mov.walking != 1 then
call SetUnitTimeScale(mov.u,mov.SpeedFactor)
call SetUnitAnimationByIndex(mov.u,mov.animation)
set mov.walking = 1
else
call SetUnitTimeScale(mov.u,mov.SpeedFactor)
endif
set x = GetUnitX(mov.u)
set y = GetUnitY(mov.u)
set X = x + GetUnitMoveSpeed(mov.u)*INTERVAL * Cos(mov.SpecialDirection*bj_DEGTORAD) * mov.SpeedFactor
set Y = y + GetUnitMoveSpeed(mov.u)*INTERVAL * Sin(mov.SpecialDirection*bj_DEGTORAD) * mov.SpeedFactor
call SetUnitPosition(mov.u,X,Y)
if (RAbsBJ(GetUnitX(mov.u)-X)>0.5)or(RAbsBJ(GetUnitY(mov.u)-Y)>0.5)then
call SetUnitPosition(mov.u,X,y)
set boolX = RAbsBJ(GetUnitX(mov.u)-X)<=0.5
call SetUnitPosition(mov.u,x,Y)
set boolY = RAbsBJ(GetUnitY(mov.u)-Y)<=0.5
if boolX then
call SetUnitPosition(mov.u,X,y)
elseif boolY then
call SetUnitPosition(mov.u,x,Y)
else
call SetUnitPosition(mov.u,x,y)
endif
endif
else
// Normal movement
set left = IsKeyDown(KEY_LEFT,Player(i))
set right = IsKeyDown(KEY_RIGHT,Player(i))
set up = IsKeyDown(KEY_UP,Player(i))
set down = IsKeyDown(KEY_DOWN,Player(i))
//right down
if right then
if down then
call SetUnitFacing(mov.u,GetUnitFacing(mov.u)-mov.ViewChange * -REVERSED_BACKWARDS_MOVING)
else
call SetUnitFacing(mov.u,GetUnitFacing(mov.u)-mov.ViewChange)
endif
set mov.ViewChange = mov.ViewChange * TURN_ACCELERATION
elseif not left then
set mov.ViewChange = DEFAULT_VIEW_CHANGE
endif
//left down
if left then
if down then
call SetUnitFacing(mov.u,GetUnitFacing(mov.u)+mov.ViewChange * -REVERSED_BACKWARDS_MOVING)
else
call SetUnitFacing(mov.u,GetUnitFacing(mov.u)+mov.ViewChange)
endif
set mov.ViewChange = mov.ViewChange * TURN_ACCELERATION
elseif not right then
set mov.ViewChange = DEFAULT_VIEW_CHANGE
endif
if mov.ViewChange > 179 then
set mov.ViewChange = 179
endif
//up down
if up then
if mov.walking != 1 then
call SetUnitTimeScale(mov.u,mov.SpeedFactor)
call SetUnitAnimationByIndex(mov.u,mov.animation)
set mov.walking = 1
else
call SetUnitTimeScale(mov.u,mov.SpeedFactor)
endif
set x = GetUnitX(mov.u)
set y = GetUnitY(mov.u)
set X = x + GetUnitMoveSpeed(mov.u)*INTERVAL * Cos(GetUnitFacing(mov.u)*bj_DEGTORAD) * mov.SpeedFactor
set Y = y + GetUnitMoveSpeed(mov.u)*INTERVAL * Sin(GetUnitFacing(mov.u)*bj_DEGTORAD) * mov.SpeedFactor
//down down
elseif down then
if mov.walking != 2 then
call SetUnitTimeScale(mov.u,-BACKWARDS_MOVING_FACTOR * mov.SpeedFactor)
call SetUnitAnimationByIndex(mov.u,mov.animation)
set mov.walking = 2
else
call SetUnitTimeScale(mov.u,-BACKWARDS_MOVING_FACTOR * mov.SpeedFactor)
endif
set x = GetUnitX(mov.u)
set y = GetUnitY(mov.u)
set X = x - GetUnitMoveSpeed(mov.u) * INTERVAL * Cos(GetUnitFacing(mov.u)*bj_DEGTORAD) * BACKWARDS_MOVING_FACTOR * mov.SpeedFactor
set Y = y - GetUnitMoveSpeed(mov.u) * INTERVAL * Sin(GetUnitFacing(mov.u)*bj_DEGTORAD) * BACKWARDS_MOVING_FACTOR * mov.SpeedFactor
endif
//move
if down or up then
call SetUnitPosition(mov.u,X,Y)
if (RAbsBJ(GetUnitX(mov.u)-X)>0.5)or(RAbsBJ(GetUnitY(mov.u)-Y)>0.5)then
call SetUnitPosition(mov.u,X,y)
set boolX = RAbsBJ(GetUnitX(mov.u)-X)<=0.5
call SetUnitPosition(mov.u,x,Y)
set boolY = RAbsBJ(GetUnitY(mov.u)-Y)<=0.5
if boolX then
call SetUnitPosition(mov.u,X,y)
elseif boolY then
call SetUnitPosition(mov.u,x,Y)
else
call SetUnitPosition(mov.u,x,y)
endif
endif
else
if mov.walking != 0 then
call SetUnitAnimation(mov.u,"stand")
call SetUnitTimeScale(mov.u,1)
set mov.walking = 0
endif
endif
endif
endif
set i = i + 1
endloop
endmethod
static method onInit takes nothing returns nothing
set .tim = CreateTimer()
call TimerStart(.tim,INTERVAL,true,function ArrowKeyMovement.Walking)
endmethod
endstruct
function GetMovementUnit takes player p returns unit
return ArrowKeyMovement[p].u
endfunction
function SetMovementUnitAnimation takes player p, integer animation returns nothing
set ArrowKeyMovement[p].animation = animation
endfunction
function ReleaseMovementUnit takes player p returns nothing
if ArrowKeyMovement[p].u != null then
set ArrowKeyMovement[p].walking = 0
call SetUnitAnimation(ArrowKeyMovement[p].u,"stand")
call SetUnitTimeScale(ArrowKeyMovement[p].u,1)
set ArrowKeyMovement[p].u = null
endif
endfunction
function SetMovementUnit takes unit u, player p, integer anim returns nothing
if u == null then
call ReleaseMovementUnit(p)
return
endif
if ArrowKeyMovement[p].u != null then
call ReleaseMovementUnit(p)
endif
call SetUnitAnimation(ArrowKeyMovement[p].u,"stand")
set ArrowKeyMovement[p].u = u
set ArrowKeyMovement[p].animation = anim
endfunction
//! runtextmacro ArrowKeyMovement_Plugins_Functions()
private function Init takes nothing returns nothing
//! runtextmacro Init_ArrowKeyMovement_Plugins()
endfunction
endlibrary
library ArrowKeyMovementPlugins
// code your own plugins for my Arrow key movement system!
// how you do that is explained in detail in the "How to use the Movement System Plugins"
// comment included in this map
//
//
// the plugins I coded for the test map are:
// 1. running fast/dashing when double pressing up
// 2. turning around (180°) when double pressing down
// 3. moving left without changing face direction when double pressing left
// 4. moving right without changing face direction when double pressing right
//! textmacro Init_ArrowKeyMovement_Plugins
local trigger t
// This is the initialization for turning around on double down press
set t = CreateTrigger()
call TriggerAddAction(t, function OnDoubleDownPress)
call TriggerRegisterKeyDoublePressEvent(t,KEY_DOWN)
// This is the initialization for dashing on double up press
set t = CreateTrigger()
call TriggerAddAction(t, function OnDoubleUpPress)
call TriggerRegisterKeyDoublePressEvent(t,KEY_UP)
// This is the initialization for sliding left on double left press
set t = CreateTrigger()
call TriggerAddAction(t, function OnDoubleLeftPress)
call TriggerRegisterKeyDoublePressEvent(t,KEY_LEFT)
// This is the initialization for sliding right on double right press
set t = CreateTrigger()
call TriggerAddAction(t, function OnDoubleRightPress)
call TriggerRegisterKeyDoublePressEvent(t,KEY_RIGHT)
// This is the initialization for stoping the dash of double up press
set t = CreateTrigger()
call TriggerAddAction(t, function OnDoubleUpRelease)
call TriggerRegisterKeyDoubleInterruptEvent(t,KEY_UP)
// This is the initialization for stoping slide of double left press
set t = CreateTrigger()
call TriggerAddAction(t, function OnDoubleLeftRelease)
call TriggerRegisterKeyDoubleInterruptEvent(t,KEY_LEFT)
// This is the initialization for stoping slide of double right press
set t = CreateTrigger()
call TriggerAddAction(t, function OnDoubleRightRelease)
call TriggerRegisterKeyDoubleInterruptEvent(t,KEY_RIGHT)
//! endtextmacro
//! textmacro ArrowKeyMovement_Plugins_Functions
// This is the function for turning around on double down press
private function OnDoubleDownPress takes nothing returns nothing
local ArrowKeyMovement mov = ArrowKeyMovement[GetTriggerPlayer()]
set mov.SpecialDirectionActive = false
call SetUnitFacing(mov.u,GetUnitFacing(mov.u)-180)
endfunction
// This is the function for dashing on double up press
private function OnDoubleUpPress takes nothing returns nothing
local ArrowKeyMovement mov = ArrowKeyMovement[GetTriggerPlayer()]
set mov.SpecialDirectionActive = false
set mov.SpeedFactor = 2
endfunction
// This is the function for sliding left on double left press
private function OnDoubleLeftPress takes nothing returns nothing
local ArrowKeyMovement mov = ArrowKeyMovement[GetTriggerPlayer()]
set mov.SpecialDirectionActive = true
set mov.SpecialDirection = GetUnitFacing(mov.u) + 90
set mov.SpeedFactor = 0.6
endfunction
// This is the function for sliding right on double right press
private function OnDoubleRightPress takes nothing returns nothing
local ArrowKeyMovement mov = ArrowKeyMovement[GetTriggerPlayer()]
set mov.SpecialDirectionActive = true
set mov.SpecialDirection = GetUnitFacing(mov.u) - 90
set mov.SpeedFactor = 0.6
endfunction
// This is the function for stoping the dash of double up press
private function OnDoubleUpRelease takes nothing returns nothing
set ArrowKeyMovement[GetTriggerPlayer()].SpeedFactor = 1
endfunction
// This is the function for stoping slide of double left press
private function OnDoubleLeftRelease takes nothing returns nothing
local ArrowKeyMovement mov = ArrowKeyMovement[GetTriggerPlayer()]
set mov.SpecialDirectionActive = false
set mov.SpeedFactor = 1
endfunction
// This is the function for stoping slide of double right press
private function OnDoubleRightRelease takes nothing returns nothing
local ArrowKeyMovement mov = ArrowKeyMovement[GetTriggerPlayer()]
set mov.SpecialDirectionActive = false
set mov.SpeedFactor = 1
endfunction
//! endtextmacro
endlibrary