library CAMS requires T32, TimerUtils
/*
*********************************************
* Advanced Combat and Movement System *
* v 1.3 by 3yeballz *
*********************************************
***************************************************************************************************************
* latest version: www.hiveworkshop.com/forums/spells-569/a-191033/ *
* Timer32 by Jesus4Lyf: www.thehelper.net/forums/showthread.php/132538-Timer32 *
* TimerUtils by Vexorian: www.wc3c.net/showthread.php?t=101322 *
***************************************************************************************************************
******************************************************* API *******************************************************************
*
* function RegisterUnitArrowKey takes unit u, player p, integer anim, boolean jump, integer unitid, integer jumpanim, real atkrange returns nothing
* u: unit that should register in the system
* p: owner of registered unit
* anim: animation id for walking
* jump: enable/disable jump ability
* unitid: rawcode of collision detection unit. only necessary if jump == true. set to 0 if not needed
* jumpanim: animation id for jumping. only necessary if jump == true. set to 0 if not needed
* atkrange : attack range of the unit. attack range in object editor must be bigger. only necessary if you use combat mode
*
* function UnregisterUnitArrowKey takes player p returns nothing
* Unregisters the currently registered unit for player p.
* You MUST unregister a unit before registering a new one.
*
* function GetRegisteredUnitArrowKey takes player p returns unit
* Returns the registered unit from player p.
* If there is no unit registered it returns null.
*
* function GetUnitTarget takes unit u returns unit
* Returns the targeted unit while using the combat system.
* Returns null if unit u is not registered.
*
* function GetUnitTargetByPlayer takes player p returns unit
* Returns the targeted unit by the currently registered unit from player p.
* Returns null if there is no registered unit for player p.
*
* function GetUnitFTarget takes unit u returns unit
* Returns the friendly targeted unit while using the combat system.
* Returns null if unit u is not registered.
*
* function GetUnitFTargetByPlayer takes player p returns unit
* Returns the friendly targeted unit by the currently registered unit from player p.
* Returns null if there is no registered unit for player p.
*
* function IsUnitRegisteredArrowKey takes unit u returns boolean
* Use this to check if a unit is registered in the system.
*
* function IsUnitJumping takes unit u returns boolean
* Returns true if the unit is jumping and if it is the registered one.
* You should only unregister a unit if it's not jumping.
*
* function CanUnitJump takes unit u returns boolean
* Returns true if the unit is able to jump.
* Returns false if it's not the registered one.
*
* function CanUnitJumpByPlayer takes player p returns boolean
* Returns true if the registered unit by player p is able to jump.
* Returns false if there is no unit registered.
*
* function SetMoveSpeed takes unit u, real r1, real r2, real r3, real r4, real t returns nothing
* Changes the move speed of unit u to r1.
* r2: move speed side, r3: move speed back (must be negative), r4: move speed run
* t: turn speed in degrees per interval
* Input of 0 will be ignored. Does nothing if unit u is not registered.
*
* function SetMoveSpeedByPlayer takes player p, real r1, real r2, real r3, real r4, real t returns nothing
* Changes the move speed of player p's registered unit to r1.
* r2: move speed side, r3: move speed back (must be negative), r4: move speed run
* t: turn speed in degrees per interval
* Input of 0 will be ignored. Does nothing if there is no unit registered for player p.
*
* function SetAnimSpeed takes unit u, real r1, real r2, real r3, real r4 returns nothing
* Changes the animation speed of unit u to r1.
* r2: animation speed side, r3: animation speed back, r4: animation speed run
* Input of 0 will be ignored. Does nothing if unit u is not registered.
*
* function SetAnimSpeedByPlayer takes player p, real r1, real r2, real r3, real r4 returns nothing
* Changes the animation speed of player p's registered unit to r1.
* r2: animation speed side, r3: animation speed back, r4: animation speed run
* Input of 0 will be ignored. Does nothing if there is no unit registered for player p.
*
* function SetUnitXArrowKey takes unit u, real r returns nothing
* Sets the x-location of unit u, if it is registered.
*
* function SetUnitXByPlayer takes player p, real r returns nothing
* Sets the x-location of player p's registered unit, if there is a unit registered.
*
* function SetUnitYArrowKey takes unit u, real r returns nothing
* Sets the y-location of unit u, if it is registered.
*
* function SetUnitYByPlayer takes player p, real r returns nothing
* Sets the y-location of player p's registered unit, if there is a unit registered.
*
* function SetUnitFacingArrowKey takes unit u, real r returns nothing
* Sets the facing of unit u, if it is registered.
*
* function SetUnitFacingByPlayer takes player p, real r returns nothing
* Sets the facing of player p's registered unit, if there is a unit registered.
*
* function ResetTarget takes unit u returns nothing
* Resets all target data of unit u, if it is registered.
*
* function ResetTargetByPlayer takes player p returns nothing
* Resets all target data of player p's registered unit, if there is a unit registered.
*
* function DisableMove takes unit u, real duration returns nothing
* Disables the ability to move for unit u for a given period of time
*
* function DisableMoveByPlayer takes player p, real duration returns nothing
* Disables the ability to move for player p's registered unit for a given period of time
*
*******************************************************************************************************************************
************************************************ User Configuration **********************************************************/
globals
// if you want the system to deal with the whole movement then set this to true
// notice that your character cannot e.g. move to a target if it detects one
// and you cannot use any rightclicks on the ground or target
private constant boolean NOMOUSE = true
// enables/disables combat mode and the use of all abilities that go with it
private constant boolean COMBAT_MODE = true
// the timer interval to change facing
private constant real INTERVAL = 0.03125
// the default turn speed in degrees per interval
private constant real TURN_SPEED = 4.
// the default move speed per interval. unit's movement speed is MOVE_SPEED/INTERVAL
private constant real MOVE_SPEED = 9.
private constant real MOVE_SPEED_SIDE = 8.
private constant real MOVE_SPEED_BACK = -6.
private constant real MOVE_SPEED_RUN = 12.
// default animation speed for different movement states
private constant real ANIM_SPEED = 1.
private constant real ANIM_SPEED_SIDE = 0.7
private constant real ANIM_SPEED_BACK = -0.6
private constant real ANIM_SPEED_RUN = 1.3
// the angle facing change when moving sidewards + up/down
// the bigger the value the less you can move up/down while moving sidewards
// must be between 0 and 90
private constant real LEFT_SIDE_FACING = -45.
private constant real RIGHT_SIDE_FACING = 45.
// maximum interval to detect a doubleclick
private constant real DBLCLICKTIME = 0.3
// those constants are only important if you use the jump ability
// if COMBAT_MODE: rawcode of sold unit to trigger jump
// else: rawcode for jump ability
private constant integer JUMPID = 'e001'
// maximum distance tolerance to detect landing point, the lower the more accurate
// should be bigger than 1 to work correctly
private constant real JUMPTOLERANCE = 3.
// default callback count for one jump
// increasing this will increase the time in air
private constant integer JUMPCOUNT = 40
// default jump height after JUMPCOUNT/2 callbacks. local maximum of parabola
private constant real JUMPHEIGHT = 220.
// combat mode related constants
// rawcode of sold unit to trigger selection
private constant integer SELECTID = 'e003'
// rawcode of sold unit to trigger friendly selection
private constant integer FSELECTID = 'e006'
// rawcode of sold unit to trigger unselection
private constant integer UNSELECTID = 'e004'
// rawcode of sold unit to trigger attack on/off
private constant integer ATTACKID = 'e005'
// maximum number of targets to switch
private constant integer ARRAY_SIZE = 100
// maximum distance to check for new enemies
private constant real COMBATRADIUS = 1400.
// string used to detect current target while attack mode off
private constant string COMBAT_ON = "Abilities\\Spells\\Orc\\SpiritLink\\SpiritLinkTarget.mdl"
// string used to detect current target while attack mode on
private constant string COMBAT_OFF = "war3mapImported\\Haste.mdx"
// attachment point for the effect to detect current target
private constant string ATTACHPNT = "chest"
endglobals
/*************************************************** System Code *************************************************************/
private module CAMSInit
private static method onInit takes nothing returns nothing
local trigger t1 = CreateTrigger()
local trigger t2 = CreateTrigger()
local trigger t3 = CreateTrigger()
local trigger t4 = CreateTrigger()
local trigger t5 = CreateTrigger()
local trigger t6 = CreateTrigger()
local trigger t7 = CreateTrigger()
local trigger t8 = CreateTrigger()
local trigger t9 = CreateTrigger()
static if COMBAT_MODE then
local trigger t10 = CreateTrigger()
local trigger t11 = CreateTrigger()
local trigger t12 = CreateTrigger()
local trigger t13 = CreateTrigger()
endif
local integer i = 0
loop
exitwhen i > 11
if GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i))==MAP_CONTROL_USER then
call TriggerRegisterPlayerEvent(t1, Player(i), EVENT_PLAYER_ARROW_UP_DOWN)
call TriggerRegisterPlayerEvent(t2, Player(i), EVENT_PLAYER_ARROW_UP_UP)
call TriggerRegisterPlayerEvent(t3, Player(i), EVENT_PLAYER_ARROW_LEFT_DOWN)
call TriggerRegisterPlayerEvent(t4, Player(i), EVENT_PLAYER_ARROW_LEFT_UP)
call TriggerRegisterPlayerEvent(t5, Player(i), EVENT_PLAYER_ARROW_RIGHT_DOWN)
call TriggerRegisterPlayerEvent(t6, Player(i), EVENT_PLAYER_ARROW_RIGHT_UP)
call TriggerRegisterPlayerEvent(t7, Player(i), EVENT_PLAYER_ARROW_DOWN_DOWN)
call TriggerRegisterPlayerEvent(t8, Player(i), EVENT_PLAYER_ARROW_DOWN_UP)
static if COMBAT_MODE then
call TriggerRegisterPlayerUnitEvent(t9, Player(i), EVENT_PLAYER_UNIT_SELL, null)
call TriggerRegisterPlayerUnitEvent(t10, Player(i), EVENT_PLAYER_UNIT_SELL, null)
call TriggerRegisterPlayerUnitEvent(t11, Player(i), EVENT_PLAYER_UNIT_SELL, null)
call TriggerRegisterPlayerUnitEvent(t12, Player(i), EVENT_PLAYER_UNIT_SELL, null)
call TriggerRegisterPlayerUnitEvent(t13, Player(i), EVENT_PLAYER_UNIT_SELL, null)
else
call TriggerRegisterPlayerUnitEvent(t9, Player(i), EVENT_PLAYER_UNIT_SPELL_CAST, null)
endif
endif
set i = i + 1
endloop
call TriggerAddCondition(t1, Filter(function thistype.UpDown))
call TriggerAddCondition(t2, Filter(function thistype.UpUp))
call TriggerAddCondition(t3, Filter(function thistype.LeftDown))
call TriggerAddCondition(t4, Filter(function thistype.LeftUp))
call TriggerAddCondition(t5, Filter(function thistype.RightDown))
call TriggerAddCondition(t6, Filter(function thistype.RightUp))
call TriggerAddCondition(t7, Filter(function thistype.DownDown))
call TriggerAddCondition(t8, Filter(function thistype.DownUp))
call TriggerAddCondition(t9, Filter(function thistype.JumpInit))
static if COMBAT_MODE then
call TriggerAddCondition(t10, Filter(function thistype.SelectInit))
call TriggerAddCondition(t11, Filter(function thistype.FSelectInit))
call TriggerAddCondition(t12, Filter(function thistype.Unselect))
call TriggerAddCondition(t13, Filter(function thistype.StartAttack))
endif
set t1 = null
set t2 = null
set t3 = null
set t4 = null
set t5 = null
set t6 = null
set t7 = null
set t8 = null
set t9 = null
static if COMBAT_MODE then
set t10 = null
set t11 = null
set t12 = null
set t13 = null
set cfilter = Filter(function thistype.CheckForNewEnemy)
set fcfilter = Filter(function thistype.CheckForNewAlly)
set tfilter = Filter(function thistype.TargetDies)
set ftfilter = Filter(function thistype.FTargetDies)
endif
static if NOMOUSE then
set filter = Filter(function thistype.DisableMove)
else
set filter = Filter(function thistype.NewOrder)
endif
set dfilter = Filter(function thistype.UnitDies)
set rfilter = Filter(function thistype.UnitRevives)
static if LIBRARY_Event then
set MOVE = CreateEvent()
endif
endmethod
endmodule
struct CAMS
private static boolexpr filter
private static boolexpr dfilter
private static boolexpr rfilter
private static group g = CreateGroup()
private static boolean dblclicked = false
private static real newx = 0.
private static real newy = 0.
private static real newz = 0.
private static real jumpfactor = JUMPHEIGHT / (JUMPCOUNT/2 * JUMPCOUNT/2)
private static boolean boolx = false
private static boolean booly = false
private static integer playerid = 0
private static location Loc = Location(0,0)
static if COMBAT_MODE then
private static real newfacing = 0.
private static boolexpr cfilter
private static boolexpr fcfilter
private static boolexpr tfilter
private static boolexpr ftfilter
private static unit selectedunit = null
private static integer selectcount = 0
private static unit array selectable [8191]
endif
// general boolean instance variables
readonly boolean inuse
private boolean up
private boolean left
private boolean right
private boolean down
private boolean break
private boolean disabled
// movement system instance variables
private unit u
private player p
private integer anim
private real x
private real y
private real z
private real facing
readonly real speed
readonly real ms
readonly real mss
readonly real msb
readonly real msr
readonly real ts
readonly real as
readonly real ass
readonly real asb
readonly real asr
static if not NOMOUSE then
private boolean order
endif
private boolean running
private boolean sidewards
private real sfacing
private trigger trg
private trigger death
private trigger revive
// jump system instance variables
private unit cunit
private boolean jump
private boolean isjumping
private integer janim
private real jx
private real jy
private real jh
private real jf
private integer jc
private integer jcmax
// combat system instance variables
static if COMBAT_MODE then
private unit target
private unit ftarget
private unit array targeted [ARRAY_SIZE]
private unit array ftargeted [ARRAY_SIZE]
private integer tc
private integer ftc
private integer tp
private integer ftp
private effect selection
private boolean atk
private real atkrange
private boolean attacking
private trigger td
private trigger ftd
endif
// timer related instance variables
private timer t
private timer sidetimer
private timer dtimer
private timer dblclick
private integer timerstate
// timerstate:
// 1 -> Up
// 2 -> Left
// 3 -> Right
// 4 -> Down
static if NOMOUSE then
private static method DisableMove takes nothing returns boolean
if GetIssuedOrderId() == OrderId("move") or GetIssuedOrderId() == OrderId("smart") or GetIssuedOrderId() == OrderId("attack") then
set playerid = GetPlayerId(GetTriggerPlayer())
call TimerStart(CreateTimer(), 0., false, function thistype.Order)
endif
return false
endmethod
private static method Order takes nothing returns nothing
call IssueImmediateOrder(thistype(playerid).u, "stop")
endmethod
else
private static method NewOrder takes nothing returns boolean
local thistype this
if GetIssuedOrderId() == OrderId("move") or GetIssuedOrderId() == OrderId("smart") or GetIssuedOrderId() == OrderId("attack") then
set this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if .isjumping then
return false
endif
set .order = true
static if COMBAT_MODE then
set .atk = false
set .sidewards = false
if .attacking then
set .target = null
set .tc = 1
set .tp = 1
call DestroyEffect(.selection)
set .selection = null
set .attacking = false
endif
if GetOrderTargetUnit() != null then
if IsUnitEnemy(GetOrderTargetUnit(), Player(id-1)) then
set .target = GetOrderTargetUnit()
set .atk = true
set .sidewards = true
call DestroyEffect(.selection)
if GetLocalPlayer() == Player(id-1) then
set .selection = AddSpecialEffectTarget(COMBAT_ON, .target, ATTACHPNT)
else
set .selection = AddSpecialEffectTarget("", .target, ATTACHPNT)
endif
endif
endif
endif
endif
return false
endmethod
endif
private static method UnitDies takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetOwningPlayer(GetTriggerUnit()))+1)
set .inuse = false
set .speed = 0.
set .running = false
set .sidewards = false
call SetUnitFlyHeight(.u, 0., 0.)
set .isjumping = false
static if COMBAT_MODE then
if .target != null then
set .target = null
set .tc = 1
set .tp = 1
call DestroyEffect(.selection)
set .selection = null
set .atk = false
set .attacking = false
call DestroyTrigger(.td)
call DestroyTrigger(.ftd)
endif
if .ftarget != null then
set .ftarget = null
set .ftc = 1
set .ftp = 1
endif
endif
return false
endmethod
private static method UnitRevives takes nothing returns boolean
set thistype(GetPlayerId(GetOwningPlayer(GetTriggerUnit()))+1).inuse = true
return false
endmethod
private method periodic takes nothing returns nothing
if not .inuse then
return
endif
if .isjumping then
set .jc = .jc + 1
set .x = .x + Cos(.jf) * .speed
set .y = .y + Sin(.jf) * .speed
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
call MoveLocation(Loc, .x, .y)
set .jh = -jumpfactor * (.jc - JUMPCOUNT/2) * (.jc - JUMPCOUNT/2) + JUMPHEIGHT - GetLocationZ(Loc) + .z
call SetUnitFlyHeight(.u, .jh, 0.)
static if COMBAT_MODE then
if .atk then
set newx = .x - GetUnitX(.target)
set newy = .y - GetUnitY(.target)
if .atkrange > SquareRoot(newx*newx+newy*newy) then
call DisableTrigger(.trg)
call IssueTargetOrder(.u, "attack", .target)
call EnableTrigger(.trg)
set .attacking = true
else
set .attacking = false
call IssueImmediateOrder(.u, "stop")
endif
else
call IssueImmediateOrder(.u, "stop")
endif
else
call IssueImmediateOrder(.u, "stop")
endif
if .jc == .jcmax then
call SetUnitFlyHeight(.u, 0., 0.)
call SetUnitPosition(.cunit, .x, .y)
set .x = GetUnitX(.cunit)
set .y = GetUnitY(.cunit)
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
set .jc = 0
set .isjumping = false
//! textmacro InitMovement
if .sidewards then
if .right then
if .up then
set .speed = .mss
set .sfacing = .facing - RIGHT_SIDE_FACING
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
elseif .down then
set .speed = .msb
set .sfacing = .facing + RIGHT_SIDE_FACING
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
else
set .speed = .mss
set .sfacing = .facing - 90.
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
elseif .left then
if .up then
set .speed = .mss
set .sfacing = .facing - LEFT_SIDE_FACING
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
elseif .down then
set .speed = .msb
set .sfacing = .facing + LEFT_SIDE_FACING
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
else
set .speed = .mss
set .sfacing = .facing + 90.
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
elseif .up then
set .sidewards = false
set .speed = .ms
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .as)
elseif .down then
set .sidewards = false
set .speed = .msb
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
else
set .sidewards = false
set .speed = 0.
call SetUnitAnimation(.u, "stand")
call SetUnitTimeScale(.u, .as)
endif
else
if .up then
call SetUnitAnimationByIndex(.u, .anim)
if .running then
set .speed = .msr
call SetUnitTimeScale(.u, .asr)
else
set .speed = .ms
call SetUnitTimeScale(.u, .as)
endif
if .right then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.RightPeriodic)
elseif .left then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.LeftPeriodic)
endif
elseif .down then
set .speed = .msb
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
if .right then
set .sidewards = true
set .sfacing = .facing + RIGHT_SIDE_FACING
elseif .left then
set .sidewards = true
set .sfacing = .facing + LEFT_SIDE_FACING
endif
else
set .speed = 0.
set .running = false
call SetUnitAnimation(.u, "stand")
if .right then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.RightPeriodic)
elseif .left then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.LeftPeriodic)
endif
endif
endif
if .atk then
set .sidewards = true
endif
//! endtextmacro
//! runtextmacro InitMovement()
endif
else
if .disabled then
return
endif
static if NOMOUSE then
//! textmacro Movement
static if COMBAT_MODE then
if .atk then
if .right then
if .up then
if .speed < (.mss-0.3) or .speed > (.mss+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
set .speed = .mss
set .sfacing = .facing - RIGHT_SIDE_FACING
elseif .down then
if .speed < (.msb-0.3) or .speed > (.msb+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
set .speed = .msb
set .sfacing = .facing + RIGHT_SIDE_FACING
else
if .speed < (.mss-0.3) or .speed > (.mss+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
set .speed = .mss
set .sfacing = .facing - 90.
endif
elseif .left then
if .up then
if .speed < (.mss-0.3) or .speed > (.mss+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
set .speed = .mss
set .sfacing = .facing - LEFT_SIDE_FACING
elseif .down then
if .speed < (.msb-0.3) or .speed > (.msb+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
set .speed = .msb
set .sfacing = .facing + LEFT_SIDE_FACING
else
if .speed < (.mss-0.3) or .speed > (.mss+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
endif
set .speed = .mss
set .sfacing = .facing + 90.
endif
elseif .up then
if .speed < (.ms-0.3) or .speed > (.ms+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .as)
endif
set .speed = .ms
set .sfacing = .facing
elseif .down then
if .speed < (.msb-0.3) or .speed > (.msb+0.3) then
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
endif
set .speed = .msb
set .sfacing = .facing
else
if .speed < -0.3 or .speed > 0.3 then
call SetUnitAnimation(.u, "stand")
call SetUnitTimeScale(.u, .as)
endif
set .speed = 0.
endif
if .speed > 0. or .speed < 0. then
set newx = .x + Cos(.sfacing * bj_DEGTORAD) * .speed
set newy = .y + Sin(.sfacing * bj_DEGTORAD) * .speed
if .jump then
call SetUnitPosition(.cunit, newx, newy)
if (RAbsBJ(GetUnitX(.cunit)-newx) > 0.5) or (RAbsBJ(GetUnitY(.cunit)-newy) > 0.5) then
call SetUnitPosition(.cunit, newx, .y)
set boolx = RAbsBJ(GetUnitX(.cunit)-newx) <= 0.5
call SetUnitPosition(.cunit, .x, newy)
set booly = RAbsBJ(GetUnitY(.cunit)-newy) <= 0.5
if boolx then
set .x = newx
elseif booly then
set .y = newy
endif
else
set .x = newx
set .y = newy
endif
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
else
call SetUnitPosition(.u, newx, newy)
if (RAbsBJ(GetUnitX(.u)-newx) > 0.5) or (RAbsBJ(GetUnitY(.u)-newy) > 0.5) then
call SetUnitPosition(.u, newx, .y)
set boolx = RAbsBJ(GetUnitX(.u)-newx) <= 0.5
call SetUnitPosition(.u, .x, newy)
set booly = RAbsBJ(GetUnitY(.u)-newy) <= 0.5
if boolx then
set .x = newx
elseif booly then
set .y = newy
endif
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
else
set .x = newx
set .y = newy
endif
endif
endif
set newfacing = Atan2(GetUnitY(.target) - .y, GetUnitX(.target) - .x) * bj_RADTODEG
set .sfacing = .sfacing + newfacing - .facing
set .facing = newfacing
call SetUnitFacing(.u, .facing)
set newx = .x - GetUnitX(.target)
set newy = .y - GetUnitY(.target)
if .atkrange > SquareRoot(newx*newx+newy*newy) then
call DisableTrigger(.trg)
call IssueTargetOrder(.u, "attack", .target)
call EnableTrigger(.trg)
call SetUnitTimeScale(.u, .as)
set .attacking = true
else
set .attacking = false
call IssueImmediateOrder(.u, "stop")
endif
else
if .speed > 0. or .speed < 0. then
if .sidewards then
set newx = .x + Cos(.sfacing * bj_DEGTORAD) * .speed
set newy = .y + Sin(.sfacing * bj_DEGTORAD) * .speed
else
set newx = .x + Cos(.facing * bj_DEGTORAD) * .speed
set newy = .y + Sin(.facing * bj_DEGTORAD) * .speed
call SetUnitFacing(.u, .facing)
endif
if .jump then
call SetUnitPosition(.cunit, newx, newy)
if (RAbsBJ(GetUnitX(.cunit)-newx) > 0.5) or (RAbsBJ(GetUnitY(.cunit)-newy) > 0.5) then
call SetUnitPosition(.cunit, newx, .y)
set boolx = RAbsBJ(GetUnitX(.cunit)-newx) <= 0.5
call SetUnitPosition(.cunit, .x, newy)
set booly = RAbsBJ(GetUnitY(.cunit)-newy) <= 0.5
if boolx then
set .x = newx
elseif booly then
set .y = newy
endif
else
set .x = newx
set .y = newy
endif
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
else
call SetUnitPosition(.u, newx, newy)
if (RAbsBJ(GetUnitX(.u)-newx) > 0.5) or (RAbsBJ(GetUnitY(.u)-newy) > 0.5) then
call SetUnitPosition(.u, newx, .y)
set boolx = RAbsBJ(GetUnitX(.u)-newx) <= 0.5
call SetUnitPosition(.u, .x, newy)
set booly = RAbsBJ(GetUnitY(.u)-newy) <= 0.5
if boolx then
set .x = newx
elseif booly then
set .y = newy
endif
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
else
set .x = newx
set .y = newy
endif
endif
else
call SetUnitFacing(.u, .facing)
endif
call IssueImmediateOrder(.u, "stop")
endif
else
if .speed > 0. or .speed < 0. then
if .sidewards then
set newx = .x + Cos(.sfacing * bj_DEGTORAD) * .speed
set newy = .y + Sin(.sfacing * bj_DEGTORAD) * .speed
else
set newx = .x + Cos(.facing * bj_DEGTORAD) * .speed
set newy = .y + Sin(.facing * bj_DEGTORAD) * .speed
call SetUnitFacing(.u, .facing)
endif
if .jump then
call SetUnitPosition(.cunit, newx, newy)
if (RAbsBJ(GetUnitX(.cunit)-newx) > 0.5) or (RAbsBJ(GetUnitY(.cunit)-newy) > 0.5) then
call SetUnitPosition(.cunit, newx, .y)
set boolx = RAbsBJ(GetUnitX(.cunit)-newx) <= 0.5
call SetUnitPosition(.cunit, .x, newy)
set booly = RAbsBJ(GetUnitY(.cunit)-newy) <= 0.5
if boolx then
set .x = newx
elseif booly then
set .y = newy
endif
else
set .x = newx
set .y = newy
endif
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
else
call SetUnitPosition(.u, newx, newy)
if (RAbsBJ(GetUnitX(.u)-newx) > 0.5) or (RAbsBJ(GetUnitY(.u)-newy) > 0.5) then
call SetUnitPosition(.u, newx, .y)
set boolx = RAbsBJ(GetUnitX(.u)-newx) <= 0.5
call SetUnitPosition(.u, .x, newy)
set booly = RAbsBJ(GetUnitY(.u)-newy) <= 0.5
if boolx then
set .x = newx
elseif booly then
set .y = newy
endif
call SetUnitX(.u, .x)
call SetUnitY(.u, .y)
else
set .x = newx
set .y = newy
endif
endif
else
call SetUnitFacing(.u, .facing)
endif
call IssueImmediateOrder(.u, "stop")
endif
//! endtextmacro
//! runtextmacro Movement()
else
if .order then
if .jump then
set .x = GetUnitX(.u)
set .y = GetUnitY(.u)
set .facing = GetUnitFacing(.u)
call SetUnitX(.cunit, .x)
call SetUnitY(.cunit, .y)
else
set .x = GetUnitX(.u)
set .y = GetUnitY(.u)
set .facing = GetUnitFacing(.u)
endif
else
//! runtextmacro Movement()
endif
endif
endif
endmethod
private static method JumpInit takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetOwningPlayer(GetTriggerUnit()))+1)
local real x
local real y
local real deltaz
local real parabolaz
local real factor = 1.
local boolean toggle = false
local boolean increase = false
local boolean decrease = false
static if COMBAT_MODE then
call RemoveUnit(GetSoldUnit())
if not (.jump and .inuse) then
return false
endif
//! textmacro JumpInit takes EVENT
if .disabled then
return false
endif
if $EVENT$ == JUMPID then
if not .isjumping then
set .isjumping = true
set .break = true
static if not NOMOUSE then
set .order = false
call IssueImmediateOrder(.cunit, "stop")
endif
call SetUnitAnimationByIndex(.u, .janim)
call SetUnitTimeScale(.u, .as)
if .sidewards then
set newx = .x + Cos(.sfacing * bj_DEGTORAD) * .speed * JUMPCOUNT
set newy = .y + Sin(.sfacing * bj_DEGTORAD) * .speed * JUMPCOUNT
call SetUnitPosition(.cunit, newx, newy)
call MoveLocation(Loc, .x, .y)
set .z = GetLocationZ(Loc)
call MoveLocation(Loc, newx, newy)
set newz = GetLocationZ(Loc)
set parabolaz = -jumpfactor * JUMPCOUNT * JUMPCOUNT / 4 + JUMPHEIGHT
set deltaz = newz - .z
loop
if (RAbsBJ(GetUnitX(.cunit)-newx) < JUMPTOLERANCE) and (RAbsBJ(GetUnitY(.cunit)-newy) < JUMPTOLERANCE) then
exitwhen (increase or (not increase and not decrease)) and RAbsBJ(deltaz-parabolaz)<JUMPTOLERANCE
exitwhen decrease and ((deltaz-parabolaz)<JUMPTOLERANCE)
endif
if deltaz-parabolaz>0. or toggle then
set factor = factor - 0.02
if increase then
set toggle = true
endif
set decrease = true
else
set factor = factor + 0.02
if decrease then
set toggle = true
set factor = 0.98
endif
set increase = true
endif
set newx = .x + Cos(.sfacing * bj_DEGTORAD) * .speed * JUMPCOUNT * factor
set newy = .y + Sin(.sfacing * bj_DEGTORAD) * .speed * JUMPCOUNT * factor
call SetUnitPosition(.cunit, newx, newy)
call MoveLocation(Loc, GetUnitX(.cunit), GetUnitY(.cunit))
set newz = GetLocationZ(Loc)
set parabolaz = -jumpfactor * (JUMPCOUNT*factor - JUMPCOUNT/2) * (JUMPCOUNT*factor - JUMPCOUNT/2) + JUMPHEIGHT
set deltaz = newz - .z
endloop
else
set newx = .x + Cos(.facing * bj_DEGTORAD) * .speed * JUMPCOUNT
set newy = .y + Sin(.facing * bj_DEGTORAD) * .speed * JUMPCOUNT
call SetUnitPosition(.cunit, newx, newy)
call MoveLocation(Loc, .x, .y)
set .z = GetLocationZ(Loc)
call MoveLocation(Loc, newx, newy)
set newz = GetLocationZ(Loc)
set parabolaz = -jumpfactor * JUMPCOUNT * JUMPCOUNT / 4 + JUMPHEIGHT
set deltaz = newz - .z
loop
if (RAbsBJ(GetUnitX(.cunit)-newx) < JUMPTOLERANCE) and (RAbsBJ(GetUnitY(.cunit)-newy) < JUMPTOLERANCE) then
exitwhen (increase or (not increase and not decrease)) and RAbsBJ(deltaz-parabolaz)<JUMPTOLERANCE
exitwhen decrease and ((deltaz-parabolaz)<JUMPTOLERANCE)
endif
if deltaz-parabolaz>0. or toggle then
set factor = factor - 0.02
if increase then
set toggle = true
endif
set decrease = true
else
set factor = factor + 0.02
if decrease then
set toggle = true
set factor = 0.98
endif
set increase = true
endif
set newx = .x + Cos(.facing * bj_DEGTORAD) * .speed * JUMPCOUNT * factor
set newy = .y + Sin(.facing * bj_DEGTORAD) * .speed * JUMPCOUNT * factor
call SetUnitPosition(.cunit, newx, newy)
call MoveLocation(Loc, GetUnitX(.cunit), GetUnitY(.cunit))
set newz = GetLocationZ(Loc)
set parabolaz = -jumpfactor * (JUMPCOUNT*factor - JUMPCOUNT/2) * (JUMPCOUNT*factor - JUMPCOUNT/2) + JUMPHEIGHT
set deltaz = newz - .z
endloop
endif
set .jx = GetUnitX(.cunit)
set .jy = GetUnitY(.cunit)
set x = .jx - .x
set y = .jy - .y
set .jf = Atan2(y, x)
set .speed = SquareRoot(x * x + y * y) / JUMPCOUNT
set .jcmax = R2I(SquareRoot((deltaz-JUMPHEIGHT) / -(JUMPHEIGHT*4 / (JUMPCOUNT*JUMPCOUNT))) + JUMPCOUNT/2)
endif
endif
//! endtextmacro
//! runtextmacro JumpInit("GetUnitTypeId(GetSoldUnit())")
else
//! runtextmacro JumpInit("GetSpellAbilityId()")
endif
return false
endmethod
static if COMBAT_MODE then
//! textmacro SelectInit takes FRIENDLY, friendly
private static method $FRIENDLY$SelectInit takes nothing returns boolean
local integer i = 1
local integer j = 1
local real x
local real y
local real X
local real Y
if GetUnitTypeId(GetSoldUnit()) != $FRIENDLY$SELECTID then
return false
endif
set playerid = GetPlayerId(GetTriggerPlayer())+1
if not thistype(playerid).inuse then
return false
endif
call DestroyTrigger(thistype(playerid).$friendly$td)
loop
exitwhen i == thistype(playerid).$friendly$tc
set x = GetUnitX(thistype(playerid).$friendly$targeted[i]) - thistype(playerid).x
set y = GetUnitY(thistype(playerid).$friendly$targeted[i]) - thistype(playerid).y
if GetWidgetLife(thistype(playerid).$friendly$targeted[i]) < 0.405 or SquareRoot(x*x+y*y) > COMBATRADIUS then
set j = i
loop
exitwhen j+1 == thistype(playerid).$friendly$tc
set thistype(playerid).$friendly$targeted[j] = thistype(playerid).$friendly$targeted[j+1]
set j = j + 1
endloop
set thistype(playerid).$friendly$targeted[j] = null
set thistype(playerid).$friendly$tc = thistype(playerid).$friendly$tc - 1
if thistype(playerid).$friendly$tp > thistype(playerid).$friendly$tc then
set thistype(playerid).$friendly$tp = thistype(playerid).$friendly$tp - 1
endif
else
set i = i + 1
endif
endloop
set selectcount = 0
call GroupEnumUnitsInRange(g, thistype(playerid).x, thistype(playerid).y, COMBATRADIUS, $friendly$cfilter)
if selectcount == 0 then
if thistype(playerid).$friendly$tc == 1 then
set thistype(playerid).$friendly$target = null
if thistype(playerid).selection != null then
call DestroyEffect(thistype(playerid).selection)
set thistype(playerid).selection = null
endif
set thistype(playerid).atk = false
set thistype(playerid).attacking = false
set thistype(playerid).sidewards = false
return false
endif
if thistype(playerid).$friendly$tp == thistype(playerid).$friendly$tc then
set thistype(playerid).$friendly$tp = 1
endif
set thistype(playerid).$friendly$target = thistype(playerid).$friendly$targeted[thistype(playerid).$friendly$tp]
set thistype(playerid).$friendly$td = CreateTrigger()
call TriggerRegisterUnitEvent(thistype(playerid).$friendly$td, thistype(playerid).$friendly$target, EVENT_UNIT_DEATH)
call TriggerAddCondition(thistype(playerid).$friendly$td, $friendly$tfilter)
else
set i = 2
set x = GetUnitX(selectable[1]) - thistype(playerid).x
set y = GetUnitY(selectable[1]) - thistype(playerid).y
set selectedunit = selectable[1]
loop
exitwhen i > selectcount
set X = GetUnitX(selectable[i]) - thistype(playerid).x
set Y = GetUnitY(selectable[i]) - thistype(playerid).y
if SquareRoot(x*x+y*y) > SquareRoot(X*X+Y*Y) then
set selectedunit = selectable[i]
set x = X
set y = Y
endif
set i = i + 1
endloop
set thistype(playerid).$friendly$target = selectedunit
set thistype(playerid).$friendly$td = CreateTrigger()
call TriggerRegisterUnitEvent(thistype(playerid).$friendly$td, thistype(playerid).$friendly$target, EVENT_UNIT_DEATH)
call TriggerAddCondition(thistype(playerid).$friendly$td, $friendly$tfilter)
set i = thistype(playerid).$friendly$tc
loop
exitwhen i == thistype(playerid).$friendly$tp
set thistype(playerid).$friendly$targeted[i] = thistype(playerid).$friendly$targeted[i-1]
set i = i - 1
endloop
set thistype(playerid).$friendly$targeted[thistype(playerid).$friendly$tp] = selectedunit
set thistype(playerid).$friendly$tc = thistype(playerid).$friendly$tc + 1
endif
set thistype(playerid).$friendly$tp = thistype(playerid).$friendly$tp + 1
if thistype(playerid).selection != null then
call DestroyEffect(thistype(playerid).selection)
set thistype(playerid).selection = null
endif
if thistype(playerid).attacking then
call DisableTrigger(thistype(playerid).trg)
call IssueTargetOrder(thistype(playerid).u, "attack", thistype(playerid).$friendly$target)
call EnableTrigger(thistype(playerid).trg)
endif
if thistype(playerid).atk then
if GetLocalPlayer() == Player(playerid-1) then
set thistype(playerid).selection = AddSpecialEffectTarget(COMBAT_ON, thistype(playerid).$friendly$target, ATTACHPNT)
else
set thistype(playerid).selection = AddSpecialEffectTarget("", thistype(playerid).$friendly$target, ATTACHPNT)
endif
static if not NOMOUSE then
set thistype(playerid).order = false
endif
else
if GetLocalPlayer() == Player(playerid-1) then
set thistype(playerid).selection = AddSpecialEffectTarget(COMBAT_OFF, thistype(playerid).$friendly$target, ATTACHPNT)
else
set thistype(playerid).selection = AddSpecialEffectTarget("", thistype(playerid).$friendly$target, ATTACHPNT)
endif
endif
return false
endmethod
//! endtextmacro
//! runtextmacro SelectInit("","")
//! runtextmacro SelectInit("F","f")
private static method CheckForNewEnemy takes nothing returns boolean
local unit u = GetFilterUnit()
local integer i = 1
if not IsUnitEnemy(u, Player(playerid-1)) or GetWidgetLife(u) < 0.405 or GetUnitAbilityLevel(u, 'Aloc') == 1 then
set u = null
return false
endif
loop
exitwhen i == thistype(playerid).tc
if thistype(playerid).targeted[i] == u then
set u = null
return false
endif
set i = i + 1
endloop
set selectcount = selectcount + 1
set selectable[selectcount] = u
set u = null
return false
endmethod
private static method CheckForNewAlly takes nothing returns boolean
local unit u = GetFilterUnit()
local integer i = 1
if not IsUnitAlly(u, Player(playerid-1)) or GetWidgetLife(u) < 0.405 or GetUnitAbilityLevel(u, 'Aloc') == 1 or GetUnitAbilityLevel(u, 'Avul') == 1 then
set u = null
return false
endif
loop
exitwhen i == thistype(playerid).ftc
if thistype(playerid).ftargeted[i] == u then
set u = null
return false
endif
set i = i + 1
endloop
set selectcount = selectcount + 1
set selectable[selectcount] = u
set u = null
return false
endmethod
private static method Unselect takes nothing returns boolean
local thistype this
if GetUnitTypeId(GetSoldUnit()) != UNSELECTID then
return false
endif
set this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if not .inuse then
return false
endif
set .target = null
set .ftarget = null
set .tc = 1
set .ftc = 1
set .tp = 1
set .ftp = 1
call DestroyEffect(.selection)
set .selection = null
set .atk = false
set .attacking = false
set .sidewards = false
call DestroyTrigger(.td)
call DestroyTrigger(.ftd)
if not .isjumping then
//! runtextmacro InitMovement()
endif
return false
endmethod
private static method StartAttack takes nothing returns boolean
local thistype this
if GetUnitTypeId(GetSoldUnit()) != ATTACKID then
return false
endif
set this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if not .inuse or .target == null then
return false
endif
call DestroyEffect(.selection)
if .atk then
set .atk = false
set .attacking = false
set .sidewards = false
if GetLocalPlayer() == Player(this-1) then
set .selection = AddSpecialEffectTarget(COMBAT_OFF, .target, ATTACHPNT)
else
set .selection = AddSpecialEffectTarget("", .target, ATTACHPNT)
endif
if not .isjumping then
//! runtextmacro InitMovement()
endif
else
set .atk = true
set .sidewards = true
if GetLocalPlayer() == Player(this-1) then
set .selection = AddSpecialEffectTarget(COMBAT_ON, .target, ATTACHPNT)
else
set .selection = AddSpecialEffectTarget("", .target, ATTACHPNT)
endif
static if not NOMOUSE then
set .order = false
endif
endif
return false
endmethod
endif
private static method TargetDies takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetOwningPlayer(GetKillingUnit()))+1)
set .target = null
set .tc = 1
set .tp = 1
call DestroyEffect(.selection)
set .selection = null
set .atk = false
set .attacking = false
set .sidewards = false
//! runtextmacro InitMovement()
return false
endmethod
private static method FTargetDies takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetOwningPlayer(GetKillingUnit()))+1)
set .ftarget = null
set .ftc = 1
set .ftp = 1
call DestroyEffect(.selection)
set .selection = null
return false
endmethod
private static method UpDown takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if .inuse then
set .up = true
static if not NOMOUSE then
set .order = false
call IssueImmediateOrder(.u, "stop")
endif
static if COMBAT_MODE then
if .isjumping or .atk then
return false
endif
else
if .isjumping then
return false
endif
endif
if .timerstate == 1 then
if TimerGetElapsed(.dblclick) < DBLCLICKTIME then
set dblclicked = true
else
call TimerStart(.dblclick, 3600., false, null)
set dblclicked = false
endif
else
set .timerstate = 1
call TimerStart(.dblclick, 3600., false, null)
set dblclicked = false
endif
if not .down then
if dblclicked then
set .running = true
set .speed = .msr
set .sidewards = false
call SetUnitTimeScale(.u, .asr)
call SetUnitAnimationByIndex(.u, .anim)
if .right then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.RightPeriodic)
elseif .left then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.LeftPeriodic)
endif
else
if .sidewards then
if .right then
set .sfacing = .facing - RIGHT_SIDE_FACING
elseif .left then
set .sfacing = .facing - LEFT_SIDE_FACING
endif
else
set .speed = .ms
call SetUnitTimeScale(.u, .as)
call SetUnitAnimationByIndex(.u, .anim)
endif
endif
endif
endif
return false
endmethod
private static method UpUp takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if .inuse then
set .up = false
static if COMBAT_MODE then
if .isjumping or .atk then
return false
endif
else
if .isjumping then
return false
endif
endif
set .running = false
if .down then
set .speed = .msb
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
elseif .sidewards then
if .right then
set .sfacing = .facing - 90.
elseif .left then
set .sfacing = .facing + 90.
endif
else
set .speed = 0.
call SetUnitAnimation(.u, "stand")
call SetUnitTimeScale(.u, .as)
endif
endif
return false
endmethod
private static method LeftDown takes nothing returns boolean
//! textmacro SideDown takes SIDE, SIDECAPS, SIDE1, SIDE2, TIMERSTATE, OP
local thistype this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if .inuse then
set .$SIDE1$ = true
static if not NOMOUSE then
set .order = false
call IssueImmediateOrder(.u, "stop")
endif
static if COMBAT_MODE then
if .isjumping or .atk then
return false
endif
else
if .isjumping then
return false
endif
endif
if not .running then
if .timerstate == $TIMERSTATE$ then
if TimerGetElapsed(.dblclick) < DBLCLICKTIME then
set dblclicked = true
set .break = true
else
call TimerStart(.dblclick, 3600., false, null)
set dblclicked = false
endif
else
set .timerstate = $TIMERSTATE$
call TimerStart(.dblclick, 3600., false, null)
set dblclicked = false
endif
else
set dblclicked = false
endif
if dblclicked then
set .speed = .mss
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .ass)
set .sidewards = true
set .sfacing = .facing $OP$ 90.
else
if not .$SIDE2$ then
if .up then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.$SIDE$Periodic)
elseif .down then
set .sidewards = true
set .sfacing = .facing + $SIDECAPS$_SIDE_FACING
else
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.$SIDE$Periodic)
endif
endif
endif
endif
return false
//! endtextmacro
//! runtextmacro SideDown("Left", "LEFT", "left", "right", "2", "+")
endmethod
private static method LeftUp takes nothing returns boolean
//! textmacro SideUp takes SIDE1, SIDE2, SIDE
local thistype this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if .inuse then
set .$SIDE1$ = false
static if COMBAT_MODE then
if .isjumping or .atk then
return false
endif
else
if .isjumping then
return false
endif
endif
if .$SIDE2$ then
if .down then
set .sidewards = true
set .sfacing = .facing + $SIDE$_SIDE_FACING
else
if .sidewards then
static if COMBAT_MODE then
if not .atk then
set .sidewards = false
endif
endif
set .speed = 0.
endif
endif
else
static if COMBAT_MODE then
if not .atk then
set .sidewards = false
endif
endif
if not .down and not .up then
set .speed = 0.
call SetUnitAnimation(.u, "stand")
call SetUnitTimeScale(.u, .as)
elseif .up then
if .running then
set .speed = .msr
call SetUnitTimeScale(.u, .asr)
else
set .speed = .ms
call SetUnitTimeScale(.u, .as)
endif
call SetUnitAnimationByIndex(.u, .anim)
elseif .down then
set .speed = .msb
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
endif
endif
endif
return false
//! endtextmacro
//! runtextmacro SideUp("left", "right", "RIGHT")
endmethod
private static method LeftPeriodic takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
if not this.disabled then
set this.facing = this.facing + this.ts
endif
if not this.left or this.break then
set this.break = false
call PauseTimer(this.sidetimer)
endif
endmethod
private static method RightDown takes nothing returns boolean
//! runtextmacro SideDown("Right", "RIGHT", "right", "left", "3", "-")
endmethod
private static method RightUp takes nothing returns boolean
//! runtextmacro SideUp("right", "left", "LEFT")
endmethod
private static method RightPeriodic takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
if not this.disabled then
set this.facing = this.facing - this.ts
endif
if not this.right or this.break then
set this.break = false
call PauseTimer(this.sidetimer)
endif
endmethod
private static method DownDown takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if .inuse then
set .down = true
static if not NOMOUSE then
set .order = false
call IssueImmediateOrder(.u, "stop")
endif
static if COMBAT_MODE then
if .isjumping or .atk then
return false
endif
else
if .isjumping then
return false
endif
endif
if .timerstate == 4 then
if (TimerGetElapsed(.dblclick)<DBLCLICKTIME) and not .sidewards then
set dblclicked = true
else
call TimerStart(.dblclick, 3600., false, null)
set dblclicked = false
endif
else
set .timerstate = 4
call TimerStart(.dblclick, 3600., false, null)
set dblclicked = false
endif
if dblclicked then
set .facing = .facing + 180.
return false
endif
if not .up then
if .sidewards then
set .speed = .msb
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
if .left then
set .sfacing = .facing - RIGHT_SIDE_FACING
elseif .right then
set .sfacing = .facing - LEFT_SIDE_FACING
endif
else
set .speed = .msb
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asb)
if .left then
set .break = true
set .sidewards = true
set .sfacing = .facing + LEFT_SIDE_FACING
elseif .right then
set .break = true
set .sidewards = true
set .sfacing = .facing + RIGHT_SIDE_FACING
endif
endif
endif
endif
return false
endmethod
private static method DownUp takes nothing returns boolean
local thistype this = thistype(GetPlayerId(GetTriggerPlayer())+1)
if .inuse then
set .down = false
static if COMBAT_MODE then
if .isjumping or .atk then
return false
endif
else
if .isjumping then
return false
endif
endif
if .up then
static if COMBAT_MODE then
if (.right or .left) and not .atk then
set .sidewards = false
endif
else
if .right or .left then
set .sidewards = false
endif
endif
if .running then
set .speed = .msr
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .asr)
else
set .speed = .ms
call SetUnitAnimationByIndex(.u, .anim)
call SetUnitTimeScale(.u, .as)
endif
else
if .sidewards then
if .right then
set .sfacing = .facing - 90.
else
set .sfacing = .facing + 90.
endif
set .speed = .mss
call SetUnitTimeScale(.u, .ass)
else
set .speed = 0.
call SetUnitAnimation(.u, "stand")
call SetUnitTimeScale(.u, .as)
if .left then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.LeftPeriodic)
elseif .right then
set .break = false
call TimerStart(.sidetimer, INTERVAL, true, function thistype.RightPeriodic)
endif
endif
endif
endif
return false
endmethod
static method Unregister takes player p returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
set .inuse = false
set .break = true
static if not COMBAT_MODE then
call UnitRemoveAbility(.u, JUMPID)
endif
call .stopPeriodic()
if .jump then
call SetUnitPosition(.cunit, .x, .y)
call SetUnitX(.u, GetUnitX(.cunit))
call SetUnitY(.u, GetUnitY(.cunit))
call RemoveUnit(.cunit)
if .isjumping then
call SetUnitFlyHeight(.u, 0., 0.)
endif
endif
call SetUnitAnimation(.u, "stand")
call IssueImmediateOrder(.u, "stop")
set .u = null
static if COMBAT_MODE then
call DestroyEffect(.selection)
endif
call ReleaseTimer(.t)
call ReleaseTimer(.sidetimer)
call ReleaseTimer(.dtimer)
call ReleaseTimer(.dblclick)
call DestroyTrigger(.trg)
call DestroyTrigger(.death)
call DestroyTrigger(.revive)
if .target != null then
call DestroyTrigger(.td)
call DestroyTrigger(.ftd)
endif
endmethod
static method GetRegisteredUnit takes player p returns unit
local thistype this = thistype(GetPlayerId(p)+1)
if .inuse then
return .u
endif
return null
endmethod
static if COMBAT_MODE then
static method GetUnitTarget takes unit u returns unit
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .inuse and .u == u then
return .target
endif
return null
endmethod
static method GetUnitTargetByPlayer takes player p returns unit
local thistype this = thistype(GetPlayerId(p)+1)
if .inuse then
return .target
endif
return null
endmethod
static method GetUnitFTarget takes unit u returns unit
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .inuse and .u == u then
return .ftarget
endif
return null
endmethod
static method GetUnitFTargetByPlayer takes player p returns unit
local thistype this = thistype(GetPlayerId(p)+1)
if .inuse then
return .ftarget
endif
return null
endmethod
endif
static method IsUnitRegistered takes unit u returns boolean
return thistype(GetPlayerId(GetOwningPlayer(u))+1).u == u
endmethod
static method IsUnitJumping takes unit u returns boolean
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
return .isjumping and .u == u
endmethod
static method CanUnitJump takes unit u returns boolean
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
return .jump and .u == u
endmethod
static method CanUnitJumpByPlayer takes player p returns boolean
local thistype this = thistype(GetPlayerId(p)+1)
return .jump and .inuse
endmethod
static method SetMoveSpeed takes unit u, real r1, real r2, real r3, real r4, real t returns nothing
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .u == u then
if r1 != 0. then
set .ms = r1
call SetUnitMoveSpeed(u, r1 * 32)
endif
if r2 != 0. then
set .mss = r2
endif
if r3 != 0. then
set .msb = r3
endif
if r4 != 0. then
set .msr = r4
endif
if t != 0. then
set .ts = t
endif
//! textmacro InitSpeed takes TYPE, SPEED
if .sidewards then
if .atk then
if .up then
set .$SPEED$ = .$TYPE$
elseif .down then
set .$SPEED$ = .$TYPE$b
elseif .left or .right then
set .$SPEED$ = .$TYPE$s
endif
else
set .$SPEED$ = .$TYPE$s
endif
else
if .running then
set .$SPEED$ = .$TYPE$r
else
if .up then
set .$SPEED$ = .$TYPE$
elseif .down then
set .$SPEED$ = .$TYPE$b
elseif .left or .right then
set .$SPEED$ = .$TYPE$s
endif
endif
endif
//! endtextmacro
//! runtextmacro InitSpeed("ms", "speed")
endif
endmethod
static method SetMoveSpeedByPlayer takes player p, real r1, real r2, real r3, real r4, real t returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
if r1 != 0. then
set .ms = r1
call SetUnitMoveSpeed(.u, r1 * 32)
endif
if r2 != 0. then
set .mss = r2
endif
if r3 != 0. then
set .msb = r3
endif
if r4 != 0. then
set .msr = r4
endif
if t != 0. then
set .ts = t
endif
//! runtextmacro InitSpeed("ms", "speed")
endmethod
static method SetAnimSpeed takes unit u, real r1, real r2, real r3, real r4 returns nothing
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .u == u then
if r1 != 0. then
set .as = r1
endif
if r2 != 0. then
set .ass = r2
endif
if r3 != 0. then
set .asb = r3
endif
if r4 != 0. then
set .asr = r4
endif
//! runtextmacro InitSpeed("as", "as")
endif
endmethod
static method SetAnimSpeedByPlayer takes player p, real r1, real r2, real r3, real r4 returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
if r1 != 0. then
set .as = r1
endif
if r2 != 0. then
set .ass = r2
endif
if r3 != 0. then
set .asb = r3
endif
if r4 != 0. then
set .asr = r4
endif
//! runtextmacro InitSpeed("as", "as")
endmethod
static method SetX takes unit u, real r returns nothing
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .inuse and .u == u then
set .x = r
call SetUnitX(.u, r)
endif
endmethod
static method SetXPlayer takes player p, real r returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
if .inuse then
set .x = r
call SetUnitX(.u, r)
endif
endmethod
static method SetY takes unit u, real r returns nothing
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .inuse and .u == u then
set .y = r
call SetUnitY(.u, r)
endif
endmethod
static method SetYPlayer takes player p, real r returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
if .inuse then
set .y = r
call SetUnitY(.u, r)
endif
endmethod
static method SetFacing takes unit u, real r returns nothing
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .inuse and .u == u then
set .facing = r
call SetUnitFacing(.u, r)
endif
endmethod
static method SetFacingPlayer takes player p, real r returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
if .inuse then
set .facing = r
call SetUnitFacing(.u, r)
endif
endmethod
static method ResetTarget takes unit u returns nothing
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
if .inuse and .u == u then
set .target = null
set .tc = 1
set .tp = 1
call DestroyEffect(.selection)
set .selection = null
set .atk = false
set .attacking = false
set .sidewards = false
call DestroyTrigger(.td)
if not .isjumping then
//! runtextmacro InitMovement()
endif
endif
endmethod
static method ResetTargetPlayer takes player p returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
if .inuse then
set .target = null
set .tc = 1
set .tp = 1
call DestroyEffect(.selection)
set .selection = null
set .atk = false
set .attacking = false
set .sidewards = false
call DestroyTrigger(.td)
if not .isjumping then
//! runtextmacro InitMovement()
endif
endif
endmethod
private static method Enable takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
set this.disabled = false
endmethod
static method DisableMoving takes unit u, real dur returns nothing
local thistype this = thistype(GetPlayerId(GetOwningPlayer(u))+1)
set .disabled = true
call TimerStart(.dtimer, dur, false, function thistype.Enable)
endmethod
static method DisableMovingPlayer takes player p, real dur returns nothing
local thistype this = thistype(GetPlayerId(p)+1)
set .disabled = true
call TimerStart(.dtimer, dur, false, function thistype.Enable)
endmethod
implement T32x
static method create takes unit u, player p, integer animation, boolean jump, integer unitid, integer jumpanim, real atkrange returns thistype
local thistype this = thistype(GetPlayerId(p)+1)
local integer i = 1
debug if .inuse then
debug call BJDebugMsg("RegisterUnitArrowKey: Warning! Multiple registries detected")
debug endif
// init general boolean instance variables
set .inuse = true
set .up = false
set .left = false
set .right = false
set .down = false
set .break = false
set .disabled = false
// init movement system instance variables
set .u = u
set .p = p
call UnitAddAbility(u, 'Arav')
call UnitRemoveAbility(u, 'Arav')
set .anim = animation
set .x = GetUnitX(u)
set .y = GetUnitY(u)
set .z = 0.
set .facing = GetUnitFacing(u)
set .speed = 0.
set .ms = MOVE_SPEED
set .mss = MOVE_SPEED_SIDE
set .msb = MOVE_SPEED_BACK
set .msr = MOVE_SPEED_RUN
set .ts = TURN_SPEED
set .as = ANIM_SPEED
set .ass = ANIM_SPEED_SIDE
set .asb = ANIM_SPEED_BACK
set .asr = ANIM_SPEED_RUN
static if not NOMOUSE then
set .order = false
endif
set .running = false
set .sidewards = false
set .sfacing = 0.
set .trg = CreateTrigger()
call TriggerRegisterUnitEvent(.trg, u, EVENT_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterUnitEvent(.trg, u, EVENT_UNIT_ISSUED_TARGET_ORDER)
call TriggerAddCondition(.trg, filter)
set .death = CreateTrigger()
call TriggerRegisterUnitEvent(.death, u, EVENT_UNIT_DEATH)
call TriggerAddCondition(.death, dfilter)
set .revive = CreateTrigger()
call TriggerRegisterUnitEvent(.revive, u, EVENT_UNIT_HERO_REVIVE_FINISH)
call TriggerAddCondition(.revive, rfilter)
// init jump system instance variables
if jump then
static if not COMBAT_MODE then
call UnitAddAbility(u, JUMPID)
endif
set .cunit = CreateUnit(Player(15), unitid, GetUnitX(u), GetUnitY(u), bj_UNIT_FACING)
endif
set .jump = jump
set .isjumping = false
set .janim = jumpanim
set .jx = 0.
set .jy = 0.
set .jh = 0.
set .jf = 0.
set .jc = 0
set .jcmax = 0
// init combat system instance variables
static if COMBAT_MODE then
set .target = null
set .ftarget = null
loop
exitwhen i > ARRAY_SIZE
set .targeted[i] = null
set .ftargeted[i] = null
set i = i + 1
endloop
set .tc = 1
set .ftc = 1
set .tp = 1
set .ftp = 1
set .selection = null
set .atk = false
set .atkrange = atkrange
set .attacking = false
endif
// init timer related instance variables
set .sidetimer = NewTimer()
call SetTimerData(.sidetimer, this)
set .dtimer = NewTimer()
call SetTimerData(.dtimer, this)
set .dblclick = NewTimer()
set .timerstate = 0
call TimerStart(.dblclick, 3600., false, null)
return this
endmethod
implement CAMSInit
endstruct
function RegisterUnitArrowKey takes unit u, player p, integer anim, boolean jump, integer unitid, integer jumpanim, real atkrange returns nothing
call CAMS.create(u, p, anim, jump, unitid, jumpanim, atkrange).startPeriodic()
endfunction
function UnregisterUnitArrowKey takes player p returns nothing
call CAMS.Unregister(p)
endfunction
function GetRegisteredUnitArrowKey takes player p returns unit
return CAMS.GetRegisteredUnit(p)
endfunction
static if COMBAT_MODE then
function GetUnitTarget takes unit u returns unit
return CAMS.GetUnitTarget(u)
endfunction
function GetUnitTargetByPlayer takes player p returns unit
return CAMS.GetUnitTargetByPlayer(p)
endfunction
function GetUnitFTarget takes unit u returns unit
return CAMS.GetUnitFTarget(u)
endfunction
function GetUnitFTargetByPlayer takes player p returns unit
return CAMS.GetUnitFTargetByPlayer(p)
endfunction
endif
function IsUnitRegisteredArrowKey takes unit u returns boolean
return CAMS.IsUnitRegistered(u)
endfunction
function IsUnitJumping takes unit u returns boolean
return CAMS.IsUnitJumping(u)
endfunction
function CanUnitJump takes unit u returns boolean
return CAMS.CanUnitJump(u)
endfunction
function CanUnitJumpByPlayer takes player p returns boolean
return CAMS.CanUnitJumpByPlayer(p)
endfunction
function SetMoveSpeed takes unit u, real r1, real r2, real r3, real r4, real t returns nothing
call CAMS.SetMoveSpeed(u, r1, r2, r3, r4, t)
endfunction
function SetMoveSpeedByPlayer takes player p, real r1, real r2, real r3, real r4, real t returns nothing
call CAMS.SetMoveSpeedByPlayer(p, r1, r2, r3, r4, t)
endfunction
function SetAnimSpeed takes unit u, real r1, real r2, real r3, real r4 returns nothing
call CAMS.SetAnimSpeed(u, r1, r2, r3, r4)
endfunction
function SetAnimSpeedByPlayer takes player p, real r1, real r2, real r3, real r4 returns nothing
call CAMS.SetAnimSpeedByPlayer(p, r1, r2, r3, r4)
endfunction
function SetUnitXArrowKey takes unit u, real r returns nothing
call CAMS.SetX(u, r)
endfunction
function SetUnitXByPlayer takes player p, real r returns nothing
call CAMS.SetXPlayer(p, r)
endfunction
function SetUnitYArrowKey takes unit u, real r returns nothing
call CAMS.SetY(u, r)
endfunction
function SetUnitYByPlayer takes player p, real r returns nothing
call CAMS.SetYPlayer(p, r)
endfunction
function SetUnitFacingArrowKey takes unit u, real r returns nothing
call CAMS.SetFacing(u, r)
endfunction
function SetUnitFacingByPlayer takes player p, real r returns nothing
call CAMS.SetFacingPlayer(p, r)
endfunction
function ResetTarget takes unit u returns nothing
call CAMS.ResetTarget(u)
endfunction
function ResetTargetByPlayer takes player p returns nothing
call CAMS.ResetTargetPlayer(p)
endfunction
function DisableMove takes unit u, real duration returns nothing
call CAMS.DisableMoving(u, duration)
endfunction
function DisableMoveByPlayer takes player p, real duration returns nothing
call CAMS.DisableMovingPlayer(p, duration)
endfunction
endlibrary