From 9bb464e428d02322badbe1530533a572cdfe3a48 Mon Sep 17 00:00:00 2001 From: Max5377 <69468517+Max5377@users.noreply.github.com> Date: Mon, 9 Oct 2023 00:27:25 +0300 Subject: [PATCH] Fixes and changes for functions in LuaBody Rewrite of GetAltitudeRelTo: 1. This function is moved to body class to support this functionality in C++ code; 2. This function is used in the LUA version of GetAltitudeRelTo, GetGroundPosition and GetGPS for consistency in calculating altitudes; 3. This function supports the choice of which height to calculate (sea-level, above-ground). Other change: GetGPS is moved to LuaShip.cpp to support this function for other ships, not only the player. Fixes for this issues: 1. GetAltitudeRelTo using player pos no matter what first argument is passed; 2. GetGroundPosition returns nil when not in the rotating frame of ref; 3. GetGPS sometimes return different height than GetAltitudeRelTo; 4. Access violation when trying to access frameBody, frameRotation and call GetGroundPosition when body doesn't have frame of ref (ex. when ship is hyperspacing). Co-Authored-By: Webster Sheets <4218491+web-eworks@users.noreply.github.com> --- src/Body.cpp | 30 ++++++++++ src/Body.h | 8 +++ src/lua/LuaBody.cpp | 125 +++++++++++++++++++++++------------------- src/lua/LuaPlayer.cpp | 87 ++--------------------------- src/lua/LuaShip.cpp | 55 ++++++++++++++++++- 5 files changed, 167 insertions(+), 138 deletions(-) diff --git a/src/Body.cpp b/src/Body.cpp index f7c8541057a..5df398a5f4b 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -259,6 +259,36 @@ vector3d Body::GetVelocityRelTo(const Body *relTo) const return GetVelocityRelTo(relTo->m_frame) - relTo->GetVelocityRelTo(relTo->m_frame); } +double Body::GetAltitudeRelTo(const Body* relTo, AltitudeType altType) +{ + vector3d pos = GetPositionRelTo(relTo); + double center_dist = pos.Length(); + if (relTo && relTo->IsType(ObjectType::TERRAINBODY)) { + const TerrainBody* terrain = static_cast(relTo); + vector3d surface_pos = pos.Normalized(); + double radius; + if (altType != AltitudeType::DEFAULT) + { + radius = altType == AltitudeType::SEA_LEVEL ? terrain->GetSystemBody()->GetRadius() : + terrain->GetTerrainHeight(surface_pos); + } + else + { + radius = terrain->GetSystemBody()->GetRadius(); + if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) { + radius = terrain->GetTerrainHeight(surface_pos); + } + } + double altitude = center_dist - radius; + if (altitude < 0) + altitude = 0; + return altitude; + } + else { + return center_dist; + } +} + void Body::OrientOnSurface(double radius, double latitude, double longitude) { vector3d up = vector3d(cos(latitude) * cos(longitude), sin(latitude) * cos(longitude), sin(longitude)); diff --git a/src/Body.h b/src/Body.h index ed7bc9f54dc..06ca027dcb2 100644 --- a/src/Body.h +++ b/src/Body.h @@ -43,6 +43,13 @@ enum class ObjectType { // }; +enum class AltitudeType { + //SEA_LEVEL if distant, ABOVE_TERRAIN otherwise + DEFAULT, + SEA_LEVEL, + ABOVE_TERRAIN +}; + #define OBJDEF(__thisClass, __parentClass, __TYPE) \ static constexpr ObjectType StaticType() { return ObjectType::__TYPE; } \ static constexpr ObjectType SuperType() { return __parentClass::StaticType(); } \ @@ -175,6 +182,7 @@ class Body : public DeleteEmitter, public PropertiedObject { vector3d GetInterpPositionRelTo(FrameId relToId) const; vector3d GetInterpPositionRelTo(const Body *relTo) const; matrix3x3d GetInterpOrientRelTo(FrameId relToId) const; + double GetAltitudeRelTo(const Body* relTo, AltitudeType altType = AltitudeType::DEFAULT); // should set m_interpolatedTransform to the smoothly interpolated value // (interpolated by 0 <= alpha <=1) between the previous and current physics tick diff --git a/src/lua/LuaBody.cpp b/src/lua/LuaBody.cpp index c0882c94ba5..e9d909df101 100644 --- a/src/lua/LuaBody.cpp +++ b/src/lua/LuaBody.cpp @@ -26,6 +26,7 @@ #include "Ship.h" #include "SpaceStation.h" #include "Star.h" +#include namespace PiGui { // Declared in LuaPiGuiInternal.h @@ -44,20 +45,20 @@ namespace PiGui { * . */ -/* - * Attribute: label - * - * The label for the body. This is what is displayed in the HUD and usually - * matches the name of the planet, space station, etc if appropriate. - * - * Availability: - * - * alpha 10 - * - * Status: - * - * stable - */ + /* + * Attribute: label + * + * The label for the body. This is what is displayed in the HUD and usually + * matches the name of the planet, space station, etc if appropriate. + * + * Availability: + * + * alpha 10 + * + * Status: + * + * stable + */ /* * Attribute: seed @@ -102,7 +103,6 @@ static int l_body_attr_seed(lua_State *l) * * stable */ - static int l_body_attr_path(lua_State *l) { Body *b = LuaObject::CheckFromLua(1); @@ -222,7 +222,6 @@ static int l_body_set_component(lua_State *l) * * stable */ - static int l_body_get_velocity_rel_to(lua_State *l) { Body *b = LuaObject::CheckFromLua(1); @@ -336,6 +335,7 @@ static int l_body_is_more_important_than(lua_State *l) LuaPush(l, PiGui::first_body_is_more_important_than(body, other)); return 1; } + /* * Method: GetPositionRelTo * @@ -355,7 +355,6 @@ static int l_body_is_more_important_than(lua_State *l) * * stable */ - static int l_body_get_position_rel_to(lua_State *l) { Body *b = LuaObject::CheckFromLua(1); @@ -365,6 +364,13 @@ static int l_body_get_position_rel_to(lua_State *l) return 1; } +static std::unordered_map altitudeTypesStringMap = +{ + {"default", AltitudeType::DEFAULT}, + {"sea-level", AltitudeType::SEA_LEVEL}, + {"above-ground", AltitudeType::ABOVE_TERRAIN} +}; + /* * Method: GetAltitudeRelTo * @@ -375,6 +381,8 @@ static int l_body_get_position_rel_to(lua_State *l) * Parameters: * * other - the other body + * (optional) altType - what altitude to calculate (sea-level, above-ground) + * if not specified, sea-level for distant bodies, above-ground otherwise * * Availability: * @@ -384,28 +392,26 @@ static int l_body_get_position_rel_to(lua_State *l) * * stable */ - static int l_body_get_altitude_rel_to(lua_State *l) { + Body *b = LuaObject::CheckFromLua(1); const Body *other = LuaObject::CheckFromLua(2); - vector3d pos = Pi::player->GetPositionRelTo(other); - double center_dist = pos.Length(); - if (other && other->IsType(ObjectType::TERRAINBODY)) { - const TerrainBody *terrain = static_cast(other); - vector3d surface_pos = pos.Normalized(); - double radius = terrain->GetSystemBody()->GetRadius(); - if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) { - radius = terrain->GetTerrainHeight(surface_pos); + std::string typeString = LuaPull(l, 3, "default"); + AltitudeType altType = AltitudeType::DEFAULT; + if (typeString.compare("default")) + { + if (auto str = altitudeTypesStringMap.find(typeString); str != altitudeTypesStringMap.end()) + { + altType = str->second; + } + else + { + return luaL_error(l, "invalid altitude type: %s", typeString.c_str()); } - double altitude = center_dist - radius; - if (altitude < 0) - altitude = 0; - LuaPush(l, altitude); - return 1; - } else { - LuaPush(l, center_dist); - return 1; } + double altitude = b->GetAltitudeRelTo(other, altType); + LuaPush(l, altitude); + return 1; } /* @@ -493,6 +499,13 @@ static int l_body_attr_frame_body(lua_State *l) } Frame *f = Frame::GetFrame(b->GetFrame()); + + if (!f) + { + lua_pushnil(l); + return 1; + } + LuaObject::PushToLua(f->GetBody()); return 1; } @@ -522,6 +535,12 @@ static int l_body_attr_frame_rotating(lua_State *l) } Frame *f = Frame::GetFrame(b->GetFrame()); + if (!f) + { + lua_pushnil(l); + return 1; + } + lua_pushboolean(l, f->IsRotFrame()); return 1; } @@ -601,8 +620,7 @@ static int l_body_distance_to(lua_State *l) /* * Method: GetGroundPosition * - * Get latitude, longitude and altitude of a dynamic body close to the ground or nil the body is not a dynamic body - * or is not close to the ground. + * Get latitude, longitude and altitude of frame of ref of a dynamic body or nil if the body is not a dynamic body * * > latitude, longitude, altitude = body:GetGroundPosition() * @@ -636,22 +654,20 @@ static int l_body_get_ground_position(lua_State *l) } Frame *f = Frame::GetFrame(b->GetFrame()); - if (!f->IsRotFrame()) - return 0; + if (!f) + { + lua_pushnil(l); + return 1; + } vector3d pos = b->GetPosition(); double latitude = atan2(pos.y, sqrt(pos.x * pos.x + pos.z * pos.z)); double longitude = atan2(pos.x, pos.z); lua_pushnumber(l, latitude); lua_pushnumber(l, longitude); Body *astro = f->GetBody(); - if (astro->IsType(ObjectType::TERRAINBODY)) { - double radius = static_cast(astro)->GetTerrainHeight(pos.Normalized()); - double altitude = pos.Length() - radius; - lua_pushnumber(l, altitude); - } else { - lua_pushnil(l); - } + double altitude = b->GetAltitudeRelTo(astro); + lua_pushnumber(l, altitude); return 3; } @@ -711,7 +727,6 @@ static int l_body_find_nearest_to(lua_State *l) * * stable */ - static int l_body_get_phys_radius(lua_State *l) { Body *b = LuaObject::CheckFromLua(1); @@ -752,31 +767,31 @@ static bool push_body_to_lua(Body *body) LuaObject::PushToLua(body); break; case ObjectType::MODELBODY: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::SHIP: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::PLAYER: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::SPACESTATION: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::PLANET: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::STAR: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::CARGOBODY: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::MISSILE: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; case ObjectType::HYPERSPACECLOUD: - LuaObject::PushToLua(dynamic_cast(body)); + LuaObject::PushToLua(static_cast(body)); break; default: return false; diff --git a/src/lua/LuaPlayer.cpp b/src/lua/LuaPlayer.cpp index c2b29036ad0..e9af361079b 100644 --- a/src/lua/LuaPlayer.cpp +++ b/src/lua/LuaPlayer.cpp @@ -47,7 +47,6 @@ static int l_player_is_player(lua_State *l) * * stable */ - static int l_get_nav_target(lua_State *l) { Player *p = LuaObject::CheckFromLua(1); @@ -74,7 +73,6 @@ static int l_get_nav_target(lua_State *l) * * stable */ - static int l_set_nav_target(lua_State *l) { Player *p = LuaObject::CheckFromLua(1); @@ -147,7 +145,6 @@ static int l_change_cruise_speed(lua_State *l) * * stable */ - static int l_get_combat_target(lua_State *l) { Player *p = LuaObject::CheckFromLua(1); @@ -174,7 +171,6 @@ static int l_get_combat_target(lua_State *l) * * stable */ - static int l_set_combat_target(lua_State *l) { Player *p = LuaObject::CheckFromLua(1); @@ -202,7 +198,6 @@ static int l_set_combat_target(lua_State *l) * * stable */ - static int l_get_hyperspace_target(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -234,7 +229,6 @@ static int l_get_hyperspace_target(lua_State *l) * * stable */ - static int l_set_hyperspace_target(lua_State *l) { LuaObject::CheckFromLua(1); @@ -280,7 +274,6 @@ static int l_get_mouse_direction(lua_State *l) * * stable */ - static int l_get_is_mouse_active(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -303,7 +296,6 @@ static int l_get_is_mouse_active(lua_State *l) * * stable */ - static int l_get_max_delta_v(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -327,7 +319,6 @@ static int l_get_max_delta_v(lua_State *l) * * stable */ - static int l_get_current_delta_v(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -350,7 +341,6 @@ static int l_get_current_delta_v(lua_State *l) * * stable */ - static int l_get_remaining_delta_v(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -361,6 +351,12 @@ static int l_get_remaining_delta_v(lua_State *l) return 1; } +static std::map thrusters_map = { + { "forward", THRUSTER_FORWARD }, + { "reverse", THRUSTER_REVERSE }, + { "up", THRUSTER_UP }, +}; + /* * Method: GetAcceleration * @@ -380,13 +376,6 @@ static int l_get_remaining_delta_v(lua_State *l) * * stable */ - -static std::map thrusters_map = { - { "forward", THRUSTER_FORWARD }, - { "reverse", THRUSTER_REVERSE }, - { "up", THRUSTER_UP }, -}; - static int l_get_acceleration(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -416,7 +405,6 @@ static int l_get_acceleration(lua_State *l) * * stable */ - static int l_get_distance_to_zero_v(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -443,7 +431,6 @@ static int l_get_distance_to_zero_v(lua_State *l) * * stable */ - static int l_get_maneuver_time(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -466,7 +453,6 @@ static int l_get_maneuver_time(lua_State *l) * * stable */ - static int l_get_maneuver_velocity(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -494,7 +480,6 @@ static int l_get_maneuver_velocity(lua_State *l) * * stable */ - static int l_get_heading_pitch_roll(lua_State *l) { // Player *player = LuaObject::CheckFromLua(1); @@ -576,65 +561,6 @@ static int l_toggle_rotation_damping(lua_State *l) return 0; } -/* - * Function: GetGPS() - * - * Get altitude, speed, and position of player's ship - * - * Example: - * - * > alt, vspd, lat, long = player:GetGPS() - * - * Returns: - * - * alt - altitude - * - * vspd - vertical speed - * - * latitude - latitude - * - * longitude - longitude - * - */ -static int l_get_gps(lua_State *l) -{ - Player *player = LuaObject::CheckFromLua(1); - vector3d pos = Pi::player->GetPosition(); - double center_dist = pos.Length(); - FrameId playerFrameId = player->GetFrame(); - Frame *playerFrame = Frame::GetFrame(playerFrameId); - if (playerFrameId.valid()) { - Body *astro = Frame::GetFrame(playerFrameId)->GetBody(); - if (astro && astro->IsType(ObjectType::TERRAINBODY)) { - TerrainBody *terrain = static_cast(astro); - if (!playerFrame->IsRotFrame()) - playerFrame = Frame::GetFrame(playerFrame->GetRotFrame()); - vector3d surface_pos = pos.Normalized(); - double radius = terrain->GetSystemBody()->GetRadius(); - if (center_dist <= 3.0 * terrain->GetMaxFeatureRadius()) { - radius = terrain->GetTerrainHeight(surface_pos); - } - double altitude = center_dist - radius; - vector3d velocity = player->GetVelocity(); - double vspeed = velocity.Dot(surface_pos); - if (fabs(vspeed) < 0.05) vspeed = 0.0; // Avoid alternating between positive/negative zero - - // RefreshHeadingPitch(); - - if (altitude < 0) altitude = 0; - LuaPush(l, altitude); - LuaPush(l, vspeed); - const float lat = RAD2DEG(asin(surface_pos.y)); - const float lon = RAD2DEG(atan2(surface_pos.x, surface_pos.z)); - LuaPush(l, lat); - LuaPush(l, lon); - return 4; - // } - } - } - return 0; -} - static int l_get_alert_state(lua_State *l) { Player *player = LuaObject::CheckFromLua(1); @@ -883,7 +809,6 @@ void LuaObject::RegisterClass() { "GetMouseDirection", l_get_mouse_direction }, { "GetRotationDamping", l_get_rotation_damping }, { "SetRotationDamping", l_set_rotation_damping }, - { "GetGPS", l_get_gps }, { "ToggleRotationDamping", l_toggle_rotation_damping }, { "GetAlertState", l_get_alert_state }, { "GetLowThrustPower", l_get_low_thrust_power }, diff --git a/src/lua/LuaShip.cpp b/src/lua/LuaShip.cpp index 102140a3270..ec530964021 100644 --- a/src/lua/LuaShip.cpp +++ b/src/lua/LuaShip.cpp @@ -171,7 +171,6 @@ static int l_ship_get_ship_class(lua_State *l) * * experimental */ - static int l_ship_set_hull_percent(lua_State *l) { LUA_DEBUG_START(l); @@ -262,7 +261,6 @@ static int l_ship_set_fuel_percent(lua_State *l) * * experimental */ - static int l_ship_explode(lua_State *l) { LUA_DEBUG_START(l); @@ -1153,6 +1151,58 @@ static int l_ship_get_position(lua_State *l) return 1; } +/* + * Function: GetGPS() + * + * Get altitude, speed, and position of a ship + * + * Example: + * + * > alt, vspd, lat, long = ship:GetGPS() + * + * Returns: + * + * alt - altitude + * + * vspd - vertical speed + * + * latitude - latitude + * + * longitude - longitude + * + */ +static int l_get_gps(lua_State* l) +{ + Ship* ship = LuaObject::CheckFromLua(1); + vector3d pos = ship->GetPosition(); + FrameId shipFrameId = ship->GetFrame(); + Frame* shipFrame = Frame::GetFrame(shipFrameId); + if (shipFrameId.valid()) { + Body* astro = Frame::GetFrame(shipFrameId)->GetBody(); + if (astro && astro->IsType(ObjectType::TERRAINBODY)) { + if (!shipFrame->IsRotFrame()) + shipFrame = Frame::GetFrame(shipFrame->GetRotFrame()); + double altitude = ship->GetAltitudeRelTo(astro); + vector3d surface_pos = pos.Normalized(); + vector3d velocity = ship->GetVelocity(); + double vspeed = velocity.Dot(surface_pos); + if (fabs(vspeed) < 0.05) vspeed = 0.0; // Avoid alternating between positive/negative zero + + // RefreshHeadingPitch(); + + LuaPush(l, altitude); + LuaPush(l, vspeed); + const float lat = RAD2DEG(asin(surface_pos.y)); + const float lon = RAD2DEG(atan2(surface_pos.x, surface_pos.z)); + LuaPush(l, lat); + LuaPush(l, lon); + return 4; + // } + } + } + return 0; +} + /* Method: GetHullTemperature * * Return the current hull temperature (0.0 - 1.0). @@ -1721,6 +1771,7 @@ void LuaObject::RegisterClass() { "GetHyperspaceCountdown", l_ship_get_hyperspace_countdown }, { "IsHyperspaceActive", l_ship_is_hyperspace_active }, + { "GetGPS", l_get_gps }, { "GetHullTemperature", l_ship_get_hull_temperature }, { "GetGunTemperature", l_ship_get_gun_temperature },