starting playing the wherigo

Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
2026-02-13 02:41:12 +01:00
parent 50267e47dc
commit f9c45ca81f
34 changed files with 4055 additions and 84 deletions

View File

@@ -0,0 +1,215 @@
#include "lua/game_engine.h"
extern "C" {
#include <lua.h>
#include <lauxlib.h>
}
#include <wx/log.h>
namespace wherigo {
// Define the custom event
wxDEFINE_EVENT(EVT_GAME_STATE_CHANGED, GameStateEvent);
wxBEGIN_EVENT_TABLE(GameEngine, wxEvtHandler)
EVT_TIMER(wxID_ANY, GameEngine::onGameTick)
wxEND_EVENT_TABLE()
GameEngine& GameEngine::getInstance() {
static GameEngine instance;
return instance;
}
GameEngine::GameEngine() : m_gameTimer(this) {
}
GameEngine::~GameEngine() {
shutdown();
}
void GameEngine::init(lua_State *L, int cartridgeRef) {
m_luaState = L;
m_cartridgeRef = cartridgeRef;
wxLogDebug("GameEngine initialized");
}
void GameEngine::shutdown() {
stop();
m_luaState = nullptr;
m_cartridgeRef = -1;
}
void GameEngine::start() {
if (m_running) return;
m_running = true;
m_gameTimer.Start(1000); // 1 second tick
wxLogDebug("GameEngine started");
}
void GameEngine::stop() {
if (!m_running) return;
m_gameTimer.Stop();
m_running = false;
wxLogDebug("GameEngine stopped");
}
void GameEngine::updatePlayerPosition(double lat, double lng, double alt) {
m_playerLat = lat;
m_playerLng = lng;
m_playerAlt = alt;
if (!m_luaState) return;
// Update Player.ObjectLocation in Lua
lua_getglobal(m_luaState, "Player");
if (lua_istable(m_luaState, -1)) {
lua_newtable(m_luaState);
lua_pushnumber(m_luaState, lat);
lua_setfield(m_luaState, -2, "latitude");
lua_pushnumber(m_luaState, lng);
lua_setfield(m_luaState, -2, "longitude");
lua_pushnumber(m_luaState, alt);
lua_setfield(m_luaState, -2, "altitude");
lua_setfield(m_luaState, -2, "ObjectLocation");
}
lua_pop(m_luaState, 1);
checkZones();
}
void GameEngine::onGameTick(wxTimerEvent& event) {
if (!m_luaState || !m_running) return;
checkTimers();
// Notify listeners of potential state changes
notifyStateChanged();
}
void GameEngine::checkTimers() {
if (!m_luaState) return;
// Iterate through all global variables to find running timers
lua_getglobal(m_luaState, "_G");
lua_pushnil(m_luaState);
while (lua_next(m_luaState, -2) != 0) {
if (lua_istable(m_luaState, -1)) {
lua_getfield(m_luaState, -1, "ClassName");
if (lua_isstring(m_luaState, -1) && strcmp(lua_tostring(m_luaState, -1), "ZTimer") == 0) {
lua_pop(m_luaState, 1); // pop ClassName
lua_getfield(m_luaState, -1, "Running");
bool running = lua_toboolean(m_luaState, -1);
lua_pop(m_luaState, 1);
if (running) {
// Get timer info
lua_getfield(m_luaState, -1, "Name");
const char *name = lua_isstring(m_luaState, -1) ? lua_tostring(m_luaState, -1) : "(unnamed)";
lua_pop(m_luaState, 1);
lua_getfield(m_luaState, -1, "Remaining");
lua_Number remaining = lua_isnumber(m_luaState, -1) ? lua_tonumber(m_luaState, -1) : -1;
lua_pop(m_luaState, 1);
// If Remaining not set, initialize from Duration
if (remaining < 0) {
lua_getfield(m_luaState, -1, "Duration");
remaining = lua_isnumber(m_luaState, -1) ? lua_tonumber(m_luaState, -1) : 0;
lua_pop(m_luaState, 1);
}
// Decrement remaining time
remaining -= 1.0;
lua_pushnumber(m_luaState, remaining);
lua_setfield(m_luaState, -2, "Remaining");
// Call OnTick if exists
lua_getfield(m_luaState, -1, "OnTick");
if (lua_isfunction(m_luaState, -1)) {
lua_pushvalue(m_luaState, -2); // push timer as self
if (lua_pcall(m_luaState, 1, 0, 0) != 0) {
wxLogError("Timer OnTick error: %s", lua_tostring(m_luaState, -1));
lua_pop(m_luaState, 1);
}
} else {
lua_pop(m_luaState, 1);
}
// Check if elapsed
if (remaining <= 0) {
wxLogDebug("Timer elapsed: %s", name);
// Stop the timer
lua_pushboolean(m_luaState, 0);
lua_setfield(m_luaState, -2, "Running");
// Call OnElapsed if exists
lua_getfield(m_luaState, -1, "OnElapsed");
if (lua_isfunction(m_luaState, -1)) {
lua_pushvalue(m_luaState, -2); // push timer as self
if (lua_pcall(m_luaState, 1, 0, 0) != 0) {
wxLogError("Timer OnElapsed error: %s", lua_tostring(m_luaState, -1));
lua_pop(m_luaState, 1);
}
} else {
lua_pop(m_luaState, 1);
}
}
}
} else {
lua_pop(m_luaState, 1); // pop ClassName
}
}
lua_pop(m_luaState, 1); // pop value
}
lua_pop(m_luaState, 1); // pop _G
}
void GameEngine::checkZones() {
if (!m_luaState) return;
// Iterate through all global variables to find zones
lua_getglobal(m_luaState, "_G");
lua_pushnil(m_luaState);
while (lua_next(m_luaState, -2) != 0) {
if (lua_istable(m_luaState, -1)) {
lua_getfield(m_luaState, -1, "ClassName");
if (lua_isstring(m_luaState, -1) && strcmp(lua_tostring(m_luaState, -1), "Zone") == 0) {
lua_pop(m_luaState, 1); // pop ClassName
lua_getfield(m_luaState, -1, "Active");
bool active = lua_toboolean(m_luaState, -1);
lua_pop(m_luaState, 1);
if (active) {
// TODO: Check if player is inside zone using Points
// For now, just log that we would check
lua_getfield(m_luaState, -1, "Name");
const char *name = lua_isstring(m_luaState, -1) ? lua_tostring(m_luaState, -1) : "(unnamed)";
lua_pop(m_luaState, 1);
// This is where you would implement point-in-polygon check
// and call OnEnter/OnExit callbacks
}
} else {
lua_pop(m_luaState, 1); // pop ClassName
}
}
lua_pop(m_luaState, 1); // pop value
}
lua_pop(m_luaState, 1); // pop _G
}
void GameEngine::notifyStateChanged() {
GameStateEvent event(EVT_GAME_STATE_CHANGED);
ProcessEvent(event);
}
} // namespace wherigo