564 lines
17 KiB
Plaintext
564 lines
17 KiB
Plaintext
/**
|
|
* Laps Knockout mode
|
|
*/
|
|
// #RequireContext CSmMode
|
|
|
|
#Extends "Modes/Nadeo/Trackmania/Base/TrackmaniaBase.Script.txt"
|
|
|
|
#Const CompatibleMapTypes "TrackMania\\TM_Race,TM_Race"
|
|
#Const Version "2023-09-25"
|
|
#Const ScriptName "Modes/TM2020-Gamemodes/TM_LapsKnockout.Script.txt"
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
// Libraries
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
#Include "TextLib" as TL
|
|
#Include "MathLib" as ML
|
|
#Include "Libs/Nadeo/Trackmania/MainMenu/Constants.Script.txt" as MenuConsts
|
|
#Include "Libs/Nadeo/Trackmania/Modes/Laps/StateManager.Script.txt" as StateMgr
|
|
#Include "Libs/Nadeo/TMGame/Modes/Base/UIModules/ScoresTable_Server.Script.txt" as UIModules_ScoresTable
|
|
#Include "Libs/Nadeo/TMGame/Modes/Base/UIModules/TimeGap_Server.Script.txt" as UIModules_TimeGap
|
|
#Include "Libs/Nadeo/TMGame/Modes/Base/UIModules/Checkpoint_Server.Script.txt" as UIModules_Checkpoint
|
|
#Include "Libs/Nadeo/TMGame/Modes/Base/UIModules/PauseMenuOnline_Server.Script.txt" as UIModules_PauseMenu_Online
|
|
#Include "Libs/Nadeo/Trackmania/Modes/LapsCommon/Libs/Constants.Script.txt" as LibLaps_Constants
|
|
|
|
#Include "Libs/Nadeo/TMGame/Modes/Base/UIModules/BigMessage_Server.Script.txt" as UIModules_BigMessage
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
// Settings
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
#Setting S_DisableGiveUp True as _("Disable give up")
|
|
#Setting S_WarmUpNb 0 as _("Number of warm up")
|
|
#Setting S_WarmUpDuration 0 as _("Duration of one warm up")
|
|
#Setting S_WarmUpTimeout -1 as _("Warm up timeout")
|
|
|
|
#Setting S_NbLapsWithoutKO 0 as "Number of laps without elimination"
|
|
#Setting S_EliminatedPlayersNbRanks "4,16,16" as _("Nb of players above which one extra elim. /lap. Same setting of Knock")
|
|
|
|
/* About S_EliminatedPlayersNbRanks
|
|
* Example : "8,16"
|
|
* 1 to 8 players -> 1 elimination per lap
|
|
* 9 to 16 players -> 2 eliminations per lap
|
|
* 17 or more players -> 3 eliminations per lap
|
|
*
|
|
* Example : "8,16,16"
|
|
* 1 to 8 players -> 1 eliminations per lap
|
|
* 9 to 16 players -> 2 eliminations per lap
|
|
* 17 or more players -> 4 eliminations per lap
|
|
*
|
|
* Example : "0,8"
|
|
* 1 to 8 players -> 2 eliminations per lap
|
|
* 9 or more players -> 3 eliminations per lap
|
|
*
|
|
* Example : ""
|
|
* 1 or more players -> 1 elimination per lap
|
|
*/
|
|
|
|
|
|
#Struct K_LapState {
|
|
Integer NbAliveAfter;
|
|
Integer NbEliminations;
|
|
Integer NbLapFinishers;
|
|
}
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
// Constants
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
#Const C_ModeName "Laps"
|
|
//L16N [Laps] Description of the mode rules
|
|
#Const Description _("$zIn $<$t$6F9Laps$> mode, the goal is to drive as far as possible by passing $<$t$6F9checkpoints$>.\n\nThe laps mode takes place on multilap (cyclical) maps, and is played in one go for every map.\n\nWhen the time is up, the $<$t$6F9winner$> is the player who passed the most $<$t$6F9checkpoints$>. In case of draws, the winner is the player who passed the last checkpoint first.")
|
|
|
|
#Const C_HudModulePath "" //< Path to the hud module
|
|
#Const C_ManiaAppUrl "file://Media/ManiaApps/Nadeo/Trackmania/Modes/Laps.Script.txt" //< Url of the mania app
|
|
#Const C_FakeUsersNb 0
|
|
|
|
#Const C_UploadRecord True
|
|
#Const C_DisplayRecordGhost False
|
|
#Const C_DisplayRecordMedal False
|
|
#Const C_CelebrateRecordGhost True
|
|
#Const C_CelebrateRecordMedal True
|
|
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
// Extends
|
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
|
***Match_LogVersions***
|
|
***
|
|
Log::RegisterScript(ScriptName, Version);
|
|
Log::RegisterScript(StateMgr::ScriptName, StateMgr::Version);
|
|
***
|
|
|
|
***Match_LoadLibraries***
|
|
***
|
|
StateMgr::Load();
|
|
***
|
|
|
|
***Match_UnloadLibraries***
|
|
***
|
|
StateMgr::Unload();
|
|
***
|
|
|
|
***Match_Settings***
|
|
***
|
|
MB_Settings_UseDefaultHud = (C_HudModulePath == "");
|
|
MB_Settings_UseDefaultTimer = False;
|
|
***
|
|
|
|
***Match_Rules***
|
|
***
|
|
ModeInfo::SetName(C_ModeName);
|
|
ModeInfo::SetType(ModeInfo::C_Type_FreeForAll);
|
|
ModeInfo::SetRules(Description);
|
|
ModeInfo::SetStatusMessage(_("TYPE: Free for all\nOBJECTIVE: Set the best time on the track."));
|
|
***
|
|
|
|
***Match_LoadHud***
|
|
***
|
|
if (C_HudModulePath != "") Hud_Load(C_HudModulePath);
|
|
***
|
|
|
|
***Match_AfterLoadHud***
|
|
***
|
|
ClientManiaAppUrl = C_ManiaAppUrl;
|
|
Race::SortScores(Race::C_Sort_BestRaceCheckpointsProgress);
|
|
UIModules_TimeGap::SetTimeGapMode(UIModules_TimeGap::C_TimeGapMode_BestRace);
|
|
UIModules_Checkpoint::SetRankMode(UIModules_Checkpoint::C_RankMode_BestRace);
|
|
UIModules_Checkpoint::SetVisibilityTimeDiff(False, True);
|
|
UIModules_PauseMenu_Online::SetHelp(Description);
|
|
UIModules_ScoresTable::SetScoreMode(UIModules_ScoresTable::C_Mode_Laps);
|
|
UIModules_ScoresTable::SetHideSpectators(True);
|
|
|
|
SetManialink_Panel();
|
|
***
|
|
|
|
***Match_Yield***
|
|
***
|
|
foreach (Event in PendingEvents) {
|
|
switch (Event.Type) {
|
|
// Initialize players when they join the server
|
|
case CSmModeEvent::EType::OnPlayerAdded: {
|
|
StateMgr::InitializePlayer(Event.Player);
|
|
CarRank::InitializePlayer(Event.Player);
|
|
}
|
|
}
|
|
}
|
|
|
|
StateMgr::Yield();
|
|
***
|
|
|
|
***Match_StartServer***
|
|
***
|
|
// Initialize mode
|
|
Clans::SetClansNb(0);
|
|
StateMgr::ForcePlayersStates([LibLaps_Constants::C_State_Waiting]);
|
|
WarmUp::SetAvailability(True);
|
|
Race::SetRespawnBehaviour(Race::C_RespawnBehaviour_Normal);
|
|
Race::SetupRecord(
|
|
MenuConsts::C_ScopeType_Season,
|
|
MenuConsts::C_ScopeType_PersonalBest,
|
|
MenuConsts::C_GameMode_Laps,
|
|
"",
|
|
C_UploadRecord,
|
|
C_DisplayRecordGhost,
|
|
C_DisplayRecordMedal,
|
|
C_CelebrateRecordGhost,
|
|
C_CelebrateRecordMedal
|
|
);
|
|
|
|
Race::UseAutomaticDossardColor(False);
|
|
***
|
|
|
|
***Match_InitMap***
|
|
***
|
|
declare Integer Last_NbLapsWithoutKO;
|
|
declare Integer Last_NumberOfPlayers;
|
|
declare Text Last_EliminatedPlayersNbRanks;
|
|
declare K_LapState[Integer] MatchState;
|
|
|
|
declare Integer Last_CooldownDossardUpdate = -1;
|
|
declare Boolean Last_InCooldownDossardUpdate = False;
|
|
|
|
Race::SetLapsSettings(True, -1); // force infinite lap
|
|
***
|
|
|
|
***Match_StartMap***
|
|
***
|
|
CarRank::Reset();
|
|
|
|
UIModules_ScoresTable::SetCustomPoints([]);
|
|
declare netwrite K_LapState[Integer] Net_LapsKnockout_MatchState for Teams[0]; // Note the NbLapFinishers is not updated
|
|
Net_LapsKnockout_MatchState = [];
|
|
|
|
// Warm up
|
|
---Laps_Warmup---
|
|
|
|
StartTime = Now + Race::C_SpawnDuration;
|
|
if (S_DisableGiveUp) {
|
|
Race::SetRespawnBehaviour(Race::C_RespawnBehaviour_NeverGiveUp);
|
|
} else {
|
|
Race::SetRespawnBehaviour(Race::C_RespawnBehaviour_Normal);
|
|
}
|
|
|
|
// Spawn players for the race
|
|
foreach (Score in Scores) {
|
|
declare Boolean Laps_CanSpawn for Score = True;
|
|
Laps_CanSpawn = True;
|
|
}
|
|
foreach (Player in Players) {
|
|
if (Player.Score != Null && Race::IsReadyToStart(Player)) {
|
|
declare Boolean Laps_CanSpawn for Player.Score = True;
|
|
Race::Start(Player, StartTime);
|
|
Laps_CanSpawn = False;
|
|
}
|
|
}
|
|
|
|
CarRank::Update(CarRank::C_SortCriteria_BestRace);
|
|
StateMgr::ForcePlayersStates([LibLaps_Constants::C_State_Playing]);
|
|
***
|
|
|
|
***Laps_Warmup***
|
|
***
|
|
Race::SetRespawnBehaviour(Race::C_RespawnBehaviour_Normal);
|
|
MB_WarmUp(S_WarmUpNb, S_WarmUpDuration * 1000, S_WarmUpTimeout * 1000);
|
|
***
|
|
|
|
***Match_StartRound***
|
|
***
|
|
// Once the round started, no one can join to play
|
|
Last_NumberOfPlayers = Players.count;
|
|
|
|
Last_NbLapsWithoutKO = S_NbLapsWithoutKO;
|
|
Last_EliminatedPlayersNbRanks = S_EliminatedPlayersNbRanks;
|
|
|
|
MatchState = ComputeMatchState(Last_NumberOfPlayers);
|
|
|
|
// Update UI
|
|
declare netwrite K_LapState[Integer] Net_LapsKnockout_MatchState for Teams[0]; // Note the NbLapFinishers is not updated
|
|
Net_LapsKnockout_MatchState = MatchState;
|
|
|
|
foreach (LapNb => State in MatchState.sortkeyreverse()) {
|
|
Race::SetLapsSettings(False, LapNb); // Set number of laps with number of
|
|
break;
|
|
}
|
|
|
|
// Reset Dossard Color
|
|
foreach (Player in Players) {
|
|
Player.Dossard_Color = <1., 1., 1.>;
|
|
}
|
|
|
|
Last_CooldownDossardUpdate = -1;
|
|
Last_InCooldownDossardUpdate = False;
|
|
|
|
if (Last_NbLapsWithoutKO == 1) {
|
|
UIManager.UIAll.SendChat(Last_NbLapsWithoutKO ^ " lap without eliminations");
|
|
} else if (Last_NbLapsWithoutKO > 1){
|
|
UIManager.UIAll.SendChat(Last_NbLapsWithoutKO ^ " laps without eliminations");
|
|
}
|
|
***
|
|
|
|
***Match_PlayLoop***
|
|
***
|
|
// Manage race events
|
|
foreach (Event in Race::GetPendingEvents()) {
|
|
Race::ValidEvent(Event);
|
|
|
|
// Waypoint
|
|
if (Event.Type == Events::C_Type_Waypoint) {
|
|
if (Event.Player != Null) {
|
|
if (Event.IsEndLap) {
|
|
Scores::UpdatePlayerBestLapIfBetter(Event.Player);
|
|
|
|
if (MatchState.existskey(Event.Player.CurrentLapNumber)) {
|
|
MatchState[Event.Player.CurrentLapNumber].NbLapFinishers += 1;
|
|
|
|
// Proceed kick
|
|
if (MatchState[Event.Player.CurrentLapNumber].NbLapFinishers >= MatchState[Event.Player.CurrentLapNumber].NbAliveAfter) {
|
|
foreach (Player in Players) {
|
|
if (Player.SpawnStatus != CSmPlayer::ESpawnStatus::Spawned) continue;
|
|
|
|
if (Player.CurrentLapNumber < Event.Player.CurrentLapNumber) {
|
|
EliminatePlayer(Player);
|
|
}
|
|
}
|
|
|
|
foreach (LapNb => State in MatchState) {
|
|
if (LapNb > Event.Player.CurrentLapNumber) {
|
|
break;
|
|
}
|
|
MatchState.removekey(LapNb);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Event.IsEndRace) {
|
|
// waiting GetCustomPoints function in ScoresTable_Server
|
|
declare netwrite Text[][Text] Net_TMGame_ScoresTable_CustomPoints for Teams[0];
|
|
declare Text[][Text] CustomTimes = Net_TMGame_ScoresTable_CustomPoints;
|
|
foreach (Player in Players) {
|
|
if (Player != Event.Player) {
|
|
CustomTimes[Player.User.WebServicesUserId] = [_("|Status|K.O."), "f00"];
|
|
}
|
|
}
|
|
UIModules_ScoresTable::SetCustomPoints(CustomTimes);
|
|
UIManager.UIAll.SendChat("Player $<$ff6" ^ Event.Player.User.Name ^ "$> $<$6f6wins the match!$>");
|
|
MB_StopMatch();
|
|
}
|
|
|
|
// Update best race at each checkpoint to sort scores with C_Sort_BestRaceCheckpointsProgress
|
|
Scores::UpdatePlayerBestRace(Event.Player);
|
|
|
|
CarRank::ThrottleUpdate(CarRank::C_SortCriteria_BestRace);
|
|
|
|
if (Last_CooldownDossardUpdate == -1) {
|
|
UpdateDossardColors(MatchState);
|
|
Last_CooldownDossardUpdate = Now + 1000;
|
|
} else {
|
|
Last_InCooldownDossardUpdate = True;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Manage mode events
|
|
foreach (Event in PendingEvents) {
|
|
if (Event.HasBeenPassed || Event.HasBeenDiscarded) continue;
|
|
Events::Invalid(Event);
|
|
}
|
|
|
|
if (Last_CooldownDossardUpdate != -1 && Now > Last_CooldownDossardUpdate) {
|
|
Last_CooldownDossardUpdate = -1;
|
|
if (Last_InCooldownDossardUpdate) {
|
|
Last_InCooldownDossardUpdate = False;
|
|
UpdateDossardColors(MatchState);
|
|
}
|
|
}
|
|
|
|
if (Last_NbLapsWithoutKO != S_NbLapsWithoutKO || Last_EliminatedPlayersNbRanks != S_EliminatedPlayersNbRanks) {
|
|
Last_NbLapsWithoutKO = S_NbLapsWithoutKO;
|
|
Last_EliminatedPlayersNbRanks = S_EliminatedPlayersNbRanks;
|
|
|
|
MatchState = ComputeMatchState(Last_NumberOfPlayers);
|
|
|
|
// Update UI
|
|
declare netwrite K_LapState[Integer] Net_LapsKnockout_MatchState for Teams[0]; // Note the NbLapFinishers is not updated
|
|
Net_LapsKnockout_MatchState = MatchState;
|
|
|
|
foreach (LapNb => State in MatchState.sortkeyreverse()) {
|
|
Race::SetLapsSettings(False, LapNb); // Set number of laps with number of
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Players.count > 0 && PlayersNbAlive <= 0) {
|
|
MB_StopMatch();
|
|
}
|
|
***
|
|
|
|
***Match_EndMap***
|
|
***
|
|
// Ensure that we stop the match (after a vote for the next map, ...)
|
|
MB_StopMatch();
|
|
|
|
EndTime = -1;
|
|
StateMgr::ForcePlayersStates([LibLaps_Constants::C_State_Waiting]);
|
|
|
|
CarRank::Update(CarRank::C_SortCriteria_BestRace);
|
|
Race::SortScores(Race::C_Sort_BestRaceCheckpointsProgress);
|
|
Scores::SetPlayerWinner(Scores::GetBestPlayer(Scores::C_Sort_BestRaceCheckpointsProgress));
|
|
Race::StopSkipOutroAll();
|
|
***
|
|
|
|
/*
|
|
*
|
|
* Functions
|
|
*
|
|
*/
|
|
|
|
/** Compute Match State based on S_EliminatedPlayersNbRanks and number of Players
|
|
*
|
|
* @return K_LapState[Integer]
|
|
*/
|
|
K_LapState[Integer] ComputeMatchState(Integer _NumberOfPlayers) {
|
|
declare K_LapState[Integer] MatchState;
|
|
|
|
declare Integer[] Eliminations = [0];
|
|
foreach (EliminationText in TL::Split(",", S_EliminatedPlayersNbRanks)) {
|
|
declare Integer Elimination = TL::ToInteger(EliminationText);
|
|
if (Elimination > 0) { // -1 if error
|
|
Eliminations.add(Elimination);
|
|
}
|
|
}
|
|
|
|
declare Integer KickedPlayers = 0;
|
|
declare Integer LapNumber = S_NbLapsWithoutKO + 1;
|
|
|
|
while (KickedPlayers <= _NumberOfPlayers) {
|
|
while (_NumberOfPlayers - KickedPlayers < Eliminations[Eliminations.count - 1]) {
|
|
Eliminations.removekey(Eliminations.count - 1);
|
|
}
|
|
|
|
if (_NumberOfPlayers - KickedPlayers - Eliminations.count < Eliminations[Eliminations.count - 1]) {
|
|
Eliminations.removekey(Eliminations.count - 1);
|
|
}
|
|
|
|
declare Integer Alive = _NumberOfPlayers - KickedPlayers - Eliminations.count;
|
|
|
|
if (Alive <= 0) break;
|
|
|
|
MatchState[LapNumber] = K_LapState {
|
|
NbAliveAfter = Alive,
|
|
NbEliminations = Eliminations.count
|
|
};
|
|
|
|
KickedPlayers += Eliminations.count;
|
|
LapNumber += 1;
|
|
if (LapNumber > 255) break; // Anti crash
|
|
}
|
|
|
|
return MatchState;
|
|
}
|
|
|
|
/** Update Dossard Color of Players depending of the Lap and the Rank
|
|
*
|
|
* @return Void
|
|
*/
|
|
Void UpdateDossardColors(K_LapState[Integer] _MatchState) {
|
|
Log::Log("UpdateDossardColors");
|
|
declare Integer Rank = 1;
|
|
|
|
foreach (Score in Scores) {
|
|
if (Score == Null) continue;
|
|
if (Score.User == Null) continue;
|
|
|
|
declare CSmPlayer Player = GetPlayer(Score.User.Login);
|
|
if (Player == Null) continue;
|
|
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned) continue;
|
|
|
|
declare Integer NbAlive;
|
|
|
|
if (_MatchState.existskey(Player.CurrentLapNumber + 1)) {
|
|
NbAlive = _MatchState[Player.CurrentLapNumber + 1].NbAliveAfter;
|
|
} else {
|
|
// get first lap
|
|
foreach (Value in _MatchState) {
|
|
NbAlive = Value.NbAliveAfter;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Rank > NbAlive) {
|
|
Player.Dossard_Color = <1., 0., 0.>;
|
|
} else {
|
|
Player.Dossard_Color = <1., 1., 1.>;
|
|
}
|
|
|
|
Rank += 1;
|
|
}
|
|
}
|
|
|
|
/** Eliminate Player and send a message in a Chat
|
|
*
|
|
* @return Void
|
|
*/
|
|
Void EliminatePlayer(CSmPlayer _Player) {
|
|
if (_Player == Null) return;
|
|
if (_Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned) return;
|
|
log("EliminatePlayer: " ^ _Player.User.Name ^ " (" ^ _Player.User.Login ^ ")");
|
|
Race::StopSkipOutro(_Player);
|
|
UIManager.UIAll.SendChat("Player $<$ff6" ^ _Player.User.Name ^ "$> is $<$f00eliminated$>");
|
|
}
|
|
|
|
Void SetManialink_Panel() {
|
|
declare Text MLText = """
|
|
<manialink name="LapsKnockout_Panel" version="3">
|
|
<stylesheet>
|
|
<style class="text-titles" textfont="GameFontBlack" textcolor="ffffffff" textsize="1.5" valign="center2" textprefix="$i$t"/>
|
|
<style class="text-values" textfont="GameFontSemiBold" textcolor="ffffffff" textsize="1.5" valign="center2" textprefix="$i$t" halign="right"/>
|
|
</stylesheet>
|
|
<frame id="frame-global" pos="-20 75" halign="center">
|
|
<quad pos="0 0" z-index="-1" size="40 10" bgcolor="000" opacity="0.7"/>
|
|
<label class="text-titles" pos="1 -3.5" size="27 5" text="Players alive:" />
|
|
<label id="label-players-alive" class="text-values" pos="39 -3.5" size="20 5" text="-" />
|
|
<label class="text-titles" pos="1 -7.5" size="27 5" text="KO this lap:"/>
|
|
<label id="label-KO-this-lap" class="text-values" pos="39 -7.5" size="20 5" text="-"/>
|
|
</frame>
|
|
<script><!--
|
|
#Include "TextLib" as TL
|
|
#Include "MathLib" as ML
|
|
|
|
{{{dumptype(K_LapState)}}}
|
|
|
|
Void DevLog(Text _LogText) {
|
|
declare netread Text Net_ScriptEnvironment for Teams[0] = "production";
|
|
if (Net_ScriptEnvironment == "development") log("[RVC] " ^ _LogText);
|
|
}
|
|
|
|
Integer GetPlayerLap(CSmPlayer _Player) {
|
|
declare netread Integer Net_Race_Helpers_PlayerLap for _Player;
|
|
if (Net_Race_Helpers_PlayerLap > 0) {
|
|
return Net_Race_Helpers_PlayerLap;
|
|
}
|
|
return _Player.CurrentLapNumber + 1;
|
|
}
|
|
|
|
main() {
|
|
DevLog("Starting LapsKnockout Panel");
|
|
declare CMlFrame Frame_Global <=> (Page.GetFirstChild("frame-global") as CMlFrame);
|
|
declare CMlLabel Label_Players_Alive <=> (Page.GetFirstChild("label-players-alive") as CMlLabel);
|
|
declare CMlLabel Label_KO_This_Lap <=> (Page.GetFirstChild("label-KO-this-lap") as CMlLabel);
|
|
|
|
declare netread K_LapState[Integer] Net_LapsKnockout_MatchState for Teams[0]; // Note the NbLapFinishers is not updated
|
|
|
|
declare Integer UpdateTime;
|
|
declare Integer Last_LapNb;
|
|
|
|
wait(InputPlayer != Null);
|
|
|
|
while(True) {
|
|
yield;
|
|
if (UpdateTime > Now) continue;
|
|
|
|
UpdateTime = Now + 500;
|
|
|
|
if (GUIPlayer == Null) {
|
|
Frame_Global.Visible = False;
|
|
continue;
|
|
}
|
|
|
|
Frame_Global.Visible = True;
|
|
|
|
if (Net_LapsKnockout_MatchState.count == 0) {
|
|
Label_Players_Alive.Value = "-";
|
|
Label_KO_This_Lap.Value = "-";
|
|
continue;
|
|
}
|
|
|
|
if (Last_LapNb != GetPlayerLap(GUIPlayer)) {
|
|
Last_LapNb = GetPlayerLap(GUIPlayer);
|
|
|
|
if (Net_LapsKnockout_MatchState.existskey(Last_LapNb)) {
|
|
Label_KO_This_Lap.Value = TL::ToText(Net_LapsKnockout_MatchState[Last_LapNb].NbEliminations);
|
|
Label_Players_Alive.Value = TL::ToText(Net_LapsKnockout_MatchState[Last_LapNb].NbAliveAfter + Net_LapsKnockout_MatchState[Last_LapNb].NbEliminations);
|
|
} else {
|
|
declare Integer LapNb;
|
|
foreach (Key => Dummy in Net_LapsKnockout_MatchState) {
|
|
LapNb = Key;
|
|
break;
|
|
}
|
|
|
|
Label_Players_Alive.Value = TL::ToText(Net_LapsKnockout_MatchState[LapNb].NbAliveAfter + Net_LapsKnockout_MatchState[LapNb].NbEliminations);
|
|
Label_KO_This_Lap.Value = "0";
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
--></script>
|
|
</manialink>
|
|
""";
|
|
Layers::Create("LapsKnockout_Panel", MLText);
|
|
Layers::SetType("LapsKnockout_Panel", CUILayer::EUILayerType::Normal);
|
|
Layers::Attach("LapsKnockout_Panel");
|
|
}
|