Tag Archives: maniascript

Did you know API-Arrays?

One strange thing about ManiaScript is that built-in API objects and arrays sometimes behave differently than the ones created by users.

Here’s one such behavior about arrays:
They have two types of keys.

Let me explain that with an example: The Players arrays in CSmMode. (It applies to TM as well.)
This arrays holds several player objects which (like all ManiaScript objects) have their own Ids.

In order to take a specific player object out of the array you can use the player’s Id to reference it.
Additionally you can take the Index of the object in the array.

declare Ident SomeId;
declare PlayerById <=> Players[SomeId];

declare Integer SomeIndex;
declare PlayerByIndex <=> Players[SomeIndex];

This can be really helpful. For example the Scores array gets sorted by points so you can access the best score via:

declare BestScore <=> Scores[0];

(Because the object with the index 0 has the most points.)

There’s one thing that you have to keep in mind though.
When using the Id to access an element of such an array which has an Integer key by default: It just searches for the object from beginning to the end, it’s not as performant as an actual key (with a lookup-table).

Unfortunately this is an API only feature. Your own arrays don’t support these two key-types.
You can only access their elements with a key of the type which you’ve set when declaring the array.

Greetings,
steeffeen

***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

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