WASD: resume the walk right after a weapon set switch (untested in-game)
Switching between weapon classes resets the hero's animation state inside cUI_Taskbar2::SelectWeaponSet, which dropped the walk for a tick. The hook sends the WASD walk again at once. Checkpoint before the movement rework. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
184c7058fd
commit
d296e2850b
4 files changed
+79
-12
No files matched your search
+47
-12
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "mods/wasd.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
@@ -69,19 +70,39 @@ bool IsMovementKey(int vk) {
|
||||
return (vk == 'W' || vk == 'A' || vk == 'S' || vk == 'D');
|
||||
}
|
||||
|
||||
// Called once per engine tick (10 Hz), after the game's own input handling.
|
||||
void Update(uint8_t* engine) {
|
||||
// World axes on screen: (-1,-1) up, (1,1) down, (-1,1) left, (1,-1) right.
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
namespace {
|
||||
|
||||
// The held movement keys as a screen direction in world axes: (-1,-1) up,
|
||||
// (1,1) down, (-1,1) left, (1,-1) right; 0,0 when none (or the keys belong to
|
||||
// the mouse, blocked input or a text field).
|
||||
void HeldDirection(uint8_t* engine, int& dx, int& dy) {
|
||||
dx = 0;
|
||||
dy = 0;
|
||||
const uint32_t flags = *reinterpret_cast<uint32_t*>(engine + kEngineFlags);
|
||||
const bool mouseMoving = (flags & 0x10) != 0;
|
||||
if (!mouseMoving && (flags & 0x4000) == 0 && !mods::input::TypingIntoTextField()) {
|
||||
if ((flags & 0x10) == 0 && (flags & 0x4000) == 0 && !mods::input::TypingIntoTextField()) {
|
||||
if (KeyDown('W')) { dx -= 1; dy -= 1; }
|
||||
if (KeyDown('S')) { dx += 1; dy += 1; }
|
||||
if (KeyDown('A')) { dx -= 1; dy += 1; }
|
||||
if (KeyDown('D')) { dx += 1; dy -= 1; }
|
||||
}
|
||||
}
|
||||
|
||||
void Walk(uint8_t* engine, void* creature, int dx, int dy) {
|
||||
const double length = std::sqrt(static_cast<double>(dx * dx + dy * dy));
|
||||
const int x = game::CreatureField(creature, game::kCreatureX) + static_cast<int>(dx / length * kTargetDistance);
|
||||
const int y = game::CreatureField(creature, game::kCreatureY) + static_cast<int>(dy / length * kTargetDistance);
|
||||
SendWalk(engine, creature, x, y);
|
||||
}
|
||||
|
||||
std::atomic<uint8_t*> g_engine{nullptr};
|
||||
|
||||
// Called once per engine tick (10 Hz), after the game's own input handling.
|
||||
void Update(uint8_t* engine) {
|
||||
g_engine = engine;
|
||||
int dx;
|
||||
int dy;
|
||||
HeldDirection(engine, dx, dy);
|
||||
const bool mouseMoving = (*reinterpret_cast<uint32_t*>(engine + kEngineFlags) & 0x10) != 0;
|
||||
if (dx == 0 && dy == 0) {
|
||||
if (g_move.moving && !mouseMoving) {
|
||||
if (void* creature = ControlledCreature(engine)) {
|
||||
@@ -95,16 +116,30 @@ void Update(uint8_t* engine) {
|
||||
if (!creature) {
|
||||
return;
|
||||
}
|
||||
const double length = std::sqrt(static_cast<double>(dx * dx + dy * dy));
|
||||
const int x = game::CreatureField(creature, game::kCreatureX) + static_cast<int>(dx / length * kTargetDistance);
|
||||
const int y = game::CreatureField(creature, game::kCreatureY) + static_cast<int>(dy / length * kTargetDistance);
|
||||
SendWalk(engine, creature, x, y);
|
||||
Walk(engine, creature, dx, dy);
|
||||
g_move.moving = true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void ResumeWalk() {
|
||||
uint8_t* engine = g_engine.load();
|
||||
void* creature = engine && g_move.moving ? ControlledCreature(engine) : nullptr;
|
||||
int dx;
|
||||
int dy;
|
||||
if (creature) {
|
||||
HeldDirection(engine, dx, dy);
|
||||
if (dx != 0 || dy != 0) {
|
||||
Walk(engine, creature, dx, dy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct Registration {
|
||||
Registration() { game::OnEngineTick(&Update); }
|
||||
Registration() {
|
||||
game::OnEngineTick(&Update);
|
||||
}
|
||||
} g_registration;
|
||||
} // namespace
|
||||
|
||||
|
||||
Reference in new issue
Block a user