Tag Archives: spawn

Preparing the Playground

Having built the map type and a first script test map I will let the mode load and prepare the map properly and let players spawn in their correct spawns.

When the match is about to start I call my own function PrepareMap(). The function initialises the “Bases” of the map and collects all spawns and goals in global arrays.
I save the blocks because then I don’t have to search for them when I need them: For example when I want to check if a player is planting the bomb.
Pay attention to the fact that instead of saving the blocks I only save their ids. It’s an important approach that I will explain in another post.

The ids of the spawn blocks are saved in a two-dimensional array according to their orders which have been set by the map editor while building the map.
So I know which spawns belong to which team.

As bomb spots are represented by goal posts I save their ids as well in an additional array. This one doesn’t need to have any special keys because during each round only one team attacks and tries to plant the bomb while the other team needs to defend. There is no “owning” of goals involved.

Another global variable is the number of the currently attacking team.
This number is generated randomly for the first round of each match and switches between 1 (blue) and 2 (red) before each following round.
So Defusing will for now let the attacking and defending team switch while in the Bomb Defuse mode of Counter Strike you choose your team at the beginning of a match and you will always defend or attack based on that choice.
Later I will probably add a script setting that allows you to use the Counter Strike game play.

In order to properly switch sides I switch the spawn arrays. That may be difficult to understand so I will take a closer look at the idea behind it.

Imagine the spawns array like that:
G_ClanSpawnIds =
[1 => [SpawnId11, SpawnId12], // Spawns Team 1
2 => [SpawnId21, SpawnId22]]; // Spawns Team 2

This is how the array looks after the PrepareMap() function. In the array saved for the key 1 spawn ids for the attacking side are saved while key 2 holds the defender spawns.

Start: The blue team (clan 1) attacks. When I need to spawn a player I can simply take the array referenced by the current clan of the player.

declare SpawnIds = G_ClanSpawnIds[_Player.RequestedClan];

Now I can easily choose one out these spawn ids in order to find a correct spawn for the player.

// Choose a random id out of the array
declare SpawnId = G_ClanSpawnIds[MathLib::Rand(0, G_ClanSpawnIds.count-1)];

// Take the spawn block with the chosen id
declare Spawn <=> BlockSpawns[SpawnId];

The round ends.
For taking all necessary steps before the next round starts if have a function PrepareRound().
An example is that teams need to switch sides, so in order to accomplish that I will simply switch the spawn arrays saved for the keys 1 & 2.

declare Temp = G_ClanSpawnIds[1];
G_ClanSpawnIds[1] = G_ClanSpawnIds[2];
G_ClanSpawnIds[2] = Temp;

Thanks to these 3 lines I don’t have to worry about finding a proper spawn for a player during the running match because I can simply refer to the array of spawns referenced by her/his current/requested clan number.

Additionally to collecting and managing the spawns and poles I constantly update the Clan of the Bases.
So what exactly are “Bases”?
Well, when a map is loaded the game itself automatically connects blocks and pools them into Bases. The blocks considered for these collections are all block types that have lights or colourable elements on them. Especially Spawn, Goals, Heal/Laser/Arrow Pads, Speed Paths and similar stuff.

The class CSmBase has a property Clan that can be used to colour the blocks connected by that base. This colouring gives the map a better look as you spawn in or around blocks that are coloured like your own team. You feel like actually defending your own base instead of just fighting for no reason. That’s why I always try to pay attention to proper colouring of bases.

Each CSmBase needs to be “activated” first though. That’s easily done by setting it active during the preparation of maps. It will turn on the lights of the blocks so that you will be able to see their colours.

Base.IsActive = True;
Base.Clan = 1; // Base will have color of Team 1 (usually Blue)

Now we got a proper map on which the action will take place. Next step will be to actually let the action begin. :)
You can find the current version of the script here: Defusing3.Script.txt

It’s probably quite difficult to understand the steps I’m taking only by reading the posts. A suggestion by me would be to actually load up the script ingame and analyse what the lines I added do. Maybe even try to play around with other values like switching the Base coloring by changing their “Clan”.

I’m sorry if anything is badly described. I still need to figure out which parts I have to explain extensively and which I can leave behind.

Cheerio,
steeffeen

Labels are Life

I start the next step with the almost empty script opened in the game as I create my scripts 99% directly inside the game.
(Hint: While having started a match with an own script hitting F12 on the keyboard opens the script editor, making it possible to edit it ingame. Pressing Ctrl+G shows the log.)

If you want to edit your script outside of the game you will need to restart ManiaPlanet after any change as it caches files constantly and it therefore won’t see changes in the code.

I would like to be able to walk around the map needing me to be spawned.
For this act I will use the PlayLoop label of the ModeBase script.

Each label defined in the ModeBase can be used as a point to insert our own code.
Label locations are defined via +++Name+++ or ---Name--- and the actual code for the label is surrounded by a structure like this:

***Name***
***
// Our code
***

Using --- means that only the most derived implementation of the label will be used while +++ uses every implementation. (Other scripts could extend our own script leading to more derivation levels.)

The PlayLoop is the place where you can insert code that’s executed all the time during the actual gameplay. There are other labels like for example StartServer or StartRound in which it’s possible to prepare the used resources or EndMatch in which you will probably announce the winner of the match.

During the PlayLoop I loop through all players in order spawn or unspawn them if needed by checking their SpawnStatus and possible team change or spectating requests.

For spawning I will use an own extra function in order to keep the code more clean as it might get more complex in the future.
Furthermore I use the file SM.Script.txt by Nadeo for the actual spawning action, the script needs to be included with the #Include directive first.

#Include "Libs/Nadeo/ShootMania/SM.Script.txt" as SM
This makes it possible to access functions declared in this script via the namespace “SM”.

Currently the players get simply spawned in the first spawn block I can find.

In order to be able to move around 3 more statements are needed.

UseClans = True;
Activates a team based game play which will be needed for Defusing.

StartTime = Now;
The StartTime defines the begin of the match. Players can only spawn and perform actions after the match has started, which basically means that Now needs to be bigger than or equal to StartTime.

UIManager.UIAll.UISequence = CUIConfig::EUISequence::Playing;
Let players move around with their characters. There are other sequences like for example the Intro or the Podium sequence during which the players will only be able to watch mediatracker clips.

After adding all this stuff and hitting “Save and Test” the script is saved, the match restarted and my character is actually being spawned. I’m able to move around! Yeeyy!

You can find the current version of the script here: Defusing1.Script.txt
I’ve tried to add meaningful comments. ;)

Greetings,
steeffeen