Monthly Archives: October 2013

***Labels***

In my “Defusing” series I’ve mentioned a ManiaScript technique called “Labels” which might be confusing for many developers because of its uniqueness.
Actually I myself needed some time as well in order to fully get the point of it.

A code example:

Void LogSomething() {
declare Message = "Hello World!";
+++BeforeLog+++
log(Message);
}

***BeforeLog***
***
Message ^= " It's me!";
***

Log:
Hello World! It’s me!

So what’s happening there and what do all the plusses and stars mean?

You can declare Labels between your usual statements by writing: +++LabelName+++
TGYoshi describes these declarations as “hooks” which fits pretty well.

Only declaring a label doesn’t do anything unless you actually implement it.

That’s done by writing:

***LabelName***
***
// Your code
***

So you start the implementation block by surrounding the label’s name with 3 *. Directly following is the actual implementation (code) which is surrounded by 3 * as well.

Now whenever a label-“hook” is found inside your coding the implementation of the label will be executed.
Imagine it just as if the code of the implementation is copy-pasted to the location of the declaration (hook).

In the code example the label “+++BeforeLog+++” manipulates the “Message” logged by the function “LogSomething()”.

Let me point out some things that are important to know regarding this technique:

  • Labels aren’t functions/callbacks: You can’t directly pass them parameters.
  • Labels Implementations don’t have an own scope:
    => Variables visible where the label is declared are also visible inside the label’s implementation.
    => Variables declared inside the label’s implementation are also visible afterwards outside of the implementation.
  • You can declare the same label multiple times in your script in order to execute it at different locations in your code.
  • If you implement a label that hasn’t been declared your script is still valid but your label implementation won’t be executed.
  • If you implement the same label twice (or more often) all implementations will be executed at every declaration (“hook”).
  • If another script is extending yours it will have access to all the labels declared in your script (#Extend directive).
  • Using “-” instead of “+” for the label declaration (---LabelName---) will reduce the execution of implementations to the most derived one, other implementations will be ignored.
  • (The ManiaScript compiler has an error(?): You will need to add at least one function declaration below your last label implementation, otherwise a syntax error occurs.)

Nadeo is widely using labels for their ShootMania game modes.
The “ModeBase” script (included in the game’s files) declares many different labels which mark specific moments during the execution of game modes.
If you want to build your own game mode you can extend the ModeBase and use these labels in order to execute your own code for example as soon as the script started or when a map has been loaded.

Another example is the “ModeSport” script which is extended by the game modes Elite and Heroes. It’s offering the basic round-based game play used for the modes (among other things). Additionally the ModeSport script itself is extending the ModeBase script so you can find an even deeper chain of extending scripts.

The using of labels and the extending of scripts reduces the amount of code that has to be written and improves the clarity of scripts because the code of the base script can be used for several other scripts. It can be compared to object-oriented class hierarchies.

Please don’t hesitate to comment in case you have any questions regarding Labels.

Regards,
steeffeen

It’s a Shooter!

While being able to move around is a great thing I’m still missing to be able to hit other players in order to get points and feel great!

The first thing I need are actual opponents.
In the pasts some friends of mine always helped me testing by playing my target or the subject of expriments. Even while creating the 1-line script of the previous posts they joined on my ingame server looking for discovering something new. There have been game modes that I created live while 3 of my friends where playing on my server waiting for new stuff. ;)
Shout-out to them. Thanks!

Of course they aren’t always available so I will need other targets. For that purpose bots come in handy.
There are some things you need to know about bots in ShootMania but I will cover that in another post.
For now I will simply add the following line to my script setting the desired number of bots:

Users_SetNbFakeUsers(2, 2);

With that each team has 2 bots that can be shot.
So far they don’t give points and they can’t even get eliminated though!

When a player performs actions like shooting or hitting other players events are risen. These events need to be handled and processed as by default they are ignored.
In the PlayLoop I will loop through these events and perform actions depending on the type of the events.
At this time only OnHit and OnArmorEmpty events are of interest.

An OnHit event means that a player has hit another player, I will give points based on the damage that was done by the hit. Pay attention that armor and damage is based on a ratio of 100. That means that the usual 2 armor/health you have in most game modes are actually 200 armor in the script.
That means I will divide the damage by 100 in order to get the amount of points I will grant for the hit.

Additionally I will “Discard” (ignore/destroy) events which cover self or team hits.
That’s possible by simply comparing the Shooter and the Victim of the events.

OnArmorEmpty events inform you that a player lost all of his armor, most of the times by being hit by another player but also by falling into OffZone.
If I would Discard these events the player couldn’t die.

Any valid event will be accepted by calling PassOn() with it as parameter. This will make the server process the event so that different actions will be executed. The Shooter will see +1 for each Damage dealt, the victim losing all of his armor will be eliminated and the event feed on the left hand side of the screen will get updated covering the activities that took place.

For managing the points of players I use the script “Score.Script.txt” by Nadeo that gives helpful functions, like summing up points of the current and previous rounds.
The Score object of a player has properties called Points and RoundPoints which are shown separately on the scoreboard. The function AddPoints() of the Score script adds the given amount of points to the RoundPoints.
You need to “inform” this script about the various moments in the game play like starts and ends of rounds because it can’t use the labels like our game mode script does. Currently the end round won’t be called because our round never ends, we will need to add more code in order implement correct rounds later.

What’s worth mentioning is that it’s needed to enable Rounds in the ModeBase in order to use the according labels (StartRound etc).

MB_UseSectionRound = True;

Please see the ModeBase script itself in order to learn more about the structure of it.

I will explain less and less about the script execution in the coming posts as it takes very much time and as it’s kind of boring for more experienced readers. Hopefully you will still be able to follow the development, don’t hesitate to ask if I missed explaining an important fact.

The current version of the script is available here: Defusing2.Script.txt

Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live.

– Martin Golding

See you around!
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

A new World is awaiting us!

Let’s start the ride to our goal of creating a new game mode: Defusing!

As I mentioned I will begin with a clean new file, so I need that.
I simply create an empty text file in the folder Documents/ManiaPlanet/Scripts/Modes/ShootMania/ and will edit it from now on.

Pay attention to the name of the file as it has to end with ".Script.txt" to be considered a valid script file by the ManiaPlanet game.
I simply name my file "Defusing.Script.txt" as the game mode will be called “Defusing”.

The only thing I need to do in order to get an actually running script is adding 1 line of code:

#Extends "Modes/ShootMania/ModeBase.Script.txt"

This line says that I will use another script as base and my own script is only extending the other script.
The ModeBase.Script.txt is a script file that provided by Nadeo and is therefore included in the game itself.
Its structure is handy in order to create a clear and clean game mode script. You will see later why that is.

Now I can already run the script in the game!
SM Storm -> Multiplayer -> Create -> Choose the correct file via the “Script” field -> Hit “Launch” -> Choose any map of your choice -> Click on “Play”

There we are! Our Defusing-Script is running in the game and we just discover a new world (map).
Of course nothing happens so far as the ModeBase we’re extending is only a wrapper and doesn’t actually do anything actively within the match.
The result looks like that.

And the script like that: Defusing0.Script.txt

My next aim will be to let players be spawned in a team-based matter.

If you give someone a program, you will frustrate them for a day; if you teach them how to program, you will frustrate them for a lifetime.

– David Leinweber

So see you next time!
steeffeen

Defusing Incoming!

I would like to start a blog series showing you how I usually create a ShootMania game mode using ManiaScript.

Before I started playing ShootMania there were other games which I’ve enjoyed like Age of Empires, Need for Speed or Grand Theft Auto. And probably the first First-Person-Shooter for me was Counter-Strike Source from which I would like to transfer the well known Game Mode “Bomb Defuse” to ShootMania.
In fact there’s already a game mode called “Sabotage” which basically covers what I will try to implement.

So why create another version of the game mode?
The author of Sabotage unfortunately doesn’t play ShootMania anymore and so the game mode script became old and doesn’t use all the beauty that’s possible in the meantime.
I think playing an updated and improved version of the game mode would be way more fun.

Why start all over again instead of simply improving the old script?
Well, the biggest reason: I like to do things on my own. Okay, I LOVE to do that.
Other than that the old script would have to be changed very much because of the differences in developing possibilities between when the script has been written (July 2012) and now.
That’s why I will start the Game Mode with a clean empty file.

You can’t trust code that you did not totally create yourself.

– Ken Thompson

So stay tuned for an exciting adventure of scripting and testing from 0 characters to probably more than 1000 lines of codes.
FYI: The current version of my SpeedBall Game Mode has 2284 lines. ;)

Cheerio,
steeffeen

It’s me!

Hello Folks!

Let’s start with an outlook for what you will see on this blog.

I’m always trying to help people wherever I can, so I thought about creating a little project where I share my knowledge so that others can benefit from what I’ve encountered and learned during all the projects I’ve worked on.

The result will hopefully be a page loaded up with finest programming tips and useful information on stuff regarding the ManiaPlanet games, Development, Web Hosting and Life.

Feel free to let me know if you would like to hear something about a specific topic.

I would like to finish this first post with an introduction of myself.
The name steeffeen is based on my real first name ‘Steffen’. Living in Germany and being 21 years old I’ve developed quite some stuff already.
With Pascal, PHP, Java, JavaScript, Objective-C and ManiaScript some serious and some less serious projects emerged, like iPhone and iPad Apps or Games that keep you distracted from the lectures you should be listening.

Even though I might not be the experienced developer I hope that my posts will help at least a few of you. ;)

Cheerio,
steeffeen