/**
* Mode Royal
*/
#Extends "Modes/ShootMania/ModeBase.Script.txt"
#Const CompatibleMapTypes "RoyalArena"
#Const Version "2012-08-23"
#Include "MathLib" as MathLib
#Include "TextLib" as TextLib
#Include "Libs/Nadeo/Top.Script.txt" as Top
#Include "Libs/Nadeo/Layers.Script.txt" as Layers
#Include "Libs/Nadeo/ShootMania/SM.Script.txt" as SM
#Include "Libs/Nadeo/ShootMania/Rules.Script.txt" as Rules
#Include "Libs/Nadeo/ShootMania/Score.Script.txt" as Score
/* ------------------------------------- */
// Settings
/* ------------------------------------- */
#Setting S_MapPointsLimit 150 as _("Points to win a map")
#Setting S_OffZoneActivationTime 4 as _("OffZone activation duration")
#Setting S_OffZoneTimeLimit 50 as _("OffZone shrink duration")
#Setting S_SpawnInterval 5 as _("Time between each wave of spawns")
#Setting S_OffZoneAutoStartTime 90 as _("Time before auto activation of the OffZone")
#Const C_UITickPeriod 200 ///< Update UI every xx milliseconds
#Const C_OffZoneMinRadius 8. ///< Minimum size of the OffZone at the end
#Const C_DefaultOffZoneRadius 300. ///< Default radius of the OffZone
#Const C_NbBots 0 ///< Number of bots for debug
/* ------------------------------------- */
// Globales variables
/* ------------------------------------- */
declare Integer[Ident] G_PlayerSpawnQueue; ///< A list of players to spawn
declare Ident[][Integer] G_PriorityBlockSpawnQueue; ///< A list of spawn points to use
declare Integer G_TotalPlayersSpawned; ///< Number of players spawned for the current round
/* -------------------------------------- */
// Extend
/* -------------------------------------- */
/* -------------------------------------- */
// Server start
/* -------------------------------------- */
***StartServer***
***
/* -------------------------------------- */
// Set mode options and tops
MB_UseSectionRound = True;
UseClans = False;
Top::AddTop("Pole", 5);
Top::AddTop("Hit", 5);
Top::AddTop("Survival", 5);
Top::AddTop("Round", 5);
/* ------------------------------------- */
// Create Rules
declare ModeName = "Royal";
declare ModeRules = TextLib::Compose(_("Free for all\n- Survive as long as possible to score a maximum of points.\n- Bonus points are awarded for the pole capture and for each player hit.\n- If the pole is captured then the playing area will start to shrink. If a player leaves this area he is eliminated.\n- The first player to reach %1 points wins."), TextLib::ToText(S_MapPointsLimit));
Rules::Create(ModeName, ModeRules);
/* ------------------------------------- */
// Init UI
declare LayerAttached = False;
declare LayerDetached = False;
declare LayerUpdated = False;
declare LayerSpawnQueueId = Layers::Create("SpawnQueue");
declare LayerScoresTableId = Layers::Create("ScoresTable");
declare LayerInfosId = Layers::Create("Infos");
declare LayerTopsId = Layers::Create("Tops");
declare LayerScoresInSpawnId = Layers::Create("ScoresInSpawn");
Layers::GetFromId(LayerScoresTableId).Type = CUILayer::EUILayerType::ScoresTable;
Layers::GetFromId(LayerScoresInSpawnId).Type = CUILayer::EUILayerType::ScreenIn3d;
***
/* -------------------------------------- */
// Map start
/* -------------------------------------- */
***StartMap***
***
Score::MatchBegin();
Top::MatchBegin();
Top::RoundBegin(); ///< Want global tops for the match
declare MapWinnerId = NullId;
***
/* -------------------------------------- */
// Round init
/* -------------------------------------- */
***InitRound***
***
/* ------------------------------------- */
// Init variables
UpdatePlayerSpawnQueue();
G_TotalPlayersSpawned = G_PlayerSpawnQueue.count;
declare AutoActivationInProgress = False;
declare OffZoneBonus = G_TotalPlayersSpawned;
declare RoundEndRequested = False;
declare RoundWinnerId = NullId;
declare LastSpawnTime = -S_SpawnInterval * 1000;
declare LastMessageTime = Now;
declare LastUIUpdateTime = -C_UITickPeriod;
declare Goal <=> SM::GetPole("Goal", 0);
***
/* -------------------------------------- */
// Round start
/* -------------------------------------- */
***StartRound***
***
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
UIManager.ResetAll();
SM::SetupDefaultVisibility();
Score::RoundBegin();
SetNbFakePlayers(C_NbBots, 0);
/* ------------------------------------- */
// Init goal
Goal.Gauge.Clan = 0;
Goal.Gauge.Value = 0;
Goal.Gauge.Max = S_OffZoneActivationTime * 1000;
Goal.Gauge.Speed = 0;
/* ------------------------------------- */
// Init offzone
OffZoneRadius = -1.;
OffZoneRadiusSpeed = 0.;
OffZoneCenterBlockId = Goal.Id;
/* ------------------------------------- */
// Wait enough players
WaitForPlayers(1);
/* ------------------------------------- */
// Init the players and their scores
foreach (Score in Scores) {
declare Integer PoleBonus for Score;
declare Integer SurvivalBonus for Score;
declare Integer HitBonus for Score;
PoleBonus = 0;
SurvivalBonus = 0;
HitBonus = 0;
Score.RoundPoints = 0;
}
foreach (Player in Players) {
declare Integer RoundHits for Player;
RoundHits = 0;
if (Player.Score != Null) Player.Score.RoundPoints = 1;
}
/* ------------------------------------- */
// Attach layers
LayerDetached = Layers::DetachAll(NullId);
LayerAttached = Layers::Attach("SpawnQueue", NullId);
LayerAttached = Layers::Attach("ScoresTable", NullId);
LayerAttached = Layers::Attach("Infos", NullId);
LayerAttached = Layers::Attach("ScoresInSpawn", NullId);
LayerUpdated = Layers::Update("ScoresInSpawn", UpdateLayerScoresInSpawn());
Rules::Attach();
LayerUpdated = Layers::Update("ScoresTable", UpdateLayerScoresTable());
StartTime = Now;
EndTime = -1;
UIManager.UIAll.CountdownEndTime = -1;
***
/* -------------------------------------- */
// Play loop
/* -------------------------------------- */
***PlayLoop***
***
/* ------------------------------------- */
// Spawn players
if (G_PlayerSpawnQueue.count > 0 && LastSpawnTime + (S_SpawnInterval * 1000) < Now) {
UpdateBlockSpawnQueue();
SpawnPlayers();
LastSpawnTime = Now;
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::StartRound;
UIManager.UIAll.BigMessage = _("Spawning players...");
LastMessageTime = -1;
UIManager.UIAll.CountdownEndTime = LastSpawnTime + (S_SpawnInterval * 1000);
LayerUpdated = Layers::Update("SpawnQueue", UpdateLayerSpawnQueue());
}
/* ------------------------------------- */
// OffZone can be activated
else if (G_PlayerSpawnQueue.count <= 0 && LastSpawnTime + 100 > Now) {
if (S_OffZoneAutoStartTime >= 0) UIManager.UIAll.CountdownEndTime = LastSpawnTime + (S_OffZoneAutoStartTime * 1000);
else UIManager.UIAll.CountdownEndTime = -1;
LayerDetached = Layers::Detach("SpawnQueue", NullId);
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::PhaseChange;
UIManager.UIAll.BigMessage = _("The OffZone can now be activated.");
LastMessageTime = Now;
UIManager.UIAll.Hud3dMarkers = """
""";
}
/* ------------------------------------- */
// Auto activate goal
else if (S_OffZoneAutoStartTime >= 0 && G_PlayerSpawnQueue.count <= 0
&& OffZoneRadiusSpeed == 0. && OffZoneRadius == -1
&& LastSpawnTime + (S_OffZoneAutoStartTime * 1000) < Now)
{
Goal.Gauge.Speed = Goal.Gauge.Max;
Goal.Gauge.Value = Goal.Gauge.Max + 1;
UIManager.UIAll.CountdownEndTime = -1;
AutoActivationInProgress = True;
}
/* ------------------------------------- */
// Manage event
foreach (Event in PendingEvents) {
/* ------------------------------------- */
// OnArmorEmpty
if (Event.Type == CSmModeEvent::EType::OnArmorEmpty) {
declare Integer SpawnTime for Event.Victim;
SpawnTime = Now;
UpdateSurvivalScore(Event.Victim.Id);
LayerUpdated = Layers::Update("ScoresTable", UpdateLayerScoresTable());
PassOn(Event);
}
/* ------------------------------------- */
// OnCapture
else if (Event.Type == CSmModeEvent::EType::OnCapture ) {
if( OffZoneRadiusSpeed == 0. && OffZoneRadius == -1) {
/* ------------------------------------- */
// Active OffZone
OffZoneRadius = C_DefaultOffZoneRadius;
OffZoneRadiusSpeed = C_DefaultOffZoneRadius / S_OffZoneTimeLimit;
Goal.Gauge.Max = S_OffZoneTimeLimit * 1000;
Goal.Gauge.Value = Goal.Gauge.Max;
Goal.Gauge.Speed = -1;
AutoActivationInProgress = False;
/* ------------------------------------- */
// Give points
if (Goal.Sector.PlayersIds.count > 0 && Goal.Gauge.Value >= Goal.Gauge.Max) {
declare Bonus = OffZoneBonus / Goal.Sector.PlayersIds.count;
foreach (PlayerId in Goal.Sector.PlayersIds) {
if (Players.existskey(PlayerId) && Players[PlayerId].Score != Null) {
declare PoleBonus for Players[PlayerId].Score = 0;
PoleBonus = Bonus;
Score::AddPoints(Players[PlayerId], PoleBonus);
Top::IncrementPlayerPoints("Pole", Players[PlayerId], PoleBonus);
UIManager.UIAll.SendNotice(
TextLib::Compose(_("$<%1$> activated the OffZone"), Players[PlayerId].Name),
CUIConfig::ENoticeLevel::MatchInfo, Null,
CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::PhaseChange, 0
);
}
}
} else {
UIManager.UIAll.SendNotice(
_("OffZone activated!"),
CUIConfig::ENoticeLevel::MatchInfo, Null,
CUIConfig::EAvatarVariant::Default,
CUIConfig::EUISound::PhaseChange, 0
);
}
}
LayerUpdated = Layers::Update("ScoresTable", UpdateLayerScoresTable());
PassOn(Event);
}
/* ------------------------------------- */
// OnPlayerRequestRespawn
else if (Event.Type == CSmModeEvent::EType::OnPlayerRequestRespawn) {
declare Integer SpawnTime for Event.Player;
SpawnTime = Now;
UpdateSurvivalScore(Event.Player.Id);
LayerUpdated = Layers::Update("ScoresTable", UpdateLayerScoresTable());
PassOn(Event);
}
/* ------------------------------------- */
// OnHit
else if (Event.Type == CSmModeEvent::EType::OnHit) {
if (Event.Victim != Null && Event.Shooter != Null && Event.Victim != Event.Shooter && Event.Damage > 0) {
declare RoundHits for Event.Shooter = 0;
declare LostArmor = 0;
declare CumulPoints = 0;
if (Event.Victim.Armor < Event.Damage) LostArmor = Event.Victim.Armor;
else LostArmor = Event.Damage;
for (I, 1, LostArmor / 100) {
RoundHits += 1;
declare Points = (RoundHits + 1) / 2;
Score::AddPoints(Event.Shooter, Points);
Top::IncrementPlayerPoints("Hit", Event.Shooter, Points);
CumulPoints += Points;
}
Event.ShooterPoints = CumulPoints;
if (Event.Shooter.Score != Null) {
declare HitBonus for Event.Shooter.Score = 0;
HitBonus += CumulPoints;
}
LayerUpdated = Layers::Update("ScoresTable", UpdateLayerScoresTable());
PassOn(Event);
} else {
Discard(Event);
}
}
/* ------------------------------------- */
// Others
else {
PassOn(Event);
}
}
/* ------------------------------------- */
// Active goal
if (G_PlayerSpawnQueue.count <= 0 && OffZoneRadiusSpeed == 0. && OffZoneRadius == -1 && !AutoActivationInProgress) {
if (Goal.Sector.PlayersIds.count > 0) Goal.Gauge.Speed = 1;
else Goal.Gauge.Speed = 0;
}
/* ------------------------------------- */
// Stop OffZone at MinSize
if (OffZoneRadiusSpeed > 0 && OffZoneRadius <= C_OffZoneMinRadius) {
OffZoneRadiusSpeed = 0.;
OffZoneRadius = C_OffZoneMinRadius;
}
/* ------------------------------------- */
// UI
if (LastMessageTime >= 0 && LastMessageTime + 3000 < Now) {
UIManager.UIAll.BigMessage = "";
}
if (LastUIUpdateTime + C_UITickPeriod < Now) {
LastUIUpdateTime = Now;
LayerUpdated = Layers::Update("Infos", UpdateLayerInfos());
}
/* ------------------------------------- */
// Round end conditions
if ((G_TotalPlayersSpawned > 1 && G_PlayerSpawnQueue.count <= 0 && PlayersNbAlive <= 1)
|| (G_TotalPlayersSpawned <= 1 && G_PlayerSpawnQueue.count <= 0 && PlayersNbAlive <= 0)) ///< Allow solo playing
{
foreach (Player in Players) {
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned) {
declare Integer SpawnTime for Player;
SpawnTime = Now + 1;
RoundWinnerId = Player.Id;
UpdateSurvivalScore(Player.Id);
}
if (Players.count == 1) RoundWinnerId = Player.Id;
}
MB_StopRound = True;
}
***
/* ------------------------------------- */
// Round End
/* ------------------------------------- */
***EndRound***
***
UIManager.ResetAll();
OffZoneRadiusSpeed = 0.;
Goal.Gauge.Speed = 0;
foreach (Player in Players) {
if (Player.Score != Null && Player.Score.RoundPoints > Top::GetPlayerPoints("Round", Player)) {
Top::SetPlayerPoints("Round", Player, Player.Score.RoundPoints);
}
}
LayerDetached = Layers::DetachAll(NullId);
LayerAttached = Layers::Attach("ScoresTable", NullId);
LayerAttached = Layers::Attach("Tops", NullId);
declare ManialinkTop =
Top::GetFrameTop("Survival", _("Top 5 Survival"), "-75 88", "") ^
Top::GetFrameTop("Hit", _("Top 5 Hit"), "-25 88", "") ^
Top::GetFrameTop("Pole", _("Top 5 Pole"), "25 88", "") ^
Top::GetFrameTop("Round", _("Best Round Score"), "75 88", "");
LayerUpdated = Layers::Update("ScoresTable", UpdateLayerScoresTable());
LayerUpdated = Layers::Update("Tops", ManialinkTop);
if (Players.existskey(RoundWinnerId)) {
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::EndRound;
UIManager.UIAll.BigMessage = TextLib::Compose(_("$<%1$> wins the round!"), Players[RoundWinnerId].Name);
} else {
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::EndRound;
UIManager.UIAll.BigMessage = _("|Match|Draw");
}
sleep(1000);
/* ------------------------------------- */
// Show Results
OffZoneRadius = -1.;
StartTime = -1;
EndTime = -1;
SM::UnspawnAllPlayers();
UIManager.UIAll.UISequence = CUIConfig::EUISequence::EndRound;
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
sleep(5000);
Score::RoundEnd();
sleep(3000);
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::Normal;
UIManager.UIAll.BigMessage = "";
/* ------------------------------------- */
// Map end conditions
declare MaxPoints = 0;
foreach (Score in Scores) {
if (Score.Points >= MaxPoints) {
if (Score.Points > MaxPoints) {
MapWinnerId = Score.User.Id;
} else if (Score.Points == MaxPoints) {
MapWinnerId = NullId;
}
MaxPoints = Score.Points;
}
}
if (MaxPoints >= S_MapPointsLimit) MB_StopMap = True;
***
/* ------------------------------------- */
// Map End
/* ------------------------------------- */
***EndMap***
***
Score::MatchEnd(True);
Top::RoundEnd();
Top::MatchEnd();
LayerDetached = Layers::DetachAll(NullId);
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
if (Users.existskey(MapWinnerId)) {
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::EndRound;
UIManager.UIAll.BigMessage = TextLib::Compose(_("$<%1$> wins the match!"), Users[MapWinnerId].Name);
} else {
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::EndRound;
UIManager.UIAll.BigMessage = _("|Match|Draw");
}
sleep(6000);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Podium;
LayerAttached = Layers::Attach("Tops", NullId);
sleep(3000);
UIManager.UIAll.BigMessage = "";
Mode::UnloadMap();
***
/* ------------------------------------- */
// Server End
/* ------------------------------------- */
***EndServer***
***
/* -------------------------------------- */
// Layers destruction
LayerDetached = Layers::DetachAll(NullId);
Layers::Clean();
***
/* ------------------------------------- */
// Functions
/* ------------------------------------- */
/* ------------------------------------- */
/** Wait until there's enough players to play
*
* @param _MinPlayers minimum number of players to begin
*/
Void WaitForPlayers(Integer _MinPlayers) {
UIManager.UIAll.BigMessageSound = CUIConfig::EUISound::Warning;
UIManager.UIAll.BigMessage = _("Waiting for players...");
StartTime = -1;
EndTime = -1;
while (PlayersNbTotal < _MinPlayers && !MatchEndRequested) {
yield;
}
StartTime = -1;
UIManager.UIAll.BigMessage = "";
}
/* ------------------------------------- */
/// Update the player spawn queue
Void UpdatePlayerSpawnQueue() {
G_PlayerSpawnQueue.clear();
foreach (Player in Players) {
declare SpawnTime for Player = -1;
G_PlayerSpawnQueue[Player.Id] = SpawnTime;
}
G_PlayerSpawnQueue = G_PlayerSpawnQueue.sort();
}
/* ------------------------------------- */
/// Update the block spawn queue
Void UpdateBlockSpawnQueue() {
G_PriorityBlockSpawnQueue = [1=>Ident[], 2=>Ident[], 3=>Ident[]];
foreach (BlockSpawn in BlockSpawns) {
if (BlockSpawn.Order <= 1) G_PriorityBlockSpawnQueue[1].add(BlockSpawn.Id);
else if (BlockSpawn.Order == 2) G_PriorityBlockSpawnQueue[2].add(BlockSpawn.Id);
else if (BlockSpawn.Order >= 3) G_PriorityBlockSpawnQueue[3].add(BlockSpawn.Id);
}
}
/* ------------------------------------- */
/// Spawn the players
Void SpawnPlayers() {
declare Ident[] ToRemove;
for (I, 1, 3) {
if (G_PlayerSpawnQueue.count <= 0) break;
while (G_PriorityBlockSpawnQueue[I].count > 0) {
if (G_PlayerSpawnQueue.count <= 0) break;
declare SpawnId = G_PriorityBlockSpawnQueue[I][MathLib::Rand(0, G_PriorityBlockSpawnQueue[I].count - 1)];
declare Tmp = G_PriorityBlockSpawnQueue[I].remove(SpawnId);
foreach (PlayerId => SpawnTime in G_PlayerSpawnQueue) {
if (Players.existskey(PlayerId)) {
SM::SpawnPlayer(Players[PlayerId], 0, BlockSpawns[SpawnId]);
ToRemove.add(PlayerId);
break;
} else {
ToRemove.add(PlayerId);
}
}
foreach (Id in ToRemove) {
declare Tmp = G_PlayerSpawnQueue.removekey(Id);
}
}
}
}
/* ------------------------------------- */
/** Update survival score
*
* @param _PlayerId The player who just have been eliminated
*/
Void UpdateSurvivalScore(Ident _PlayerId) {
// When more than 3 players was spawned
if (PlayersNbAlive > 1 && G_TotalPlayersSpawned > 2) {
foreach (Player in Players) {
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned && Player.Id != _PlayerId) {
Score::AddPoints(Player, 1);
if (PlayersNbAlive == 2) Score::AddPoints(Player, (G_TotalPlayersSpawned / 2) + (G_TotalPlayersSpawned % 2));
if (PlayersNbAlive == 3) Score::AddPoints(Player, G_TotalPlayersSpawned / 2);
}
}
}
// Special case when there was less than 3 players spawned
else if (G_TotalPlayersSpawned <= 2 && PlayersNbAlive > 1) {
foreach (Player in Players) {
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawned) {
if (Player.Id == _PlayerId) {
Score::AddPoints(Player, 1);
} else {
Score::AddPoints(Player, 3);
}
}
}
}
if (!Players.existskey(_PlayerId)) return;
if (Players[_PlayerId].Score != Null) {
declare SurvivalBonus for Players[_PlayerId].Score = 0;
SurvivalBonus = G_TotalPlayersSpawned - PlayersNbAlive + 1;
if (PlayersNbAlive == 1) SurvivalBonus = SurvivalBonus + G_TotalPlayersSpawned;
if (PlayersNbAlive == 2) SurvivalBonus = SurvivalBonus + (G_TotalPlayersSpawned / 2);
Top::IncrementPlayerPoints("Survival", Players[_PlayerId], SurvivalBonus);
}
}
/* ------------------------------------- */
/** Generate the player spawn queue manialink
*
* @return The manialink Text
*/
Text UpdateLayerSpawnQueue() {
declare ML = "";
declare List = "";
declare I = 0;
declare Max = 15;
declare MoreString = TextLib::Compose(_("%1 more ..."), TextLib::ToText(G_PlayerSpawnQueue.count - Max));
foreach (PlayerId => Time in G_PlayerSpawnQueue) {
if (!Players.existskey(PlayerId)) continue;
declare PseudoString = TextLib::MLEncode(Players[PlayerId].Name);
List ^= """""";
I += 1;
if (I > Max) {
List ^= """""";
I += 1;
break;
}
}
ML = """
{{{ List }}}
""";
return ML;
}
/* ------------------------------------- */
/** Generate the score table manialink
*
* @return The manialink Text
*/
Text UpdateLayerScoresTable() {
declare ML = "";
declare I = 0;
declare J = 0;
declare K = 0;
declare Max = 16;
declare PolePoints = 0;
declare RankingHit = Integer[Text];
declare RankingHitList = "";
declare RankingPole = Integer[Text];
declare RankingPoleList = "";
declare RankingSurvival = Integer[Text];
declare RankingSurvivalList = "";
foreach (Score in Scores) {
declare PoleBonus for Score = 0;
declare SurvivalBonus for Score = 0;
declare HitBonus for Score = 0;
if (HitBonus > 0) RankingHit[Score.User.Name] = HitBonus * -1;
if (SurvivalBonus > 0) RankingSurvival[Score.User.Name] = SurvivalBonus * -1;
if (PoleBonus > 0) RankingPole[Score.User.Name] = PoleBonus;
}
RankingHit = RankingHit.sort();
RankingSurvival = RankingSurvival.sort();
foreach (Pseudo => Points in RankingPole) {
PolePoints = Points;
RankingPoleList ^= """
""";
K += 1;
if (K >= 5) break;
}
foreach (Pseudo => Points in RankingHit) {
RankingHitList ^= """
""";
J += 1;
if (J >= Max) break;
}
foreach (Pseudo => Points in RankingSurvival) {
RankingSurvivalList ^= """
""";
I += 1;
if (I >= Max) break;
}
ML = """
{{{ RankingPoleList }}}
{{{ RankingSurvivalList }}}
{{{ RankingHitList }}}
""";
return ML;
}
/* ------------------------------------- */
/** Generate the info manialink
*
* @return The manialink Text
*/
Text UpdateLayerInfos() {
declare ML = "";
declare RemainString = TextLib::Compose(
_("Remaining players: %1"),
TextLib::ToText(G_PlayerSpawnQueue.count + PlayersNbAlive)
);
ML = """
""";
return ML;
}
/* ------------------------------------- */
/** Update the Scores in Spawn manialink
*
* @return The manialink string
*/
Text UpdateLayerScoresInSpawn() {
declare Top3 = "";
declare I = 0;
declare Icons = ["First", "Second", "Third"];
foreach (Score in Scores) {
declare Pseudo = TextLib::MLEncode(Score.User.Name);
Top3 ^=
"""
""";
I += 1;
if (I >= 3) break;
}
return
"""
{{{ Top3 }}}
""";
}