some tweaks

still non playable cartridges

Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
2026-06-02 23:21:56 +02:00
parent 6e29dde558
commit 92045ec6df
15 changed files with 1802 additions and 838 deletions
+4 -4
View File
@@ -16,16 +16,16 @@ public:
int OnExit() override;
bool loadCartridge(const std::string &filePath);
void startGame();
void startGame() const;
void unloadCartridge();
// Save/Load game state
bool saveGameState(const std::string &saveFilePath);
bool loadGameState(const std::string &saveFilePath);
bool saveGameState(const std::string &saveFilePath) const;
bool loadGameState(const std::string &saveFilePath) const;
std::string getAutoSavePath() const;
// Generate completion log (for wherigo.com)
bool generateCompletionLog(const std::string &logFilePath);
bool generateCompletionLog(const std::string &logFilePath) const;
std::string getCompletionLogPath() const;
lua_State* getLuaState() const { return m_luaState; }
+3
View File
@@ -39,6 +39,7 @@ public:
// Notify listeners that game state has changed
void notifyStateChanged();
void rebuildPlayerInventory();
lua_State* getLuaState() const { return m_luaState; }
int getCartridgeRef() const { return m_cartridgeRef; }
@@ -64,6 +65,8 @@ private:
double m_playerLng = 0.0;
double m_playerAlt = 0.0;
bool m_isProcessing = false;
wxDECLARE_EVENT_TABLE();
};
+183
View File
@@ -0,0 +1,183 @@
#pragma once
#include <cmath>
#include <cstring>
#include <limits>
#include <utility>
#include <vector>
extern "C" {
#include <lauxlib.h>
#include <lua.h>
}
namespace wherigo {
// ── Unit conversion ───────────────────────────────────────────────────────────
inline double distanceToMeters(double value, const char *units) {
if (!units || !strcmp(units,"meters") || !strcmp(units,"metres") || !strcmp(units,"m"))
return value;
if (!strcmp(units,"kilometers") || !strcmp(units,"kilometres") || !strcmp(units,"km"))
return value * 1000.0;
if (!strcmp(units,"feet") || !strcmp(units,"ft"))
return value * 0.3048;
if (!strcmp(units,"miles") || !strcmp(units,"mi"))
return value * 1609.344;
if (!strcmp(units,"nauticalmiles"))
return value * 1852.0;
return value;
}
inline double metersToUnit(double meters, const char *units) {
if (!units || !strcmp(units,"meters") || !strcmp(units,"metres") || !strcmp(units,"m"))
return meters;
if (!strcmp(units,"kilometers") || !strcmp(units,"kilometres") || !strcmp(units,"km"))
return meters / 1000.0;
if (!strcmp(units,"feet") || !strcmp(units,"ft"))
return meters / 0.3048;
if (!strcmp(units,"miles") || !strcmp(units,"mi"))
return meters / 1609.344;
if (!strcmp(units,"nauticalmiles"))
return meters / 1852.0;
return meters;
}
// ── Geodesic calculations ─────────────────────────────────────────────────────
// Haversine formula → {distance_meters, bearing_degrees [0,360)}
inline std::pair<double,double> haversine(double lat1, double lon1,
double lat2, double lon2) {
constexpr double R = 6371000.0;
constexpr double D2R = M_PI / 180.0;
const double rl1 = lat1*D2R, rl2 = lat2*D2R;
const double dl = (lat2-lat1)*D2R, dl2 = (lon2-lon1)*D2R;
const double a = std::sin(dl/2)*std::sin(dl/2) +
std::cos(rl1)*std::cos(rl2)*std::sin(dl2/2)*std::sin(dl2/2);
const double dist = R * 2.0 * std::asin(std::min(1.0, std::sqrt(a)));
const double brg = std::atan2(std::sin(dl2)*std::cos(rl2),
std::cos(rl1)*std::sin(rl2) -
std::sin(rl1)*std::cos(rl2)*std::cos(dl2));
return {dist, std::fmod(brg*(180.0/M_PI)+360.0, 360.0)};
}
// Destination point given start, distance (m), bearing (deg)
inline std::pair<double,double> translatePoint(double lat, double lon,
double distMeters, double bearingDeg) {
constexpr double R = 6371000.0;
constexpr double D2R = M_PI / 180.0;
constexpr double R2D = 180.0 / M_PI;
const double d = distMeters / R;
const double b = bearingDeg * D2R;
const double r1 = lat * D2R;
const double r2 = std::asin(std::sin(r1)*std::cos(d) +
std::cos(r1)*std::sin(d)*std::cos(b));
const double dl = std::atan2(std::sin(b)*std::sin(d)*std::cos(r1),
std::cos(d) - std::sin(r1)*std::sin(r2));
return {r2*R2D, lon + dl*R2D};
}
// Ray-casting point-in-polygon. pts = {lat, lon} pairs.
inline bool pointInPolygon(double playerLat, double playerLon,
const std::vector<std::pair<double,double>>& pts) {
const int n = static_cast<int>(pts.size());
if (n < 3) return false;
bool inside = false;
for (int i = 0, j = n-1; i < n; j = i++) {
const double lati = pts[i].first, loni = pts[i].second;
const double latj = pts[j].first, lonj = pts[j].second;
if (((lati > playerLat) != (latj > playerLat)) &&
(playerLon < (lonj-loni)*(playerLat-lati)/(latj-lati) + loni))
inside = !inside;
}
return inside;
}
// Distance (m) from point to nearest point on segment; optionally returns that point
inline double distToSegment(double plat, double plon,
double lat1, double lon1,
double lat2, double lon2,
double *nearLatOut = nullptr,
double *nearLonOut = nullptr) {
const double dlat = lat2-lat1, dlon = lon2-lon1;
const double len2 = dlat*dlat + dlon*dlon;
const double t = (len2 > 1e-12)
? std::max(0.0, std::min(1.0,
((plat-lat1)*dlat + (plon-lon1)*dlon) / len2))
: 0.0;
const double nLat = lat1 + t*dlat, nLon = lon1 + t*dlon;
if (nearLatOut) *nearLatOut = nLat;
if (nearLonOut) *nearLonOut = nLon;
return haversine(plat, plon, nLat, nLon).first;
}
// Nearest edge of zone polygon → {distance_m, bearing_deg}
inline std::pair<double,double> nearestZoneEdge(
double plat, double plon,
const std::vector<std::pair<double,double>>& pts) {
double minDist = std::numeric_limits<double>::max(), minBrg = 0.0;
const int n = static_cast<int>(pts.size());
for (int i = 0, j = n-1; i < n; j = i++) {
double nLat, nLon;
const double d = distToSegment(plat, plon,
pts[j].first, pts[j].second, pts[i].first, pts[i].second,
&nLat, &nLon);
if (d < minDist) {
minDist = d;
minBrg = haversine(plat, plon, nLat, nLon).second;
}
}
return {minDist, minBrg};
}
// ── Lua table helpers ─────────────────────────────────────────────────────────
// Push a Distance object (value in meters) with __call metatable
inline void pushDistance(lua_State *L, double meters) {
lua_newtable(L);
lua_pushnumber(L, meters);
lua_setfield(L, -2, "value");
lua_pushstring(L, "Distance");
lua_setfield(L, -2, "_classname");
luaL_getmetatable(L, "Wherigo.Distance");
if (lua_istable(L, -1))
lua_setmetatable(L, -2);
else
lua_pop(L, 1);
}
// Push a Bearing object (value in degrees [0,360)) with __call metatable
inline void pushBearing(lua_State *L, double degrees) {
lua_newtable(L);
lua_pushnumber(L, std::fmod(degrees+360.0, 360.0));
lua_setfield(L, -2, "value");
lua_pushstring(L, "Bearing");
lua_setfield(L, -2, "_classname");
luaL_getmetatable(L, "Wherigo.Bearing");
if (lua_istable(L, -1))
lua_setmetatable(L, -2);
else
lua_pop(L, 1);
}
// Read zone Points array from Lua table at absolute stack index
inline std::vector<std::pair<double,double>> readZonePoints(lua_State *L, int zoneIdx) {
std::vector<std::pair<double,double>> pts;
lua_getfield(L, zoneIdx, "Points");
if (!lua_istable(L, -1)) { lua_pop(L, 1); return pts; }
const int n = static_cast<int>(lua_objlen(L, -1));
pts.reserve(n);
for (int i = 1; i <= n; ++i) {
lua_rawgeti(L, -1, i);
if (lua_istable(L, -1)) {
lua_getfield(L, -1, "latitude"); double lat = lua_tonumber(L,-1); lua_pop(L,1);
lua_getfield(L, -1, "longitude"); double lon = lua_tonumber(L,-1); lua_pop(L,1);
pts.push_back({lat, lon});
}
lua_pop(L, 1);
}
lua_pop(L, 1);
return pts;
}
} // namespace wherigo
+34 -7
View File
@@ -1,25 +1,52 @@
#pragma once
#include <wx/frame.h>
#include <wx/timer.h>
#include <wx/webview.h>
#include <vector>
#include <string>
#include <utility>
#include <vector>
struct SimPoint {
double lat;
double lon;
};
struct ZoneInfo {
double lat;
double lon;
std::string name;
};
class MapSimFrame : public wxFrame {
public:
MapSimFrame(wxWindow* parent, double centerLat = 53.3, double centerLon = 10.39, const std::vector<std::pair<double, double>>& zoneCoords = {});
MapSimFrame(wxWindow* parent,
double centerLat = 53.3, double centerLon = 10.39,
const std::vector<ZoneInfo>& zoneInfos = {});
void AddSimPoint(double lat, double lon);
void StartSimulation();
private:
wxWebView* m_webView;
std::vector<SimPoint> m_route;
std::vector<std::pair<double, double>> m_zoneCoords;
void OnWebViewEvent(wxWebViewEvent& event);
void OnPlay(wxCommandEvent& event);
wxWebView* m_webView = nullptr;
wxTimer m_simTimer;
size_t m_simIndex = 0;
std::vector<SimPoint> m_route;
std::vector<ZoneInfo> m_zoneInfos;
bool m_pageLoaded = false;
void SendPositionToEngine(double lat, double lon);
void syncZonesOnMap();
void OnScriptMessage(wxWebViewEvent& event);
void OnWebViewLoaded(wxWebViewEvent& event);
void OnGameStateChanged(wxEvent& event);
void OnClose(wxCloseEvent& event);
void OnPlay(wxCommandEvent& event);
void OnClear(wxCommandEvent& event);
void OnSimTimer(wxTimerEvent& event);
wxDECLARE_EVENT_TABLE();
};
+1 -1
View File
@@ -25,7 +25,7 @@ public:
int getSelectedButton() const { return m_selectedButton; }
private:
void onButton(wxCommandEvent &event);
void onButton(const wxCommandEvent &event);
int m_selectedButton = -1;
};