- Joined
- Feb 27, 2019
- Messages
- 833
Hello! I am using MoveSpeedX by PurgeandFire
MoveSpeedX for GUI v1.1.0.0
If I use Remove Unit there is sometimes an issue in which a new unit will not get any extra move speed above 522 applied. The first 7-10 times the unit is created it will get the correct extra move speed, then it stops working for about 2-3 times then works again, stops working and so on. It works flawlessly if I use Kill unit instead of Remove unit. My humble guess is that it cant detect a removed unit, only dead units somewhere in the code. If I change UDexWasted to a lower value than the default 15 the problem presents itself earlier.
This is how I apply the move speed:
* How to add an OR condition that checks if a unit has been removed/doesnt exist in vJazz?
* Do you have any other idea why the extra movement speed is not applied?
My guess is I should add the condition here:
if IsUnitType(u, UNIT_TYPE_DEAD) then
call this.destroy()
MoveSpeedX for GUI v1.1.0.0
If I use Remove Unit there is sometimes an issue in which a new unit will not get any extra move speed above 522 applied. The first 7-10 times the unit is created it will get the correct extra move speed, then it stops working for about 2-3 times then works again, stops working and so on. It works flawlessly if I use Kill unit instead of Remove unit. My humble guess is that it cant detect a removed unit, only dead units somewhere in the code. If I change UDexWasted to a lower value than the default 15 the problem presents itself earlier.
This is how I apply the move speed:
-
Unit - Create 1 ENSNAREDUMMY for (Owner of (Triggering unit)) at (Position of (Triggering unit)) facing (Position of tempunit)
-
Set VariableSet U_ENSNAREDUMMY = (Last created unit)
-
Unit - Set U_ENSNAREDUMMY movement speed to 700.00
* How to add an OR condition that checks if a unit has been removed/doesnt exist in vJazz?
* Do you have any other idea why the extra movement speed is not applied?
My guess is I should add the condition here:
if IsUnitType(u, UNIT_TYPE_DEAD) then
call this.destroy()
-
Unit Indexer
-
Events
-
Map initialization
-
-
Conditions
-
Actions
-
Custom script: call ExecuteFunc("InitializeUnitIndexer")
-
Custom script: endfunction
-
-------- --------
-
-------- This is the most important function - it provides an index for units as they enter the map --------
-
-------- --------
-
Custom script: function IndexUnit takes nothing returns boolean
-
Custom script: local integer pdex = udg_UDex
-
-------- --------
-
-------- You can use the boolean UnitIndexerEnabled to protect some of your undesirable units from being indexed --------
-
-------- - Example: --------
-
-------- -- Set UnitIndexerEnabled = False --------
-
-------- -- Unit - Create 1 Dummy for (Triggering player) at TempLoc facing 0.00 degrees --------
-
-------- -- Set UnitIndexerEnabled = True --------
-
-------- --------
-
-------- You can also customize the following block - if conditions are false the (Matching unit) won't be indexed. --------
-
-------- --------
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
UnitIndexerEnabled Equal to True
-
-
Then - Actions
-
-------- --------
-
-------- Generate a unique integer index for this unit --------
-
-------- --------
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
UDexRecycle Equal to 0
-
-
Then - Actions
-
Set VariableSet UDex = (UDexGen + 1)
-
Set VariableSet UDexGen = UDex
-
-
Else - Actions
-
Set VariableSet UDex = UDexRecycle
-
Set VariableSet UDexRecycle = UDexNext[UDex]
-
-
-
-------- --------
-
-------- Link index to unit, unit to index --------
-
-------- --------
-
Set VariableSet UDexUnits[UDex] = (Matching unit)
-
Unit - Set the custom value of UDexUnits[UDex] to UDex
-
-------- --------
-
-------- Use a doubly-linked list to store all active indexes --------
-
-------- --------
-
Set VariableSet UDexPrev[UDexNext[0]] = UDex
-
Set VariableSet UDexNext[UDex] = UDexNext[0]
-
Set VariableSet UDexNext[0] = UDex
-
-------- --------
-
-------- Fire index event for UDex --------
-
-------- --------
-
Set VariableSet UnitIndexEvent = 0.00
-
Set VariableSet UnitIndexEvent = 1.00
-
Set VariableSet UnitIndexEvent = 0.00
-
Custom script: set udg_UDex = pdex
-
-
Else - Actions
-
-
Custom script: return false
-
Custom script: endfunction
-
-------- --------
-
-------- The next function is called each time a unit enters the map --------
-
-------- --------
-
Custom script: function IndexNewUnit takes nothing returns boolean
-
Custom script: local integer pdex = udg_UDex
-
Custom script: local integer ndex
-
-------- --------
-
-------- Recycle indices of units no longer in-play every (15) units created --------
-
-------- --------
-
Set VariableSet UDexWasted = (UDexWasted + 1)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
UDexWasted Equal to 15
-
-
Then - Actions
-
Set VariableSet UDexWasted = 0
-
Set VariableSet UDex = UDexNext[0]
-
Custom script: loop
-
Custom script: exitwhen udg_UDex == 0
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Custom value of UDexUnits[UDex]) Equal to 0
-
-
Then - Actions
-
-------- --------
-
-------- Remove index from linked list --------
-
-------- --------
-
Custom script: set ndex = udg_UDexNext[udg_UDex]
-
Custom script: set udg_UDexNext[udg_UDexPrev[udg_UDex]] = ndex
-
Custom script: set udg_UDexPrev[ndex] = udg_UDexPrev[udg_UDex]
-
Set VariableSet UDexPrev[UDex] = 0
-
-------- --------
-
-------- Fire deindex event for UDex --------
-
-------- --------
-
Set VariableSet UnitIndexEvent = 2.00
-
Set VariableSet UnitIndexEvent = 0.00
-
-------- --------
-
-------- Recycle the index for later use --------
-
-------- --------
-
Set VariableSet UDexUnits[UDex] = No unit
-
Set VariableSet UDexNext[UDex] = UDexRecycle
-
Set VariableSet UDexRecycle = UDex
-
Custom script: set udg_UDex = ndex
-
-
Else - Actions
-
Set VariableSet UDex = UDexNext[UDex]
-
-
-
Custom script: endloop
-
Custom script: set udg_UDex = pdex
-
-
Else - Actions
-
-
-------- --------
-
-------- Handle the entering unit (Matching unit) --------
-
-------- --------
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Custom value of (Matching unit)) Equal to 0
-
-
Then - Actions
-
Custom script: call IndexUnit()
-
-
Else - Actions
-
-
Custom script: return false
-
Custom script: endfunction
-
-------- --------
-
-------- The next function initializes the core of the system --------
-
-------- --------
-
Custom script: function InitializeUnitIndexer takes nothing returns nothing
-
Custom script: local integer i = 0
-
Custom script: local region re = CreateRegion()
-
Custom script: local rect r = GetWorldBounds()
-
Set VariableSet UnitIndexerEnabled = True
-
Custom script: call RegionAddRect(re, r)
-
Custom script: call TriggerRegisterEnterRegion(CreateTrigger(), re, Filter(function IndexNewUnit))
-
Custom script: call RemoveRect(r)
-
Custom script: set re = null
-
Custom script: set r = null
-
Custom script: loop
-
Custom script: call GroupEnumUnitsOfPlayer(bj_lastCreatedGroup, Player(i), Filter(function IndexUnit))
-
Custom script: set i = i + 1
-
Custom script: exitwhen i == 16
-
Custom script: endloop
-
-------- --------
-
-------- This is the "Unit Indexer Initialized" event, use it instead of "Map Initialization" for best results --------
-
-------- --------
-
Set VariableSet UnitIndexEvent = 3.00
-
Set VariableSet UnitIndexEvent = 0.00
-
-
Code:
library MoveSpeedXGUI /* v1.1.0.0
*************************************************************************************
*
* This library allows you to set unit movement speeds beyond 522 without bugs.
* This is an extension of the library MoveSpeedX, but is formatted for GUI use.
* Credits to Jesus4Lyf for the original system.
*
************************************************************************************
*
* SETTINGS
*/
globals
private constant real PERIOD = 0.03125
// This is the period on which all units will be run.
// If you lower this value, movement bonuses will be smoother,
// but will require more processing power (lag more).
// Also, the lower this is, the higher the move speed can be
// before it starts bugging on waypoints. The lowest valid
// period is 0.00125. A period of 0.00625 is very robust.
private constant real MARGIN = 0.01
// This is the margin of approximation when comparing reals.
// You will most likely not need to change this.
endglobals
/*
************************************************************************************
*
* Functions
*
* function GetUnitMoveSpeedX takes unit whichUnit returns real
* - Returns a unit movement speed. The GUI function will
* - not return the correct value. This function will always
* - return the correct value regardless of whether the unit
* - has a movement speed beyond 522.
*
************************************************************************************
*
* REQUIREMENTS
*
* 1. JassNewGen Pack v5d
* 2. JassHelper 0.A.2.B
* 3. Any unit indexer
*
* HOW TO IMPLEMENT
*
* 1. Copy the 'folder' MoveSpeedX.
* 2. Paste it into your map.
* 3. Open "Advanced -> Gameplay Constants".
* 4. Checkmark "Use Custom Gameplay Constants".
* 5. Find the field, "Movement - Unit Speed - Maximum", change
* that to 522.
* 6. Find the field, "Movement - Unit Speed - Minimum", hold
* shift and click, and change it to 0.
* 7. Read HOW TO USE.
*
************************************************************************************
*
* HOW TO USE
*
* This system will automatically work by itself. You can use the
* normal GUI function for modifying unit movement speeds. Simply
* use "Unit - Set Movement Speed", input whatever value you want,
* and you are good to go! It will handle values beyond 522 by itself.
*
* HOWEVER, the GUI function will not return correct values if a unit
* has a movement speed greater than 522. To fix this, use the function
* GetUnitMoveSpeedX to return the correct value. A sample is given in
* the trigger "Speed Change" in the test map.
*
************************************************************************************
*
* NOTES
*
* Units that were issued orders as groups might not *always* end up in the proper
* "order". (they might not end up in an organized formation) They do sometimes though.
* This is only for units with speeds above 522.
*
* This also will not factor in bonuses and probably not slows either.
*
* Units may waddle around the point for a little bit. Reduce PERIOD to fix
* it a little bit. I recommend about 0.02 if you have really high speeds.
*
************************************************************************************/
private function ApproxEqual takes real A, real B returns boolean
return (A >= (B - MARGIN)) and (A <= (B + MARGIN))
endfunction
private module M
private static trigger issued = CreateTrigger()
thistype next
thistype prev
boolean enabled
unit curr
real speed
real x
real y
real ox
real oy
method destroy takes nothing returns nothing
set this.next.prev = this.prev
set this.prev.next = this.next
set this.enabled = false
endmethod
private static method periodic takes nothing returns nothing
local thistype this = thistype(0).next // first instance in list
local real nx // the x-coordinate after tick
local real ny // the y-coordinate after tick
local real dx // distance between new-x and old-x
local real dy // distance between new-y and old-y
local real d // distance between new point and old point
local integer order // the unit's current order
local unit u // unit being affected
loop
exitwhen this == 0
set u = .curr
set nx = GetUnitX(u)
set ny = GetUnitY(u)
if IsUnitType(u, UNIT_TYPE_DEAD) then
call this.destroy()
elseif not ApproxEqual(nx, .x) or not ApproxEqual(ny, .y) then
if (not IsUnitPaused(u)) and GetUnitAbilityLevel(u, 'BSTN') == 0 and GetUnitAbilityLevel(u, 'BPSE') == 0 then
set order = GetUnitCurrentOrder(u)
set dx = nx - .x
set dy = ny - .y
set d = SquareRoot(dx * dx + dy * dy)
set dx = dx / d * .speed // move the unit offset-x by this
set dy = dy / d * .speed // move the unit offset-y by this
if (order == 851986 or order == 851971) and /*
*/ (this.ox - nx)*(this.ox - nx) < (dx*dx) and /*
*/ (this.oy - ny)*(this.oy - ny) < (dy*dy) then
// if the unit is issued a move or smart order and they are near their destination
// then move them there instantly (removes a bit of glitchyness towards the end)
call SetUnitX(u, .ox)
call SetUnitY(u, .oy)
set .x = .ox
set .y = .oy
call IssueImmediateOrderById(u, 851972) // order them to stop
else
set .x = nx + dx
set .y = ny + dy
call SetUnitX(u, .x)
call SetUnitY(u, .y)
endif
endif
endif
set this = this.next
endloop
set u = null
endmethod
static method create takes unit whichUnit, real newSpeed returns thistype
local thistype this = GetUnitUserData(whichUnit)
set this.next = thistype(0).next
set thistype(0).next.prev = this
set thistype(0).next = this
set this.prev = 0
set this.curr = whichUnit
set this.speed = (newSpeed - 522) * PERIOD
set this.x = GetUnitX(whichUnit)
set this.y = GetUnitY(whichUnit)
set this.enabled = true
return this
endmethod
static method update takes unit whichUnit, real newSpeed returns nothing
local thistype this = GetUnitUserData(whichUnit)
if this.enabled then
if newSpeed > 522 then
set this.speed = (newSpeed - 522) * PERIOD
else
call this.destroy()
endif
elseif newSpeed > 522 then
call thistype.create(whichUnit, newSpeed)
endif
endmethod
private static method storeOrderPoint takes nothing returns boolean
local thistype this = GetUnitUserData(GetTriggerUnit())
set this.ox = GetOrderPointX()
set this.oy = GetOrderPointY()
return false
endmethod
private static method onInit takes nothing returns nothing
call TimerStart(CreateTimer(), PERIOD, true, function thistype.periodic)
call TriggerRegisterAnyUnitEventBJ(issued, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerAddCondition(issued, Condition(function thistype.storeOrderPoint))
endmethod
endmodule
private struct MoveSpeedStruct extends array
implement M
endstruct
function GetUnitMoveSpeedX takes unit whichUnit returns real
if MoveSpeedStruct(GetUnitUserData(whichUnit)).enabled then
return udg_UnitSpeedX[GetUnitUserData(whichUnit)]
endif
return GetUnitMoveSpeed(whichUnit)
endfunction
function SetUnitMoveSpeedX takes unit whichUnit, real newSpeed returns nothing
call MoveSpeedStruct.update(whichUnit, newSpeed)
set udg_UnitSpeedX[GetUnitUserData(whichUnit)] = newSpeed
endfunction
hook SetUnitMoveSpeed SetUnitMoveSpeedX
endlibrary