mirror of
				https://github.com/OpenFusionProject/OpenFusion.git
				synced 2025-10-31 00:30:15 +00:00 
			
		
		
		
	Merge e88ef52d12 into 4592fc42af
				
					
				
			This commit is contained in:
		| @@ -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 | ||||
|   | ||||
| @@ -66,7 +66,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 | ||||
| @@ -99,31 +99,43 @@ 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]; | ||||
|  | ||||
|     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 (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; | ||||
|     } | ||||
|  | ||||
|     // 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<int>* rankScores = &EPRewards[EPData[mapNum].EPID].first; | ||||
|     std::vector<int>* rankRewards = &EPRewards[EPData[mapNum].EPID].second; | ||||
|     std::vector<int>* rankScores = &EPRewards[epInfo.EPID].first; | ||||
|     std::vector<int>* rankRewards = &EPRewards[epInfo.EPID].second; | ||||
|  | ||||
|     // top ranking | ||||
|     int topRank = 0; | ||||
|   | ||||
| @@ -7,7 +7,11 @@ | ||||
| #include <set> | ||||
|  | ||||
| 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 { | ||||
|   | ||||
| @@ -375,7 +375,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; | ||||
| @@ -584,8 +584,19 @@ 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"]; | ||||
|  | ||||
|             // 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"]; | ||||
|             } | ||||
|  | ||||
|             // score cutoffs | ||||
|             std::vector<int> rankScores; | ||||
| @@ -686,7 +697,7 @@ static void loadEggs(json& eggData, int32_t* nextId) { | ||||
|     } | ||||
| } | ||||
|  | ||||
| /*  | ||||
| /* | ||||
|  * Load gruntwork output, if it exists | ||||
|  */ | ||||
| static void loadGruntworkPre(json& gruntwork, int32_t* nextId) { | ||||
| @@ -1361,7 +1372,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; | ||||
|   | ||||
| @@ -67,6 +67,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"); | ||||
|  | ||||
| @@ -111,6 +114,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); | ||||
|   | ||||
| @@ -38,6 +38,7 @@ namespace settings { | ||||
|     extern int MONITORPORT; | ||||
|     extern int MONITORINTERVAL; | ||||
|     extern bool DISABLEFIRSTUSEFLAG; | ||||
|     extern bool OGRACINGSCORES; | ||||
|  | ||||
|     void init(); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 FinnHornhoover
					FinnHornhoover