From e0f9f411056c235947b809cb21c477aa5acca1b4 Mon Sep 17 00:00:00 2001 From: Aki Date: Wed, 3 Apr 2024 01:31:01 +0200 Subject: Fixed mission points reward calculation --- StarsEx/CMakeLists.txt | 2 ++ StarsEx/DebriefDlg.cpp | 13 ++------ StarsEx/Player.cpp | 71 +++++++++++------------------------------- StarsEx/Player.h | 3 +- StarsEx/Sim.cpp | 3 +- StarsEx/SimEvent.cpp | 52 +++++++++++++++++++++++++++++-- StarsEx/SimEvent.h | 46 ++++++++++++++++----------- StarsEx/test/ShipStats.cpp | 29 +++++++++++++++++ StarsEx/test/dump_missions.cpp | 1 + 9 files changed, 134 insertions(+), 86 deletions(-) create mode 100644 StarsEx/test/ShipStats.cpp create mode 100644 StarsEx/test/dump_missions.cpp diff --git a/StarsEx/CMakeLists.txt b/StarsEx/CMakeLists.txt index 6a6b4d6..3e9dc83 100644 --- a/StarsEx/CMakeLists.txt +++ b/StarsEx/CMakeLists.txt @@ -332,7 +332,9 @@ endif() add_executable( ${PROJECT_NAME}_test test/AudioConfig.cpp + test/ShipStats.cpp test/Stardate.cpp + test/dump_missions.cpp ) generate_emulator(${PROJECT_NAME}_test LIBS Opcode ArchiveEx) target_link_libraries(${PROJECT_NAME}_test PRIVATE ${PROJECT_NAME} GTest::gtest_main) diff --git a/StarsEx/DebriefDlg.cpp b/StarsEx/DebriefDlg.cpp index 1cd919b..b613e3c 100644 --- a/StarsEx/DebriefDlg.cpp +++ b/StarsEx/DebriefDlg.cpp @@ -185,16 +185,9 @@ DebriefDlg::Show() ShipStats* stats = ShipStats::GetStats(i); if (stats && !strcmp(ship->Name(), stats->GetName())) { stats->Summarize(); - - Player* player = Player::GetCurrentPlayer(); - int points = stats->GetPoints() + stats->GetCommandPoints(); - - if (player && sim) - points = player->GetMissionPoints(stats, sim->StartTime()) + stats->GetCommandPoints(); - - char score[32]; - sprintf_s(score, "%d %s", points, ContentBundle::GetInstance()->GetText("DebriefDlg.points").data()); - mission_score->SetText(score); + const auto points = stats->EffectivePoints(); + mission_score->SetText(Text::format( + "%d %s", points, ContentBundle::GetInstance()->GetText("DebriefDlg.points").data())); break; } } diff --git a/StarsEx/Player.cpp b/StarsEx/Player.cpp index 091c808..f299079 100644 --- a/StarsEx/Player.cpp +++ b/StarsEx/Player.cpp @@ -13,25 +13,25 @@ #include "Player.h" +#include #include -#include "NetLobbyServer.h" -#include "NetLayer.h" -#include "Ship.h" -#include "SimEvent.h" +#include "Bitmap.h" #include "Campaign.h" #include "CampaignSaveGame.h" -#include "Random.h" -#include "HUDView.h" -#include "Mfd.h" - +#include "Clock.h" +#include "ContentBundle.h" #include "DataLoader.h" #include "Encrypt.h" -#include "ParseUtil.h" #include "FormatUtil.h" -#include "Bitmap.h" -#include "Clock.h" -#include "ContentBundle.h" +#include "HUDView.h" +#include "Mfd.h" +#include "NetLayer.h" +#include "NetLobbyServer.h" +#include "ParseUtil.h" +#include "Random.h" +#include "Ship.h" +#include "SimEvent.h" // +-------------------------------------------------------------------+ @@ -634,54 +634,19 @@ Player::CommandRankRequired(int ship_class) // +-------------------------------------------------------------------+ -int -Player::GetMissionPoints(ShipStats* s, std::int_fast32_t flight_time_) -{ - int result = 0; - - if (s) { - result = s->GetPoints(); - - // if player survived mission, award one experience point - // for each minute of action, in ten point blocks: - if (!s->GetDeaths() && !s->GetColls()) { - int minutes = flight_time_ / 60; - minutes /= 10; - minutes *= 10; - result += minutes; - - if (s->HasEvent(SimEvent::DOCK)) - result += 100; - } - else { - result -= (int) (2.5 * Ship::Value(s->GetShipClass())); - } - - if (result < 0) - result = 0; - } - - return result; -} - -// +-------------------------------------------------------------------+ - void -Player::ProcessStats(ShipStats* s, std::int_fast32_t flight_time_) +Player::ProcessStats(ShipStats* s) { - if (!s) return; - + if (!s) + return; int old_rank = Rank(); - int pts = GetMissionPoints(s, flight_time_); - - AddPoints(pts); - AddPoints(s->GetCommandPoints()); + AddMissions(1); + AddPoints(s->EffectivePoints()); AddKills(s->GetGunKills()); AddKills(s->GetMissileKills()); AddLosses(s->GetDeaths()); AddLosses(s->GetColls()); - AddMissions(1); - AddFlightTime(flight_time_); + AddFlightTime(s->FlightTime()); int rank = Rank(); diff --git a/StarsEx/Player.h b/StarsEx/Player.h index 62e8700..867e2ca 100644 --- a/StarsEx/Player.h +++ b/StarsEx/Player.h @@ -116,8 +116,7 @@ public: Text EncodeStats(); void DecodeStats(const char* stats); - int GetMissionPoints(ShipStats* stats, std::int_fast32_t flight_time_); - void ProcessStats(ShipStats* stats, std::int_fast32_t flight_time_); + void ProcessStats(ShipStats* stats); bool EarnedAward(AwardInfo* a, ShipStats* s); static const char* RankName(int rank); diff --git a/StarsEx/Sim.cpp b/StarsEx/Sim.cpp index f938b7a..5e49cb0 100644 --- a/StarsEx/Sim.cpp +++ b/StarsEx/Sim.cpp @@ -206,7 +206,8 @@ Sim::CommitMission() if (s->IsPlayer()) { Player* p = Player::GetCurrentPlayer(); - p->ProcessStats(s, starshatter::engine::MissionTime()); + s->SetFlightTime(starshatter::engine::MissionTime()); + p->ProcessStats(s); if (mission && mission->Type() == Mission::TRAINING && s->GetDeaths() == 0 && s->GetColls() == 0) diff --git a/StarsEx/SimEvent.cpp b/StarsEx/SimEvent.cpp index 35eb117..42ce240 100644 --- a/StarsEx/SimEvent.cpp +++ b/StarsEx/SimEvent.cpp @@ -12,9 +12,11 @@ */ #include "SimEvent.h" -#include "Sim.h" + #include "Clock.h" #include "ContentBundle.h" +#include "Ship.h" +#include "Sim.h" // +====================================================================+ @@ -191,6 +193,52 @@ ShipStats::Summarize() } } + +long double +ShipStats::FlightTime() const +{ + return flight_time; +} + + +void +ShipStats::SetFlightTime(long double seconds) +{ + flight_time = seconds; +} + + +static int +FlightTimeBonus(const ShipStats* stats) +{ + static constexpr long double TEN_MINUTES {600.0l}; + return static_cast(stats->FlightTime() / TEN_MINUTES) * 10; +} + + +static int +DockBonus(const ShipStats* stats) +{ + return stats->HasEvent(SimEvent::DOCK) ? 100 : 0; +} + + +static int +LossPenalty(const ShipStats* stats) +{ + return 2.5 * Ship::Value(stats->GetShipClass()); +} + + +int +ShipStats::EffectivePoints() const +{ + const auto whole {GetPoints() + GetCommandPoints()}; + if (GetDeaths() > 0 || GetColls() > 0) + return std::max(0, whole - LossPenalty(this)); + return whole + FlightTimeBonus(this) + DockBonus(this); +} + // +--------------------------------------------------------------------+ SimEvent* @@ -209,7 +257,7 @@ ShipStats::AddEvent(int event, const char* tgt, const char* info) } bool -ShipStats::HasEvent(int event) +ShipStats::HasEvent(int event) const { for (int i = 0; i < events.size(); i++) if (events[i]->GetEvent() == event) diff --git a/StarsEx/SimEvent.h b/StarsEx/SimEvent.h index 66d6342..c8bd092 100644 --- a/StarsEx/SimEvent.h +++ b/StarsEx/SimEvent.h @@ -11,14 +11,11 @@ Simulation Universe and Region classes */ -#ifndef SimEvent_h -#define SimEvent_h +#pragma once -#include "Types.h" -#include "List.h" -#include "Text.h" +#include +#include -// +--------------------------------------------------------------------+ class Sim; class SimRegion; @@ -28,19 +25,32 @@ class SimHyper; class CombatGroup; class CombatUnit; -// +--------------------------------------------------------------------+ class SimEvent { public: static const char* TYPENAME() { return "SimEvent"; } - enum EVENT { LAUNCH=1, DOCK, LAND, EJECT, CRASH, COLLIDE, DESTROYED, - MAKE_ORBIT, BREAK_ORBIT, QUANTUM_JUMP, - LAUNCH_SHIP, RECOVER_SHIP, - FIRE_GUNS, FIRE_MISSILE, DROP_DECOY, - GUNS_KILL, MISSILE_KILL, - LAUNCH_PROBE, SCAN_TARGET + enum EVENT { + LAUNCH=1, + DOCK, + LAND, + EJECT, + CRASH, + COLLIDE, + DESTROYED, + MAKE_ORBIT, + BREAK_ORBIT, + QUANTUM_JUMP, + LAUNCH_SHIP, + RECOVER_SHIP, + FIRE_GUNS, + FIRE_MISSILE, + DROP_DECOY, + GUNS_KILL, + MISSILE_KILL, + LAUNCH_PROBE, + SCAN_TARGET, }; SimEvent(int event, const char* tgt=0, const char* info=0); @@ -66,7 +76,6 @@ private: int count; }; -// +--------------------------------------------------------------------+ class ShipStats { @@ -104,6 +113,8 @@ public: int GetGunHits() const { return gun_hits; } int GetMissileShots() const { return missile_shots; } int GetMissileHits() const { return missile_hits; } + long double FlightTime() const; + int EffectivePoints() const; bool IsPlayer() const { return player; } @@ -111,7 +122,7 @@ public: GetEvents() { return events; } SimEvent* AddEvent(SimEvent* e); SimEvent* AddEvent(int event, const char* tgt=0, const char* info=0); - bool HasEvent(int event); + bool HasEvent(int event) const; void SetShipClass(int c) { ship_class = c; } void SetIFF(int i) { iff = i; } @@ -129,6 +140,7 @@ public: void AddMissileHit() { missile_hits++; } void AddPoints(int p) { points += p; } void AddCommandPoints(int p) { cmd_points += p; } + void SetFlightTime(long double seconds); private: Text name; @@ -155,8 +167,6 @@ private: int points; int cmd_points; + long double flight_time; List events; }; - -#endif // SimEvent_h - diff --git a/StarsEx/test/ShipStats.cpp b/StarsEx/test/ShipStats.cpp new file mode 100644 index 0000000..1430573 --- /dev/null +++ b/StarsEx/test/ShipStats.cpp @@ -0,0 +1,29 @@ +#include + +#include +#include + + +TEST(StarsEx, EffectivePoints) +{ + Clock::Init(); + ShipStats::Initialize(); + auto* first = ShipStats::Find("first"); + ASSERT_NE(nullptr, first); + EXPECT_EQ(0, first->EffectivePoints()); + first->SetFlightTime(590.0l); + EXPECT_EQ(0, first->EffectivePoints()); + first->SetFlightTime(610.0l); + EXPECT_EQ(10, first->EffectivePoints()); + first->SetFlightTime(1210.0l); + EXPECT_EQ(20, first->EffectivePoints()); + const auto* destroyed = first->AddEvent(SimEvent::DESTROYED); + first->Summarize(); + EXPECT_EQ(0, first->EffectivePoints()); + auto* second = ShipStats::Find("second"); + ASSERT_NE(nullptr, second); + const auto* docked = second->AddEvent(SimEvent::DOCK); + EXPECT_EQ(100, second->EffectivePoints()); + ShipStats::Close(); + Clock::Close(); +} diff --git a/StarsEx/test/dump_missions.cpp b/StarsEx/test/dump_missions.cpp new file mode 100644 index 0000000..a0e5ffc --- /dev/null +++ b/StarsEx/test/dump_missions.cpp @@ -0,0 +1 @@ +int dump_missions = 0; -- cgit v1.1