Code: Select all
#RequireContext CSmMode
#Include "Libs/Nadeo/Mode.Script.txt"
#Include "Libs/Nadeo/ShootMania/SM.Script.txt" as SM
#Include "Libs/Nadeo/ShootMania/Score.Script.txt" as Score
#Include "MathLib" as MathLib
#Include "TextLib" as TextLib
#Const CompatibleMapTypes "EliteArena MeleeArena"
#Const Version "2012-06-13"
#Const ModeVer "v1.0"
#Const C_UITickInterval 200
#Setting TimeLimit 600 as "Time limit"
#Setting PointLimit 25 as "Point limit"
#Setting SwitchInt 20 as "Switch interval"
#Setting SelfElimCost 3 as "Self elimination mode cost"
declare Ident[] SpawnsList;
declare Ident LatestSpawnId;
Void FillSpawnsList() {
foreach (BlockSpawn in BlockSpawns) { SpawnsList.add(BlockSpawn.Id); }
}
Void SpawnPlayers(CSmPlayer _Player) {
if (SpawnsList.count == 0) FillSpawnsList();
declare SpawnId = NullId;
while (True) {
SpawnId = SpawnsList[MathLib::Rand(0, SpawnsList.count - 1)];
if (SpawnId != LatestSpawnId) break;
if (SpawnsList.count == 1) break;
}
SM::SpawnPlayer(_Player, 0, BlockSpawns[SpawnId]);
LatestSpawnId = SpawnId;
declare Tmp = SpawnsList.remove(SpawnId);
}
Text UpdateLayerInfos(CSmPlayer _Player) {
if (_Player.Score == Null) return "";
return """
<frame posn="150 -88">
<label posn="0 1" halign="left" valign="bottom" text="/{{{ Scores.count }}}"/>
<label posn="0 0" halign="right" valign="bottom" style="TextRaceChrono" text="{{{ Scores.keyof(_Player.Score) + 1 }}}"/>
</frame>
""";
}
/* ------------------------------------- */
/** Get the help manialink string.
*
* @return The manialink string
*/
Text UpdateLayerSpawnScreen() {
declare Text ML;
declare TempForI18n = _("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.");
ML = """
<script><!--
main () {
declare FrameRules <=> Page.GetFirstChild("FrameRules");
declare FrameShow <=> Page.GetFirstChild("FrameShow");
declare ShowRules = False;
while(True) {
if (ShowRules) {
FrameRules.Show();
FrameShow.Hide();
} else {
FrameRules.Hide();
FrameShow.Show();
}
yield;
// process events.
foreach (Event in PendingEvents) {
switch (Event.Type) {
case CMlEvent::Type::MouseClick :
{
if (Event.ControlId == "FrameRules") ShowRules = !ShowRules;
}
case CMlEvent::Type::KeyPress:
{
if (Event.CharPressed == "2424832") ShowRules = !ShowRules; // F1
}
}
}
}
}
--></script>
<frame posn="0 -70 0" id="FrameShow">
<quad posn="0 0 10" sizen="140 20" halign="center" valign="center" style="Bgs1InRace" substyle="BgTitle3_5" />
<label posn="0 0 11" scale="2" halign="center" valign="center" style="TextTitle3" text="{{{ _("Press F1 to show rules") }}}" />
</frame>
<frame posn="0 50 1" id="FrameRules">
<frame posn="0 0 5">
<quad posn="0 0 10" sizen="120 20" halign="center" valign="center" style="Bgs1InRace" substyle="BgTitle3_5" />
<label posn="0 0 11" scale="2" halign="center" valign="center" style="TextTitle3" text="$fffOscillation" />
</frame>
<frame posn="0 -10 5">
<quad posn="0 0 10" sizen="300 120" halign="center" bgcolor="222c" />
<label posn="-145 -5 11" sizen="192 5" scale="1.5" autonewline="1" style="TextCardSmallScores2" text="{{{"Modes:\n1. Normal Mode - This is standard melee.\n2. Self-eliminations cost __ points! - If you die from offzone or backspace, you lose __ points, where __ is a number.\n3. UNLIMITED! POWER!! - Gives everyone 10x weapon power gain for the mode's duration.\n4. Don't die! - If you die while this mode is active, you do not respawn until it changes.\n5. Spawn with 3 armor points! - If you spawn during this mode, you have 3 armor points.\n6. Spawn with Laser only! - If you spawn during this mode, you get the laser only. The other weapons do not work.\n7. Spawn with Nucleus only! - Same as mode 6, but with the Nucleus, not the Laser.\n8. DOULBE POINTS! - This mode doubles every hit's point worth (1 -> 2, 2 -> 4).\n9. It's a one-hit wonder! - Everyone's HP is set to 1 at the start of this mode.\n10. Health: Refilled! - Completley refills your health.\n\nThis is version 1.4"}}}" />
</frame>
</frame>
""";
return ML;
}
main() {
UseClans = False;
declare LayerSpawnScreen <=> UIManager.UILayerCreate();
LayerSpawnScreen.Type = CUILayer::EUILayerType::ScreenIn3d;
while (!ServerShutdownRequested) {
LoadMap();
SpawnsList.clear();
LatestSpawnId = NullId;
Score::MatchBegin();
Score::RoundBegin();
MatchEndRequested = False;
UIManager.ResetAll();
SM::SetupDefaultVisibility();
LayerSpawnScreen.ManialinkPage = UpdateLayerSpawnScreen();
UIManager.UIAll.UILayers.add(LayerSpawnScreen);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Intro;
UIManager.UIAll.BigMessage = """New match on {{{Map.MapName}}}$z$s by {{{Map.AuthorNickName}}}""";
wait(UIManager.UIAll.UISequenceIsCompleted);
sleep(2000);
UIManager.UIAll.BigMessage = "";
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
declare LastUITick = 0;
StartTime = Now;
EndTime = StartTime + (TimeLimit * 1000);
declare Integer Mode = 0;
declare Integer PrevMode = -1;
declare Integer NextSwitch = Now;
declare WarningGiven = 1;
declare ModeCount = 1;
declare ShotsFired = 0;
while (!MatchEndRequested && !ServerShutdownRequested)
{
yield;
if (Now >= NextSwitch - 5000 && WarningGiven == 0) {
UIManager.UIAll.SendChat("""$fffOscillation #$0f0{{{ModeCount}}}$fff will start oscillating in $0f0five $fffseconds.""");
WarningGiven = 1;
}
if(Now == NextSwitch - 5000){
WarningGiven = 0;
UIManager.UIAll.BigMessage = "5";
LastUITick = Now;
WarningGiven = 1;
}
if(Now == NextSwitch - 4000){
WarningGiven = 0;
UIManager.UIAll.BigMessage = "4";
LastUITick = Now;
WarningGiven = 1;
}
if(Now == NextSwitch - 3000){
WarningGiven = 0;
UIManager.UIAll.BigMessage = "3";
LastUITick = Now;
WarningGiven = 1;
}
if(Now == NextSwitch - 2000){
WarningGiven = 0;
UIManager.UIAll.BigMessage = "2";
LastUITick = Now;
WarningGiven = 1;
}
if(Now == NextSwitch - 1000){
WarningGiven = 0;
UIManager.UIAll.BigMessage = "1";
LastUITick = Now;
WarningGiven = 1;
}
if (Now >= NextSwitch) {
WarningGiven = 0;
ModeCount += 1;
NextSwitch = Now + (SwitchInt * 1000);
while (Mode == PrevMode) {
Mode = MathLib::Rand(0,12);
}
PrevMode = Mode;
switch (Mode) {
case 0:
UIManager.UIAll.BigMessage = "Normal Mode";
case 1:
UIManager.UIAll.BigMessage = """Self-eliminations cost {{{SelfElimCost}}} points!""";
case 2:
UIManager.UIAll.BigMessage = "Spawn with 3 Armor Points!";
case 3:
UIManager.UIAll.BigMessage = "UNLIMITED! POWER!!";
case 4:
UIManager.UIAll.BigMessage = "Don't get eliminated!";
case 5:
UIManager.UIAll.BigMessage = "Spawn with Laser only!";
case 6:
UIManager.UIAll.BigMessage = "Spawn with Nucleus only!";
case 7:
UIManager.UIAll.BigMessage = "DOUBLE POINTS!";
case 8: {
UIManager.UIAll.BigMessage = "It's a one-hit wonder!";
foreach(Player in Players) {
Player.Armor = 100;
}
}
case 9: {
UIManager.UIAll.BigMessage = "Health: Refilled!";
foreach (Player in Players) {
Player.Armor = Player.ArmorMax;
}
}
case 10: {
UIManager.UIAll.BigMessage = "Ammo Regaining!";
foreach(Player in Players) {
Player.AmmoGain = 10.0;
}
}
case 11:
UIManager.UIAll.BigMessage = "Spawn with Arrow only!";
}
}
foreach (Event, PendingEvents) {
if (Event.Type == CSmModeEvent::EType::OnArmorEmpty) {
if (Event.Shooter == Event.Victim || Event.Shooter == Null) {
if (Mode == 1) {
Score::RemovePoints(Event.Victim, SelfElimCost);
} else {
Score::RemovePoints(Event.Victim, 1);
}
}
PassOn(Event);
} else if (Event.Type == CSmModeEvent::EType::OnShoot) {
ShotsFired += 1;
PassOn(Event);
} else if (Event.Type == CSmModeEvent::EType::OnHit) {
if (Event.Shooter == Event.Victim) {
Discard(Event);
} else {
declare Points = Event.Damage / 100;
if (Mode == 7) {
Points = Points * 2;
}
Score::AddPoints(Event.Shooter, Points);
Event.ShooterPoints = Points;
PassOn(Event);
}
} else if (Event.Type == CSmModeEvent::EType::OnPlayerRequestRespawn) {
if (Mode == 1) {
Score::RemovePoints(Event.Player, SelfElimCost);
} else if (Mode != 2 || Mode != 5 || Mode != 6 || Mode != 11) {
Score::RemovePoints(Event.Player, 1);
}
if (Mode == 2 || Mode == 5 || Mode == 6 || Mode == 11) {
Discard(Event);
} else {
PassOn(Event);
}
} else {
PassOn(Event);
}
}
foreach (Player in Players) {
//Other things
if (Mode == 3) {
Player.AmmoGain = 10.0;
} else {
Player.AmmoGain = 1.0;
}
// Spawn
if (Mode != 4) {
if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned && !Player.RequestsSpectate) {
if (Mode == 2) {
Player.ArmorMax = 300;
} else {
Player.ArmorMax = 200;
}
if (Mode == 5) {
SetPlayerWeapon(Player, CSmMode::EWeapon::Laser, False);
} else if (Mode == 6) {
SetPlayerWeapon(Player, CSmMode::EWeapon::Nucleus, False);
} else if (Mode == 11) {
SetPlayerWeapon(Player, CSmMode::EWeapon::Arrow, False);
} else {
SetPlayerWeapon(Player, CSmMode::EWeapon::Rocket, True);
}
SpawnPlayers(Player);
}
}
}
/* -------------------------------------- */
// Update UI
if (LastUITick + C_UITickInterval < Now) {
declare UsedLayers = Ident[];
// Add layer and create it if necessary
foreach (Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI == Null) continue;
declare CUILayer LayerInfos;
if (UI.UILayers.count != 1) {
LayerInfos <=> UIManager.UILayerCreate();
UI.UILayers.add(LayerInfos);
} else {
LayerInfos <=> UI.UILayers[0];
}
UsedLayers.add(LayerInfos.Id);
LayerInfos.ManialinkPage = UpdateLayerInfos(Player);
}
// Remove layers
declare LayersToRemove = Ident[];
foreach (Layer in UIManager.UILayers) {
if (!UsedLayers.exists(Layer.Id) && Layer != LayerSpawnScreen) {
LayersToRemove.add(Layer.Id);
}
}
foreach (LayerId in LayersToRemove) {
UIManager.UILayerDestroy(UIManager.UILayers[LayerId]);
}
LastUITick = Now;
}
////////////////////////////////////
// victory conditions
declare IsMatchOver = False;
if (Now > EndTime)
IsMatchOver = True;
foreach (Player in Players) {
if (Player.Score != Null && Player.Score.RoundPoints >= PointLimit)
IsMatchOver = True;
}
if (IsMatchOver)
break;
}
Score::RoundEnd();
Score::MatchEnd(True);
////////////////////////////////////
// End match sequence.
declare CUser Winner <=> Null;
declare MaxPoints = 0;
foreach (Score in Scores) {
if (Score.Points > MaxPoints) {
MaxPoints = Score.Points;
Winner <=> Score.User;
} else if (Score.Points == MaxPoints) {
Winner <=> Null;
}
}
foreach (Player in Players) {
if (Player.User != Winner)
UnspawnPlayer(Player);
}
if (Winner != Null) {
UIManager.UIAll.BigMessage = TextLib::Compose(_("$<%1$> wins the match!"), Winner.Name);
} else {
UIManager.UIAll.BigMessage = _("|Match|Draw");
}
UIManager.UIAll.SendChat("""Fun fact: $0f0{{{ShotsFired}}}$fff shots were fired this match.""");
sleep(5000);
UIManager.UIAll.UISequence = CUIConfig::EUISequence::Podium;
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::ForcedVisible;
wait(UIManager.UIAll.UISequenceIsCompleted);
UIManager.UIAll.ScoreTableVisibility = CUIConfig::EVisibility::Normal;
UIManager.UIAll.BigMessage = "";
UnloadMap();
}
UIManager.UILayerDestroy(LayerSpawnScreen);
}