kapsubm wrote:seems not, i dont understand why nadeo just doesnt want to post examples, or really, just push out platform, stunt.
they do have it allready, just deleted it out of the game before releasing it. - the scripts should not be much different from the original tmnf .
You have some !...
Available examples : all those of title Storm in UserData/Scripts/ of the dedicated, and the few existing modes made by players. Only ones that we have not are Elite, Joust and Heroes ones (would probably be the more interesting ones for advanced work as they are the more complex, but protected mostly to avoid fake or modified ones in competitions in seems).
Basic maniascript syntax :
http://forum.maniaplanet.com/viewtopic.php?f=279&t=1672
http://forum.maniaplanet.com/viewtopic. ... 982#p91487
http://konte.org/trackmania/maniascript ... ml#General
http://destroflyer.mania-community.de/m ... t/page.php (german)
Several things are still missing, but most can be understood by studying examples... see also below for some replies about some of them (can't just give links as not in public part)
Classes description :
http://forum.maniaplanet.com/viewtopic. ... 05#p105879
http://mlepp.com/sm/maniascript/html/big_8h_source.html
note that because of #RequireContext CSmMode at script beginning, most variables which seems gloable are in fact CSmMode members, that are listed in big.h
About directive: declare xxx for yyy
about: declare xxx for yyy
Few general API infos
Most scripts will begin with '#RequireContext CSmMode' (or '#RequireContext CSmMode'), which basically means that all its members and methods can be used directly (like if they were globals variables or functions). You can see its contents in
CSmMode and
http://slig.info/ms/docs/2012-07-25/htm ... ource.html
So, to access map, maps, players, UI managment, etc. you have Map, MapList array, Players array, UIManager, etc.
To make changes on players UI you have essentially 2 ways : UIManager.UIAll to make the same change on all players UI, or UIManager.GetUI(player) to make a change on a specific player ; both return a
CUIConfig which allow various UI changes.
Look a little the main classes description, then look at the existing nadeo and custom gametypes, if you already have minimum programmation knowledge then you should be able to understand many parts. After it's up to you to look more both examples and classes, and make tests (start by modifying some existing script). You will probably still have problems to understand few parts, but you won't be the only one...
How to view script, edit it, test it ?
To test, create a server with your game, select the wanted script, a map, and start it : you can use F12 to see, edit, and test the script, ctrl+g to see the console (any 'log("xxx");' goes to the console).
Note that
any error will stop the script ! Use ctrl+g (2 times) to see where is was stopped and the error message.
About built-in editor and debug
Gugli wrote:The Script editor is not exactly the same depending on the context. Some entry points are different when you're editing a plugin script, a game mode script or a maptype script.
When in the editor :
- you can use the plugin menu to edit or create a plugin script.
- you can press F12 to edit the maptype script
When you create a multiplayer server :
- you can press F12 to edit the game mode.
So, the simplest way to begin, is to create a private Melee server for example. Then press F12, then save the script as "MyNewMode.Script.txt" or something approaching. And start reading /editing.
Next time you want to edit again your script, start a game with MyNewMode instead of Melee.
Examples :
You can start with the built-in examples ( Documents/Scripts/Modes/ShootMania/ ; some of them are not visible in the game but are in the dedicated files, in UserData/Scripts/Modes/ShootMania/ ; you can't see the scripts of gamemodes inculded in a title pack, like Elite, Heroes or Joust)
You can also look at custom scripts :
http://forum.maniaplanet.com/viewtopic. ... 36&t=11556 and
http://forum.maniaplanet.com/viewtopic. ... 36&t=12558
More advanced things ...
Communication between server maniascript and client/manialink maniascript
Eole wrote:There's a way for Manialink to communicate with the CSmMode. If you take a look at the Elite mode script, you can see it in the Warmup Manialink.
When you declare a variable like that in the manialink script:
Code: Select all
declare netwrite MyVariable for UI = 0;
MyVariable = 10;
Then this variable is accessible in the UI that contains this Manialink.
Code: Select all
// If the Manialink is in a player UI
declare UI <=> UIManager.GetUI(PlayerWithManialink);
if (UI != Null) {
declare netread MyVariable for UI = 0;
// Now MyVariable = 10;
}
OR
// If the Manialink is in the global UI
declare netread MyVariable for UIManager.UIAll = 0;
// Now MyVariable = 10;
But be aware that there's a delay between a change of value in the manialink and the change of this value in the mode script. The netread and netwrite keywords are there to speed up this process a little. But I think Gugli should be able to explain that way better than me.
Gugli wrote:Eole is perfectly right. The examples he gave are clear so I don't feel the need to continue. But don't hesitate to ask if you require more info on netread/netwrite.
Why there is such a difference :
In editor : the MapType script and the Manialink are run on the same computer. You can directly access the Manialink object. There is always one MapType for one Manialink.
In game : the Mode script is executed on the server, and the Manialink scripts are executed on the clients. And there's one server for many clients. That's why it's a bit more difficult to communicate. We have tried to make network communication as easy as possible for scripters, but it is still a bit more difficult than local variable access.
Text Compose : use game built-in word translations
Gugli wrote:Concerning the Text "Compose" function, it's a feature, allowing client-side translations :
When the server Mode script do something such as :
Code: Select all
UIManager.UIAll.BigMessage = "Hello !";
Basically, the text "Hello !" will be sent to every player. The client can then translate it. to "Salut !" for exemple.
When you use
Code: Select all
UIManager.UIAll.BigMessage = "Hello "^Player.Login^"!";
the text "Hello Gugli!" will be sent to every player : this text is unknown, and can not be translated T_T
To allow text translation, you can use compose :
Code: Select all
UIManager.UIAll.BigMessage = TextLib::Compose("Hello $<%1$>!", Player.Login);
The text "_Hello $<%1$> !_World" will be sent ( _ is in fact a weird unicode character ). The client will attempt to translate "Hello $<%1$> !", it will find "Salut $<%1$> !", and then replace the "%1". The client will then show : "Salut Gugli !".
Labels ( +++xxx+++ , ---xxx--- , ***xxx*** )
Gugli wrote:I call those "labels", and they are related to the #Extends directive.
In a script, you can add some labels, they indicate specific locations in your code, like "+++RoundBegin+++".
This way, if another person wants to add some features to your script, she/he will be only have to use #Extends "Name\Of\Your\Script", and add her/his code with the syntax :
Code: Select all
#Extends "Name\Of\Your\Script"
***RoundBegin***
***
// Some code I'd like to see executed when a new round begins
...
***
As you've seen, there are two syntaxes to create a label : +++Label+++ and ---Label---
The +++ one indicates that the label must be replaced by the sum of every code section with matching name.
The --- one in indicates that the label must be replaced only by the most derived matching section.
Examples :
Code: Select all
// File1
+++LabelPlus+++
---LabelMinus---
Code: Select all
// File2
#Extends "File1"
***LabelPlus***
***
ContentsPlus1
***
***LabelMinus***
***
ContentsMinus1
***
Code: Select all
// File3
#Extends "File2"
***LabelPlus***
***
ContentsPlus2
***
***LabelMinus***
***
ContentsMinus2
***
File3 will be an equivalent of :
Code: Select all
// File1
ContentsPlus1
ContentsPlus2
ContentsMinus2
So mostly, you can use the +++ labels, when you declare a special moment in your script, every derived script will add its own actions there.
And you can use --- when you declare a specific test or action like "TestCapture" : any script can override this test, but it would be pointless to make the test twice or more, since only one result is used, the most derived one.
Gugli wrote:The short answer is no. If you do not plan to extend a script, labels are useless.
But if you have to choose, it's better to write
than to write
You never know... someone may want to extends your script ^_^
Another detail, if you have more that one ***BeginRound*** in the same file, they will either be concatenated (for +++ labels) or the last one will prevail (for --- labels).
MathLib and TextLib functions (from a drmaxkurt post) :
Code: Select all
#Include "MathLib" as MathLib
MathLib::AbsInteger();
MathLib::AbsReal();
MathLib::ToReal();
MathLib::Sin();
MathLib::Cos();
MathLib::Tan();
MathLib::Atan2();
MathLib::Exp();
MathLib::RandReal();
MathLib::RandInteger();
MathLib::NearestReal();
MathLib::NearestInteger();
MathLib::FloorInteger();
MathLib::CeilingInteger();
MathLib::DistanceVec3(); => MathLib::Distance()
MathLib::AngleVec3();
#Include "TextLib" as TextLib
TextLib::ToReal();
TextLib::ToInteger();
TextLib::Substring();
TextLib::SubText();
TextLib::Length();
TextLib::ToText();
TextLib::TimeToText();
TextLib::Compose();
TextLib::MLEncode();
About UI optimisation
Gugli wrote:Slig wrote:I wonder how the underlying system is optimized against what does maniascripts about UIAll and players UI changes...
When the changed values are taken into account ? at next yield/wait/sleep ? or immediatly ?
for example, if i do such silly thing :
Code: Select all
foreach(Player in Players) {
declare UI <=> UIManager.GetUI(Player);
if (UI==Null) continue;
// previous UI.BigMessage is "john"
UI.BigMessage = "john"; // (1)
UI.BigMessage = ""; // (2)
UI.BigMessage = "james"; // (3)
UI.BigMessage = "john"; // (4)
}
The UI changes are sent only every 500ms and if there is an actual change.
So in your 1st example : if the 500ms tick occurs between (2) an (3), the empty string "" will be sent, resulting in some time (500ms + ping variation) without message on the client.
The problem with the layers is not the network (the same 500ms check exists), but the time spent by the server to generate the contents of the layers. String handling and such likes can be long, so it is better to avoid doing that every 10ms. Especially when you know they won't be sent before 500ms.
The same goes for unnecessary UILayers.reset() and UILayers.add(). It does not cost much, but it can become a problem if there are many players.
Also, when you want to have very dynamic pages on the client, it is better to use a Manialink <script> markup.[/quote]
SEND EVENTS (with values) between server maniascript and xmlrpc server script
(thanks to that
post from w1lla)
xmlrpc script -> maniascript
use method TriggerModeScriptEvent(string, string) , then in maniascript check events in XmlRpc.PendingEvents
maniascript -> xmlrpc script
use XmlRpc.SendCallback(Text Param1,Text Param2) , then in xmlrpc script check the callback ManiaPlanet.ModeScriptCallback