From 1cb457b49f8edb36909aca0c737f3c3caa83f02d 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/Player/Ship 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: 1. GetGPS is moved to Ship.lua to support this function for other ships, not only the player. Implementing this function in C++ is considered unnecessary because of slightly different parameter interface and because of this can be simplified a lot; 2. GetGroundPosition also supports the choice of which altitude to calculate (sea level or above terrain). 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> --- data/libs/Ship.lua | 34 +++++++++ data/meta/CoreObject/Body.meta.lua | 12 ++-- src/Body.cpp | 30 ++++++++ src/Body.h | 8 +++ src/enum_table.cpp | 9 +++ src/enum_table.h | 1 + src/lua/LuaBody.cpp | 112 +++++++++++++++++------------ src/lua/LuaPlayer.cpp | 74 ------------------- src/lua/LuaShip.cpp | 2 - 9 files changed, 156 insertions(+), 126 deletions(-) diff --git a/data/libs/Ship.lua b/data/libs/Ship.lua index ad9c8464a8f..cbdfe5fdc6f 100644 --- a/data/libs/Ship.lua +++ b/data/libs/Ship.lua @@ -668,6 +668,40 @@ function Ship:OnScoopCargo(cargoType) return success end + +-- +-- Method: GetGPS +-- +-- Get altitude, speed, and position of a ship +-- +-- > alt, vspd, lat, long = ship:GetGPS() +-- +-- Returns: +-- +-- alt - altitude +-- +-- vspd - vertical speed +-- +-- lat - latitude +-- +-- lon - longitude +-- +-- Availability: +-- +-- November, 2023 +-- +-- Status: +-- +-- experimental +-- +function Ship:GetGPS() + local lat, lon, altitude = self:GetGroundPosition() + local vspd = self:GetVelocityRelTo(self.frameBody):dot(self:GetPositionRelTo(self.frameBody):normalized()) + lat = math.rad2deg(lat) + lon = math.rad2deg(lon) + return altitude, vspd, lat, lon +end + -- -- Method: Enroll -- diff --git a/data/meta/CoreObject/Body.meta.lua b/data/meta/CoreObject/Body.meta.lua index 42c6edee4c9..e3fbf3eafd9 100644 --- a/data/meta/CoreObject/Body.meta.lua +++ b/data/meta/CoreObject/Body.meta.lua @@ -81,11 +81,12 @@ function Body:DistanceTo(otherBody) end --- Get the body's position relative to its parent frame. --- ---- If the parent is a TerrainBody, altitude will be the height above terrain in meters. +--- If the parent is a TerrainBody, altitude will be the height above terrain or sea level in meters. +---@param boolean? terrainRelative ---@return number latitude the latitude of the body in radians ---@return number longitude the longitude of the body in radians ----@return number? altitude altitude above the ground in meters -function Body:GetGroundPosition() end +---@return number? altitude altitude above the ground or sea level in meters +function Body:GetGroundPosition(terrainRelative) end --- Find the nearest object of a type ---@param type PhysicsObjectType @@ -104,11 +105,12 @@ function Body:GetPositionRelTo(other) end --- Get the body's altitude relative to another body. --- ---- Returns height above terrain if the other body is a TerrainBody or +--- Returns height above terrain or sea level if the other body is a TerrainBody or --- distance between bodies otherwise. ---@param other Body +---@param boolean? terrainRelative ---@return number altitude -function Body:GetAltitudeRelTo(other) end +function Body:GetAltitudeRelTo(other, terrainRelative) end ---@return number function Body:GetPhysicalRadius() end 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..3e6b7a5be1c 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/enum_table.cpp b/src/enum_table.cpp index e8ee25f5b0e..4d0e6b4d929 100644 --- a/src/enum_table.cpp +++ b/src/enum_table.cpp @@ -35,6 +35,13 @@ const struct EnumItem ENUM_PhysicsObjectType[] = { { 0, 0 }, }; +const struct EnumItem ENUM_AltitudeType[] = { + { "DEFAULT", int(AltitudeType::DEFAULT) }, + { "SEA_LEVEL", int(AltitudeType::SEA_LEVEL) }, + { "ABOVE_TERRAIN", int(AltitudeType::ABOVE_TERRAIN) }, + { 0, 0 }, +}; + const struct EnumItem ENUM_ShipAIError[] = { { "NONE", int(Ship::AIERROR_NONE) }, { "GRAV_TOO_HIGH", int(Ship::AIERROR_GRAV_TOO_HIGH) }, @@ -308,6 +315,7 @@ const struct EnumItem ENUM_ShipControllerFlightControlState[] = { const struct EnumTable ENUM_TABLES[] = { { "PhysicsObjectType", ENUM_PhysicsObjectType }, + { "AltitudeType", ENUM_AltitudeType }, { "ShipAIError", ENUM_ShipAIError }, { "ShipFlightState", ENUM_ShipFlightState }, { "ShipJumpStatus", ENUM_ShipJumpStatus }, @@ -338,6 +346,7 @@ const struct EnumTable ENUM_TABLES[] = { const struct EnumTable ENUM_TABLES_PUBLIC[] = { { "PhysicsObjectType", ENUM_PhysicsObjectType }, + { "AltitudeType", ENUM_AltitudeType }, { "ShipAIError", ENUM_ShipAIError }, { "ShipFlightState", ENUM_ShipFlightState }, { "ShipJumpStatus", ENUM_ShipJumpStatus }, diff --git a/src/enum_table.h b/src/enum_table.h index 8bf3bbc9f2d..bf31bd0a8aa 100644 --- a/src/enum_table.h +++ b/src/enum_table.h @@ -17,6 +17,7 @@ struct EnumTable { }; extern const struct EnumItem ENUM_PhysicsObjectType[]; +extern const struct EnumItem ENUM_AltitudeType[]; extern const struct EnumItem ENUM_ShipAIError[]; extern const struct EnumItem ENUM_ShipFlightState[]; extern const struct EnumItem ENUM_ShipJumpStatus[]; diff --git a/src/lua/LuaBody.cpp b/src/lua/LuaBody.cpp index c0882c94ba5..ca58b42ed60 100644 --- a/src/lua/LuaBody.cpp +++ b/src/lua/LuaBody.cpp @@ -102,7 +102,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 +221,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 +334,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 +354,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); @@ -370,11 +368,19 @@ static int l_body_get_position_rel_to(lua_State *l) * * Get the body's altitude relative to another body * - * > body:GetAltitudeRelTo(otherBody) - * * Parameters: * * other - the other body + * (optional) terrainRelative - what altitude to calculate (sea-level(false), above-terrain(true)) + * if not specified, sea-level for distant bodies, above-ground otherwise + * + * Examples: + * + * > -- Get relative altitude to other body + * > body:GetAltitudeRelTo(otherBody) + * + * > -- Get relative above terrain altitude to other body + * > body:GetAltitudeRelTo(otherBody, true) * * Availability: * @@ -384,28 +390,19 @@ 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); - } - double altitude = center_dist - radius; - if (altitude < 0) - altitude = 0; - LuaPush(l, altitude); - return 1; - } else { - LuaPush(l, center_dist); - return 1; + AltitudeType altType = AltitudeType::DEFAULT; + if (!lua_isnoneornil(l, 3)) + { + bool terrainRelative = lua_toboolean(l, 3); + altType = terrainRelative ? AltitudeType::ABOVE_TERRAIN : AltitudeType::SEA_LEVEL; } + double altitude = b->GetAltitudeRelTo(other, altType); + LuaPush(l, altitude); + return 1; } /* @@ -493,6 +490,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 +526,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,11 +611,15 @@ 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() * + * Parameters: + * + * (optional) terrainRelative - what altitude to calculate (sea-level(false), above-terrain(true)) + * if not specified, sea-level for distant bodies, above-terrain otherwise + * * Returns: * * latitude - the latitude of the body in radians @@ -619,6 +633,11 @@ static int l_body_distance_to(lua_State *l) * > lat = math.rad2deg(lat) * > long = math.rad2deg(long) * + * > -- Get ground position of the player with sea-level altitude + * > local lat, long, alt = Game.player:GetGroundPosition(false) + * > lat = math.rad2deg(lat) + * > long = math.rad2deg(long) + * * Availability: * * July 2013 @@ -630,28 +649,33 @@ static int l_body_distance_to(lua_State *l) static int l_body_get_ground_position(lua_State *l) { Body *b = LuaObject::CheckFromLua(1); + AltitudeType altType = AltitudeType::DEFAULT; + if (!lua_isnoneornil(l, 2)) + { + bool terrainRelative = lua_toboolean(l, 2); + altType = terrainRelative ? AltitudeType::ABOVE_TERRAIN : AltitudeType::SEA_LEVEL; + } + if (!b->IsType(ObjectType::DYNAMICBODY)) { lua_pushnil(l); return 1; } 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, altType); + lua_pushnumber(l, altitude); return 3; } @@ -711,7 +735,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 +775,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; @@ -788,7 +811,6 @@ static bool pi_lua_body_serializer(lua_State *l, Json &out) { Body *body = LuaObject::GetFromLua(-1); if (!body) return false; - out = Json(Pi::game->GetSpace()->GetIndexForBody(body)); return true; } diff --git a/src/lua/LuaPlayer.cpp b/src/lua/LuaPlayer.cpp index c2b29036ad0..e479a97b768 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); @@ -416,7 +406,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 +432,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 +454,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 +481,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 +562,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 +810,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..1b307e5c988 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);