Oscillation Total Makeover - Version 2.0 Small Problem

You can talk about ManiaScript for ManiaPlanet here

Moderator: English Moderator

Post Reply
User avatar
bryan1998
Posts: 98
Joined: 03 Sep 2011, 00:41
Location: Washington, USA
Contact:

Oscillation Total Makeover - Version 2.0 Small Problem

Post by bryan1998 »

Hello!

I found an Alpha mode at http://forum.maniaplanet.com/viewtopic. ... 8#p115582/. Note that I do not have access to the Alpha forum, so that is a link to the regular forum. Oh, and the script is by Realspace.

I have decided to do a TOTAL makeover on it, taking almost all code from the most recent Melee mode. All works fine and dandy, except for 1 small little problem - a runtime error. It doesn't affect gameplay much, but it does prevent 1 thing from happening - showing point limit on the score table. The error goes something like:

Code: Select all

[190, 19] Invalid access to parameter (Null object or elem not found in array) : UIManager.UILayers[###20]>.ManialinkPage
This is the piece of code that is causing it:

Code: Select all

LayerScoresTable.ManialinkPage = """
	<frame posn="0 -47">
		<quad posn="0 0 1" sizen="40 8" style="Bgs1InRace" halign="center" substyle="BgList"/>
		<label posn="0 -2 2" sizen="40 8" halign="center" text="{{{_("Point limit")}}}: {{{ S_PointLimit }}}" />
	</frame>
""";
Entire script: https://dl.dropbox.com/u/62510870/Mania ... Script.txt
Last edited by bryan1998 on 30 Jul 2012, 16:19, edited 1 time in total.
User avatar
Eole
Nadeo
Nadeo
Posts: 1265
Joined: 26 Apr 2011, 21:08

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by Eole »

Replace line 389:

Code: Select all

if (!UsedLayers.exists(Layer.Id) && Layer != LayerSpawnScreen) {
By:

Code: Select all

if (!UsedLayers.exists(Layer.Id) && Layer != LayerSpawnScreen && Layer != LayerScoresTable) {
The layer was deleted during the round, so after the map change the script couldn't find it anymore.
Contribute to the ManiaPlanet documentation on GitHub
A question about ManiaScript? Ask it here!
User avatar
bryan1998
Posts: 98
Joined: 03 Sep 2011, 00:41
Location: Washington, USA
Contact:

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by bryan1998 »

Thank you! I'm gonna do some Dropbox folder re-organizing, so the link will be broken until I update it.
User avatar
bryan1998
Posts: 98
Joined: 03 Sep 2011, 00:41
Location: Washington, USA
Contact:

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by bryan1998 »

I have another question - how can I hide a UIManager.UIAll.StatusMessage after a period of time?

EDIT: Can someone please merge my previous post with this one? Also delete this line while merging.
User avatar
Eole
Nadeo
Nadeo
Posts: 1265
Joined: 26 Apr 2011, 21:08

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by Eole »

Something quick:

Code: Select all

// Outside the play loop
declare LastStatusMessageTime = 0;

// Inside the play loop
while (Playing) {
    // Something happen, set my status message once
    if (SomethingHappen) {
        UIManager.UIAll.StatusMessage = "My status message";
        LastStatusMessageTime = Now;
        SomethingHappen = False;
    }
    // If a status message is displayed since more than 3 seconds, erase it
    if (LastStatusMessageTime + 3000 < Now) {
        UIManager.UIAll.StatusMessage = "";
    }
}
Contribute to the ManiaPlanet documentation on GitHub
A question about ManiaScript? Ask it here!
User avatar
bryan1998
Posts: 98
Joined: 03 Sep 2011, 00:41
Location: Washington, USA
Contact:

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by bryan1998 »

Thanks!
User avatar
BragonHightake
Posts: 250
Joined: 17 Aug 2011, 00:22

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by BragonHightake »

A new Oscillation version would be cool.
Maybe with a highjump or a fly mode. (as in the editor, if you press F)
User avatar
w1lla
Posts: 2287
Joined: 15 Jun 2010, 11:09
Location: Netherlands
Contact:

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by w1lla »

always missed a countdown timer for it so i made own of my own. Its based upon the old script but it can be altered to make it work with the new one.

It also works on EliteMaps aswell as anyother Maps.

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"
#Const	Version				"2012-08-31"
#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;	
	//SetNbFakePlayers(10,0);
	declare LayerSpawnScreen <=> UIManager.UILayerCreate();
	LayerSpawnScreen.Type = CUILayer::EUILayerType::ScreenIn3d;
	while (!ServerShutdownRequested) {
		LoadMap();
		XmlRpc.SendCallback("beginMap",MapName);
		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");
		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";
			WarningGiven = 1;
			}
			if(Now == NextSwitch - 4000){
			WarningGiven = 0;
			UIManager.UIAll.BigMessage = "4";
			WarningGiven = 1;
			}
			if(Now == NextSwitch - 3000){
			WarningGiven = 0;
			UIManager.UIAll.BigMessage = "3";
			WarningGiven = 1;
			}
			if(Now == NextSwitch - 2000){
			WarningGiven = 0;
			UIManager.UIAll.BigMessage = "2";
			WarningGiven = 1;
			}
			if(Now == NextSwitch - 1000){
			WarningGiven = 0;
			UIManager.UIAll.BigMessage = "1";
			WarningGiven = 1;
			}
			if (Now >= NextSwitch) {
				WarningGiven = 0;
				ModeCount += 1;
				NextSwitch = Now + (SwitchInt * 1000);
				while (Mode == PrevMode) {
					Mode = MathLib::Rand(0,10);
				}
				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;
						}
					}
				}
			}
			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);
						}
					}
					XmlRpc.SendCallback("playerDeath", Event.Victim.Login);	
					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;
						}
						XmlRpc.SendCallback("playerHit", "Victim:"^Event.Victim.Login^";Shooter:"^Event.Shooter.Login^";"^Points);
						Score::AddPoints(Event.Shooter, Points);
						PassOn(Event);
					
            
						// Play sound and notice if someone is close to win
						if (Event.Shooter != Null && Event.Shooter.Score != Null) {
							declare Gap = PointLimit - Event.Shooter.Score.RoundPoints;
							if (Gap <= 3 && Gap > 0) {
								declare Variant = 3 - Gap;
								declare Msg = "";
								if (Gap > 1)
									Msg = TextLib::Compose(_("$<%1$> is %2 points from victory!"), Event.Shooter.Name, TextLib::ToText(Gap));
								else 
									Msg = TextLib::Compose(_("$<%1$> is 1 point from victory!"), Event.Shooter.Name);
								UIManager.UIAll.SendNotice(
									Msg, 
									CUIConfig::ENoticeLevel::PlayerInfo, 
									Null, CUIConfig::EAvatarVariant::Default, 
									CUIConfig::EUISound::TieBreakPoint, Variant
								);
							} else if (Gap <= 0) {
								UIManager.UIAll.SendNotice(
									TextLib::Compose(_("$<%1$> gets the final hit!"), Event.Shooter.Name), 
									CUIConfig::ENoticeLevel::PlayerInfo, 
									Null, CUIConfig::EAvatarVariant::Default, 
									CUIConfig::EUISound::VictoryPoint, 0
								);
								
							}
						}
						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) {			
						Score::RemovePoints(Event.Player, 1);
					}
					if (Mode == 2 || Mode == 5 || Mode == 6) {
						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 {
							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();
		XmlRpc.SendCallback("endRound",MapName);
		Score::MatchEnd(True);	
		
		
		declare PlayerList = "";
        	foreach (Player in Players) {
        		PlayerList = PlayerList^(Player.Login^":"^Player.Score.Points^";");
	        }
        	foreach (Player in Spectators) {
        		PlayerList = PlayerList^(Player.Login^":"^Player.Score.Points^";");
	        }
	
		XmlRpc.SendCallback("endMap",PlayerList);
		////////////////////////////////////
		// 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);
}
TM² Info
SM Info
QM Info

OS: Windows 10 x64 Professional
MB: MSI 970A-G46
Processor: AMD FX-6300 3500 mHz
RAM Memory: 16 GB DDR3
Video: SAPPHIRE DUAL-X R9 280X 3GB GDDR5
KB: Logitech G510s
Mouse: Logitech G300s
Mode Creation
ManiaScript Docs
User avatar
BragonHightake
Posts: 250
Joined: 17 Aug 2011, 00:22

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by BragonHightake »

Something is wrong with your script, the server does not start.
User avatar
w1lla
Posts: 2287
Joined: 15 Jun 2010, 11:09
Location: Netherlands
Contact:

Re: Oscillation Total Makeover - Version 2.0 Small Problem

Post by w1lla »

For me it works on B1.3b
TM² Info
SM Info
QM Info

OS: Windows 10 x64 Professional
MB: MSI 970A-G46
Processor: AMD FX-6300 3500 mHz
RAM Memory: 16 GB DDR3
Video: SAPPHIRE DUAL-X R9 280X 3GB GDDR5
KB: Logitech G510s
Mouse: Logitech G300s
Mode Creation
ManiaScript Docs
Post Reply

Return to “ManiaScript”

Who is online

Users browsing this forum: No registered users and 1 guest