From f4b36b8f738953e4dc831d38c3f4b54dc7da02fc Mon Sep 17 00:00:00 2001 From: FinnHornhoover Date: Mon, 24 Jul 2023 00:33:19 +0300 Subject: [PATCH 1/4] added alternate racing score funcitonality --- src/Racing.cpp | 38 +++++++++++++++++++++++++++----------- src/Racing.hpp | 6 +++++- src/TableData.cpp | 35 +++++++++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 16 deletions(-) diff --git a/src/Racing.cpp b/src/Racing.cpp index 565850c..180d483 100644 --- a/src/Racing.cpp +++ b/src/Racing.cpp @@ -64,7 +64,7 @@ static void racingCancel(CNSocket* sock, CNPacketData* data) { INITSTRUCT(sP_FE2CL_REP_EP_RACE_CANCEL_SUCC, resp); sock->sendPacket(resp, P_FE2CL_REP_EP_RACE_CANCEL_SUCC); - /* + /* * This request packet is used for both cancelling the race via the * NPC at the start, *and* failing the race by running out of time. * If the latter is to happen, the client disables movement until it @@ -97,31 +97,47 @@ static void racingEnd(CNSocket* sock, CNPacketData* data) { if (EPData.find(mapNum) == EPData.end() || EPData[mapNum].EPID == 0) return; // IZ not found - uint64_t now = getTime() / 1000; + EPInfo& epInfo = EPData[mapNum]; + EPRace& epRace = EPRaces[sock]; + // if there are no divide-by-zero dangers, and at least one factor has been specified + // we switch over to OG scoring + bool useOGScoring = (epInfo.maxPods > 0) && (epInfo.maxTime > 0) && ( + (epInfo.scaleFactor > 0.0) || (epInfo.podFactor > 0.0) || (epInfo.timeFactor > 0.0)); - int timeDiff = now - EPRaces[sock].startTime; - int score = 500 * EPRaces[sock].collectedRings.size() - 10 * timeDiff; - if (score < 0) score = 0; // lol - int fm = score * plr->level * (1.0f / 36) * 0.3f; + uint64_t now = getTime() / 1000; + int timeDiff = now - epRace.startTime; + int podsCollected = epRace.collectedRings.size(); + int score = 0, fm = 0; + + if (useOGScoring) { + score = std::min(epInfo.maxScore, (int)std::exp( + (epInfo.podFactor * podsCollected) / epInfo.maxPods + - (epInfo.timeFactor * timeDiff) / epInfo.maxTime + + epInfo.scaleFactor)); + fm = (1.0 + std::exp(epInfo.scaleFactor - 1.0) * epInfo.podFactor * podsCollected) / epInfo.maxPods; + } else { + score = std::max(0, 500 * podsCollected - 10 * timeDiff); + fm = score * plr->level * (1.0f / 36) * 0.3f; + } // we submit the ranking first... Database::RaceRanking postRanking = {}; - postRanking.EPID = EPData[mapNum].EPID; + postRanking.EPID = epInfo.EPID; postRanking.PlayerID = plr->iID; - postRanking.RingCount = EPRaces[sock].collectedRings.size(); + postRanking.RingCount = podsCollected; postRanking.Score = score; postRanking.Time = timeDiff; postRanking.Timestamp = getTimestamp(); Database::postRaceRanking(postRanking); // ...then we get the top ranking, which may or may not be what we just submitted - Database::RaceRanking topRankingPlayer = Database::getTopRaceRanking(EPData[mapNum].EPID, plr->iID); + Database::RaceRanking topRankingPlayer = Database::getTopRaceRanking(epInfo.EPID, plr->iID); INITSTRUCT(sP_FE2CL_REP_EP_RACE_END_SUCC, resp); // get rank scores and rewards - std::vector* rankScores = &EPRewards[EPData[mapNum].EPID].first; - std::vector* rankRewards = &EPRewards[EPData[mapNum].EPID].second; + std::vector* rankScores = &EPRewards[epInfo.EPID].first; + std::vector* rankRewards = &EPRewards[epInfo.EPID].second; // top ranking int topRank = 0; diff --git a/src/Racing.hpp b/src/Racing.hpp index f6e6acb..90cc9f2 100644 --- a/src/Racing.hpp +++ b/src/Racing.hpp @@ -5,7 +5,11 @@ #include "servers/CNShardServer.hpp" struct EPInfo { - int zoneX, zoneY, EPID, maxScore, maxTime; + // available through XDT (maxScore may be updated by drops) + int zoneX, zoneY, EPID, maxScore; + // (maybe) available through drops + int maxTime = 0, maxPods = 0; + double scaleFactor = 0.0, podFactor = 0.0, timeFactor = 0.0; }; struct EPRace { diff --git a/src/TableData.cpp b/src/TableData.cpp index a685cee..de05177 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -363,7 +363,7 @@ static void loadPaths(json& pathData, int32_t* nextId) { Transport::NPCPaths.push_back(pathTemplate); } std::cout << "[INFO] Loaded " << Transport::NPCPaths.size() << " NPC paths" << std::endl; - + } catch (const std::exception& err) { std::cerr << "[FATAL] Malformed paths.json file! Reason:" << err.what() << std::endl; @@ -572,8 +572,35 @@ static void loadDrops(json& dropData) { continue; } + EPInfo& epInfo = Racing::EPData[EPMap]; + // time limit isn't stored in the XDT, so we include it in the reward table instead - Racing::EPData[EPMap].maxTime = race["TimeLimit"]; + epInfo.maxTime = (int)race["TimeLimit"]; + + // update max score (if present) + if (race.find("ScoreCap") != race.end()) { + epInfo.maxScore = (int)race["ScoreCap"]; + } + + // update max pods (if present) + if (race.find("TotalPods") != race.end()) { + epInfo.maxPods = (int)race["TotalPods"]; + } + + // update scale factor (if present) + if (race.find("ScaleFactor") != race.end()) { + epInfo.scaleFactor = (double)race["ScaleFactor"]; + } + + // update pod factor (if present) + if (race.find("PodFactor") != race.end()) { + epInfo.podFactor = (double)race["PodFactor"]; + } + + // update time factor (if present) + if (race.find("TimeFactor") != race.end()) { + epInfo.timeFactor = (double)race["TimeFactor"]; + } // score cutoffs std::vector rankScores; @@ -674,7 +701,7 @@ static void loadEggs(json& eggData, int32_t* nextId) { } } -/* +/* * Load gruntwork output, if it exists */ static void loadGruntworkPre(json& gruntwork, int32_t* nextId) { @@ -1349,7 +1376,7 @@ void TableData::flush() { targetIDs.push_back(tID); for (int32_t tType : path.targetTypes) targetTypes.push_back(tType); - + pathObj["iBaseSpeed"] = path.speed; pathObj["iTaskID"] = path.escortTaskID; pathObj["bRelative"] = path.isRelative; From 30b2f4eb3661c338b8c786bde5a5ceabd904beeb Mon Sep 17 00:00:00 2001 From: FinnHornhoover Date: Tue, 10 Oct 2023 22:36:10 +0300 Subject: [PATCH 2/4] added config option for racing score modes --- config.ini | 5 +++++ src/Racing.cpp | 6 +----- src/TableData.cpp | 20 ++------------------ src/settings.cpp | 4 ++++ src/settings.hpp | 1 + 5 files changed, 13 insertions(+), 23 deletions(-) diff --git a/config.ini b/config.ini index fb7977d..be14f07 100644 --- a/config.ini +++ b/config.ini @@ -51,6 +51,11 @@ motd=Welcome to OpenFusion! # and pre-Academy builds must *not* contain it. #enabledpatches=1013 +# Use Original FusionFall's racing score and reward calculation? +# Set false to use Retro's calculation, make sure you have the correct +# patch(es) loaded. +ogracingscores=true + # xdt json filename #xdtdata=xdt.json # NPC json filename diff --git a/src/Racing.cpp b/src/Racing.cpp index 180d483..e8977d2 100644 --- a/src/Racing.cpp +++ b/src/Racing.cpp @@ -99,17 +99,13 @@ static void racingEnd(CNSocket* sock, CNPacketData* data) { EPInfo& epInfo = EPData[mapNum]; EPRace& epRace = EPRaces[sock]; - // if there are no divide-by-zero dangers, and at least one factor has been specified - // we switch over to OG scoring - bool useOGScoring = (epInfo.maxPods > 0) && (epInfo.maxTime > 0) && ( - (epInfo.scaleFactor > 0.0) || (epInfo.podFactor > 0.0) || (epInfo.timeFactor > 0.0)); uint64_t now = getTime() / 1000; int timeDiff = now - epRace.startTime; int podsCollected = epRace.collectedRings.size(); int score = 0, fm = 0; - if (useOGScoring) { + if (settings::OGRACINGSCORES) { score = std::min(epInfo.maxScore, (int)std::exp( (epInfo.podFactor * podsCollected) / epInfo.maxPods - (epInfo.timeFactor * timeDiff) / epInfo.maxTime diff --git a/src/TableData.cpp b/src/TableData.cpp index de05177..f562b04 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -577,28 +577,12 @@ static void loadDrops(json& dropData) { // time limit isn't stored in the XDT, so we include it in the reward table instead epInfo.maxTime = (int)race["TimeLimit"]; - // update max score (if present) - if (race.find("ScoreCap") != race.end()) { + // the following has to be present based on the score calculation method + if (settings::OGRACINGSCORES) { epInfo.maxScore = (int)race["ScoreCap"]; - } - - // update max pods (if present) - if (race.find("TotalPods") != race.end()) { epInfo.maxPods = (int)race["TotalPods"]; - } - - // update scale factor (if present) - if (race.find("ScaleFactor") != race.end()) { epInfo.scaleFactor = (double)race["ScaleFactor"]; - } - - // update pod factor (if present) - if (race.find("PodFactor") != race.end()) { epInfo.podFactor = (double)race["PodFactor"]; - } - - // update time factor (if present) - if (race.find("TimeFactor") != race.end()) { epInfo.timeFactor = (double)race["TimeFactor"]; } diff --git a/src/settings.cpp b/src/settings.cpp index 14d8de4..a148cbb 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -66,6 +66,9 @@ int settings::MONITORINTERVAL = 5000; // event mode settings int settings::EVENTMODE = 0; +// racing score mode +bool settings::OGRACINGSCORES = true; + void settings::init() { INIReader reader("config.ini"); @@ -110,6 +113,7 @@ void settings::init() { EVENTMODE = reader.GetInteger("shard", "eventmode", EVENTMODE); DISABLEFIRSTUSEFLAG = reader.GetBoolean("shard", "disablefirstuseflag", DISABLEFIRSTUSEFLAG); ANTICHEAT = reader.GetBoolean("shard", "anticheat", ANTICHEAT); + OGRACINGSCORES = reader.GetBoolean("shard", "ogracingscores", OGRACINGSCORES); MONITORENABLED = reader.GetBoolean("monitor", "enabled", MONITORENABLED); MONITORPORT = reader.GetInteger("monitor", "port", MONITORPORT); MONITORINTERVAL = reader.GetInteger("monitor", "interval", MONITORINTERVAL); diff --git a/src/settings.hpp b/src/settings.hpp index 1ea3a43..4986784 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -36,6 +36,7 @@ namespace settings { extern int MONITORPORT; extern int MONITORINTERVAL; extern bool DISABLEFIRSTUSEFLAG; + extern bool OGRACINGSCORES; void init(); } From e88ef52d12ba34212e07b7d6de51f719c9711cc3 Mon Sep 17 00:00:00 2001 From: FinnHornhoover <30576665+FinnHornhoover@users.noreply.github.com> Date: Tue, 10 Oct 2023 23:06:42 +0300 Subject: [PATCH 3/4] commented out default config value Co-authored-by: Gent Semaj --- config.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.ini b/config.ini index be14f07..c4d73fb 100644 --- a/config.ini +++ b/config.ini @@ -54,7 +54,7 @@ motd=Welcome to OpenFusion! # Use Original FusionFall's racing score and reward calculation? # Set false to use Retro's calculation, make sure you have the correct # patch(es) loaded. -ogracingscores=true +#ogracingscores=true # xdt json filename #xdtdata=xdt.json From b146328484cb55442d6718c55e79977e5e1693f3 Mon Sep 17 00:00:00 2001 From: FinnHornhoover Date: Wed, 11 Oct 2023 14:12:40 +0300 Subject: [PATCH 4/4] removed config option, og scoring now forced --- config.ini | 5 ----- src/Racing.cpp | 16 +++++----------- src/Racing.hpp | 6 +++--- src/TableData.cpp | 14 +++++--------- src/settings.cpp | 4 ---- src/settings.hpp | 1 - 6 files changed, 13 insertions(+), 33 deletions(-) diff --git a/config.ini b/config.ini index c4d73fb..fb7977d 100644 --- a/config.ini +++ b/config.ini @@ -51,11 +51,6 @@ motd=Welcome to OpenFusion! # and pre-Academy builds must *not* contain it. #enabledpatches=1013 -# Use Original FusionFall's racing score and reward calculation? -# Set false to use Retro's calculation, make sure you have the correct -# patch(es) loaded. -#ogracingscores=true - # xdt json filename #xdtdata=xdt.json # NPC json filename diff --git a/src/Racing.cpp b/src/Racing.cpp index e8977d2..62cfe47 100644 --- a/src/Racing.cpp +++ b/src/Racing.cpp @@ -103,18 +103,12 @@ static void racingEnd(CNSocket* sock, CNPacketData* data) { uint64_t now = getTime() / 1000; int timeDiff = now - epRace.startTime; int podsCollected = epRace.collectedRings.size(); - int score = 0, fm = 0; - if (settings::OGRACINGSCORES) { - score = std::min(epInfo.maxScore, (int)std::exp( - (epInfo.podFactor * podsCollected) / epInfo.maxPods - - (epInfo.timeFactor * timeDiff) / epInfo.maxTime - + epInfo.scaleFactor)); - fm = (1.0 + std::exp(epInfo.scaleFactor - 1.0) * epInfo.podFactor * podsCollected) / epInfo.maxPods; - } else { - score = std::max(0, 500 * podsCollected - 10 * timeDiff); - fm = score * plr->level * (1.0f / 36) * 0.3f; - } + int score = std::min(epInfo.maxScore, (int)std::exp( + (epInfo.podFactor * podsCollected) / epInfo.maxPods + - (epInfo.timeFactor * timeDiff) / epInfo.maxTime + + epInfo.scaleFactor)); + int fm = (1.0 + std::exp(epInfo.scaleFactor - 1.0) * epInfo.podFactor * podsCollected) / epInfo.maxPods; // we submit the ranking first... Database::RaceRanking postRanking = {}; diff --git a/src/Racing.hpp b/src/Racing.hpp index 90cc9f2..44ad739 100644 --- a/src/Racing.hpp +++ b/src/Racing.hpp @@ -7,9 +7,9 @@ struct EPInfo { // available through XDT (maxScore may be updated by drops) int zoneX, zoneY, EPID, maxScore; - // (maybe) available through drops - int maxTime = 0, maxPods = 0; - double scaleFactor = 0.0, podFactor = 0.0, timeFactor = 0.0; + // available through drops + int maxTime, maxPods; + double scaleFactor, podFactor, timeFactor; }; struct EPRace { diff --git a/src/TableData.cpp b/src/TableData.cpp index f562b04..1ee8322 100644 --- a/src/TableData.cpp +++ b/src/TableData.cpp @@ -576,15 +576,11 @@ static void loadDrops(json& dropData) { // time limit isn't stored in the XDT, so we include it in the reward table instead epInfo.maxTime = (int)race["TimeLimit"]; - - // the following has to be present based on the score calculation method - if (settings::OGRACINGSCORES) { - epInfo.maxScore = (int)race["ScoreCap"]; - epInfo.maxPods = (int)race["TotalPods"]; - epInfo.scaleFactor = (double)race["ScaleFactor"]; - epInfo.podFactor = (double)race["PodFactor"]; - epInfo.timeFactor = (double)race["TimeFactor"]; - } + epInfo.maxScore = (int)race["ScoreCap"]; + epInfo.maxPods = (int)race["TotalPods"]; + epInfo.scaleFactor = (double)race["ScaleFactor"]; + epInfo.podFactor = (double)race["PodFactor"]; + epInfo.timeFactor = (double)race["TimeFactor"]; // score cutoffs std::vector rankScores; diff --git a/src/settings.cpp b/src/settings.cpp index a148cbb..14d8de4 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -66,9 +66,6 @@ int settings::MONITORINTERVAL = 5000; // event mode settings int settings::EVENTMODE = 0; -// racing score mode -bool settings::OGRACINGSCORES = true; - void settings::init() { INIReader reader("config.ini"); @@ -113,7 +110,6 @@ void settings::init() { EVENTMODE = reader.GetInteger("shard", "eventmode", EVENTMODE); DISABLEFIRSTUSEFLAG = reader.GetBoolean("shard", "disablefirstuseflag", DISABLEFIRSTUSEFLAG); ANTICHEAT = reader.GetBoolean("shard", "anticheat", ANTICHEAT); - OGRACINGSCORES = reader.GetBoolean("shard", "ogracingscores", OGRACINGSCORES); MONITORENABLED = reader.GetBoolean("monitor", "enabled", MONITORENABLED); MONITORPORT = reader.GetInteger("monitor", "port", MONITORPORT); MONITORINTERVAL = reader.GetInteger("monitor", "interval", MONITORINTERVAL); diff --git a/src/settings.hpp b/src/settings.hpp index 4986784..1ea3a43 100644 --- a/src/settings.hpp +++ b/src/settings.hpp @@ -36,7 +36,6 @@ namespace settings { extern int MONITORPORT; extern int MONITORINTERVAL; extern bool DISABLEFIRSTUSEFLAG; - extern bool OGRACINGSCORES; void init(); }