Add support of points for the future cup
This commit is contained in:
parent
685d6ad3fb
commit
654c2b4dde
@ -4,7 +4,7 @@
|
||||
#Extends "Modes/Nadeo/Trackmania/Base/TrackmaniaRoundsBase.Script.txt"
|
||||
|
||||
#Const CompatibleMapTypes "TrackMania\\TM_Race,TM_Race"
|
||||
#Const Version "2024-04-08"
|
||||
#Const Version "2024-05-08"
|
||||
#Const ScriptName "Modes/TM2020-Gamemodes/LastManStanding.Script.txt"
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
||||
@ -26,7 +26,7 @@
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
||||
#Setting S_ForceLapsNb 1
|
||||
#Setting S_RoundsPerMap 1 as _("Number of rounds per map") ///< Number of round to play on one map before going to the next one
|
||||
|
||||
#Setting S_MapsPerMatch 4 as "Only used if S_KeepScoresBetweenRounds = True"
|
||||
|
||||
#Setting S_AFKIdleTime 120000 as "Time before being an AFK player will be kicked"
|
||||
|
||||
@ -36,6 +36,7 @@
|
||||
#Setting S_MalusEveryNSecs 10 as "Roll a new Malus every N Sec"
|
||||
#Setting S_NextMalusPreparationTime 10 as "Time given to players to prepare them before a Malus"
|
||||
#Setting S_MalusDuration 5 as "Malus Duration"
|
||||
#Setting S_KeepScoresBetweenRounds False
|
||||
|
||||
#Setting S_TrustClientSimu False
|
||||
#Setting S_UseCrudeExtrapolation False
|
||||
@ -119,7 +120,6 @@ XmlRpc::UnregisterCallback(C_Callback_CustomChat_ChatMessage);
|
||||
***
|
||||
MB_Settings_UseDefaultTimer = False;
|
||||
MB_Settings_UseDefaultHud = (C_HudModulePath == "");
|
||||
MB_Settings_UseDefaultPodiumSequence = False;
|
||||
Rounds_Settings_UseDefaultSpawnManagement = False;
|
||||
MB_Settings_UseDefaultIntroSequence = False;
|
||||
***
|
||||
@ -184,6 +184,7 @@ StateMgr::Yield();
|
||||
Clans::SetClansNb(0);
|
||||
UsePvPCollisions = True;
|
||||
UsePvECollisions = True;
|
||||
Scores::SaveInScore(Scores::C_Points_Match);
|
||||
StateMgr::ForcePlayersStates([StateMgr::C_State_Waiting]);
|
||||
WarmUp::SetAvailability(True);
|
||||
CarRank::Reset();
|
||||
@ -192,8 +193,6 @@ ResetNetworkVariables();
|
||||
|
||||
***Match_InitMap***
|
||||
***
|
||||
declare Integer Map_ValidRoundsNb;
|
||||
|
||||
declare Integer Map_TimeBeforeMalus;
|
||||
declare Integer Map_TimeBeforeNightmare;
|
||||
declare Integer Map_MalusEveryNSecs;
|
||||
@ -201,6 +200,8 @@ declare Integer Map_NextMalusPreparationTime;
|
||||
declare Integer Map_MalusDuration;
|
||||
declare Integer Map_RoundsPerMap;
|
||||
|
||||
declare Text[] Map_AccountIdsOfEliminated;
|
||||
|
||||
declare Text[] AccountIdsOfPlayers for This = [];
|
||||
declare Integer LandmarkIndex for This = 0;
|
||||
declare K_Malus[Text] MalusQueue;
|
||||
@ -220,7 +221,7 @@ declare netwrite Integer Net_RoundsPerMap for Teams[0] = 0;
|
||||
declare netwrite Integer Net_CurrentRoundNb for Teams[0] = 0;
|
||||
|
||||
ResetNetworkVariables();
|
||||
UIModules_ScoresTable::SetCustomTimes([]);
|
||||
ResetCustomPoints();
|
||||
|
||||
// Map Intro
|
||||
declare Boolean MapIsCompatible;
|
||||
@ -235,6 +236,7 @@ if (!MapIsCompatible) {
|
||||
UIManager.UIAll.QueueMessage(3000, 1, CUIConfig::EMessageDisplay::Big, _("This map is not valid"));
|
||||
MB_Sleep(3000);
|
||||
MB_StopMap();
|
||||
MB_SetValidMap(False);
|
||||
} else if (S_IntroTime > 0) {
|
||||
declare netwrite Boolean Net_LMS_IsIntro for Teams[0] = False;
|
||||
Net_LMS_IsIntro = True;
|
||||
@ -272,8 +274,9 @@ declare Boolean ThrottleUpdate;
|
||||
|
||||
***Match_StartRound***
|
||||
***
|
||||
Scores::Clear();
|
||||
UIModules_ScoresTable::SetCustomTimes([]);
|
||||
ResetCustomPoints();
|
||||
UIModules_ScoresTable::SetScoreMode(UIModules_ScoresTable::C_Mode_Points);
|
||||
Race::SortScores(Race::C_Sort_RoundPoints);
|
||||
|
||||
declare netwrite Integer Net_LMS_AFKIdleTime for Teams[0] = 120000;
|
||||
Net_LMS_AFKIdleTime = S_AFKIdleTime;
|
||||
@ -298,7 +301,7 @@ Net_DisplayUI = True;
|
||||
Net_TimeBeforeMalus = MalusTime;
|
||||
Net_NextMalus = -1;
|
||||
Net_RoundsPerMap = Map_RoundsPerMap;
|
||||
Net_CurrentRoundNb = Map_ValidRoundsNb + 1;
|
||||
Net_CurrentRoundNb = MB_GetValidRoundCount();
|
||||
MalusQueue = [];
|
||||
|
||||
// Spawn players for the race
|
||||
@ -352,7 +355,7 @@ UIManager.UIAll.SendChat("$<$ff3$> Stay the most time on the structure. $<$ff
|
||||
XmlRpc::SendCallback(C_Callback_CustomChat_ChatMessage, ["$<$ff3$> Stay the most time on the structure. $<$ff9GL HF!$>"]);
|
||||
***
|
||||
|
||||
|
||||
// @mslint-disable-next-line max-statements
|
||||
***Match_PlayLoop***
|
||||
***
|
||||
// Manage race events
|
||||
@ -368,16 +371,19 @@ foreach (Event in RacePendingEvents) {
|
||||
|
||||
Scores::UpdatePlayerBestRaceIfBetter(Event.Player);
|
||||
Race::StopSkipOutro(Event.Player);
|
||||
UpdateCustomRanking(Event.Player.User, False);
|
||||
UpdateCustomRanking(Event.Player.User, Event.Player, False);
|
||||
if (Event.Player.User != Null) Map_AccountIdsOfEliminated.add(Event.Player.User.WebServicesUserId);
|
||||
}
|
||||
case Events::C_Type_GiveUp: {
|
||||
ThrottleUpdate = True;
|
||||
UpdateCustomRanking(Event.Player.User, True);
|
||||
UpdateCustomRanking(Event.Player.User, Event.Player, True);
|
||||
if (Event.Player.User != Null) Map_AccountIdsOfEliminated.add(Event.Player.User.WebServicesUserId);
|
||||
}
|
||||
case Events::C_Type_Eliminated: {
|
||||
ThrottleUpdate = True;
|
||||
Race::StopSkipOutro(Event.Player);
|
||||
UpdateCustomRanking(Event.Player.User, True);
|
||||
UpdateCustomRanking(Event.Player.User, Event.Player, True);
|
||||
if (Event.Player.User != Null) Map_AccountIdsOfEliminated.add(Event.Player.User.WebServicesUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -390,9 +396,10 @@ foreach (Event in PendingEvents) {
|
||||
if (Event.Type == CSmModeEvent::EType::OnPlayerRemoved) {
|
||||
if (Event.User == Null ) continue;
|
||||
if (!AccountIdsOfPlayers.exists(Event.User.WebServicesUserId)) continue;
|
||||
if (IsEliminated(Event.User, Null)) continue;
|
||||
if (Map_AccountIdsOfEliminated.exists(Event.User.WebServicesUserId)) continue;
|
||||
ThrottleUpdate = True;
|
||||
UpdateCustomRanking(Event.User, True);
|
||||
UpdateCustomRanking(Event.User, Null, True);
|
||||
Map_AccountIdsOfEliminated.add(Event.User.WebServicesUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -403,8 +410,9 @@ if (!ThrottleUpdate && Net_PlayersNbAlive != PlayersNbAlive) {
|
||||
if (Player.User == Null || Player.Score == Null) continue;
|
||||
if (!AccountIdsOfPlayers.exists(Player.User.WebServicesUserId)) continue;
|
||||
if (Player.SpawnStatus != CSmPlayer::ESpawnStatus::NotSpawned) continue;
|
||||
if (IsEliminated(Player.User, Player.Score)) continue;
|
||||
UpdateCustomRanking(Player.User, True);
|
||||
if (Map_AccountIdsOfEliminated.exists(Player.User.WebServicesUserId)) continue;
|
||||
UpdateCustomRanking(Player.User, Player, True);
|
||||
Map_AccountIdsOfEliminated.add(Player.User.WebServicesUserId);
|
||||
ThrottleUpdate = True;
|
||||
}
|
||||
}
|
||||
@ -519,6 +527,7 @@ foreach (Login => Malus in MalusQueue) {
|
||||
|
||||
***Match_EndRound***
|
||||
***
|
||||
UIModules_BigMessage::SetMessage("");
|
||||
PendingMalus = False;
|
||||
ActiveMalus = False;
|
||||
Net_DisplayUI = False;
|
||||
@ -539,43 +548,73 @@ if (Round_ForceEndRound || Round_SkipPauseRound) {
|
||||
}
|
||||
MB_SetValidRound(False);
|
||||
} else {
|
||||
Map_ValidRoundsNb += 1;
|
||||
if (S_KeepScoresBetweenRounds) {
|
||||
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
|
||||
MB_Sleep((S_ChatTime*1000)/2);
|
||||
|
||||
declare CSmScore WinnerScore <=> Scores::GetBestPlayer(Scores::C_Sort_RoundPoints);
|
||||
if (WinnerScore == Null) {
|
||||
foreach (Score in Scores) {
|
||||
if (Score.BestRaceTimes.count <= 0 && Score.User != Null && AccountIdsOfPlayers.exists(Score.User.WebServicesUserId)) {
|
||||
declare CSmPlayer Player = GetPlayer(Score.User.Login);
|
||||
if (Player != Null && !Player.RequestsSpectate) {
|
||||
WinnerScore <=> Score;
|
||||
break;
|
||||
ComputeRoundPoints();
|
||||
UIModules_ScoresTable::SetCustomPoints([]);
|
||||
UIModules_ScoresTable::DisplayRoundPoints(True);
|
||||
MB_Sleep((S_ChatTime*1000)/2);
|
||||
|
||||
Scores::EndRound();
|
||||
Race::SortScores(Race::C_Sort_TotalPoints);
|
||||
MB_Sleep((S_ChatTime*1000)/2);
|
||||
} else {
|
||||
declare CSmScore WinnerScore <=> Scores::GetBestPlayer(Scores::C_Sort_RoundPoints);
|
||||
if (WinnerScore == Null) {
|
||||
foreach (Score in Scores) {
|
||||
if (Score.BestRaceTimes.count <= 0 && Score.User != Null && AccountIdsOfPlayers.exists(Score.User.WebServicesUserId)) {
|
||||
declare CSmPlayer Player = GetPlayer(Score.User.Login);
|
||||
if (Player != Null && !Player.RequestsSpectate) {
|
||||
WinnerScore <=> Score;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Scores::SetPlayerWinner(WinnerScore);
|
||||
|
||||
ModeUtils::PlaySound(CUIConfig::EUISound::EndRound, 0);
|
||||
|
||||
if (WinnerScore == Null) {
|
||||
UIModules_BigMessage::SetMessage(_("|Match|Draw"));
|
||||
} else {
|
||||
UIModules_BigMessage::SetMessage(_("$<%1$> wins the match!"), WinnerScore.User.WebServicesUserId);
|
||||
}
|
||||
|
||||
Scores::EndRound();
|
||||
Race::SortScores(Race::C_Sort_TotalPoints);
|
||||
MB_Sleep((S_ChatTime*1000)/2);
|
||||
|
||||
UIModules_BigMessage::SetMessage("");
|
||||
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
|
||||
MB_Sleep((S_ChatTime*1000)/2);
|
||||
|
||||
Scores::Clear();
|
||||
}
|
||||
Scores::SetPlayerWinner(WinnerScore);
|
||||
|
||||
ModeUtils::PlaySound(CUIConfig::EUISound::EndRound, 0);
|
||||
|
||||
if (WinnerScore == Null) {
|
||||
UIModules_BigMessage::SetMessage(_("|Match|Draw"));
|
||||
} else {
|
||||
UIModules_BigMessage::SetMessage(_("$<%1$> wins the match!"), WinnerScore.User.WebServicesUserId);
|
||||
}
|
||||
|
||||
Scores::EndRound();
|
||||
Race::SortScores(Race::C_Sort_TotalPoints);
|
||||
|
||||
MB_Sleep(5000);
|
||||
UIModules_BigMessage::SetMessage("");
|
||||
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
|
||||
MB_Sleep((S_ChatTime*1000)/2);
|
||||
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::Normal;
|
||||
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
|
||||
|
||||
if (MapIsOver(Map_ValidRoundsNb)) MB_StopMatch();
|
||||
}
|
||||
UIModules_ScoresTable::DisplayRoundPoints(False);
|
||||
UIModules_ScoresTable::SetCustomPoints([]);
|
||||
|
||||
if (MapIsOver()) MB_StopMap();
|
||||
}
|
||||
***
|
||||
|
||||
|
||||
***Match_EndMap***
|
||||
***
|
||||
if (MatchIsOver()) {
|
||||
MB_StopMatch();
|
||||
if (!S_KeepScoresBetweenRounds) MB_SkipPodiumSequence();
|
||||
|
||||
declare CSmScore Winner <=> Scores::GetBestPlayer(Scores::C_Sort_MatchPoints);
|
||||
Scores::SetPlayerWinner(Winner);
|
||||
} else {
|
||||
MB_SkipPodiumSequence();
|
||||
}
|
||||
***
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
||||
@ -600,30 +639,13 @@ Void ResetNetworkVariables() {
|
||||
Net_CurrentRoundNb = 0;
|
||||
}
|
||||
|
||||
|
||||
/** Check if a Player is already considered eliminated
|
||||
*
|
||||
* @param _User The User
|
||||
* @param _Score The Score, can be Null but it will search the Score in Scores
|
||||
*
|
||||
* @return Return True if the player have a time
|
||||
*/
|
||||
Boolean IsEliminated(CUser _User, CSmScore _Score) {
|
||||
if (UIModules_ScoresTable::GetCustomTimes().existskey(_User.WebServicesUserId)) return True;
|
||||
if (_Score == Null) {
|
||||
foreach (Score in Scores) {
|
||||
if (Score.User == Null) continue;
|
||||
if (Score.User == _User) {
|
||||
if (Score.PrevRaceTimes.count > 0) return True;
|
||||
else return False;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (_Score.PrevRaceTimes.count > 0) {
|
||||
return True;
|
||||
Void ResetCustomPoints() {
|
||||
declare Text[][Text] CustomPoints = [];
|
||||
foreach (Score in Scores) {
|
||||
if (Score.User == Null) continue;
|
||||
CustomPoints[Score.User.WebServicesUserId] = ["--:--.---"];
|
||||
}
|
||||
|
||||
return False;
|
||||
UIModules_ScoresTable::SetCustomPoints(CustomPoints);
|
||||
}
|
||||
|
||||
/** Detect if all players are in Turtle
|
||||
@ -647,7 +669,7 @@ Boolean AllPlayersAreInTurtle() {
|
||||
*
|
||||
* @return The Malus Time or -1 in no Malus
|
||||
*/
|
||||
Integer GetTimeBeforeMalus(Integer _StartTime, Integer _TimeBeforeMalus, Integer _TimeBeforeNightmare) {
|
||||
Integer GetTimeBeforeMalus(Integer _StartTime, Integer _TimeBeforeMalus, Integer _TimeBeforeNightmare) {
|
||||
declare Integer MalusTime;
|
||||
if (_TimeBeforeMalus >= 0 && (_TimeBeforeMalus < _TimeBeforeNightmare || _TimeBeforeNightmare == -1)) {
|
||||
MalusTime = _StartTime + (_TimeBeforeMalus * 1000);
|
||||
@ -663,24 +685,46 @@ Boolean AllPlayersAreInTurtle() {
|
||||
/** Update the Scores Table with hidden custom points
|
||||
*
|
||||
* @param _User The User who is eliminated
|
||||
* @param _Player The Player who is eliminated. Can be Null
|
||||
* @param _OverrideTime Compute time because it not ended the Map
|
||||
*/
|
||||
Void UpdateCustomRanking(CUser _User, Boolean _OverrideTime) {
|
||||
Void UpdateCustomRanking(CUser _User, CSmPlayer _Player, Boolean _OverrideTime) {
|
||||
if (_User == Null) return;
|
||||
|
||||
declare Text[][Text] CustomPoints = UIModules_ScoresTable::GetCustomPoints();
|
||||
|
||||
if (_OverrideTime) {
|
||||
declare Integer[Text] CustomTimes = UIModules_ScoresTable::GetCustomTimes();
|
||||
CustomTimes[_User.WebServicesUserId] = Now - StartTime;
|
||||
UIModules_ScoresTable::SetCustomTimes(CustomTimes);
|
||||
if (_OverrideTime || _Player == Null || _Player.RaceWaypointTimes.count == 0) {
|
||||
CustomPoints[_User.WebServicesUserId] = [TL::TimeToText(Now - StartTime, True, True)];
|
||||
} else {
|
||||
CustomPoints[_User.WebServicesUserId] = [TL::TimeToText(_Player.RaceWaypointTimes[-1], True, True)];
|
||||
}
|
||||
UIModules_ScoresTable::SetCustomPoints(CustomPoints);
|
||||
UIManager.UIAll.SendChat("""$<$ff3$> Player $<$ff9{{{_User.Name}}}$> is eliminated""");
|
||||
XmlRpc::SendCallback(C_Callback_CustomChat_ChatMessage, ["""$<$ff3$> Player $<$ff9{{{_User.Name}}}$> is eliminated"""]);
|
||||
}
|
||||
|
||||
/** Distribute real RoundPoints using Points Repartition
|
||||
* Only used when S_KeepScoresBetweenRounds = True
|
||||
*/
|
||||
Void ComputeRoundPoints() {
|
||||
declare Integer[] PointsRepartition = PointsRepartition::GetPointsRepartition();
|
||||
foreach (Key => Score in Scores) {
|
||||
declare Integer Points = 0;
|
||||
if (PointsRepartition.count > 0) {
|
||||
if (PointsRepartition.existskey(Key)) {
|
||||
Points = PointsRepartition[Key];
|
||||
} else {
|
||||
Points = PointsRepartition[PointsRepartition.count - 1];
|
||||
}
|
||||
}
|
||||
Scores::SetPlayerRoundPoints(Score, Points);
|
||||
}
|
||||
}
|
||||
|
||||
/** Update the scores table footer text
|
||||
*
|
||||
*/
|
||||
Void UpdateScoresTableFooter() {
|
||||
Void UpdateScoresTableFooter() {
|
||||
declare Text Footer = "";
|
||||
if (S_MalusDuration <= 0 || (S_TimeBeforeMalus < 0 && S_TimeBeforeNightmare < 0)) {
|
||||
Footer ^= "Malus disabled";
|
||||
@ -697,11 +741,18 @@ Boolean AllPlayersAreInTurtle() {
|
||||
Message ^= """%{{{Parts.count + 1}}}{{{TL::TimeToText(S_TimeBeforeNightmare*1000)}}}""";
|
||||
Parts.add("Time Before NM: ");
|
||||
}
|
||||
if (S_KeepScoresBetweenRounds) {
|
||||
if (Parts.count > 0) Message ^= "\n";
|
||||
Message ^= """%{{{Parts.count + 1}}}{{{MB_GetMapCount()}}}/{{{S_MapsPerMatch}}}""";
|
||||
//L16N [Rounds] Number of maps played during the match.
|
||||
Parts.add(_("Maps : "));
|
||||
}
|
||||
|
||||
switch (Parts.count) {
|
||||
case 0: Footer = Message;
|
||||
case 1: Footer = TL::Compose(Message, Parts[0]);
|
||||
case 2: Footer = TL::Compose(Message, Parts[0], Parts[1]);
|
||||
case 3: Footer = TL::Compose(Message, Parts[0], Parts[1], Parts[2]);
|
||||
}
|
||||
}
|
||||
UIModules_ScoresTable::SetFooterInfo(Footer);
|
||||
@ -1052,12 +1103,20 @@ Void SetML() {
|
||||
|
||||
|
||||
/** Check if we should go to the next map
|
||||
*
|
||||
* @param _ValidRoundsNb Number of valid rounds played
|
||||
*
|
||||
* @return True if it is the case, false otherwise
|
||||
*/
|
||||
Boolean MapIsOver(Integer _ValidRoundsNb) {
|
||||
if (S_RoundsPerMap > 0 && _ValidRoundsNb >= S_RoundsPerMap) return True; //< There is a rounds limit and it is reached
|
||||
Boolean MapIsOver() {
|
||||
log("""MapIsOver> S_RoundsPerMap: {{{S_RoundsPerMap}}} / MB_GetValidRoundCount() {{{MB_GetValidRoundCount()}}}""");
|
||||
if (S_RoundsPerMap > 0 && MB_GetValidRoundCount() >= S_RoundsPerMap) return True; //< There is a rounds limit and it is reached
|
||||
return False;
|
||||
}
|
||||
|
||||
/** Check if the match is over
|
||||
* @return True if it is the case, false otherwise
|
||||
*/
|
||||
Boolean MatchIsOver() {
|
||||
log("""MatchIsOver> S_KeepScoresBetweenRounds: {{{S_KeepScoresBetweenRounds}}} / MB_GetValidMapCount() {{{MB_GetValidMapCount()}}} / S_MapsPerMatch {{{S_MapsPerMatch}}}""");
|
||||
if (!S_KeepScoresBetweenRounds) return True;
|
||||
if (MB_GetValidMapCount() >= S_MapsPerMatch) return True;
|
||||
return False;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user