From b26d552f19402c1eeebd8e49fa16aed9ae6adae0 Mon Sep 17 00:00:00 2001 From: Corey Sotiropoulos Date: Mon, 20 Jan 2025 20:38:30 -0500 Subject: [PATCH 1/2] Fix setSpeed Lua binding - Speed is dynamic and shouldn't be set directly. Make it protected and change speed by changing the base speed or apply an override modifier. - Manually changing speed for run pathing is unnecessary (see Dark Ixion). - Luopan and bind set base speed to 0. - Remove references to old speed settings. Fix "speed" GM command. --- scripts/commands/speed.lua | 8 +- scripts/effects/bind.lua | 4 +- scripts/globals/dark_ixion.lua | 7 +- scripts/globals/garrison.lua | 2 +- scripts/globals/pets/luopan.lua | 2 - scripts/globals/utils.lua | 4 +- scripts/specs/core/CBaseEntity.lua | 12 +- scripts/zones/Apollyon/mobs/Proto-Omega.lua | 2 +- .../mobs/Qiqirn_Treasure_Hunter.lua | 2 +- .../zones/Dynamis-Valkurm/mobs/Fairy_Ring.lua | 2 +- .../mobs/Cactrot_Rapido.lua | 3 +- .../Grauberg_[S]/mobs/Vasiliceratops.lua | 2 +- .../zones/Lufaise_Meadows/mobs/Flockbock.lua | 11 -- .../mobs/Watch_Wamoura.lua | 4 +- .../Periqia/instances/seagull_grounded.lua | 14 +- .../Rolanberry_Fields_[S]/mobs/Dyinyinga.lua | 2 +- .../Waughroon_Shrine/mobs/Princess_Jelly.lua | 2 +- .../Waughroon_Shrine/mobs/Queen_Jelly.lua | 2 +- .../zones/Xarcabard/mobs/Boreal_Coeurl.lua | 11 +- scripts/zones/Xarcabard/mobs/Boreal_Hound.lua | 11 +- scripts/zones/Xarcabard/mobs/Boreal_Tiger.lua | 11 +- src/map/ai/controllers/mob_controller.cpp | 2 +- src/map/ai/controllers/pet_controller.cpp | 2 +- .../controllers/player_charm_controller.cpp | 4 +- src/map/ai/controllers/trust_controller.cpp | 8 +- src/map/ai/helpers/pathfind.cpp | 11 +- src/map/entities/baseentity.cpp | 12 ++ src/map/entities/baseentity.h | 14 +- src/map/entities/battleentity.cpp | 138 +++++++++--------- src/map/entities/battleentity.h | 3 +- src/map/instance_loader.cpp | 10 +- src/map/lua/lua_baseentity.cpp | 60 ++++++-- src/map/lua/lua_baseentity.h | 4 +- src/map/packets/entity_update.cpp | 2 +- src/map/utils/mobutils.cpp | 4 +- src/map/utils/petutils.cpp | 5 +- src/map/utils/trustutils.cpp | 10 +- src/map/utils/zoneutils.cpp | 6 +- 38 files changed, 228 insertions(+), 185 deletions(-) diff --git a/scripts/commands/speed.lua b/scripts/commands/speed.lua index 2b6eb291940..9a0829ff7e1 100644 --- a/scripts/commands/speed.lua +++ b/scripts/commands/speed.lua @@ -34,11 +34,7 @@ commandObj.onTrigger = function(player, speed) local baseSpeed = speed if speed == 0 then - if player:hasStatusEffect(xi.effect.MOUNTED) then - baseSpeed = 40 + xi.settings.map.MOUNT_SPEED_MOD - else - baseSpeed = 50 + xi.settings.map.SPEED_MOD - end + baseSpeed = xi.settings.map.BASE_SPEED player:printToPlayer('Returning to your regular speed.') else @@ -48,7 +44,7 @@ commandObj.onTrigger = function(player, speed) end player:setMod(xi.mod.MOVE_SPEED_OVERRIDE, speed) - player:setSpeed(baseSpeed) + player:setBaseSpeed(baseSpeed) end return commandObj diff --git a/scripts/effects/bind.lua b/scripts/effects/bind.lua index 2aa4895730b..7ca9ee2f3da 100644 --- a/scripts/effects/bind.lua +++ b/scripts/effects/bind.lua @@ -5,7 +5,8 @@ local effectObject = {} effectObject.onEffectGain = function(target, effect) - effect:addMod(xi.mod.MOVE_SPEED_OVERRIDE, 300) -- Any number over 255 will make you stop + effect:setPower(target:getBaseSpeed()) + target:setBaseSpeed(0) -- Immunobreak reset. target:setMod(xi.mod.BIND_IMMUNOBREAK, 0) @@ -15,6 +16,7 @@ effectObject.onEffectTick = function(target, effect) end effectObject.onEffectLose = function(target, effect) + target:setBaseSpeed(effect:getPower()) end return effectObject diff --git a/scripts/globals/dark_ixion.lua b/scripts/globals/dark_ixion.lua index 4c344cd0c54..0fc372e146f 100644 --- a/scripts/globals/dark_ixion.lua +++ b/scripts/globals/dark_ixion.lua @@ -386,6 +386,7 @@ xi.darkixion.onMobDespawn = function(mob) end xi.darkixion.onMobSpawn = function(mob) + mob:setBaseSpeed(70) xi.darkixion.roamingMods(mob) SetServerVariable('DarkIxion_PopTime', os.time()) mob:setLocalVar('wasKilled', 0) @@ -403,11 +404,6 @@ xi.darkixion.onMobRoam = function(mob) then -- 60s of running away, time to repop somewhere else xi.darkixion.repop(mob) - elseif mob:getLocalVar('RunAway') ~= 0 then - -- run fast before repopping - mob:setSpeed(180) -- movement +350% = 40 * 4.5 - else - mob:setSpeed(70) -- movement +75% = 40 * 1.75 end if not mob:isFollowingPath() then @@ -436,7 +432,6 @@ xi.darkixion.onMobEngage = function(mob, target) mob:setLocalVar('run', 0) mob:setLocalVar('PhaseChange', os.time() + math.random(60, 240)) - mob:setSpeed(70) -- movement +75% = 40 * 1.75 end xi.darkixion.onMobDisengage = function(mob) diff --git a/scripts/globals/garrison.lua b/scripts/globals/garrison.lua index 8405873d4cb..ec9306b46a3 100644 --- a/scripts/globals/garrison.lua +++ b/scripts/globals/garrison.lua @@ -189,7 +189,7 @@ xi.garrison.spawnNPC = function(zone, zoneData, pos, name, groupId, look) mob:spawn() DisallowRespawn(mob:getID(), true) - mob:setSpeed(25) + mob:setBaseSpeed(25) mob:setAllegiance(1) -- NPCs don't cast spells or use TP skills diff --git a/scripts/globals/pets/luopan.lua b/scripts/globals/pets/luopan.lua index 2e4f4b1743c..b78311048c0 100644 --- a/scripts/globals/pets/luopan.lua +++ b/scripts/globals/pets/luopan.lua @@ -10,8 +10,6 @@ xi.pets.luopan.onMobSpawn = function(mob) mob:timer(600000, function(mobArg) mobArg:setHP(0) end) - - mob:setMod(xi.mod.MOVE_SPEED_OVERRIDE, 256) -- this mod > 255 = no movement end xi.pets.luopan.onMobDeath = function(mob) diff --git a/scripts/globals/utils.lua b/scripts/globals/utils.lua index 75cc5a032fd..4b7abb4e000 100644 --- a/scripts/globals/utils.lua +++ b/scripts/globals/utils.lua @@ -904,7 +904,7 @@ function utils.mobTeleport(mob, hideDuration, pos, disAnim, reapAnim) mob:setMagicCastingEnabled(false) mob:setMobAbilityEnabled(false) mob:setPos(pos, 0) - mob:setSpeed(0) + mob:setBaseSpeed(0) -- TODO: Temporary workaround ---@diagnostic enable: param-type-mismatch @@ -916,7 +916,7 @@ function utils.mobTeleport(mob, hideDuration, pos, disAnim, reapAnim) mobArg:setAutoAttackEnabled(true) mobArg:setMagicCastingEnabled(true) mobArg:setMobAbilityEnabled(true) - mobArg:setSpeed(mobSpeed) + mobArg:setBaseSpeed(mobSpeed) mobArg:entityAnimationPacket(reapAnim) if mobArg:isDead() then diff --git a/scripts/specs/core/CBaseEntity.lua b/scripts/specs/core/CBaseEntity.lua index 91b38af357b..c183949bb61 100644 --- a/scripts/specs/core/CBaseEntity.lua +++ b/scripts/specs/core/CBaseEntity.lua @@ -1342,9 +1342,19 @@ end function CBaseEntity:getSpeed() end +---@nodiscard +---@return integer +function CBaseEntity:getBaseSpeed() +end + +---@param speedVal integer +---@return nil +function CBaseEntity:setBaseSpeed(speedVal) +end + ---@param speedVal integer ---@return nil -function CBaseEntity:setSpeed(speedVal) +function CBaseEntity:setAnimationSpeed(speedVal) end ---@nodiscard diff --git a/scripts/zones/Apollyon/mobs/Proto-Omega.lua b/scripts/zones/Apollyon/mobs/Proto-Omega.lua index a414dcb5f4e..6be5c84daf5 100644 --- a/scripts/zones/Apollyon/mobs/Proto-Omega.lua +++ b/scripts/zones/Apollyon/mobs/Proto-Omega.lua @@ -54,7 +54,7 @@ entity.onMobSpawn = function(mob) mob:setBehavior(bit.bor(mob:getBehavior(), xi.behavior.NO_TURN)) -- base speed of 60 is based on retail capture and applies to all forms -- also has standard boost (2.5x) up to 150 when target is out of range - mob:setSpeed(60) + mob:setBaseSpeed(60) quadrupedForm(mob) end diff --git a/scripts/zones/Arrapago_Remnants/mobs/Qiqirn_Treasure_Hunter.lua b/scripts/zones/Arrapago_Remnants/mobs/Qiqirn_Treasure_Hunter.lua index 9139c702729..2dccf33cbdd 100644 --- a/scripts/zones/Arrapago_Remnants/mobs/Qiqirn_Treasure_Hunter.lua +++ b/scripts/zones/Arrapago_Remnants/mobs/Qiqirn_Treasure_Hunter.lua @@ -17,7 +17,7 @@ entity.onMobRoamAction = function(mob) local prog = instance:getProgress() if not mob:isFollowingPath() then - mob:setSpeed(40) + mob:setBaseSpeed(40) mob:pathThrough(ID.points[stage][prog].route, 9) end end diff --git a/scripts/zones/Dynamis-Valkurm/mobs/Fairy_Ring.lua b/scripts/zones/Dynamis-Valkurm/mobs/Fairy_Ring.lua index 32049a429f3..051fe76bd1a 100644 --- a/scripts/zones/Dynamis-Valkurm/mobs/Fairy_Ring.lua +++ b/scripts/zones/Dynamis-Valkurm/mobs/Fairy_Ring.lua @@ -6,7 +6,7 @@ local entity = {} entity.onMobSpawn = function(mob) - mob:setSpeed(70) + mob:setBaseSpeed(70) mob:setMobSkillAttack(2008) -- use mephitic spare as its auto attack mob:addImmunity(xi.immunity.LIGHT_SLEEP) mob:addImmunity(xi.immunity.DARK_SLEEP) diff --git a/scripts/zones/Eastern_Altepa_Desert/mobs/Cactrot_Rapido.lua b/scripts/zones/Eastern_Altepa_Desert/mobs/Cactrot_Rapido.lua index 6f4eeb6c8f4..ea005d80146 100644 --- a/scripts/zones/Eastern_Altepa_Desert/mobs/Cactrot_Rapido.lua +++ b/scripts/zones/Eastern_Altepa_Desert/mobs/Cactrot_Rapido.lua @@ -116,7 +116,8 @@ local pathNodes = entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.ONE_WAY_LINKING, 1) - mob:setSpeed(250) + mob:setBaseSpeed(72) + mob:setAnimationSpeed(180) mob:pathThrough(pathNodes, bit.bor(xi.path.flag.PATROL, xi.path.flag.RUN)) end diff --git a/scripts/zones/Grauberg_[S]/mobs/Vasiliceratops.lua b/scripts/zones/Grauberg_[S]/mobs/Vasiliceratops.lua index bd6e3f0a012..501031e6de7 100644 --- a/scripts/zones/Grauberg_[S]/mobs/Vasiliceratops.lua +++ b/scripts/zones/Grauberg_[S]/mobs/Vasiliceratops.lua @@ -14,7 +14,7 @@ entity.onMobInitialize = function(mob) mob:addImmunity(xi.immunity.PETRIFY) mob:setMod(xi.mod.DOUBLE_ATTACK, 100) - mob:setSpeed(100) + mob:setBaseSpeed(100) end entity.onMobWeaponSkillPrepare = function(mob, target) diff --git a/scripts/zones/Lufaise_Meadows/mobs/Flockbock.lua b/scripts/zones/Lufaise_Meadows/mobs/Flockbock.lua index 8c97b0bfbb7..4a9bdb6c6e1 100644 --- a/scripts/zones/Lufaise_Meadows/mobs/Flockbock.lua +++ b/scripts/zones/Lufaise_Meadows/mobs/Flockbock.lua @@ -29,17 +29,6 @@ entity.onMobSpawn = function(mob) mob:setLocalVar('[rage]timer', 3600) -- 60 minutes end --- TODO: Mob's movement speed is increased while chasing target. --- It's tricky to emulate this exact mechanic, because on retail 'chase' --- is triggered not only while the mob engaged, but also when target is out of range. -entity.onMobEngage = function(mob) - mob:setSpeed(100) -end - -entity.onMobDisengage = function(mob) - mob:setSpeed(40) -end - entity.onMobDeath = function(mob, player, optParams) xi.hunts.checkHunt(mob, player, 442) end diff --git a/scripts/zones/Navukgo_Execution_Chamber/mobs/Watch_Wamoura.lua b/scripts/zones/Navukgo_Execution_Chamber/mobs/Watch_Wamoura.lua index 5da23d1fb8b..69a51a0da6e 100644 --- a/scripts/zones/Navukgo_Execution_Chamber/mobs/Watch_Wamoura.lua +++ b/scripts/zones/Navukgo_Execution_Chamber/mobs/Watch_Wamoura.lua @@ -6,7 +6,7 @@ local entity = {} local function curl(mob) - mob:setSpeed(20) + mob:setBaseSpeed(20) mob:setMod(xi.mod.DMG, -9500) mob:addStatusEffect(xi.effect.BLAZE_SPIKES, 100, 0, 0) mob:setAnimationSub(5) @@ -14,7 +14,7 @@ local function curl(mob) end local function stretch(mob) - mob:setSpeed(100) + mob:setBaseSpeed(100) mob:delMod(xi.mod.DMG, -9500) mob:delStatusEffect(xi.effect.BLAZE_SPIKES) mob:setAnimationSub(4) diff --git a/scripts/zones/Periqia/instances/seagull_grounded.lua b/scripts/zones/Periqia/instances/seagull_grounded.lua index cd8b2ba2850..f57dbfabb39 100644 --- a/scripts/zones/Periqia/instances/seagull_grounded.lua +++ b/scripts/zones/Periqia/instances/seagull_grounded.lua @@ -381,14 +381,14 @@ instanceObject.onTrack = function(instance) mob:setLocalVar('pathLeg', 1) mob:showText(mob, ID.text.EXCALIACE_CRAB1) - mob:setSpeed(60) + mob:setBaseSpeed(60) break elseif enemys:getFamily() == 197 then -- pugil - mob:setSpeed(75) + mob:setBaseSpeed(75) mob:showText(mob, ID.text.EXCALIACE_DEBAUCHER1) break elseif enemys:getFamily() == 86 then -- doomed - mob:setSpeed(100) + mob:setBaseSpeed(100) mob:showText(mob, ID.text.EXCALIACE_DEBAUCHER2) break end @@ -425,13 +425,13 @@ instanceObject.onTrack = function(instance) mob:setLocalVar('runStart', 0) mob:setLocalVar('chatMessage', 1) mob:setLocalVar('mobChatMessage', 0) - mob:setSpeed(40) + mob:setBaseSpeed(40) break else mob:showText(mob, ID.text.EXCALIACE_TOO_CLOSE) mob:setLocalVar('chatMessage', 1) mob:setLocalVar('mobChatMessage', 0) - mob:setSpeed(40) + mob:setBaseSpeed(40) break end end @@ -441,7 +441,7 @@ instanceObject.onTrack = function(instance) mob:setLocalVar('moveStatus', 0) if chatMessage == 0 then mob:showText(mob, ID.text.EXCALIACE_TOO_CLOSE) - mob:setSpeed(40) + mob:setBaseSpeed(40) mob:setLocalVar('chatMessage', 1) mob:setLocalVar('mobChatMessage', 0) break @@ -502,7 +502,7 @@ instanceObject.onTrack = function(instance) mob:setLocalVar('runTimer', os.time() + math.random(30, 40)) mob:showText(mob, ID.text.EXCALIACE_RUN) mob:setLocalVar('runStart', 1) - mob:setSpeed(100) + mob:setBaseSpeed(100) end end end diff --git a/scripts/zones/Rolanberry_Fields_[S]/mobs/Dyinyinga.lua b/scripts/zones/Rolanberry_Fields_[S]/mobs/Dyinyinga.lua index e7dc5f9dfc6..f658f58917a 100644 --- a/scripts/zones/Rolanberry_Fields_[S]/mobs/Dyinyinga.lua +++ b/scripts/zones/Rolanberry_Fields_[S]/mobs/Dyinyinga.lua @@ -11,7 +11,7 @@ local entity = {} entity.onMobInitialize = function(mob) - mob:setSpeed(100) + mob:setBaseSpeed(100) mob:setMobMod(xi.mobMod.ADD_EFFECT, 1) mob:setMod(xi.mod.AURA_SIZE, -575) -- 6.25 + (-575) / 100 = .5' end diff --git a/scripts/zones/Waughroon_Shrine/mobs/Princess_Jelly.lua b/scripts/zones/Waughroon_Shrine/mobs/Princess_Jelly.lua index 6288749814d..64d8be72750 100644 --- a/scripts/zones/Waughroon_Shrine/mobs/Princess_Jelly.lua +++ b/scripts/zones/Waughroon_Shrine/mobs/Princess_Jelly.lua @@ -44,7 +44,7 @@ entity.onMobInitialize = function(mob) end entity.onMobSpawn = function(mob) - mob:setSpeed((50 + xi.settings.map.SPEED_MOD) * 0.05) -- ~5% of normal movementspeed + mob:setBaseSpeed(xi.settings.map.BASE_SPEED * 0.05) -- ~5% of normal movementspeed mob:setMod(xi.mod.REGEN, 3) mob:setLocalVar('mobElement', math.random(1, 8)) mob:addMod(mevaList[mob:getLocalVar('mobElement')][1], -250) diff --git a/scripts/zones/Waughroon_Shrine/mobs/Queen_Jelly.lua b/scripts/zones/Waughroon_Shrine/mobs/Queen_Jelly.lua index 4a9ec3b1eb2..092cb927f41 100644 --- a/scripts/zones/Waughroon_Shrine/mobs/Queen_Jelly.lua +++ b/scripts/zones/Waughroon_Shrine/mobs/Queen_Jelly.lua @@ -15,7 +15,7 @@ entity.onMobInitialize = function(mob) end entity.onMobSpawn = function(mob) - mob:setSpeed(60) + mob:setBaseSpeed(60) end entity.onMobDeath = function(mob, player, optParams) diff --git a/scripts/zones/Xarcabard/mobs/Boreal_Coeurl.lua b/scripts/zones/Xarcabard/mobs/Boreal_Coeurl.lua index fd4c50fd5de..3d115dde6b0 100644 --- a/scripts/zones/Xarcabard/mobs/Boreal_Coeurl.lua +++ b/scripts/zones/Xarcabard/mobs/Boreal_Coeurl.lua @@ -50,9 +50,9 @@ end entity.onPathPoint = function(mob) if math.random(1, 100) <= 50 then - mob:setSpeed(0) + mob:setBaseSpeed(0) mob:timer(math.random(4000, 8000), function(mobArg) - mobArg:setSpeed(baseSpeed) + mobArg:setBaseSpeed(baseSpeed) end) mob:timer(lookDelay, function(mobArg) @@ -62,6 +62,7 @@ entity.onPathPoint = function(mob) end entity.onMobRoam = function(mob) + mob:setMobMod(xi.mobMod.NO_MOVE, 0) local pathingIndex = mob:getLocalVar('pathingIndex') if @@ -71,7 +72,6 @@ entity.onMobRoam = function(mob) local pathFlag = xi.pathflag.SLIDE if math.random(1, 100) <= 50 then -- sometimes he runs between points - mob:setSpeed(baseSpeed * 1.5) pathFlag = pathFlag + xi.pathflag.RUN end @@ -82,14 +82,15 @@ entity.onMobRoam = function(mob) end entity.onMobEngage = function(mob) - mob:setSpeed(baseSpeed) + mob:setBaseSpeed(baseSpeed) end entity.onMobSpawn = function(mob) mob:addImmunity(xi.immunity.STUN) mob:setMobMod(xi.mobMod.ALWAYS_AGGRO, 1) + mob:setMobMod(xi.mobMod.NO_MOVE, 0) mob:setMod(xi.mod.FASTCAST, 30) - mob:setSpeed(baseSpeed) + mob:setBaseSpeed(baseSpeed) -- Failsafe to make sure NPC is down when NM is up if xi.settings.main.OLDSCHOOL_G2 then GetNPCByID(ID.npc.BOREAL_COEURL_QM):showNPC(0) diff --git a/scripts/zones/Xarcabard/mobs/Boreal_Hound.lua b/scripts/zones/Xarcabard/mobs/Boreal_Hound.lua index 33f2bc07ae3..4af3cfff6e9 100644 --- a/scripts/zones/Xarcabard/mobs/Boreal_Hound.lua +++ b/scripts/zones/Xarcabard/mobs/Boreal_Hound.lua @@ -52,9 +52,9 @@ end entity.onPathPoint = function(mob) if math.random(1, 100) <= 50 then - mob:setSpeed(0) + mob:setBaseSpeed(0) mob:timer(math.random(4000, 8000), function(mobArg) - mobArg:setSpeed(baseSpeed) + mobArg:setBaseSpeed(baseSpeed) end) mob:timer(lookDelay, function(mobArg) @@ -64,6 +64,7 @@ entity.onPathPoint = function(mob) end entity.onMobRoam = function(mob) + mob:setMobMod(xi.mobMod.NO_MOVE, 0) local pathingIndex = mob:getLocalVar('pathingIndex') if @@ -73,7 +74,6 @@ entity.onMobRoam = function(mob) local pathFlag = xi.pathflag.SLIDE if math.random(1, 100) <= 50 then -- sometimes he runs between points - mob:setSpeed(baseSpeed * 1.5) pathFlag = pathFlag + xi.pathflag.RUN end @@ -84,15 +84,16 @@ entity.onMobRoam = function(mob) end entity.onMobEngage = function(mob) - mob:setSpeed(baseSpeed) + mob:setBaseSpeed(baseSpeed) end entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.WEAPON_BONUS, 50) mob:setMobMod(xi.mobMod.ALWAYS_AGGRO, 1) + mob:setMobMod(xi.mobMod.NO_MOVE, 0) mob:addImmunity(xi.immunity.SILENCE) mob:addImmunity(xi.immunity.PARALYZE) - mob:setSpeed(baseSpeed) + mob:setBaseSpeed(baseSpeed) -- Failsafe to make sure NPC is down when NM is up if xi.settings.main.OLDSCHOOL_G2 then GetNPCByID(ID.npc.BOREAL_HOUND_QM):showNPC(0) diff --git a/scripts/zones/Xarcabard/mobs/Boreal_Tiger.lua b/scripts/zones/Xarcabard/mobs/Boreal_Tiger.lua index 5761ec693b4..0da9ef31fed 100644 --- a/scripts/zones/Xarcabard/mobs/Boreal_Tiger.lua +++ b/scripts/zones/Xarcabard/mobs/Boreal_Tiger.lua @@ -47,9 +47,9 @@ end entity.onPathPoint = function(mob) if math.random(1, 100) <= 50 then - mob:setSpeed(0) + mob:setBaseSpeed(0) mob:timer(math.random(4000, 8000), function(mobArg) - mobArg:setSpeed(baseSpeed) + mobArg:setBaseSpeed(baseSpeed) end) mob:timer(lookDelay, function(mobArg) @@ -59,6 +59,7 @@ entity.onPathPoint = function(mob) end entity.onMobRoam = function(mob) + mob:setMobMod(xi.mobMod.NO_MOVE, 0) local pathingIndex = mob:getLocalVar('pathingIndex') if @@ -68,7 +69,6 @@ entity.onMobRoam = function(mob) local pathFlag = xi.pathflag.SLIDE if math.random(1, 100) <= 50 then -- sometimes he runs between points - mob:setSpeed(baseSpeed * 1.5) pathFlag = pathFlag + xi.pathflag.RUN end @@ -79,12 +79,13 @@ entity.onMobRoam = function(mob) end entity.onMobEngage = function(mob) - mob:setSpeed(baseSpeed) + mob:setBaseSpeed(baseSpeed) end entity.onMobSpawn = function(mob) mob:setMobMod(xi.mobMod.ALWAYS_AGGRO, 1) - mob:setSpeed(baseSpeed) + mob:setMobMod(xi.mobMod.NO_MOVE, 0) + mob:setBaseSpeed(baseSpeed) -- Failsafe to make sure NPC is down when NM is up if xi.settings.main.OLDSCHOOL_G2 then GetNPCByID(ID.npc.BOREAL_TIGER_QM):showNPC(0) diff --git a/src/map/ai/controllers/mob_controller.cpp b/src/map/ai/controllers/mob_controller.cpp index 20bcaa66270..d14efe76c63 100644 --- a/src/map/ai/controllers/mob_controller.cpp +++ b/src/map/ai/controllers/mob_controller.cpp @@ -720,7 +720,7 @@ void CMobController::Move() if (((currentDistance > closeDistance) || move) && PMob->PAI->CanFollowPath()) { - if (PMob->speed != 0 && PMob->getMobMod(MOBMOD_NO_MOVE) == 0 && m_Tick >= m_LastSpecialTime) + if (PMob->GetSpeed() != 0 && PMob->getMobMod(MOBMOD_NO_MOVE) == 0 && m_Tick >= m_LastSpecialTime) { // attempt to teleport to target (if in range) if (PMob->getMobMod(MOBMOD_TELEPORT_TYPE) == 2) diff --git a/src/map/ai/controllers/pet_controller.cpp b/src/map/ai/controllers/pet_controller.cpp index db70a13a2a4..65a86c003ae 100644 --- a/src/map/ai/controllers/pet_controller.cpp +++ b/src/map/ai/controllers/pet_controller.cpp @@ -127,7 +127,7 @@ void CPetController::DoRoamTick(time_point tick) } PPet->PAI->PathFind->FollowPath(m_Tick); } - else if (PPet->speed > 0) + else if (PPet->GetSpeed() > 0) { PPet->PAI->PathFind->WarpTo(PPet->PMaster->loc.p, PetRoamDistance); } diff --git a/src/map/ai/controllers/player_charm_controller.cpp b/src/map/ai/controllers/player_charm_controller.cpp index 9ae01b37f33..e6bb73ee1cd 100644 --- a/src/map/ai/controllers/player_charm_controller.cpp +++ b/src/map/ai/controllers/player_charm_controller.cpp @@ -81,7 +81,7 @@ void CPlayerCharmController::DoCombatTick(time_point tick) std::unique_ptr err; if (!POwner->CanAttack(PTarget, err)) { - if (POwner->speed > 0) + if (POwner->GetSpeed() > 0) { POwner->PAI->PathFind->PathAround(PTarget->loc.p, 2.0f, PATHFLAG_WALLHACK | PATHFLAG_RUN); POwner->PAI->PathFind->FollowPath(m_Tick); @@ -108,7 +108,7 @@ void CPlayerCharmController::DoRoamTick(time_point tick) { POwner->PAI->PathFind->FollowPath(m_Tick); } - else if (POwner->speed > 0) + else if (POwner->GetSpeed() > 0) { POwner->PAI->PathFind->WarpTo(POwner->PMaster->loc.p, RoamDistance); } diff --git a/src/map/ai/controllers/trust_controller.cpp b/src/map/ai/controllers/trust_controller.cpp index 5c34f39af66..32a0d7fce87 100644 --- a/src/map/ai/controllers/trust_controller.cpp +++ b/src/map/ai/controllers/trust_controller.cpp @@ -140,7 +140,7 @@ void CTrustController::DoCombatTick(time_point tick) if (PTarget) { - if (POwner->PAI->CanFollowPath() && POwner->speed > 0) + if (POwner->PAI->CanFollowPath() && POwner->GetSpeed() > 0) { float currentDistanceToTarget = distance(POwner->loc.p, PTarget->loc.p); float currentDistanceToMaster = distance(POwner->loc.p, PMaster->loc.p); @@ -171,7 +171,7 @@ void CTrustController::DoCombatTick(time_point tick) case TRUST_MOVEMENT_TYPE::MELEE: { std::unique_ptr err; - if (!POwner->CanAttack(PTarget, err) && POwner->speed > 0) + if (!POwner->CanAttack(PTarget, err) && POwner->GetSpeed() > 0) { if (currentDistanceToTarget > RoamDistance) { @@ -180,7 +180,7 @@ void CTrustController::DoCombatTick(time_point tick) { POwner->PAI->PathFind->FollowPath(m_Tick); } - else if (POwner->speed > 0) + else if (POwner->GetSpeed() > 0) { POwner->PAI->PathFind->StepTo(PTarget->loc.p, true); } @@ -288,7 +288,7 @@ void CTrustController::DoRoamTick(time_point tick) { POwner->PAI->PathFind->FollowPath(m_Tick); } - else if (POwner->speed > 0) + else if (POwner->GetSpeed() > 0) { POwner->PAI->PathFind->StepTo(PFollowTarget->loc.p, true); } diff --git a/src/map/ai/helpers/pathfind.cpp b/src/map/ai/helpers/pathfind.cpp index 8ccd19b5470..1840630b92d 100644 --- a/src/map/ai/helpers/pathfind.cpp +++ b/src/map/ai/helpers/pathfind.cpp @@ -361,17 +361,12 @@ void CPathFind::FollowPath(time_point tick) void CPathFind::StepTo(const position_t& pos, bool run) { TracyZoneScoped; - bool speedChange = false; - if (auto* PBattleEntity = dynamic_cast(m_POwner)) - { - speedChange = PBattleEntity->speed != PBattleEntity->UpdateSpeed(run); - } - - float speed = m_POwner->speed; + bool speedChange = m_POwner->GetSpeed() != m_POwner->UpdateSpeed(run); + float speed = m_POwner->GetSpeed(); if (const auto* PMobEntity = dynamic_cast(m_POwner)) { - if (PMobEntity->speed == 0 && (m_roamFlags & ROAMFLAG_WORM)) + if (PMobEntity->GetSpeed() == 0 && (m_roamFlags & ROAMFLAG_WORM)) { speed = 20; } diff --git a/src/map/entities/baseentity.cpp b/src/map/entities/baseentity.cpp index 5ff55515d14..8d33caea102 100644 --- a/src/map/entities/baseentity.cpp +++ b/src/map/entities/baseentity.cpp @@ -116,6 +116,18 @@ uint8 CBaseEntity::GetRotPos() const return loc.p.rotation; } +uint8 CBaseEntity::GetSpeed() const +{ + return speed; +} + +uint8 CBaseEntity::UpdateSpeed(bool run) +{ + std::ignore = run; + speed = baseSpeed; + return speed; +} + void CBaseEntity::HideName(bool hide) { if (hide) diff --git a/src/map/entities/baseentity.h b/src/map/entities/baseentity.h index f4083e7ca0a..b594545f700 100644 --- a/src/map/entities/baseentity.h +++ b/src/map/entities/baseentity.h @@ -268,11 +268,13 @@ class CBaseEntity virtual const std::string& getName(); // Internal name of entity virtual const std::string& getPacketName(); // Name of entity sent to the client - uint16 getZone() const; // Current zone - float GetXPos() const; // Position of co-ordinate X - float GetYPos() const; // Position of co-ordinate Y - float GetZPos() const; // Position of co-ordinate Z - uint8 GetRotPos() const; + uint16 getZone() const; // Current zone + float GetXPos() const; // Position of co-ordinate X + float GetYPos() const; // Position of co-ordinate Y + float GetZPos() const; // Position of co-ordinate Z + uint8 GetRotPos() const; + uint8 GetSpeed() const; + virtual uint8 UpdateSpeed(bool run = false); void HideName(bool hide); // hide / show name void GhostPhase(bool ghost); // makes mob semi transparent @@ -316,7 +318,6 @@ class CBaseEntity uint8 animation; // animation uint8 animationsub; // Additional animation parameter uint8 baseSpeed; // base movement speed - uint8 speed; // speed of movement uint8 animationSpeed; // speed of movement animation uint8 namevis; ALLEGIANCE_TYPE allegiance; // what types of targets the entity can fight @@ -337,6 +338,7 @@ class CBaseEntity protected: std::map m_localVars; + uint8 speed; // speed of movement }; #endif // _BASEENTITY_H diff --git a/src/map/entities/battleentity.cpp b/src/map/entities/battleentity.cpp index 0d1e34fff9d..59c7a369717 100644 --- a/src/map/entities/battleentity.cpp +++ b/src/map/entities/battleentity.cpp @@ -306,98 +306,94 @@ uint8 CBattleEntity::UpdateSpeed(bool run) { outputSpeed = settings::get("map.MOUNT_SPEED") / 2; outputSpeed *= (100 + getMod(Mod::MOUNT_MOVE)) / 100; - speed = std::clamp(outputSpeed, std::numeric_limits::min(), std::numeric_limits::max()); - - return speed; } + else if (baseSpeed == 0 || getMod(Mod::MOVE_SPEED_OVERRIDE) > 255) + { + outputSpeed = 0; + } + else if (getMod(Mod::MOVE_SPEED_OVERRIDE) > 0) + { + // GM speed bypass. + // Speed cap can be bypassed. Ex. Feast of swords. GM speed. + // TODO: Find exceptions. Add them here. + outputSpeed = getMod(Mod::MOVE_SPEED_OVERRIDE); + } + else + { + // Gear penalties. + int8 additiveMods = static_cast(getMod(Mod::MOVE_SPEED_STACKABLE)); - // Gear penalties. - int8 additiveMods = static_cast(getMod(Mod::MOVE_SPEED_STACKABLE)); - - // Gravity and Curse. They seem additive to each other and the sum seems to be multiplicative. - float weightFactor = std::clamp(1.0f - static_cast(getMod(Mod::MOVE_SPEED_WEIGHT_PENALTY)) / 100.0f, 0.1f, 1.0f); + // Gravity and Curse. They seem additive to each other and the sum seems to be multiplicative. + float weightFactor = std::clamp(1.0f - static_cast(getMod(Mod::MOVE_SPEED_WEIGHT_PENALTY)) / 100.0f, 0.1f, 1.0f); - // Flee. - float fleeFactor = std::clamp(1.0f + static_cast(getMod(Mod::MOVE_SPEED_FLEE)) / 10000.0f, 1.0f, 2.0f); + // Flee. + float fleeFactor = std::clamp(1.0f + static_cast(getMod(Mod::MOVE_SPEED_FLEE)) / 10000.0f, 1.0f, 2.0f); - // Cheer KI's - float cheerFactor = (99.0f + static_cast(getMod(Mod::MOVE_SPEED_CHEER))) / 99.0f; + // Cheer KI's + float cheerFactor = (99.0f + static_cast(getMod(Mod::MOVE_SPEED_CHEER))) / 99.0f; - // Bolter's Roll. Additive - uint8 boltersRollEffect = static_cast(getMod(Mod::MOVE_SPEED_BOLTERS_ROLL)); + // Bolter's Roll. Additive + uint8 boltersRollEffect = static_cast(getMod(Mod::MOVE_SPEED_BOLTERS_ROLL)); - // Positive movement speed from gear and from Atmas. Only highest applies. Multiplicative to base speed. - float gearFactor = 1.0f; + // Positive movement speed from gear and from Atmas. Only highest applies. Multiplicative to base speed. + float gearFactor = 1.0f; - if (objtype == TYPE_PC) - { - gearFactor = std::clamp(1.0f + static_cast(getMaxGearMod(Mod::MOVE_SPEED_GEAR_BONUS)) / 100.0f, 1.0f, 1.25f); - } + if (objtype == TYPE_PC) + { + gearFactor = std::clamp(1.0f + static_cast(getMaxGearMod(Mod::MOVE_SPEED_GEAR_BONUS)) / 100.0f, 1.0f, 1.25f); + } - // Quickening and Mazurka. They share a cap. Additive. - uint8 mazurkaQuickeningEffect = std::clamp(getMod(Mod::MOVE_SPEED_QUICKENING) + getMod(Mod::MOVE_SPEED_MAZURKA), 0, 10); + // Quickening and Mazurka. They share a cap. Additive. + uint8 mazurkaQuickeningEffect = std::clamp(getMod(Mod::MOVE_SPEED_QUICKENING) + getMod(Mod::MOVE_SPEED_MAZURKA), 0, 10); - // We have all the modifiers needed. Calculate final speed. - // This MUST BE DONE IN THIS ORDER. Using int8 data type, we use that to floor. - outputSpeed = baseSpeed + additiveMods; - outputSpeed = outputSpeed * weightFactor; - outputSpeed = outputSpeed * fleeFactor; - outputSpeed = outputSpeed * cheerFactor; - outputSpeed = outputSpeed + boltersRollEffect; - outputSpeed = outputSpeed * gearFactor; - if (outputSpeed > 0) - { - outputSpeed = outputSpeed + mazurkaQuickeningEffect; - } + // We have all the modifiers needed. Calculate final speed. + // This MUST BE DONE IN THIS ORDER. Using int8 data type, we use that to floor. + outputSpeed = baseSpeed + additiveMods; + outputSpeed = outputSpeed * weightFactor; + outputSpeed = outputSpeed * fleeFactor; + outputSpeed = outputSpeed * cheerFactor; + outputSpeed = outputSpeed + boltersRollEffect; + outputSpeed = outputSpeed * gearFactor; + if (outputSpeed > 0) + { + outputSpeed = outputSpeed + mazurkaQuickeningEffect; + } - // Set cap if a PC (Default 80). - if (objtype == TYPE_PC) - { - outputSpeed = std::clamp(outputSpeed, 0, settings::get("map.SPEED_LIMIT")); - } + // Set cap if a PC (Default 80). + if (objtype == TYPE_PC) + { + outputSpeed = std::clamp(outputSpeed, 0, settings::get("map.SPEED_LIMIT")); + } - if (run && outputSpeed > 0 && getMod(Mod::MOVE_SPEED_OVERRIDE) == 0) - { - float multiplier = settings::get("map.MOB_RUN_SPEED_MULTIPLIER"); - if (multiplier > 1.0f) + if (run && outputSpeed > 0) { - if (auto* mobEntity = dynamic_cast(this)) + float multiplier = settings::get("map.MOB_RUN_SPEED_MULTIPLIER"); + if (multiplier > 1.0f) { - // mob has a custom multiplier - if (mobEntity->getMobMod(MOBMOD_RUN_SPEED_MULT) > 0) + if (auto* mobEntity = dynamic_cast(this)) { - multiplier = mobEntity->getMobMod(MOBMOD_RUN_SPEED_MULT) / 100.0f; - } + // mob has a custom multiplier + if (mobEntity->getMobMod(MOBMOD_RUN_SPEED_MULT) > 0) + { + multiplier = mobEntity->getMobMod(MOBMOD_RUN_SPEED_MULT) / 100.0f; + } - // if some weight penalty (like gravity) then cut the multiplier - // (for mobs with default boost of 2.5 then boost becomes 1.20) - if (mobEntity->getMod(Mod::MOVE_SPEED_WEIGHT_PENALTY) > 0) - { - multiplier *= 0.48f; - } + // if some weight penalty (like gravity) then cut the multiplier + // (for mobs with default boost of 2.5 then boost becomes 1.20) + if (mobEntity->getMod(Mod::MOVE_SPEED_WEIGHT_PENALTY) > 0) + { + multiplier *= 0.48f; + } - // Ensure the multiplier is at least 1.0 so that multiplier never decreases speed - multiplier = std::max(multiplier, 1.0f); + // Ensure the multiplier is at least 1.0 so that multiplier never decreases speed + multiplier = std::max(multiplier, 1.0f); - outputSpeed *= multiplier; + outputSpeed *= multiplier; + } } } } - // Speed cap can be bypassed. Ex. Feast of swords. GM speed. - // TODO: Find exceptions. Add them here. - - // GM speed bypass. - - if (getMod(Mod::MOVE_SPEED_OVERRIDE) > 255) - { - outputSpeed = 0; - } - else if (getMod(Mod::MOVE_SPEED_OVERRIDE) > 0) - { - outputSpeed = getMod(Mod::MOVE_SPEED_OVERRIDE); - } - speed = static_cast(std::clamp(outputSpeed, std::numeric_limits::min(), std::numeric_limits::max())); return speed; diff --git a/src/map/entities/battleentity.h b/src/map/entities/battleentity.h index 3a6be58bb81..44872a522af 100644 --- a/src/map/entities/battleentity.h +++ b/src/map/entities/battleentity.h @@ -564,8 +564,6 @@ class CBattleEntity : public CBaseEntity uint16 RATT(uint8 skill, uint16 bonusSkill = 0); uint16 RACC(uint8 skill, uint16 bonusSkill = 0); - uint8 UpdateSpeed(bool run = false); - bool isDead(); bool isAlive(); bool isInAdoulin(); @@ -595,6 +593,7 @@ class CBattleEntity : public CBaseEntity uint8 GetMPP() const; int32 GetMaxMP() const; void UpdateHealth(); // recalculation of the maximum amount of hp and mp, as well as adjusting their current values + uint8 UpdateSpeed(bool run = false) override; int16 GetWeaponDelay(bool tp); // returns delay of combined weapons float GetMeleeRange() const; // returns the distance considered to be within melee range of the entity diff --git a/src/map/instance_loader.cpp b/src/map/instance_loader.cpp index 1f17cacb935..867409b7159 100644 --- a/src/map/instance_loader.cpp +++ b/src/map/instance_loader.cpp @@ -135,8 +135,8 @@ CInstance* CInstanceLoader::LoadInstance() PMob->m_ModelRadius = (float)_sql->GetIntData(24); PMob->baseSpeed = (uint8)_sql->GetIntData(25); - PMob->speed = (uint8)_sql->GetIntData(25); PMob->animationSpeed = (uint8)_sql->GetIntData(25); + PMob->UpdateSpeed(); PMob->strRank = (uint8)_sql->GetIntData(26); PMob->dexRank = (uint8)_sql->GetIntData(27); @@ -259,11 +259,11 @@ CInstance* CInstanceLoader::LoadInstance() PNpc->m_TargID = _sql->GetUIntData(6) >> 16; // "quite likely" - PNpc->baseSpeed = (uint8)_sql->GetIntData(8); - PNpc->speed = (uint8)_sql->GetIntData(7); + PNpc->baseSpeed = (uint8)_sql->GetIntData(7); PNpc->animationSpeed = (uint8)_sql->GetIntData(8); - PNpc->animation = (uint8)_sql->GetIntData(9); - PNpc->animationsub = (uint8)_sql->GetIntData(10); + PNpc->UpdateSpeed(); + PNpc->animation = (uint8)_sql->GetIntData(9); + PNpc->animationsub = (uint8)_sql->GetIntData(10); PNpc->namevis = (uint8)_sql->GetIntData(11); PNpc->status = static_cast(_sql->GetIntData(12)); diff --git a/src/map/lua/lua_baseentity.cpp b/src/map/lua/lua_baseentity.cpp index d41d5d2d8ae..514d92009cb 100644 --- a/src/map/lua/lua_baseentity.cpp +++ b/src/map/lua/lua_baseentity.cpp @@ -6021,30 +6021,70 @@ bool CLuaBaseEntity::canUseMisc(uint16 misc) /************************************************************************ * Function: getSpeed() - * Purpose : Sets a player's speed or returns their current speed + * Purpose : Gets a player's current speed * Example : player:getSpeed() * Notes : ************************************************************************/ uint8 CLuaBaseEntity::getSpeed() { - return m_PBaseEntity->speed; + return m_PBaseEntity->GetSpeed(); } /************************************************************************ - * Function: setSpeed() - * Purpose : Sets a player's speed or returns their current speed - * Example : player:setSpeed(40) + * Function: getBaseSpeed() + * Purpose : Gets a player's base speed + * Example : player:getBaseSpeed() * Notes : ************************************************************************/ -void CLuaBaseEntity::setSpeed(uint8 speedVal) +uint8 CLuaBaseEntity::getBaseSpeed() +{ + return m_PBaseEntity->baseSpeed; +} + +/************************************************************************ + * Function: setBaseSpeed() + * Purpose : Sets a player's base speed + * Example : player:setBaseSpeed(40) + * Notes : + ************************************************************************/ + +void CLuaBaseEntity::setBaseSpeed(uint8 speedVal) +{ + auto speed = std::min(speedVal, 255); + + if (m_PBaseEntity->baseSpeed != speed) + { + m_PBaseEntity->baseSpeed = speed; + m_PBaseEntity->UpdateSpeed(); + + if (m_PBaseEntity->objtype == TYPE_PC) + { + auto* PChar = static_cast(m_PBaseEntity); + PChar->pushPacket(PChar); + } + else + { + m_PBaseEntity->loc.zone->UpdateEntityPacket(m_PBaseEntity, ENTITY_UPDATE, UPDATE_POS); + } + } +} + +/************************************************************************ + * Function: setAnimationSpeed() + * Purpose : Sets a player's animation speed + * Example : player:setAnimationSpeed(40) + * Notes : + ************************************************************************/ + +void CLuaBaseEntity::setAnimationSpeed(uint8 speedVal) { auto speed = std::min(speedVal, 255); - if (m_PBaseEntity->speed != speed) + if (m_PBaseEntity->animationSpeed != speed) { - m_PBaseEntity->speed = speed; + m_PBaseEntity->animationSpeed = speed; if (m_PBaseEntity->objtype == TYPE_PC) { @@ -18717,7 +18757,9 @@ void CLuaBaseEntity::Register() SOL_REGISTER("canUseMisc", CLuaBaseEntity::canUseMisc); SOL_REGISTER("getSpeed", CLuaBaseEntity::getSpeed); - SOL_REGISTER("setSpeed", CLuaBaseEntity::setSpeed); + SOL_REGISTER("getBaseSpeed", CLuaBaseEntity::getBaseSpeed); + SOL_REGISTER("setBaseSpeed", CLuaBaseEntity::setBaseSpeed); + SOL_REGISTER("setAnimationSpeed", CLuaBaseEntity::setAnimationSpeed); SOL_REGISTER("getPlaytime", CLuaBaseEntity::getPlaytime); SOL_REGISTER("getTimeCreated", CLuaBaseEntity::getTimeCreated); diff --git a/src/map/lua/lua_baseentity.h b/src/map/lua/lua_baseentity.h index 6a2ce651205..69911413b6c 100644 --- a/src/map/lua/lua_baseentity.h +++ b/src/map/lua/lua_baseentity.h @@ -326,7 +326,9 @@ class CLuaBaseEntity bool canUseMisc(uint16 misc); // Check misc flags of current zone. uint8 getSpeed(); - void setSpeed(uint8 speedVal); + uint8 getBaseSpeed(); + void setBaseSpeed(uint8 speedVal); + void setAnimationSpeed(uint8 speedVal); uint32 getPlaytime(sol::object const& shouldUpdate); int32 getTimeCreated(); diff --git a/src/map/packets/entity_update.cpp b/src/map/packets/entity_update.cpp index 4ca71a3e97e..39290632642 100644 --- a/src/map/packets/entity_update.cpp +++ b/src/map/packets/entity_update.cpp @@ -118,7 +118,7 @@ void CEntityUpdatePacket::updateWith(CBaseEntity* PEntity, ENTITYUPDATE type, ui ref(0x14) = PEntity->loc.p.z; ref(0x18) = PEntity->loc.p.moving; ref(0x1A) = PEntity->m_TargID << 1; - ref(0x1C) = PEntity->speed; + ref(0x1C) = PEntity->GetSpeed(); ref(0x1D) = PEntity->animationSpeed; } diff --git a/src/map/utils/mobutils.cpp b/src/map/utils/mobutils.cpp index 6453e1fb93b..7fb8c7cbda9 100644 --- a/src/map/utils/mobutils.cpp +++ b/src/map/utils/mobutils.cpp @@ -1576,8 +1576,8 @@ namespace mobutils PMob->m_ModelRadius = (float)_sql->GetIntData(21); PMob->baseSpeed = (uint8)_sql->GetIntData(22); // Overwrites baseentity.cpp's defined baseSpeed - PMob->speed = (uint8)_sql->GetIntData(22); // Overwrites baseentity.cpp's defined speed PMob->animationSpeed = (uint8)_sql->GetIntData(22); // Overwrites baseentity.cpp's defined animationSpeed + PMob->UpdateSpeed(); PMob->strRank = (uint8)_sql->GetIntData(23); PMob->dexRank = (uint8)_sql->GetIntData(24); @@ -1738,8 +1738,8 @@ namespace mobutils PMob->m_ModelRadius = (float)_sql->GetIntData(21); PMob->baseSpeed = (uint8)_sql->GetIntData(22); // Overwrites baseentity.cpp's defined baseSpeed - PMob->speed = (uint8)_sql->GetIntData(22); // Overwrites baseentity.cpp's defined speed PMob->animationSpeed = (uint8)_sql->GetIntData(22); // Overwrites baseentity.cpp's defined animationSpeed + PMob->UpdateSpeed(); PMob->strRank = (uint8)_sql->GetIntData(23); PMob->dexRank = (uint8)_sql->GetIntData(24); diff --git a/src/map/utils/petutils.cpp b/src/map/utils/petutils.cpp index a4178cf4479..f115df2d43e 100644 --- a/src/map/utils/petutils.cpp +++ b/src/map/utils/petutils.cpp @@ -353,8 +353,8 @@ namespace petutils } PMob->baseSpeed = petStats->speed; - PMob->speed = petStats->speed; PMob->animationSpeed = petStats->speed; + PMob->UpdateSpeed(); PMob->UpdateHealth(); PMob->health.tp = 0; @@ -1035,7 +1035,8 @@ namespace petutils // TODO: make pets use entity flags PPet->m_flags = 0x0000008B; // Just sit, do nothing - PPet->speed = 0; + PPet->baseSpeed = 0; + PPet->UpdateSpeed(); FinalizePetStatistics(PMaster, PPet); } diff --git a/src/map/utils/trustutils.cpp b/src/map/utils/trustutils.cpp index 0943c0ec9d6..4f1f251884c 100644 --- a/src/map/utils/trustutils.cpp +++ b/src/map/utils/trustutils.cpp @@ -437,12 +437,12 @@ namespace trustutils PTrust->HPscale = trustData->HPscale; PTrust->MPscale = trustData->MPscale; PTrust->baseSpeed = trustData->baseSpeed; - PTrust->speed = trustData->baseSpeed; PTrust->animationSpeed = trustData->animationSpeed; - PTrust->m_TrustID = trustData->trustID; - PTrust->status = STATUS_TYPE::NORMAL; - PTrust->m_ModelRadius = trustData->radius; - PTrust->m_EcoSystem = trustData->EcoSystem; + PTrust->UpdateSpeed(); + PTrust->m_TrustID = trustData->trustID; + PTrust->status = STATUS_TYPE::NORMAL; + PTrust->m_ModelRadius = trustData->radius; + PTrust->m_EcoSystem = trustData->EcoSystem; PTrust->SetMJob(trustData->mJob); PTrust->SetSJob(trustData->sJob); diff --git a/src/map/utils/zoneutils.cpp b/src/map/utils/zoneutils.cpp index 8f059852766..2c6eec7d0f1 100644 --- a/src/map/utils/zoneutils.cpp +++ b/src/map/utils/zoneutils.cpp @@ -342,9 +342,9 @@ namespace zoneutils PNpc->m_TargID = rset->get("flag") >> 16; - PNpc->speed = rset->get("speed"); // Overwrites baseentity.cpp's defined speed PNpc->animationSpeed = rset->get("speedsub"); // Overwrites baseentity.cpp's defined animationSpeed - PNpc->baseSpeed = rset->get("speedsub"); // Overwrites baseentity.cpp's defined baseSpeed + PNpc->baseSpeed = rset->get("speed"); // Overwrites baseentity.cpp's defined baseSpeed + PNpc->UpdateSpeed(); PNpc->animation = rset->get("animation"); PNpc->animationsub = rset->get("animationsub"); @@ -490,8 +490,8 @@ namespace zoneutils PMob->m_ModelRadius = (float)sql->GetIntData(25); PMob->baseSpeed = (uint8)sql->GetIntData(26); - PMob->speed = (uint8)sql->GetIntData(26); PMob->animationSpeed = (uint8)sql->GetIntData(26); + PMob->UpdateSpeed(); PMob->strRank = (uint8)sql->GetIntData(27); PMob->dexRank = (uint8)sql->GetIntData(28); From 6ddab9d41e03f88cdb12be8cc2f9691791a3403d Mon Sep 17 00:00:00 2001 From: Corey Sotiropoulos Date: Tue, 21 Jan 2025 00:23:32 -0500 Subject: [PATCH 2/2] Adjust GM speed command Clamp to uint8 range with negative option to bind. --- scripts/commands/speed.lua | 22 ++++------------------ src/map/entities/battleentity.cpp | 2 +- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/scripts/commands/speed.lua b/scripts/commands/speed.lua index 9a0829ff7e1..2e8554462b6 100644 --- a/scripts/commands/speed.lua +++ b/scripts/commands/speed.lua @@ -11,11 +11,6 @@ commandObj.cmdprops = parameters = 'i' } -local function error(player, msg) - player:printToPlayer(msg) - player:printToPlayer('!speed <0-255>') -end - commandObj.onTrigger = function(player, speed) if not speed then player:printToPlayer(string.format('Current Speed: %u', player:getSpeed())) @@ -24,27 +19,18 @@ commandObj.onTrigger = function(player, speed) end -- Validate speed amount - if speed < 0 or speed > 255 then - error(player, 'Invalid speed amount.') - - return - end - - -- Bypass speed and inform player. - local baseSpeed = speed + speed = utils.clamp(speed, -1, 255) if speed == 0 then - baseSpeed = xi.settings.map.BASE_SPEED - player:printToPlayer('Returning to your regular speed.') else player:printToPlayer('Bypassing regular speed calculations and limits.') - player:printToPlayer('Set speed value to "0" to return to your regular speed.') - player:printToPlayer(string.format('New speed: %u', speed)) + player:printToPlayer('Set speed value to "0" to return to your regular speed, any negative number to bind.') + player:printToPlayer(string.format('New speed: %u', speed == -1 and 0 or speed)) end player:setMod(xi.mod.MOVE_SPEED_OVERRIDE, speed) - player:setBaseSpeed(baseSpeed) + player:recalculateStats() end return commandObj diff --git a/src/map/entities/battleentity.cpp b/src/map/entities/battleentity.cpp index 59c7a369717..6981ff4e1db 100644 --- a/src/map/entities/battleentity.cpp +++ b/src/map/entities/battleentity.cpp @@ -307,7 +307,7 @@ uint8 CBattleEntity::UpdateSpeed(bool run) outputSpeed = settings::get("map.MOUNT_SPEED") / 2; outputSpeed *= (100 + getMod(Mod::MOUNT_MOVE)) / 100; } - else if (baseSpeed == 0 || getMod(Mod::MOVE_SPEED_OVERRIDE) > 255) + else if (baseSpeed == 0 || getMod(Mod::MOVE_SPEED_OVERRIDE) < 0) { outputSpeed = 0; }