├── evidence-version.txt
├── .editorconfig
├── blacklist.xml
├── Media
├── Manialinks
│ ├── pursuitpro-advert.xml
│ └── PursuitUIExtension.xml
├── Characters
│ ├── Pursuit.xml
│ ├── Overrunning.xml
│ └── GalaxyDefault.xml
└── Settings
│ ├── Pursuit.xml
│ └── Galaxy.xml
├── update-feed.xml
├── README.md
└── Scripts
├── Libs
└── domino54
│ ├── WebLayers.Script.txt
│ ├── PlayerList.Script.txt
│ ├── Bindings.Script.txt
│ ├── XMLGenerator.Script.txt
│ ├── CustomNames.Script.txt
│ ├── SplitScreenLib.Script.txt
│ ├── TrackMania
│ ├── CylinderHitbox.Script.txt
│ └── Checkpoints.Script.txt
│ ├── Blacklist.Script.txt
│ ├── Openplanet.Script.txt
│ ├── MarkersPro.Script.txt
│ ├── EditAnchors.Script.txt
│ ├── ServerAuth.Script.txt
│ └── LeaderDisplay.Script.txt
├── ManiaApps
└── GalaxyTitles
│ └── MenuController.Script.txt
├── MapTypes
├── ShootMania
│ ├── GiantHuntArena.Script.txt
│ ├── PayloadRaceArena.Script.txt
│ ├── TeamMeleeArena.Script.txt
│ ├── SpeedBallV2Arena.Script.txt
│ ├── HordeArena.Script.txt
│ ├── JailbreakV2Arena.Script.txt
│ ├── PayloadArena.Script.txt
│ ├── GoldenDunkV2Arena.Script.txt
│ └── HungerGamesV2Arena.Script.txt
└── TrackMania
│ ├── PursuitArena.Script.txt
│ └── GoalHuntArena.Script.txt
├── Modes
└── ShootMania
│ ├── InvasionSolo.Script.txt
│ └── CustomWeapons+.Script.txt
└── EditorPlugins
└── AutoGhostBlocks.Script.txt
/evidence-version.txt:
--------------------------------------------------------------------------------
1 | 2016-10-17
2 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | indent_style = tab
2 | indent_size = 4
3 |
--------------------------------------------------------------------------------
/blacklist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/Media/Manialinks/pursuitpro-advert.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/update-feed.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Media/Characters/Pursuit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Canyon Car
5 | Vehicle available by default in TrackMania² Canyon.
6 | file://Media/Manialinks/TrackMania/Pursuit/Characters/CanyonCar.png
7 | F00
8 | true
9 |
10 |
11 | Stadium Car
12 | Vehicle available by default in TrackMania² Stadium.
13 | file://Media/Manialinks/TrackMania/Pursuit/Characters/StadiumCar.png
14 | 0F7
15 |
16 |
17 | Valley Car
18 | Vehicle available by default in TrackMania² Valley.
19 | file://Media/Manialinks/TrackMania/Pursuit/Characters/ValleyCar.png
20 | 7F0
21 | true
22 |
23 |
24 | Lagoon Car
25 | Vehicle available by default in TrackMania² Lagoon.
26 | file://Media/Manialinks/TrackMania/Pursuit/Characters/LagoonCar.png
27 | 07F
28 | true
29 | 15
30 | modulepurchase
31 |
32 |
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dommy's ManiaPlanet scripts
2 | [](http://www.gnu.org/licenses/gpl-3.0)  
3 |
4 | All ManiaScript libraries written by Dommy for ManiaPlanet gaming system. Files include sources of ShootMania Galaxy pack game modes and libraries used by TrackMania² Pursuit game mode. Feel free to use them for your projects, but remember to credit me in your final work. If you got any ideas or suggestions for my work, or you want to contribute to the translations collection, don't be afraid to open an issue or do a pull request! ❤️️
5 |
6 | ⚠️ **Note:** TrackMania² Pursuit game mode is closed source. Don't bother asking for its source, unless you plan a large, one-time event that would run on this mode.
7 |
8 | ## Documentation
9 |
10 | A full documentation of my work is under (long) construction. 👷 As soon something is finished, it will be linked here...
11 |
12 | ## Useful links
13 |
14 | * [ManiaPlanet - platform for TrackMania² and ShootMania games by Nadeo](http://maniaplanet.com/)
15 | * [My Facebook blog](https://facebook.com/dominotitles)
16 | * [My YouTube channel](https://youtube.com/dommy54x)
17 | * [Discord server for ShootMania Galaxy & TrackMania² Pursuit](https://discord.gg/BBHC3sT)
18 |
--------------------------------------------------------------------------------
/Media/Characters/Overrunning.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | Canyon Car
15 | Vehicle available by default in TrackMania² Canyon.
16 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/CanyonCar.png
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Stadium Car
27 | Vehicle available by default in TrackMania² Stadium.
28 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/StadiumCar.png
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | Valley Car
39 | Vehicle available by default in TrackMania² Valley.
40 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/ValleyCar.png
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Lagoon Car
51 | Vehicle available by default in TrackMania² Lagoon.
52 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/LagoonCar.png
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/WebLayers.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY WEB LAYERS by domino54 //
3 | // script version: 2015-10-31 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * This library allows to display custom manialink layers from
8 | * URLs or manialink codes, just by putting them in hidden script
9 | * setting, separated with spaces. Useful for displaying custom
10 | * server widgets, eg. music plugin, logos, context menus.
11 | */
12 |
13 | #Const Version "2015-10-31"
14 | #Const ScriptName "WebLayers.Script.txt"
15 |
16 | #Include "TextLib" as TL
17 | #Include "Libs/Nadeo/Layers2.Script.txt" as Layers
18 |
19 | // ---------------------------------- //
20 | // Global variables
21 | // ---------------------------------- //
22 | declare Text[] G_LayersAddress; ///< Loaded layers address
23 | declare Text G_PrevSettingValue; ///< Previous setting value
24 |
25 | // ---------------------------------- //
26 | // Functions
27 | // ---------------------------------- //
28 |
29 | // ---------------------------------- //
30 | // Public
31 | // ---------------------------------- //
32 |
33 | // ---------------------------------- //
34 | /** Return the version number of the script
35 | *
36 | * @return The version number of the script
37 | */
38 | Text GetScriptVersion() {
39 | return Version;
40 | }
41 |
42 | // ---------------------------------- //
43 | /** Return the name of the script
44 | *
45 | * @return The name of the script
46 | */
47 | Text GetScriptName() {
48 | return ScriptName;
49 | }
50 |
51 | // ---------------------------------- //
52 | /** Update the custom interface layers
53 | *
54 | * /!\ Put this function inside ***Yield*** label, using script setting as the parameter /!\
55 | *
56 | * @param _LayersURLs Setting containing custom layers addresses
57 | */
58 | Void Update(Text _LayersURLs) {
59 | if (_LayersURLs == G_PrevSettingValue) return;
60 | G_PrevSettingValue = _LayersURLs;
61 |
62 | // Get new layers URLs
63 | declare NewLayers = TL::Split(" ", _LayersURLs);
64 |
65 | // ---------------------------------- //
66 | // Create new layers
67 | foreach (Layer in NewLayers) if (!G_LayersAddress.exists(Layer)) {
68 | G_LayersAddress.add(Layer);
69 | Layers::Create("WebLayers:"^Layer, Layer);
70 | Layers::Attach("WebLayers:"^Layer);
71 | }
72 |
73 | // ---------------------------------- //
74 | // Destroy old layers
75 | declare LayersToRemove = Text[];
76 | foreach (Layer in G_LayersAddress) if (!NewLayers.exists(Layer)) {
77 | LayersToRemove.add(Layer);
78 | Layers::Detach("WebLayers:"^Layer);
79 | Layers::Destroy("WebLayers:"^Layer);
80 | }
81 | foreach (Layer in LayersToRemove) {
82 | declare Removed = G_LayersAddress.remove(Layer);
83 | }
84 | }
--------------------------------------------------------------------------------
/Scripts/ManiaApps/GalaxyTitles/MenuController.Script.txt:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------- //
2 | // SHOOTMANIA GALAXY MENU CONTROLLER by domino54 //
3 | // script version: 2017-07-11 //
4 | // ----------------------------------------------- //
5 |
6 | #RequireContext CManiaAppTitle
7 |
8 | /**
9 | * Exclusive for GalaxyTitles.
10 | *
11 | * The main controller for ShootMania Galaxy title pack menu.
12 | */
13 |
14 | #Const Version "2017-07-11"
15 | #Const ScriptName "ManiaApps/domino54/GalaxyTitles/MenuController.Script.txt"
16 |
17 | #Include "Libs/Nadeo/Env.Script.txt" as Env
18 | #Include "Libs/Nadeo/Log.Script.txt" as Log
19 | #Include "Libs/domino54/ManialinkEffects.Script.txt" as Effects
20 | #Include "Libs/domino54/GalaxyTitles/MenuTabsMgr.Script.txt" as Tabs
21 |
22 | // ---------------------------------- //
23 | // Constants
24 | // ---------------------------------- //
25 | #Const C_MenuController_ContextDefault 0
26 | #Const C_MenuController_ContextChangelog 1
27 | #Const C_MenuController_ContextLegalInfo 2
28 | #Const C_MenuController_ContextJoinWindow 3
29 | #Const C_MenuController_ContextConfirm 4
30 |
31 | // ---------------------------------- //
32 | // Main
33 | // ---------------------------------- //
34 | main() {
35 | Env::Set(Env::Env_Development());
36 |
37 | // ---------------------------------- //
38 | // Variables
39 | declare ActiveMenuContext = C_MenuController_ContextDefault;
40 |
41 | /// Update
42 | declare PrevMenuContext = -1;
43 |
44 | // ---------------------------------- //
45 | // Log libraries used by the controller
46 | Log::Load();
47 | Log::RegisterScript(ScriptName, Version);
48 | Log::RegisterScript(Log::GetScriptName(), Log::GetScriptVersion());
49 | Log::RegisterScript(Effects::GetScriptName(), Effects::GetScriptVersion());
50 | Log::RegisterScript(Tabs::GetScriptName(), Tabs::GetScriptVersion());
51 | Log::DisplayScripts();
52 |
53 | // ---------------------------------- //
54 | // Build the menus
55 | Tabs::Load();
56 | Tabs::AddTab("Home");
57 | Tabs::AddTab("Multiplayer");
58 | Tabs::AddTab("Statistics");
59 | Tabs::AddTab("Editors");
60 | Tabs::AddTab("Settings");
61 | Tabs::Build();
62 |
63 | Effects::SetColor(<1., .75, 0.>);
64 |
65 | // ---------------------------------- //
66 | // Yield
67 | // ---------------------------------- //
68 | while (True) {
69 | yield;
70 |
71 | // ---------------------------------- //
72 | // Active context change
73 | if (PrevMenuContext != ActiveMenuContext) {
74 | PrevMenuContext = ActiveMenuContext;
75 |
76 | Tabs::SetVisibility(ActiveMenuContext == C_MenuController_ContextDefault);
77 | }
78 |
79 | // ---------------------------------- //
80 | // User requests leaving the title
81 | if (Tabs::RequestsQuitTitle()) {
82 | Menu_Quit();
83 | break;
84 | }
85 | }
86 | }
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/PlayerList.Script.txt:
--------------------------------------------------------------------------------
1 |
2 | // Experimental library
3 |
4 | #Include "Libs/Nadeo/Layers2.Script.txt" as Layers
5 |
6 | #Const C_LibTeamsInfo_LibUILayerId "LibTeamsInfo:Players"
7 | #Const C_LibTeamsInfo_LayerDefaultPos <40., -5.>
8 | #Const C_LibTeamsInfo_MaxIconsInRow 8
9 | #Const C_LibTeamsInfo_MaxNbColumns 1
10 |
11 | declare Boolean G_LibTeamsInfo_IsLibraryLoaded;
12 |
13 | Text Private_CreateManialinkTeamsInfo() {
14 |
15 | declare Size = <40., 5.>;
16 |
17 | declare PlayersListLeft = "";
18 | declare PlayersListRight = "";
19 |
20 | for (I, 0, C_LibTeamsInfo_MaxIconsInRow * C_LibTeamsInfo_MaxNbColumns - 1) {
21 | declare Y = I % C_LibTeamsInfo_MaxIconsInRow * -Size.Y;
22 | declare X = I / C_LibTeamsInfo_MaxIconsInRow * Size.X;
23 | PlayersListLeft ^= "";
24 | PlayersListRight ^= "";
25 | }
26 |
27 | return """
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 | {{{PlayersListLeft}}}
39 |
40 |
41 |
43 |
44 | """;
45 | }
46 |
47 | Void Show() {
48 | if (!G_LibTeamsInfo_IsLibraryLoaded) return;
49 | Layers::Attach(C_LibTeamsInfo_LibUILayerId);
50 | }
51 |
52 | Void Hide() {
53 | if (!G_LibTeamsInfo_IsLibraryLoaded) return;
54 | Layers::Detach(C_LibTeamsInfo_LibUILayerId);
55 | }
56 |
57 | Void SetVisibility(Boolean _IsVisible) {
58 | if (!G_LibTeamsInfo_IsLibraryLoaded) return;
59 | if (_IsVisible) Show();
60 | else Hide();
61 | }
62 |
63 | Void OpponentsArmorVisibility(Boolean _IsVisible) {
64 | if (!G_LibTeamsInfo_IsLibraryLoaded) return;
65 | declare netwrite Boolean Net_LibTeamsInfo_ShowOpponentsArmor for Teams[0];
66 | Net_LibTeamsInfo_ShowOpponentsArmor = _IsVisible;
67 | }
68 |
69 | Void Unload() {
70 | Hide();
71 | Layers::Destroy(C_LibTeamsInfo_LibUILayerId);
72 | G_LibTeamsInfo_IsLibraryLoaded = False;
73 | }
74 |
75 | Void Load() {
76 | Unload();
77 | G_LibTeamsInfo_IsLibraryLoaded = True;
78 |
79 | Layers::Create(C_LibTeamsInfo_LibUILayerId, Private_CreateManialinkTeamsInfo());
80 | OpponentsArmorVisibility(False);
81 | }
82 |
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/Bindings.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY BINDINGS by domino54 //
3 | // script version: 2017-10-09 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * A simple library used to let users customize
8 | * keyboard inputs of custom game interfaces.
9 | */
10 |
11 | #Const Version "2017-10-09"
12 | #Const ScriptName "Libs/domino54/Bindings.Script.txt"
13 |
14 | // ---------------------------------- //
15 | // Functons
16 | // ---------------------------------- //
17 |
18 | // ---------------------------------- //
19 | // Public
20 | // ---------------------------------- //
21 |
22 | // ---------------------------------- //
23 | /** Return the version number of the script.
24 | *
25 | * @return The version number of the script.
26 | */
27 | Text GetScriptVersion() { return Version; }
28 |
29 | // ---------------------------------- //
30 | /** Return the name of the script.
31 | *
32 | * @return The name of the script.
33 | */
34 | Text GetScriptName() { return ScriptName; }
35 |
36 | // ---------------------------------- //
37 | /** Get the functions of Bindings library.
38 | *
39 | * @return The library functions.
40 | */
41 | Text Functions() {
42 | return """
43 | // ---------------------------------- //
44 | /** Get the currently set key for an input.
45 | *
46 | * @param _BindingId Id of the input to get key.
47 | * @param _DefaultKey Default key of the input.
48 | *
49 | * @return Key used by the input.
50 | */
51 | Text Bindings_GetKey(Text _BindingId, Text _DefaultKey) {
52 | if (LocalUser == Null || _BindingId == "") return _DefaultKey;
53 |
54 | declare persistent Text[Text] Persistent_LibBindings_UserBindings for LocalUser;
55 | if (!Persistent_LibBindings_UserBindings.existskey(_BindingId)) return _DefaultKey;
56 | return Persistent_LibBindings_UserBindings[_BindingId];
57 | }
58 |
59 | // ---------------------------------- //
60 | /** Set a new key for an input.
61 | *
62 | * @param _BindingId Id of the input to set new key.
63 | * @param _NewKeyName Name of the new key to set.
64 | * @param _DefaultKey Default key of the input.
65 | */
66 | Void Bindings_SetKey(Text _BindingId, Text _NewKeyName, Text _DefaultKey) {
67 | if (LocalUser == Null || _BindingId == "") return;
68 |
69 | declare persistent Text[Text] Persistent_LibBindings_UserBindings for LocalUser;
70 | if (_NewKeyName != _DefaultKey) Persistent_LibBindings_UserBindings[_BindingId] = _NewKeyName;
71 | else {
72 | declare Removed = Persistent_LibBindings_UserBindings.removekey(_BindingId);
73 | }
74 | }
75 |
76 | // ---------------------------------- //
77 | /** Return True, when certain input is used.
78 | *
79 | * @param _BindingId Id of the input to listen to.
80 | * @param _DefaultKey Default key of the input.
81 | */
82 | Boolean Bindings_Listener(Text _BindingId, Text _DefaultKey) {
83 | if (LocalUser == Null || IsInGameMenuDisplayed || _BindingId == "" || PendingEvents.count <= 0) return False;
84 |
85 | foreach (Event in PendingEvents) {
86 | if (Event.Type != CMlEvent::Type::KeyPress) continue;
87 | if (Event.KeyName == Bindings_GetKey(_BindingId, _DefaultKey)) return True;
88 | }
89 | return False;
90 | }
91 | """;
92 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/GiantHuntArena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // GIANT HUNT ARENA by domino54 //
3 | // script version: 2017-05-08 //
4 | // -------------------------------------- //
5 |
6 | #RequireContext CSmMapType
7 |
8 | #Const Version "2017-05-08"
9 | #Const MapTypeVersion 1
10 | #Const ScriptName "MapTypes/ShootMania/GiantHuntArena.Script.txt"
11 |
12 | #Include "TextLib" as TL
13 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
14 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
15 | // Custom libraries
16 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
17 |
18 | // ---------------------------------- //
19 | // Constants
20 | // ---------------------------------- //
21 | #Const C_Rules "$<%11.$> Place at least one one SpawnHunters.\n$<%12.$> Place at least one SpawnGiant.\n$<%13.$> Place a bunch of Checkpoints as targets for the Giant. Goals are also accepted."
22 |
23 | // ---------------------------------- //
24 | // Functions
25 | // ---------------------------------- //
26 |
27 | // ---------------------------------- //
28 | /// Initialize the anchors
29 | Void InitAnchors() {
30 | foreach (Anchor in AnchorData) {
31 | if (Anchor.DefaultTag == "Spawn") {
32 | if (Anchor.Tag != "SpawnHunters" && Anchor.Tag != "SpawnGiant") Anchor.Tag = "SpawnHunters";
33 | }
34 | else Anchor.Tag = Anchor.DefaultTag;
35 | Anchor.Order = Anchor.DefaultOrder;
36 | }
37 | }
38 |
39 | // ---------------------------------- //
40 | /// Check if the map is valid
41 | Void UpdateValidability() {
42 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
43 | InitAnchors();
44 | Anchor::UpdateAnchorCounts();
45 |
46 | if (!Anchor::HasAtLeastOneAnchor("SpawnHunters", 0, _("You must place at least one \"SpawnHunters\"!"))) return;
47 | if (!Anchor::HasAtLeastOneAnchor("SpawnGiant", 0, _("You must place at least one \"SpawnGiant\"!"))) return;
48 | if (!Anchor::HasAtLeastOneAnchor("Checkpoint", 0, _("You must place at least one \"Checkpoint\"!"))) return;
49 |
50 | // Map is valid
51 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
52 | }
53 |
54 | // ---------------------------------- //
55 | /// Show the anchor edition manialink
56 | Void EditAnchorData(Ident _EditedAnchorDataId) {
57 | if (_EditedAnchorDataId == NullId) return;
58 | UpdateValidability();
59 | EditAnchors::EditAnchor(_EditedAnchorDataId);
60 | UpdateValidability();
61 | }
62 |
63 | // ---------------------------------- //
64 | // Main
65 | // ---------------------------------- //
66 | main() {
67 | MapType::SetVersion(MapTypeVersion);
68 | UpdateValidability();
69 | CustomEditAnchorData = True;
70 |
71 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
72 | EditAnchors::SetAvailableTags(["Spawn" => ["SpawnHunters", "SpawnGiant"]]);
73 |
74 | // ---------------------------------- //
75 | // Yield
76 | // ---------------------------------- //
77 | while (True) {
78 | yield;
79 |
80 | // ---------------------------------- //
81 | // Events management
82 | foreach (Event in PendingEvents) {
83 | switch (Event.Type) {
84 | case CPluginEvent::Type::MapModified : UpdateValidability();
85 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
86 | }
87 | }
88 | }
89 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/PayloadRaceArena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // PAYLOAD RACE ARENA by domino54 //
3 | // script version: 2017-08-22 //
4 | // -------------------------------------- //
5 |
6 | #RequireContext CSmMapType
7 |
8 | #Const Version "2017-08-22"
9 | #Const MapTypeVersion 1
10 | #Const ScriptName "PayloadRaceArena.Script.txt"
11 |
12 | #Include "TextLib" as TL
13 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
14 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
15 | // Custom libraries
16 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
17 |
18 | // ---------------------------------- //
19 | // Constants
20 | // ---------------------------------- //
21 | #Const C_Rules "$<%11.$> Place exactly one Spawn #1 and one Spawn #2.\n$<%12.$> Place one Goal #1 and one Goal #2.\n$<%13.$> Place exactly one Payload #1 and Payload #2 bot paths, connecting area near Spawn with the Goal. Bot paths have to be the same length."
22 |
23 | // ---------------------------------- //
24 | // Functions
25 | // ---------------------------------- //
26 |
27 | // ---------------------------------- //
28 | /// Initialize the anchors
29 | Void InitAnchors() {
30 | foreach (Anchor in AnchorData) {
31 | if (Anchor.DefaultTag == "Spawn") {
32 | if (Anchor.Tag != "Spawn") Anchor.Tag = Anchor.DefaultTag;
33 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
34 | } else if (Anchor.DefaultTag == "Goal" || Anchor.DefaultTag == "Checkpoint") {
35 | if (Anchor.Tag != "Goal") Anchor.Tag = "Goal";
36 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
37 | } else {
38 | Anchor.Tag = Anchor.DefaultTag;
39 | Anchor.Order = Anchor.DefaultOrder;
40 | }
41 | }
42 | }
43 |
44 | // ---------------------------------- //
45 | /// Check if the map is valid
46 | Void UpdateValidability() {
47 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
48 | InitAnchors();
49 | Anchor::UpdateAnchorCounts();
50 |
51 | // ---------------------------------- //
52 | // Check if map has exactly one landmark type per team
53 | for (I, 1, 2) {
54 | if (
55 | !Anchor::HasExactlyOneAnchor("Spawn", I, TL::Compose(_("You must place exactly one Spawn #%1"), ""^I)) ||
56 | !Anchor::HasExactlyOneAnchor("Goal", I, TL::Compose(_("You must place exactly one Goal #%1"), ""^I))
57 | ) return;
58 | }
59 |
60 | // Map is valid
61 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
62 | }
63 |
64 | // ---------------------------------- //
65 | /// Show the anchor edition manialink
66 | Void EditAnchorData(Ident _EditedAnchorDataId) {
67 | if (_EditedAnchorDataId == NullId) return;
68 | UpdateValidability();
69 | EditAnchors::EditAnchor(_EditedAnchorDataId);
70 | UpdateValidability();
71 | }
72 |
73 | // ---------------------------------- //
74 | // Main
75 | // ---------------------------------- //
76 | main() {
77 | MapType::SetVersion(MapTypeVersion);
78 | UpdateValidability();
79 | CustomEditAnchorData = True;
80 |
81 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
82 | EditAnchors::SetAvailableTags([
83 | "Spawn" => ["Spawn #1", "Spawn #2"],
84 | "Goal" => ["Goal #1", "Goal #2"],
85 | "Checkpoint" => ["Goal #1", "Goal #2"]
86 | ]);
87 |
88 | // ---------------------------------- //
89 | // Yield
90 | // ---------------------------------- //
91 | while (True) {
92 | yield;
93 |
94 | // ---------------------------------- //
95 | // Events management
96 | foreach (Event in PendingEvents) {
97 | switch (Event.Type) {
98 | case CPluginEvent::Type::MapModified : UpdateValidability();
99 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
100 | }
101 | }
102 | }
103 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/TrackMania/PursuitArena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // PURSUIT TM ARENA by domino54 //
3 | // script version: 2018-04-08 //
4 | // -------------------------------------- //
5 |
6 | #RequireContext CTmMapType
7 |
8 | #Const Version "2018-04-08"
9 | #Const MapTypeVersion 1
10 | #Const ScriptName "MapTypes/TrackMania/PursuitArena.Script.txt"
11 |
12 | #Include "MathLib" as ML
13 | #Include "TextLib" as TL
14 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
15 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
16 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
17 | #Include "Libs/domino54/TrackMania/OffZoneEdit.Script.txt" as OffZone
18 |
19 | #Const C_Rules "$<%11.$> Place exactly one StartFinish.\n$<%12.$> Place at least one Checkpoint.\n$<%13.$>Place exactly one Podium."
20 |
21 | // ---------------------------------- //
22 | // Functions
23 | // ---------------------------------- //
24 |
25 | // ---------------------------------- //
26 | /// Initialize the anchors
27 | Void InitAnchors() {
28 | foreach (Anchor in AnchorData) {
29 | Anchor.Order = Anchor.DefaultOrder;
30 | Anchor.Tag = Anchor.DefaultTag;
31 | }
32 | }
33 |
34 | // ---------------------------------- //
35 | /// Check if the map is valid
36 | Void UpdateValidability() {
37 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
38 | InitAnchors();
39 | Anchor::UpdateAnchorCounts();
40 |
41 | // ---------------------------------- //
42 | // Check if the map has spawn and checkpoints
43 | if (!Anchor::HasExactlyOneAnchor("StartFinish", 0, _("You must place exactly one StartFinish."))) return;
44 | if (!Anchor::HasAtLeastOneAnchor("Checkpoint", 0, _("You must place at least one Checkpoint."))) return;
45 |
46 | declare HasPodium = False;
47 | foreach (Block in Blocks) {
48 | if (Block.BlockModel == Null || TL::Find("Podium", Block.BlockModel.Name, False, False)) continue;
49 | HasPodium = True;
50 | }
51 | if (!HasPodium) return;
52 |
53 | // Map is valid
54 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
55 | }
56 |
57 | // ---------------------------------- //
58 | /// Show the anchor edition manialink
59 | Void EditAnchorData(Ident _EditedAnchorDataId) {
60 | if (_EditedAnchorDataId == NullId) return;
61 | UpdateValidability();
62 | EditAnchors::EditAnchor(_EditedAnchorDataId);
63 | UpdateValidability();
64 | }
65 |
66 | // ---------------------------------- //
67 | // Main
68 | // ---------------------------------- //
69 | main() {
70 | MapType::SetVersion(MapTypeVersion);
71 | OffZone::Load();
72 |
73 | UpdateValidability();
74 | CustomEditAnchorData = True;
75 |
76 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
77 | EditAnchors::SetAvailableTags(["Checkpoint" => ["Checkpoint", "Goal"]]);
78 |
79 | // ---------------------------------- //
80 | // Yield
81 | // ---------------------------------- //
82 | while (True) {
83 | yield;
84 |
85 | OffZone::Loop();
86 |
87 | // "Validate" the map
88 | Map.TMObjective_AuthorTime = 1;
89 | Map.TMObjective_GoldTime = 1;
90 | Map.TMObjective_SilverTime = 1;
91 | Map.TMObjective_BronzeTime = 1;
92 | Map.TMObjective_NbLaps = 1;
93 | Map.TMObjective_IsLapRace = False;
94 | Map.ObjectiveTextAuthor = "N/A";
95 | Map.ObjectiveTextGold = "N/A";
96 | Map.ObjectiveTextSilver = "N/A";
97 | Map.ObjectiveTextBronze = "N/A";
98 |
99 | // ---------------------------------- //
100 | // Events management
101 | foreach (Event in PendingEvents) {
102 | switch (Event.Type) {
103 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
104 | case CPluginEvent::Type::StartValidation : { }
105 | }
106 | UpdateValidability();
107 | }
108 | }
109 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/TeamMeleeArena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // TEAM MELEE ARENA by domino54 //
3 | // script version: 2016-07-01 //
4 | // -------------------------------------- //
5 |
6 | #RequireContext CSmMapType
7 |
8 | #Const Version "2016-07-01"
9 | #Const MapTypeVersion 1
10 | #Const ScriptName "TeamMeleeArena.Script.txt"
11 |
12 | #Include "TextLib" as TL
13 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
14 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
15 | // Custom libraries
16 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
17 |
18 | // ---------------------------------- //
19 | // Constants
20 | // ---------------------------------- //
21 | #Const C_Rules "$<%11.$> Place at least one Spawn #1 and one Spawn #2.\n$<%12.$> Number of spawns must remain the same for both sides."
22 |
23 | // ---------------------------------- //
24 | // Functions
25 | // ---------------------------------- //
26 |
27 | // ---------------------------------- //
28 | /// Initialize the anchors
29 | Void InitAnchors() {
30 | foreach (Anchor in AnchorData) {
31 | if (Anchor.DefaultTag == "Spawn") {
32 | if (Anchor.Tag != "Spawn") Anchor.Tag = Anchor.DefaultTag;
33 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
34 | } else {
35 | Anchor.Tag = Anchor.DefaultTag;
36 | Anchor.Order = Anchor.DefaultOrder;
37 | }
38 | }
39 | }
40 |
41 | // ---------------------------------- //
42 | /// Check if the map is valid
43 | Void UpdateValidability() {
44 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
45 | InitAnchors();
46 | Anchor::UpdateAnchorCounts();
47 |
48 | // ---------------------------------- //
49 | // Get the amount of Gates
50 | declare ClansNbSpawns = [1 => 0, 2 => 0];
51 | foreach (Data in AnchorData)
52 | if (Data.Tag == "Spawn" && ClansNbSpawns.existskey(Data.Order)) ClansNbSpawns[Data.Order] += 1;
53 |
54 | // ---------------------------------- //
55 | // Check if map has at least one Spawn per team
56 | for (I, 1, 2) {
57 | if (!Anchor::HasAtLeastOneAnchor("Spawn", I, TL::Compose(_("You must place at least one Spawn #%1"), ""^I))) return;
58 | }
59 |
60 | // ---------------------------------- //
61 | // Gates amount doesn't match
62 | if (ClansNbSpawns[1] != ClansNbSpawns[2]) {
63 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
64 | ValidabilityRequirementsMessage = _("You must place the same number of Spawn #1 and Spawn #2");
65 | return;
66 | }
67 |
68 | // Map is valid
69 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
70 | }
71 |
72 |
73 | // ---------------------------------- //
74 | /// Show the anchor edition manialink
75 | Void EditAnchorData(Ident _EditedAnchorDataId) {
76 | if (_EditedAnchorDataId == NullId) return;
77 | UpdateValidability();
78 | EditAnchors::EditAnchor(_EditedAnchorDataId);
79 | UpdateValidability();
80 | }
81 |
82 | // ---------------------------------- //
83 | // Main
84 | // ---------------------------------- //
85 | main() {
86 | MapType::SetVersion(MapTypeVersion);
87 | UpdateValidability();
88 | CustomEditAnchorData = True;
89 |
90 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
91 | EditAnchors::SetAvailableTags(["Spawn" => ["Spawn #1", "Spawn #2"]]);
92 |
93 | // ---------------------------------- //
94 | // Yield
95 | // ---------------------------------- //
96 | while (True) {
97 | yield;
98 |
99 | // ---------------------------------- //
100 | // Events management
101 | foreach (Event in PendingEvents) {
102 | switch (Event.Type) {
103 | case CPluginEvent::Type::MapModified : UpdateValidability();
104 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
105 | }
106 | }
107 | }
108 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/SpeedBallV2Arena.Script.txt:
--------------------------------------------------------------------------------
1 | // --------------------------------------------- //
2 | // SPEEDBALL V2 ARENA by domino54 //
3 | // script version: 2017-08-22 //
4 | // original concept by Awpteamoose | Steeffeen //
5 | // --------------------------------------------- //
6 |
7 | #RequireContext CSmMapType
8 |
9 | #Const Version "2017-08-22"
10 | #Const MapTypeVersion 1
11 | #Const ScriptName "SpeedBallV2Arena.Script.txt"
12 |
13 | #Include "TextLib" as TL
14 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
15 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
16 | // Custom libraries
17 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
18 |
19 | // ---------------------------------- //
20 | // Constants
21 | // ---------------------------------- //
22 | #Const C_Rules "$<%11.$> Place exactly one Spawn #1 and one Spawn #2.\n$<%12.$> Place one Goal #1 and one Goal #2. Ball will be delivered by player to one of these.\n$<%13.$> Place exactly one Checkpoint, where ball appears when round starts."
23 |
24 | // ---------------------------------- //
25 | // Functions
26 | // ---------------------------------- //
27 |
28 | // ---------------------------------- //
29 | /// Initialize the anchors
30 | Void InitAnchors() {
31 | foreach (Anchor in AnchorData) {
32 | if (Anchor.DefaultTag == "Spawn") {
33 | if (Anchor.Tag != "Spawn") Anchor.Tag = Anchor.DefaultTag;
34 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
35 | } else if (Anchor.DefaultTag == "Goal" || Anchor.DefaultTag == "Checkpoint") {
36 | if (Anchor.Tag != "Goal" && Anchor.Tag != "Checkpoint") Anchor.Tag = Anchor.DefaultTag;
37 | if (Anchor.Tag == "Goal" && Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
38 | if (Anchor.Tag == "Checkpoint" && Anchor.Order != 0) Anchor.Order = 0;
39 | } else {
40 | Anchor.Tag = Anchor.DefaultTag;
41 | Anchor.Order = Anchor.DefaultOrder;
42 | }
43 | }
44 | }
45 |
46 | // ---------------------------------- //
47 | /// Check if the map is valid
48 | Void UpdateValidability() {
49 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
50 | InitAnchors();
51 | Anchor::UpdateAnchorCounts();
52 |
53 | // ---------------------------------- //
54 | // Check if map has exactly one landmark type per team
55 | for (I, 1, 2) {
56 | if (
57 | !Anchor::HasExactlyOneAnchor("Spawn", I, TL::Compose(_("You must place exactly one Spawn #%1"), ""^I)) ||
58 | !Anchor::HasExactlyOneAnchor("Goal", I, TL::Compose(_("You must place exactly one Goal #%1"), ""^I))
59 | ) return;
60 | }
61 | if (!Anchor::HasExactlyOneAnchor("Checkpoint", 0, _("You must place exactly one Checkpoint"))) return;
62 |
63 | // Map is valid
64 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
65 | }
66 |
67 | // ---------------------------------- //
68 | /// Show the anchor edition manialink
69 | Void EditAnchorData(Ident _EditedAnchorDataId) {
70 | if (_EditedAnchorDataId == NullId) return;
71 | UpdateValidability();
72 | EditAnchors::EditAnchor(_EditedAnchorDataId);
73 | UpdateValidability();
74 | }
75 |
76 | // ---------------------------------- //
77 | // Main
78 | // ---------------------------------- //
79 | main() {
80 | MapType::SetVersion(MapTypeVersion);
81 | UpdateValidability();
82 | CustomEditAnchorData = True;
83 |
84 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
85 | EditAnchors::SetAvailableTags([
86 | "Spawn" => ["Spawn #1", "Spawn #2"],
87 | "Goal" => ["Goal #1", "Goal #2", "Checkpoint"],
88 | "Checkpoint" => ["Checkpoint", "Goal #1", "Goal #2"]
89 | ]);
90 |
91 | // ---------------------------------- //
92 | // Yield
93 | // ---------------------------------- //
94 | while (True) {
95 | yield;
96 |
97 | // ---------------------------------- //
98 | // Events management
99 | foreach (Event in PendingEvents) {
100 | switch (Event.Type) {
101 | case CPluginEvent::Type::MapModified : UpdateValidability();
102 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
103 | }
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/XMLGenerator.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // XML DOCUMENT GENERATOR by domino54 //
3 | // script version: 2015-12-12 //
4 | // -------------------------------------- //
5 |
6 | #Const Version "2015-12-12"
7 | #Const ScriptName "XMLGenerator.Script.txt"
8 |
9 | /**
10 | * This library allows to generate simple XML documents
11 | * with custom created nodes.
12 | */
13 |
14 | // ---------------------------------- //
15 | // Constants
16 | // ---------------------------------- //
17 | #Const C_LibXMLGenerator_DefaultRootName "document" ///< Default name of the document root
18 |
19 | // ---------------------------------- //
20 | // Global variables
21 | // ---------------------------------- //
22 | declare Text G_LibXMLGenerator_RootName;
23 | declare Text G_LibXMLGenerator_RootProperties;
24 | declare Text[] G_LibXMLGenerator_CreatedNodes;
25 |
26 | // ---------------------------------- //
27 | // Functions
28 | // ---------------------------------- //
29 |
30 | // ---------------------------------- //
31 | // Public
32 | // ---------------------------------- //
33 |
34 | // ---------------------------------- //
35 | /** Return the version number of the script
36 | *
37 | * @return The version number of the script
38 | */
39 | Text GetScriptVersion() {
40 | return Version;
41 | }
42 |
43 | // ---------------------------------- //
44 | /** Return the name of the script
45 | *
46 | * @return The name of the script
47 | */
48 | Text GetScriptName() {
49 | return ScriptName;
50 | }
51 |
52 | // ---------------------------------- //
53 | /// Reset everything
54 | Void Clear() {
55 | G_LibXMLGenerator_RootName = C_LibXMLGenerator_DefaultRootName;
56 | G_LibXMLGenerator_RootProperties = "";
57 | G_LibXMLGenerator_CreatedNodes.clear();
58 | }
59 |
60 | // ---------------------------------- //
61 | /** Set the root name
62 | *
63 | * @param _RootName The name of the root
64 | */
65 | Void SetRootName(Text _RootName) {
66 | if (_RootName != "") G_LibXMLGenerator_RootName = _RootName;
67 | }
68 |
69 | // ---------------------------------- //
70 | /** Set the root properties
71 | *
72 | * @param _RootProperties The root properties
73 | */
74 | Void SetRootProperties(Text[Text] _RootProperties) {
75 | declare Root = "";
76 |
77 | // Attach root properties
78 | if (_RootProperties.count > 0) foreach (Property => Value in _RootProperties) Root ^= " "^Property^"=\""^Value^"\"";
79 |
80 | // Save properties
81 | G_LibXMLGenerator_RootProperties = Root;
82 | }
83 |
84 | // ---------------------------------- //
85 | /** Create root node
86 | *
87 | * @param _NodeName The name of the node
88 | * @param _NodeProperties The node properties
89 | * @param _NodeRawText The node raw text
90 | */
91 | Void CreateNode(Text _NodeName, Text[Text] _NodeProperties, Text _NodeRawText) {
92 | if (_NodeName == "") return;
93 | declare Node = "<"^_NodeName;
94 | declare NodeIsClosed = (_NodeRawText == "");
95 |
96 | // Attach node properties
97 | if (_NodeProperties.count > 0) foreach (Property => Value in _NodeProperties) Node ^= " "^Property^"=\""^Value^"\"";
98 |
99 | // Close node or insert raw text
100 | if (NodeIsClosed) Node ^= "/>";
101 | else Node ^= ">"^_NodeRawText^""^_NodeName^">";
102 |
103 | // Save node
104 | G_LibXMLGenerator_CreatedNodes.add(Node);
105 | }
106 |
107 | // ---------------------------------- //
108 | /** Create the XML document file
109 | *
110 | * @return Complete document
111 | */
112 | Text CreateDocument() {
113 | // XML file declaration
114 | declare Document = "\n";
115 |
116 | // Get the root name
117 | declare RootName = G_LibXMLGenerator_RootName;
118 | if (G_LibXMLGenerator_RootName == "") RootName = C_LibXMLGenerator_DefaultRootName;
119 | Document ^= "<"^RootName^">\n";
120 |
121 | // Insert nodes
122 | if (G_LibXMLGenerator_CreatedNodes.count > 0) {
123 | foreach (Node in G_LibXMLGenerator_CreatedNodes) Document ^= " "^Node^"\n";
124 | }
125 |
126 | // Close document
127 | Document ^= ""^RootName^">";
128 | return Document;
129 | }
--------------------------------------------------------------------------------
/Media/Settings/Pursuit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/HordeArena.Script.txt:
--------------------------------------------------------------------------------
1 | #RequireContext CSmMapType
2 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
3 | #Include "TextLib" as TextLib
4 |
5 | /////////////////////////////////////
6 | // CheckValidationStatus
7 |
8 | Void CheckValidationStatus()
9 | {
10 | ValidationStatus = CMapType::ValidationStatus::NotValidable;
11 | Anchor::UpdateAnchorCounts();
12 | if( !Anchor::HasAtLeastOneAnchor("Goal", 0, _("You must place a Goal")) ) return;
13 | if( !Anchor::HasExactlyOneAnchor("Spawn", 0, _("You must place one Spawn")) ) return;
14 | //if( !Anchor::HasAtLeastOneAnchor("BotSpawn", 2, _("You must place a BotSpawn")) ) return;
15 | ValidationStatus = CMapType::ValidationStatus::Validated;
16 | }
17 |
18 |
19 | /////////////////////////////////////
20 | // EditObjectives
21 |
22 | Void EditObjectives()
23 | {
24 | declare metadata Integer ObjectiveAuthor for Map;
25 | declare metadata Integer ObjectiveGold for Map;
26 | declare metadata Integer ObjectiveSilver for Map;
27 | declare metadata Integer ObjectiveBronze for Map;
28 |
29 | while(True)
30 | {
31 | ManialinkText =
32 | """
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
68 | """;
69 |
70 | declare ButtonClicked for ManialinkPage = "" ;
71 | ButtonClicked = "";
72 | wait(ButtonClicked == "ButtonOk"
73 | || ButtonClicked == "ButtonCancel");
74 |
75 | if (ButtonClicked == "ButtonCancel")
76 | {
77 | break;
78 | }
79 |
80 | if (ButtonClicked == "ButtonOk")
81 | {
82 | declare Page <=> ManialinkPage;
83 | declare EntryAuthorValue <=> (Page.GetFirstChild("AuthorValue") as CMlEntry);
84 | declare EntryGoldValue <=> (Page.GetFirstChild("GoldValue") as CMlEntry);
85 | declare EntrySilverValue <=> (Page.GetFirstChild("SilverValue") as CMlEntry);
86 | declare EntryBronzeValue <=> (Page.GetFirstChild("BronzeValue") as CMlEntry);
87 |
88 | declare NewAuthor = TextLib::ToInteger(EntryAuthorValue.Value);
89 | declare NewGold = TextLib::ToInteger(EntryGoldValue.Value);
90 | declare NewSilver = TextLib::ToInteger(EntrySilverValue.Value);
91 | declare NewBronze = TextLib::ToInteger(EntryBronzeValue.Value);
92 |
93 | if (NewBronze <= NewSilver &&
94 | NewSilver <= NewGold &&
95 | NewGold <= NewAuthor)
96 | {
97 | ObjectiveAuthor = NewAuthor;
98 | ObjectiveGold = NewGold;
99 | ObjectiveSilver = NewSilver;
100 | ObjectiveBronze = NewBronze;
101 |
102 | Map.ObjectiveTextAuthor = TextLib::TimeToText(ObjectiveAuthor);
103 | Map.ObjectiveTextGold = TextLib::TimeToText(ObjectiveGold);
104 | Map.ObjectiveTextSilver = TextLib::TimeToText(ObjectiveSilver);
105 | Map.ObjectiveTextBronze = TextLib::TimeToText(ObjectiveBronze);
106 | break;
107 | }
108 | else
109 | {
110 | log("invalid values."); // TODO un e bote de dialogue
111 | }
112 | }
113 | }
114 |
115 | ManialinkText = "";
116 | }
117 |
118 |
119 | /////////////////////////////////////
120 | // Main
121 |
122 | main()
123 | {
124 | CheckValidationStatus();
125 |
126 | while (True)
127 | {
128 | yield;
129 | ManialinkText = "";
130 |
131 | foreach (Event in PendingEvents)
132 | {
133 | if (Event.Type == CPluginEvent::Type::MapModified)
134 | {
135 | CheckValidationStatus();
136 | }
137 | else if(Event.Type == CPluginEvent::Type::EditObjectives)
138 | {
139 | EditObjectives();
140 | }
141 | else if(Event.Type == CPluginEvent::Type::StartValidation)
142 | {
143 | StartTestMapWithMode("Horde.Script.txt");
144 | wait(!IsSwitchedToPlayground);
145 | }
146 | }
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/Scripts/MapTypes/TrackMania/GoalHuntArena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // GOAL HUNT TM ARENA by domino54 //
3 | // script version: 2018-04-08 //
4 | // -------------------------------------- //
5 |
6 | #RequireContext CTmMapType
7 |
8 | #Const Version "2018-04-08"
9 | #Const MapTypeVersion 1
10 | #Const ScriptName "MapTypes/TrackMania/GoalHuntArena.Script.txt"
11 |
12 | #Include "MathLib" as ML
13 | #Include "TextLib" as TL
14 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
15 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
16 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
17 | #Include "Libs/domino54/TrackMania/CheckpointsEdit.Script.txt" as Checkpoints
18 | #Include "Libs/domino54/TrackMania/OffZoneEdit.Script.txt" as OffZone
19 |
20 | #Const C_Rules "$<%11.$> Place exactly one StartFinish.\n$<%12.$> Place at least 5 Checkpoints.\n$<%13.$>Place exactly one Podium."
21 |
22 | // ---------------------------------- //
23 | // Functions
24 | // ---------------------------------- //
25 |
26 | // ---------------------------------- //
27 | /// Update the checkpoints list.
28 | Void UpdateNbCheckpoints() {
29 | declare NbCheckpointsRequired = 5;
30 | declare NbCheckpointsTotal = 0;
31 | declare NbCheckpointsSupported = Checkpoints::NbCheckpointsSaved();
32 | declare CheckpointsUnsupported = Text[];
33 |
34 | foreach (Anchor in AnchorData) {
35 | if (Anchor.DefaultTag != "Checkpoint") continue;
36 |
37 | NbCheckpointsTotal += 1;
38 |
39 | if (Anchor.Block != Null && Anchor.Block.BlockModel != Null && Checkpoints::IsSupported(Anchor.Block.BlockModel)) continue;
40 |
41 | if (Anchor.Block == Null || Anchor.Block.BlockModel == Null) CheckpointsUnsupported.add("Item");
42 | else CheckpointsUnsupported.add(Anchor.Block.BlockModel.Name);
43 | }
44 |
45 | // I agree, this is ugly
46 | ManialinkText = """
47 |
48 |
49 |
51 |
52 | """;
53 | }
54 |
55 | // ---------------------------------- //
56 | /// Initialize the anchors
57 | Void InitAnchors() {
58 | foreach (Anchor in AnchorData) {
59 | Anchor.Order = Anchor.DefaultOrder;
60 | Anchor.Tag = Anchor.DefaultTag;
61 | }
62 | }
63 |
64 | // ---------------------------------- //
65 | /// Check if the map is valid
66 | Void UpdateValidability() {
67 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
68 | InitAnchors();
69 | Anchor::UpdateAnchorCounts();
70 |
71 | // Check if the map has a multilap spawn.
72 | if (!Anchor::HasExactlyOneAnchor("StartFinish", 0, _("You must place exactly one StartFinish."))) return;
73 |
74 | // Check if the map has enough checkpoints.
75 | if (Checkpoints::NbCheckpointsSaved() < 5) {
76 | ValidationStatus = CMapType::ValidationStatus::NotValidable;
77 | ValidabilityRequirementsMessage = _("You must place at least 5 supported Checkpoints.");
78 | return;
79 | }
80 |
81 | declare HasPodium = False;
82 | foreach (Block in Blocks) {
83 | if (Block.BlockModel == Null || TL::Find("Podium", Block.BlockModel.Name, False, False)) continue;
84 | HasPodium = True;
85 | }
86 | if (!HasPodium) return;
87 |
88 | // Map is valid
89 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
90 | }
91 |
92 | // ---------------------------------- //
93 | /// Show the anchor edition manialink
94 | Void EditAnchorData(Ident _EditedAnchorDataId) {
95 | if (_EditedAnchorDataId == NullId) return;
96 | UpdateValidability();
97 | EditAnchors::EditAnchor(_EditedAnchorDataId);
98 | UpdateValidability();
99 | }
100 |
101 | // ---------------------------------- //
102 | // Main
103 | // ---------------------------------- //
104 | main() {
105 | MapType::SetVersion(MapTypeVersion);
106 | Checkpoints::SaveCheckpointsData();
107 | OffZone::Load();
108 |
109 | UpdateNbCheckpoints();
110 |
111 | CustomEditAnchorData = True;
112 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
113 | EditAnchors::SetAvailableTags(["Checkpoint" => ["Checkpoint"]]);
114 |
115 | UpdateValidability();
116 |
117 | // ---------------------------------- //
118 | // Yield
119 | // ---------------------------------- //
120 | while (True) {
121 | yield;
122 |
123 | OffZone::Loop();
124 |
125 | // "Validate" the map
126 | Map.TMObjective_AuthorTime = 1;
127 | Map.TMObjective_GoldTime = 1;
128 | Map.TMObjective_SilverTime = 1;
129 | Map.TMObjective_BronzeTime = 1;
130 | Map.TMObjective_NbLaps = 1;
131 | Map.TMObjective_IsLapRace = False;
132 | Map.ObjectiveTextAuthor = "N/A";
133 | Map.ObjectiveTextGold = "N/A";
134 | Map.ObjectiveTextSilver = "N/A";
135 | Map.ObjectiveTextBronze = "N/A";
136 |
137 | // ---------------------------------- //
138 | // Events management
139 | foreach (Event in PendingEvents) {
140 | switch (Event.Type) {
141 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
142 | case CPluginEvent::Type::StartValidation : { }
143 | case CPluginEvent::Type::MapModified : Checkpoints::SaveCheckpointsData();
144 | }
145 | UpdateValidability();
146 | UpdateNbCheckpoints();
147 | }
148 | }
149 | }
--------------------------------------------------------------------------------
/Media/Settings/Galaxy.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/Scripts/Modes/ShootMania/InvasionSolo.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // INVASION SOLO by domino54 //
3 | // script version: v3.2 @2017-06-28 //
4 | // -------------------------------------- //
5 |
6 | #Extends "Modes/ShootMania/Invasion.Script.txt"
7 |
8 | #Const DeluxeVersion "2017-06-28"
9 | #Const DeluxeScriptName "Modes/ShootMania/Invasion.Script.txt"
10 |
11 | // ---------------------------------- //
12 | // Settings
13 | // ---------------------------------- //
14 | #Setting S_UseEvolutionLevels False ///< Evolution levels are disabled in solo mode
15 | #Setting S_AutoManageAFK False ///< We don't want unspawned player
16 |
17 | // ---------------------------------- //
18 | // Extend
19 | // ---------------------------------- //
20 | ***Match_LogVersions***
21 | ***
22 | Log::RegisterScript(DeluxeScriptName, DeluxeVersion);
23 | ***
24 |
25 | // ---------------------------------- //
26 | // Galaxy settings
27 | // ---------------------------------- //
28 | ***GalaxyTitles_Settings***
29 | ***
30 | GT_UseAutoEndSequence = False;
31 | ***
32 |
33 | // ---------------------------------- //
34 | // Initialize server
35 | // ---------------------------------- //
36 | ***Match_InitServer***
37 | ***
38 | G_IsSoloMode = True;
39 | InvasionUI::SetSoloMode(G_IsSoloMode);
40 |
41 | // ---------------------------------- //
42 | // Hide name tags
43 | UIManager.UIAll.AlliesLabelsVisibility = CUIConfig::ELabelsVisibility::Never;
44 | UIManager.UIAll.TeamLabelsVisibility = CUIConfig::ELabelsVisibility::Never;
45 | UIManager.UIAll.OpposingTeamLabelsVisibility = CUIConfig::ELabelsVisibility::Never;
46 |
47 | // Hide unnecessary buttons in pause menu
48 | PauseMenu::SetSoloMode(G_IsSoloMode);
49 |
50 | // ---------------------------------- //
51 | // Unload the scores table
52 | ST2::Unload();
53 | UIManager.UIAll.ScoreTableOnlyManialink = True;
54 | UIManager.UIAll.AltMenuNoDefaultScores = True;
55 |
56 | // ---------------------------------- //
57 | // Unload the Killfeed library
58 | Killfeed::Unload();
59 | UIManager.UIAll.OverlayHideNotices = True;
60 | UIManager.UIAll.OverlayHideMapInfo = True;
61 | ***
62 |
63 | // ---------------------------------- //
64 | // Start map
65 | // ---------------------------------- //
66 | ***Match_StartMap***
67 | ***
68 | // ---------------------------------- //
69 | // Force the player's color as the bases colors
70 | UIManager.UIAll.ScoreSummary_Player1 = Players[0].Id;
71 | UIManager.UIAll.ScoreSummary_Player2 = Players[0].Id;
72 | ***
73 |
74 | // ---------------------------------- //
75 | // Round end
76 | // ---------------------------------- //
77 | ***Match_EndRound***
78 | ***
79 | // ---------------------------------- //
80 | // Solo mode sequence
81 | if (Players.existskey(0)) {
82 | declare Player <=> Players[0];
83 | AddScorePoints(Player, SoloTimeScore);
84 |
85 | // Get the scores
86 | declare TotalSoloPoints = Player.Score.Points * 10;
87 | declare SoloScoreMedal = GetMedalFromPoints(TotalSoloPoints);
88 |
89 | // ---------------------------------- //
90 | // Save the local score
91 | Player.Score.Points = ML::Clamp(Player.Score.Points, 0, 32767);
92 | Solo_SetNewRecord(Player.Score, SoloScoreMedal);
93 | InvasionSolo_SavePersonalBest(TotalSoloPoints);
94 |
95 | // Wait until player ha sclosed the medal award window
96 | while (!UIManager.UIAll.UISequenceIsCompleted) MB_Yield();
97 |
98 | // Show the summary window
99 | InvasionUI::DisplaySoloScore(True, SoloScoreMedal, TotalSoloPoints);
100 | while (!ServerShutdownRequested) MB_Yield();
101 | }
102 | ***
103 |
104 | // ---------------------------------- //
105 | /** Get the medal from points.
106 | *
107 | * @param _Points The amount of points to get the medal from.
108 | *
109 | * @return The medal according to the amount of points.
110 | */
111 | CMode::EMedal GetMedalFromPoints(Integer _Points) {
112 | if (Map == Null) return CMode::EMedal::None;
113 |
114 | // ---------------------------------- //
115 | // Read objectives from the map
116 | declare ObjectivePointsBronze = TL::ToInteger(Map.ObjectiveTextBronze);
117 | declare ObjectivePointsSilver = TL::ToInteger(Map.ObjectiveTextSilver);
118 | declare ObjectivePointsGold = TL::ToInteger(Map.ObjectiveTextGold);
119 | declare ObjectivePointsAuthor = TL::ToInteger(Map.ObjectiveTextAuthor);
120 |
121 | // Invalid scores
122 | if (
123 | ObjectivePointsAuthor <= 0 ||
124 | ObjectivePointsGold > ObjectivePointsAuthor ||
125 | ObjectivePointsSilver > ObjectivePointsGold ||
126 | ObjectivePointsBronze > ObjectivePointsSilver
127 | )
128 | return CMode::EMedal::None;
129 |
130 | // ---------------------------------- //
131 | // Return medal according to the score points
132 | if (_Points >= ObjectivePointsAuthor) return CMode::EMedal::Author;
133 | if (_Points >= ObjectivePointsGold) return CMode::EMedal::Gold;
134 | if (_Points >= ObjectivePointsSilver) return CMode::EMedal::Silver;
135 | if (_Points >= ObjectivePointsBronze) return CMode::EMedal::Bronze;
136 | return CMode::EMedal::None;
137 | }
138 |
139 | // ---------------------------------- //
140 | /** Save personal record of a player.
141 | *
142 | * @param _ScorePoints Scored points.
143 | */
144 | Void InvasionSolo_SavePersonalBest(Integer _ScorePoints) {
145 | if (!Users.existskey(0) || Map == Null) return;
146 | declare Points = ML::Max(_ScorePoints, 0);
147 | declare UID = Map.MapInfo.MapUid;
148 |
149 | declare persistent Integer[Text] Persistent_Invasion_PersonalRecords for Users[0];
150 | declare persistent Integer Persistent_Invasion_LastRecordsUpdate for Users[0];
151 |
152 | // Don't save score if smaller than current personal best
153 | if (Persistent_Invasion_PersonalRecords.existskey(UID) && Persistent_Invasion_PersonalRecords[UID] >= Points) return;
154 |
155 | Persistent_Invasion_PersonalRecords[UID] = Points;
156 | Persistent_Invasion_LastRecordsUpdate = Now;
157 | }
--------------------------------------------------------------------------------
/Media/Manialinks/PursuitUIExtension.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
155 |
156 |
--------------------------------------------------------------------------------
/Scripts/EditorPlugins/AutoGhostBlocks.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // AUTO GHOST BLOCKS by domino54 //
3 | // script version: 2015-07-08 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * This plugin enables Ghost Blocks and Air Mapping
8 | * at the editor bootup. Also allows to switch between
9 | * normal blocks and Ghost Blocks with mouse wheel
10 | * button.
11 | */
12 |
13 | #RequireContext CEditorPlugin
14 |
15 | #Const Version "2015-07-08"
16 | #Const ScriptName "AutoGhostBlocks.Script.txt"
17 |
18 | // ---------------------------------- //
19 | /** Get layer Ghost Blocks button
20 | *
21 | * @return Manialink page with Ghost Blocks button
22 | */
23 | Text GetLayerGhostBlocksButton() {
24 | return """
25 |
26 |
27 |
31 |
35 |
36 |
37 |
41 |
42 |
117 | """;
118 | }
119 |
120 | // ---------------------------------- //
121 | // Main
122 | // ---------------------------------- //
123 | main() {
124 | // ---------------------------------- //
125 | // Create manialink layer
126 | ManialinkText = GetLayerGhostBlocksButton();
127 |
128 | // ---------------------------------- //
129 | // Persistent settings
130 | declare persistent Boolean Persistent_GhostBlocks_EnableMixMapping for LocalUser = True;
131 |
132 | // ---------------------------------- //
133 | // Communicate with manialink layer
134 | declare Boolean NextPlacingMode for ManialinkPage = False;
135 |
136 | // ---------------------------------- //
137 | // Variables
138 | declare PrevPlaceMode = ::PlaceMode::Block;
139 |
140 | // ---------------------------------- //
141 | // Yield
142 | // ---------------------------------- //
143 | while (True) {
144 | yield;
145 |
146 | // ---------------------------------- //
147 | // Enable air mapping and ghost blocks through a setting
148 | EnableAirMapping = Persistent_GhostBlocks_EnableMixMapping;
149 | EnableMixMapping = Persistent_GhostBlocks_EnableMixMapping;
150 |
151 | // ---------------------------------- //
152 | // Normal block mode, if user disabled ghost blocks and is still in this mode
153 | if (!Persistent_GhostBlocks_EnableMixMapping && PlaceMode == ::PlaceMode::GhostBlock)
154 | PlaceMode = ::PlaceMode::Block;
155 |
156 | // ---------------------------------- //
157 | // Switch ghost blocks mode on mouse wheel button
158 | if (NextPlacingMode) {
159 | NextPlacingMode = False;
160 |
161 | // Ghost mode on
162 | if (PlaceMode != ::PlaceMode::GhostBlock) {
163 | PrevPlaceMode = PlaceMode;
164 | PlaceMode = ::PlaceMode::GhostBlock;
165 | }
166 | // Ghost mode off
167 | else {
168 | if (PrevPlaceMode != ::PlaceMode::Unknown) PlaceMode = PrevPlaceMode;
169 | else PlaceMode = ::PlaceMode::Block;
170 | }
171 | }
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/CustomNames.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY CUSTOM NAMES by domino54 //
3 | // script version: 2017-08-05 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * Change name of any player you want to anything.
8 | */
9 |
10 | #Const Version "2017-08-05"
11 | #Const ScriptName "Libs/domino54/CustomNames.Script.txt"
12 |
13 | #Include "Libs/Nadeo/ScoresTable2.Script.txt" as ST2
14 |
15 | // ---------------------------------- //
16 | // Functions
17 | // ---------------------------------- //
18 |
19 | // ---------------------------------- //
20 | // Public
21 | // ---------------------------------- //
22 |
23 | // ---------------------------------- //
24 | /** Return the version number of the script.
25 | *
26 | * @return The version number of the script.
27 | */
28 | Text GetScriptVersion() { return Version; }
29 |
30 | // ---------------------------------- //
31 | /** Return the name of the script.
32 | *
33 | * @return The name of the script.
34 | */
35 | Text GetScriptName() { return ScriptName; }
36 |
37 | // ---------------------------------- //
38 | /** Get the score of a player.
39 | *
40 | * @param _Player The player to get score.
41 | *
42 | * @return Score of the player.
43 | */
44 | CScore GetScore(CPlayer _Player) {
45 | if (_Player == Null) return Null;
46 | switchtype (_Player) {
47 | case CTmPlayer : {
48 | declare Player = cast(CTmPlayer, _Player);
49 | return Player.Score;
50 | }
51 | case CSmPlayer : {
52 | declare Player = cast(CSmPlayer, _Player);
53 | return Player.Score;
54 | }
55 | }
56 | return Null;
57 | }
58 |
59 | // ---------------------------------- //
60 | /** Get the score of a user.
61 | *
62 | * @param _User The user to get score.
63 | *
64 | * @return Score of the user.
65 | */
66 | CScore GetScore(CUser _User) {
67 | if (_User == Null) return Null;
68 | foreach (Score in Scores) if (Score.User == _User) return Score;
69 | return Null;
70 | }
71 |
72 | // ---------------------------------- //
73 | /** Get the score by the login.
74 | *
75 | * @param _Login Login of the score to get.
76 | *
77 | * @return Score matching the login.
78 | */
79 | CScore GetScore(Text _Login) {
80 | if (_Login == "") return Null;
81 | foreach (Score in Scores) if (Score.User.Login == _Login) return Score;
82 | return Null;
83 | }
84 |
85 | // ---------------------------------- //
86 | /** Get the name of a player.
87 | *
88 | * @param _Score Score of the player to get their name.
89 | *
90 | * @return Name of the player.
91 | */
92 | Text Get(CScore _Score) {
93 | if (_Score == Null) return "";
94 | declare netwrite Text LibCustomNames_UserName for _Score;
95 | if (LibCustomNames_UserName == "") return _Score.User.Name;
96 | return LibCustomNames_UserName;
97 | }
98 |
99 | // ---------------------------------- //
100 | /** Get the name of a player.
101 | *
102 | * @param _Player The player to get their name.
103 | *
104 | * @return Name of the player.
105 | */
106 | Text Get(CPlayer _Player) {
107 | if (_Player == Null) return "";
108 | return Get(GetScore(_Player));
109 | }
110 |
111 | // ---------------------------------- //
112 | /** Get the name of a player.
113 | *
114 | * @param _User The user to get their name.
115 | *
116 | * @return Name of the player.
117 | */
118 | Text Get(CUser _User) {
119 | if (_User == Null) return "";
120 | return Get(GetScore(_User));
121 | }
122 |
123 | // ---------------------------------- //
124 | /** Get the name of a player.
125 | *
126 | * @param _Login Login of the player to get name.
127 | *
128 | * @return Name of the player.
129 | */
130 | Text Get(Text _Login) {
131 | if (_Login == "") return "";
132 | return Get(GetScore(_Login));
133 | }
134 |
135 | // ---------------------------------- //
136 | /** Set the name of a player.
137 | *
138 | * @param _Score The score to set new name.
139 | * @param _Name New name to set.
140 | */
141 | Void Set(CScore _Score, Text _Name) {
142 | if (_Score == Null) return;
143 | declare netwrite Text LibCustomNames_UserName for _Score;
144 | LibCustomNames_UserName = _Name;
145 | }
146 |
147 | // ---------------------------------- //
148 | /** Set the name of a player.
149 | *
150 | * @param _Player The player to set new name.
151 | * @param _Name New name to set.
152 | */
153 | Void Set(CPlayer _Player, Text _Name) {
154 | if (_Player == Null) return;
155 | Set(GetScore(_Player), _Name);
156 | }
157 |
158 | // ---------------------------------- //
159 | /** Set the name of a player.
160 | *
161 | * @param _User The user to set new name.
162 | * @param _Name New name to set.
163 | */
164 | Void Set(CUser _User, Text _Name) {
165 | if (_User == Null) return;
166 | Set(GetScore(_User), _Name);
167 | }
168 |
169 | // ---------------------------------- //
170 | /** Set the name of a player.
171 | *
172 | * @param _Login Login of the player to set new name.
173 | * @param _Name New name to set.
174 | */
175 | Void Set(Text _Login, Text _Name) {
176 | if (_Login == "") return;
177 | Set(GetScore(_Login), _Name);
178 | }
179 |
180 | // ---------------------------------- //
181 | /** Reset name of a player.
182 | *
183 | * @param _Score The score to reset name.
184 | */
185 | Void Reset(CScore _Score) {
186 | Set(_Score, "");
187 | }
188 |
189 | // ---------------------------------- //
190 | /** Reset name of a player.
191 | *
192 | * @param _Player The player to reset name.
193 | */
194 | Void Reset(CPlayer _Player) {
195 | Set(_Player, "");
196 | }
197 |
198 | // ---------------------------------- //
199 | /** Reset name of a player.
200 | *
201 | * @param _User The user to reset name.
202 | */
203 | Void Reset(CUser _User) {
204 | Set(_User, "");
205 | }
206 |
207 | // ---------------------------------- //
208 | /** Reset name of a player.
209 | *
210 | * @param _Login Login of the player to reset name.
211 | */
212 | Void Reset(Text _Login) {
213 | Set(_Login, "");
214 | }
215 |
216 | // ---------------------------------- //
217 | /// Initialize name column in ScoresTable2.
218 | Void InitST2() {
219 | ST2::SetColScript("LibST_Name", """
220 | declare netread Text LibCustomNames_UserName for _Score;
221 | if (LibCustomNames_UserName != "") Label_Col.Value = LibCustomNames_UserName;
222 | else Label_Col.Value = _Score.User.Name;
223 | """);
224 | }
--------------------------------------------------------------------------------
/Scripts/Modes/ShootMania/CustomWeapons+.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // CUSTOM WEAPONS PLUS by domino54 //
3 | // script version: 1.0.1 //
4 | // -------------------------------------- //
5 |
6 | #Extends "Modes/ShootMania/Melee.Script.txt"
7 |
8 | #Const DeluxeVersion "1.0.1"
9 | #Const DeluxeScriptName "CustomActions+.Script.txt"
10 |
11 | // ---------------------------------- //
12 | // Settings
13 | // ---------------------------------- //
14 | #Setting S_RequestedActions "" as _("Primary random weapons (separate with \"|\")")
15 | #Setting S_PlayerArmorCount 3 as _("Player armor count (1 - 10)")
16 |
17 | // ---------------------------------- //
18 | // Globales variables
19 | // ---------------------------------- //
20 | declare Ident[] G_ActionId; ///< Complete array with actions
21 | declare Ident[] G_ActionsList; ///< Id of all the actions
22 | declare Integer G_LatestActionId; ///< Id of the last action used
23 |
24 | // ---------------------------------- //
25 | // Extend
26 | // ---------------------------------- //
27 |
28 | ***LogVersion***
29 | ***
30 | MB_LogVersion(DeluxeVersion, DeluxeScriptName);
31 | ***
32 |
33 | // ---------------------------------- //
34 | // Server start
35 | // ---------------------------------- //
36 | ***StartServer***
37 | ***
38 | declare Text[] SplitActionPaths;
39 | declare Text Last_RequestedActions;
40 |
41 | while (!MatchEndRequested && !ServerShutdownRequested && SplitActionPaths.count == 0) {
42 | yield;
43 | if (Last_RequestedActions != S_RequestedActions) {
44 | Last_RequestedActions = S_RequestedActions;
45 | SplitActionPaths = TextLib::Split("|", S_RequestedActions);
46 | }
47 | }
48 |
49 | ActionList_Begin();
50 | foreach (ActionPath in SplitActionPaths) G_ActionId.add(ActionList_Add(ActionPath^".Action.gbx"));
51 | ActionList_End();
52 | ***
53 |
54 | // ---------------------------------- //
55 | // Map start
56 | // ---------------------------------- //
57 | ***StartMap***
58 | ***
59 | // ---------------------------------- //
60 | // Reset actions
61 | foreach (Player in AllPlayers) {
62 | declare Boolean PlayerActionAttached for Player;
63 | PlayerActionAttached = False;
64 | }
65 | ***
66 |
67 | // ---------------------------------- //
68 | // Play loop
69 | // ---------------------------------- //
70 | ***PlayLoop***
71 | ***
72 | Users_SetNbFakeUsers(10, 0);
73 | foreach (Event in PendingEvents) {
74 | // ---------------------------------- //
75 | // On armor empty
76 | if (Event.Type == CSmModeEvent::EType::OnArmorEmpty) {
77 | declare Boolean PlayerActionAttached for Event.Victim;
78 | PlayerActionAttached = False;
79 | }
80 | // ---------------------------------- //
81 | // On custom action hit
82 | else if (Event.Type == CSmModeEvent::EType::OnActionCustomEvent) {
83 | if (Event.Param1 == "damage" && Event.Victim != Null && Event.Shooter != Event.Victim) {
84 | declare EventDamage = TextLib::ToInteger(Event.Param2[0]);
85 | declare Points = EventDamage / 100;
86 | Score::AddPoints(Event.Shooter, Points);
87 | Event.ShooterPoints = Points;
88 |
89 | // ---------------------------------- //
90 | // Play sound and notice if someone is close to win
91 | if (Event.Shooter != Null && Event.Shooter.Score != Null) {
92 | declare LastPoint for Event.Shooter.Score = 0;
93 | declare Gap = S_PointLimit - Event.Shooter.Score.RoundPoints;
94 | if (Gap > 0 && Gap <= 3) {
95 | declare Variant = 3 - Gap;
96 | declare Msg = "";
97 | if (Gap > 1) Msg = TextLib::Compose(_("$<%1$> is %2 points from victory!"), Event.Shooter.Name, TextLib::ToText(Gap));
98 | else Msg = TextLib::Compose(_("$<%1$> is 1 point from victory!"), Event.Shooter.Name);
99 | Message::SendBigMessage(Msg, 3000, 2, CUIConfig::EUISound::TieBreakPoint, Variant);
100 | } else if (Gap <= 0) {
101 | Message::SendBigMessage(
102 | TextLib::Compose(_("$<%1$> gets the final hit!"), Event.Shooter.Name),
103 | 3000, 3, CUIConfig::EUISound::VictoryPoint, 0
104 | );
105 | } else {
106 | declare SoundGap = S_PointLimit / 5;
107 | if (SoundGap < 5) SoundGap = 5;
108 | if (Event.Shooter.Score.RoundPoints / SoundGap > LastPoint) {
109 | LastPoint = Event.Shooter.Score.RoundPoints / SoundGap;
110 | declare Msg = TextLib::Compose(
111 | "$666%1 : $fff%2 / %3", _("Score"), TextLib::ToText(Event.Shooter.Score.RoundPoints), TextLib::ToText(S_PointLimit)
112 | );
113 | declare Variant = ((Event.Shooter.Score.RoundPoints / SoundGap) - 1);
114 | Message::SendBigMessage(Event.Shooter, Msg, 3000, 0, CUIConfig::EUISound::ScoreProgress, Variant);
115 | }
116 | }
117 | }
118 |
119 | RemovePlayerArmor(Event.Victim, EventDamage, Event.Shooter, Points);
120 | }
121 | }
122 | // ---------------------------------- //
123 | // On player request respawn
124 | else if (Event.Type == CSmModeEvent::EType::OnPlayerRequestRespawn) {
125 | declare Boolean PlayerActionAttached for Event.Player;
126 | PlayerActionAttached = False;
127 | }
128 | }
129 |
130 | // ---------------------------------- //
131 | // Bind actions
132 | foreach (Player in Players) {
133 | declare Boolean PlayerActionAttached for Player = False;
134 |
135 | if (Player.SpawnStatus == CSmPlayer::ESpawnStatus::Spawning && !PlayerActionAttached) {
136 | BindRandomAction(Player);
137 | PlayerActionAttached = True;
138 |
139 | if (S_PlayerArmorCount < 1) Player.ArmorMax = 100;
140 | else if (S_PlayerArmorCount > 10) Player.ArmorMax = 1000;
141 | else Player.ArmorMax = S_PlayerArmorCount * 100;
142 |
143 | Player.Armor = Player.ArmorMax;
144 | }
145 | }
146 | ***
147 |
148 | // ---------------------------------- //
149 | // Functions
150 | // ---------------------------------- //
151 |
152 | // ---------------------------------- //
153 | /** Bind random action
154 | *
155 | * @param _Player The player to bind action
156 | */
157 | Void BindRandomAction(CSmPlayer _Player) {
158 | if (G_ActionsList.count == 0) {
159 | foreach (Action in G_ActionId) G_ActionsList.add(Action);
160 | }
161 |
162 | declare ActionId = 0;
163 | while (True) {
164 | ActionId = MathLib::Rand(0, G_ActionsList.count - 1);
165 | if (ActionId != G_LatestActionId) break;
166 | if (G_ActionsList.count == 1) break;
167 | }
168 | G_LatestActionId = ActionId;
169 |
170 | ActionLoad(_Player, CSmMode::EActionSlot::Slot_A, G_ActionsList[ActionId]);
171 | ActionBind(_Player, CSmMode::EActionSlot::Slot_A, CSmMode::EActionInput::Weapon);
172 |
173 | declare Removed = G_ActionsList.remove(G_ActionsList[ActionId]);
174 | }
175 |
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/SplitScreenLib.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY SPLIT SCREEN by domino54 //
3 | // script version: 2018-03-29 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * This library features a few functions you can
8 | * insert in your ingame manialink to provide some
9 | * split screen integrations.
10 | */
11 |
12 | #Const Version "2018-03-29"
13 | #Const ScriptName "Libs/domino54/SplitScreenLib.Script.txt"
14 |
15 | // ---------------------------------- //
16 | // Functons
17 | // ---------------------------------- //
18 |
19 | // ---------------------------------- //
20 | // Public
21 | // ---------------------------------- //
22 |
23 | // ---------------------------------- //
24 | /** Return the version number of the script.
25 | *
26 | * @return The version number of the script.
27 | */
28 | Text GetScriptVersion() { return Version; }
29 |
30 | // ---------------------------------- //
31 | /** Return the name of the script.
32 | *
33 | * @return The name of the script.
34 | */
35 | Text GetScriptName() { return ScriptName; }
36 |
37 | // ---------------------------------- //
38 | /** Get the functions of Split Screen Library.
39 | *
40 | * @return The library functions.
41 | */
42 | Text Framework() {
43 | return """
44 | // ---------------------------------- //
45 | /** Check if split screen mode is enabled.
46 | *
47 | * @return True, if split screen mode is enabled.
48 | */
49 | Boolean SplitScreen_Enabled() {
50 | foreach (Player in Players) {
51 | if (Player.User.Login != "*splitscreen_0*") continue;
52 | return True;
53 | }
54 | return False;
55 | }
56 |
57 | // ---------------------------------- //
58 | /** Get the number of players in split screen mode.
59 | *
60 | * @return Number of players in split screen mode.
61 | */
62 | Integer SplitScreen_NbPlayers() {
63 | declare SS_NbPlayers = 0;
64 | foreach (Player in Players) {
65 | if (!TL::Find("*splitscreen_", Player.User.Login, True, True)) continue;
66 | SS_NbPlayers += 1;
67 | }
68 | return SS_NbPlayers;
69 | }
70 |
71 | // ---------------------------------- //
72 | /** Get the active screen split type.
73 | *
74 | * @return Active plit mode [0 => disabled, 1 => horizontal, 2 => vertical, 3 => grid].
75 | */
76 | Integer SplitScreen_SplitMode() {
77 | if (!SplitScreen_Enabled()) return 0;
78 | if (SplitScreen_NbPlayers() == 4) return 3;
79 |
80 | declare persistent Persistent_LastSplitScreenLayout for LocalUser = 0;
81 | switch (Persistent_LastSplitScreenLayout) {
82 | case 0 : return 1;
83 | case 1 : return 2;
84 | case 2 : return 3;
85 | }
86 | return 0;
87 | }
88 |
89 | // ---------------------------------- //
90 | /** Get player of a given order.
91 | *
92 | * @param _Order The order of the player to get.
93 | *
94 | * @return The desired player.
95 | */
96 | CPlayer SplitScreen_GetPlayer(Integer _Order) {
97 | if (!SplitScreen_Enabled()) return GUIPlayer;
98 | foreach (Player in Players) if (Player.User.Login == "*splitscreen_"^_Order^"*") return Player;
99 | return Null;
100 | }
101 |
102 | CTmMlPlayer SplitScreen_GetTmPlayer(Integer _Order) {
103 | declare Player <=> SplitScreen_GetPlayer(_Order);
104 | if (Player == Null || !(Player is CTmMlPlayer)) return Null;
105 | return (Player as CTmMlPlayer);
106 | }
107 |
108 | // ---------------------------------- //
109 | /** Get the position adjusted to the splitscreen layout.
110 | *
111 | * @param _Position The input position.
112 | * @param _PlayerId Order of the player on screen.
113 | * @param _HAlign Align items to left, right or centre of the screen.
114 | * @param _VAlign Align items to top, bottom or centre of the screen.
115 | * @param _Widescreen Expand elements on horizontal layout.
116 | *
117 | * @return Position according to input.
118 | */
119 | Vec2 SplitScreen_GetPosition(Vec2 _Position, Integer _PlayerId, CMlControl::AlignHorizontal _HAlign, CMlControl::AlignVertical _VAlign, Boolean _Widescreen) {
120 | if (!SplitScreen_Enabled()) return _Position;
121 |
122 | switch (SplitScreen_SplitMode()) {
123 | // Grid layout
124 | case 3 : {
125 | declare RelativeCenter = <80., 45.>;
126 | if (_PlayerId % 2 != 0) RelativeCenter.Y *= -1.;
127 | if (_PlayerId / 2 < 1) RelativeCenter.X *= -1.;
128 | return RelativeCenter + <_Position.X / 2, _Position.Y / 2>;
129 | }
130 |
131 | // Vertical layout
132 | case 2 : {
133 | declare Position = <0., _Position.Y>;
134 | switch (_HAlign) {
135 | case CMlControl::AlignHorizontal::Left : Position.X = _Position.X + 160.;
136 | case CMlControl::AlignHorizontal::Right : Position.X = _Position.X - 160.;
137 | default : Position.X = _Position.X / 2 - 80.;
138 | }
139 | if (_PlayerId != 0) Position.X += 160.;
140 | return Position;
141 | }
142 |
143 | // Horizontal layout
144 | case 1 : {
145 | declare Position = <0., 0.>;
146 | if (!_Widescreen) {
147 | Position.X = _Position.X / 2;
148 | } else switch (_HAlign) {
149 | case CMlControl::AlignHorizontal::Left : Position.X = _Position.X / 2 - 160.;
150 | case CMlControl::AlignHorizontal::Right : Position.X = _Position.X / 2 + 80.;
151 | default : Position.X = _Position.X / 2;
152 | }
153 | switch (_VAlign) {
154 | case CMlControl::AlignVertical::Top : Position.Y = _Position.Y / 2;
155 | case CMlControl::AlignVertical::Bottom : Position.Y = _Position.Y / 2 + 45.;
156 | default : Position.Y = _Position.Y / 2 + 45.;
157 | }
158 | if (_PlayerId != 0) Position.Y -= 90.;
159 | return Position;
160 | }
161 | }
162 |
163 | return _Position;
164 | }
165 |
166 | Vec2 SplitScreen_GetPosition(Vec2 _Position, Integer _PlayerId, Boolean _Widescreen) {
167 | return SplitScreen_GetPosition(_Position, _PlayerId, CMlControl::AlignHorizontal::HCenter, CMlControl::AlignVertical::VCenter, _Widescreen);
168 | }
169 |
170 | // ---------------------------------- //
171 | /** Get the scale adjusted to the splitscreen layout.
172 | *
173 | * @param _Scale The input scale.
174 | * @param _HAlign Align items to left, right or centre of the screen.
175 | * @param _VAlign Align items to top, bottom or centre of the screen.
176 | *
177 | * @return Position according to input.
178 | */
179 | Real SplitScreen_GetScale(Real _Scale, CMlControl::AlignHorizontal _HAlign, CMlControl::AlignVertical _VAlign) {
180 | if (!SplitScreen_Enabled()) return _Scale;
181 |
182 | switch (SplitScreen_SplitMode()) {
183 | // Grid layout
184 | case 3 : return _Scale / 2;
185 |
186 | // Vertical layout
187 | case 2 : return _Scale;
188 |
189 | // Horizontal layout
190 | case 1 : return _Scale / 2;
191 | }
192 |
193 | return _Scale;
194 | }
195 |
196 | Real SplitScreen_GetScale(Real _Scale) {
197 | return SplitScreen_GetScale(_Scale, CMlControl::AlignHorizontal::HCenter, CMlControl::AlignVertical::VCenter);
198 | }
199 | """;
200 | }
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/TrackMania/CylinderHitbox.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // CYLINDER HITBOX LIB by domino54 //
3 | // script version: 2016-09-25 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * This library allows to create virtual cylinder hitbox for
8 | * the cars, adjust cylinder diameter and height from player
9 | * rotation and car model size. Allows to check if hitboxes
10 | * of two players touch.
11 | */
12 |
13 | #Const Version "2016-09-25"
14 | #Const ScriptName "CylinderHitbox.Script.txt"
15 |
16 | #Include "AnimLib" as AnimLib
17 | #Include "MathLib" as MathLib
18 |
19 | // ---------------------------------- //
20 | // Constants
21 | // ---------------------------------- //
22 | #Const C_DetectionDistance 8. ///< Computes only if distance is smaller than this value
23 | #Const C_VerticalSizeSub .25 ///< Short cylinder diameter to make it more accurate at car longer side
24 |
25 | /// Sizes of visible player car models
26 | #Const C_CarModelSizes [
27 | "CanyonCar" => <4.25, 1.125, 2.>,
28 | "StadiumCar" => <4., 1., 1.75>,
29 | "ValleyCar" => <4.25, 1.25, 2.25>
30 | ]
31 |
32 | // ---------------------------------- //
33 | // Functions
34 | // ---------------------------------- //
35 |
36 | // ---------------------------------- //
37 | // Private
38 | // ---------------------------------- //
39 |
40 | // ---------------------------------- //
41 | /** Convert pitch in radians to degress
42 | *
43 | * @param _Pitch The pitch to convert
44 | *
45 | * @return Pitch converted to degress
46 | */
47 | Real Private_GetPitch(Real _Pitch) {
48 | return MathLib::Abs(_Pitch * 2 / MathLib::PI());
49 | }
50 |
51 | // ---------------------------------- //
52 | /** Get cylinder diameter
53 | *
54 | * @param _Pitch Pitch used to compute diameter
55 | *
56 | * @return Diameter of cylinder
57 | */
58 | Real Private_GetCyliDiameter(Real _Pitch) {
59 | return AnimLib::Ease("EaseInCirc", _Pitch, 1., -1., 1.);
60 | }
61 |
62 | // ---------------------------------- //
63 | /** Get cylinder height
64 | *
65 | * @param _Pitch Pitch used to compute height
66 | *
67 | * @return Height of cylinder
68 | */
69 | Real Private_GetCyliHeight(Real _Pitch) {
70 | return AnimLib::Ease("EaseOutCirc", _Pitch, 0., 1., 1.);
71 | }
72 |
73 | // ---------------------------------- //
74 | /** Distance between two points in one dimension
75 | *
76 | * @param _Pos1 Pirst point position
77 | * @param _Pos2 Second point position
78 | *
79 | * @return Distance between points
80 | */
81 | Real Private_Distance1D(Real _Pos1, Real _Pos2) {
82 | return MathLib::Sqrt(MathLib::Pow(_Pos2 - _Pos1, 2.));
83 | }
84 |
85 | // ---------------------------------- //
86 | /** Distance between two points in two dimensions
87 | *
88 | * @param _Pos1 Pirst point position
89 | * @param _Pos2 Second point position
90 | *
91 | * @return Distance between points
92 | */
93 | Real Private_Distance2D(Vec3 _Pos1, Vec3 _Pos2) {
94 | return MathLib::Sqrt(MathLib::Pow(_Pos2.X - _Pos1.X, 2.) + MathLib::Pow(_Pos2.Z - _Pos1.Z, 2.));
95 | }
96 |
97 | // ---------------------------------- //
98 | // Public
99 | // ---------------------------------- //
100 |
101 | // ---------------------------------- //
102 | /** Return the version number of the script
103 | *
104 | * @return The version number of the script
105 | */
106 | Text GetScriptVersion() {
107 | return Version;
108 | }
109 |
110 | // ---------------------------------- //
111 | /** Return the name of the script
112 | *
113 | * @return The name of the script
114 | */
115 | Text GetScriptName() {
116 | return ScriptName;
117 | }
118 |
119 | // ---------------------------------- //
120 | /** Check if hitboxes of two players touch
121 | *
122 | * @param _Player1 Pirst point position
123 | * @param _Player2 Second point position
124 | *
125 | * @return True if cylinders touch
126 | */
127 | Boolean AreTouching(CTmPlayer _Player1, CTmPlayer _Player2) {
128 | if (_Player1 == Null || _Player2 == Null) return False;
129 | if (!_Player1.IsSpawned || !_Player2.IsSpawned) return False;
130 | if (_Player1.Position == <0., 0., 0.> || _Player2.Position == <0., 0., 0.>) return False;
131 |
132 | // ---------------------------------- //
133 | // Check if cars are close enough
134 | if (MathLib::Distance(_Player1.Position, _Player2.Position) > C_DetectionDistance) return False;
135 |
136 | // ---------------------------------- //
137 | // Set hitbox model properties
138 | declare Vec3 FixedPos1 = _Player1.Position;
139 | declare Vec3 FixedPos2 = _Player2.Position;
140 |
141 | FixedPos1.Y += C_CarModelSizes[MapPlayerModelName].Y / 2;
142 | FixedPos2.Y += C_CarModelSizes[MapPlayerModelName].Y / 2;
143 |
144 | // ---------------------------------- //
145 | // Convert rad to deg pitch
146 | declare Real Player1Pitch = Private_GetPitch(_Player1.AimPitch);
147 | declare Real Player2Pitch = Private_GetPitch(_Player2.AimPitch);
148 |
149 | // ---------------------------------- //
150 | // Cylinder diameter depends on player rotation
151 | declare Real Player1Diameter;
152 | Player1Diameter = (C_CarModelSizes[MapPlayerModelName].X - C_VerticalSizeSub) * Private_GetCyliDiameter(Player1Pitch);
153 | declare Real Player2Diameter;
154 | Player2Diameter = (C_CarModelSizes[MapPlayerModelName].X - C_VerticalSizeSub) * Private_GetCyliDiameter(Player2Pitch);
155 |
156 | // ---------------------------------- //
157 | // Diameter can't be shorter than vehicle width
158 | if (Player1Diameter < C_CarModelSizes[MapPlayerModelName].Z) Player1Diameter = C_CarModelSizes[MapPlayerModelName].Z;
159 | if (Player2Diameter < C_CarModelSizes[MapPlayerModelName].Z) Player2Diameter = C_CarModelSizes[MapPlayerModelName].Z;
160 |
161 | // ---------------------------------- //
162 | // Check if cylinders touch in X and Z axis
163 | if (Private_Distance2D(FixedPos1, FixedPos2) > (Player1Diameter + Player2Diameter) / 2) return False;
164 |
165 | // ---------------------------------- //
166 | // Cylinder height depends on player rotation
167 | declare Real Player1Height = C_CarModelSizes[MapPlayerModelName].X * Private_GetCyliHeight(Player1Pitch);
168 | declare Real Player2Height = C_CarModelSizes[MapPlayerModelName].X * Private_GetCyliHeight(Player2Pitch);
169 |
170 | // ---------------------------------- //
171 | // Height can't be lower then vehicle height
172 | if (Player1Height < C_CarModelSizes[MapPlayerModelName].Y) Player1Height = C_CarModelSizes[MapPlayerModelName].Y;
173 | if (Player2Height < C_CarModelSizes[MapPlayerModelName].Y) Player2Height = C_CarModelSizes[MapPlayerModelName].Y;
174 |
175 | // ---------------------------------- //
176 | // Check if cylinders touch in Y axis
177 | if (Private_Distance1D(FixedPos1.Y, FixedPos2.Y) - (C_VerticalSizeSub * 2) > (Player1Height + Player2Height) / 2) return False;
178 |
179 | // ---------------------------------- //
180 | // Players touch
181 | return True;
182 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/JailbreakV2Arena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // JAILBREAK V2 ARENA by domino54 //
3 | // script version: 2017-08-22 //
4 | // original concept by Akbalder //
5 | // -------------------------------------- //
6 |
7 | #RequireContext CSmMapType
8 |
9 | #Const Version "2017-08-22"
10 | #Const MapTypeVersion 2
11 | #Const ScriptName "JailbreakV2Arena.Script.txt"
12 |
13 | #Include "TextLib" as TL
14 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
15 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
16 | // Custom libraries
17 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
18 |
19 | // ---------------------------------- //
20 | // Constants
21 | // ---------------------------------- //
22 | #Const C_Rules "$<%11.$> Place exactly one Spawn #1 and one Spawn #2, where players appear at the beginning of the round.\n$<%12.$> Place one JailSpawn #1 and one JailSpawn #2 in isolated rooms, where jailed players spawn after being eliminated.\n$<%13.$> Place one Goal #1 and one Goal #2 - teammates standing on them will make the Gates open and OffZone harmless.\n$<%14.$> Place the same number of Gate #1 and Gate #2 or use OffZone to build the jail doors.\n$<%15.$> Players $F00can't$g leave the jail other way than going through a Gate or the OffZone.\n$<%16.$> Gates $F00must$g be placed with their round capture plate at the outside of the jail - standing on it makes the player free."
23 |
24 | #Const C_GateTriggerSize 6.5
25 |
26 | // ---------------------------------- //
27 | // Functions
28 | // ---------------------------------- //
29 |
30 | // ---------------------------------- //
31 | /// Initialize the anchors
32 | Void InitAnchors() {
33 | foreach (Anchor in AnchorData) {
34 | if (Anchor.DefaultTag == "Spawn") {
35 | if (Anchor.Tag != "Spawn" && Anchor.Tag != "JailSpawn") Anchor.Tag = Anchor.DefaultTag;
36 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
37 | } else if (Anchor.DefaultTag == "Goal") {
38 | Anchor.Tag = Anchor.DefaultTag;
39 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
40 | } else if (Anchor.DefaultTag == "Checkpoint") {
41 | Anchor.Tag = "Goal";
42 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
43 | } else if (Anchor.DefaultTag == "Gate") {
44 | Anchor.Tag = "Gate";
45 | if (Anchor.Order != 1 && Anchor.Order != 2) Anchor.Order = 1;
46 | } else {
47 | Anchor.Tag = Anchor.DefaultTag;
48 | Anchor.Order = Anchor.DefaultOrder;
49 | }
50 | }
51 | }
52 |
53 | // ---------------------------------- //
54 | /// Save triggers locations
55 | Void SaveGateTriggers() {
56 | declare metadata Vec3[] JailbreakV2Arena_GateTriggers_1 for Map;
57 | declare metadata Vec3[] JailbreakV2Arena_GateTriggers_2 for Map;
58 |
59 | JailbreakV2Arena_GateTriggers_1.clear();
60 | JailbreakV2Arena_GateTriggers_2.clear();
61 |
62 | foreach (Data in AnchorData) {
63 | if (Data.Tag != "Gate" || Data.Block == Null) continue;
64 |
65 | declare IsDoubleGate = TL::Find("Center", Data.Block.BlockModel.Name, False, False);
66 | declare Vec3 TriggerPosition_1;
67 | declare Vec3 TriggerPosition_2;
68 |
69 | // ---------------------------------- //
70 | // First trigger position (plate)
71 | for (I, 0, 2) TriggerPosition_1[I] = Data.Block.Coord[I] * 8. + 4.;
72 | TriggerPosition_1.Y = (Data.Block.Coord.Y - CollectionGroundY) * 2.;
73 |
74 | if (IsDoubleGate) switch (Data.Block.Direction) {
75 | case CBlock::CardinalDirections::North : TriggerPosition_1.Z += 4.;
76 | case CBlock::CardinalDirections::East : TriggerPosition_1.X += 4.;
77 | case CBlock::CardinalDirections::South : TriggerPosition_1.Z += 4.;
78 | case CBlock::CardinalDirections::West : TriggerPosition_1.X += 4.;
79 | }
80 |
81 | // ---------------------------------- //
82 | // Second trigger position (behind)
83 | TriggerPosition_2 = TriggerPosition_1;
84 |
85 | switch (Data.Block.Direction) {
86 | case CBlock::CardinalDirections::North : TriggerPosition_2.Z += C_GateTriggerSize;
87 | case CBlock::CardinalDirections::East : TriggerPosition_2.X -= C_GateTriggerSize;
88 | case CBlock::CardinalDirections::South : TriggerPosition_2.Z -= C_GateTriggerSize;
89 | case CBlock::CardinalDirections::West : TriggerPosition_2.X += C_GateTriggerSize;
90 | }
91 |
92 | // ---------------------------------- //
93 | // Save triggers in map file
94 | JailbreakV2Arena_GateTriggers_1.add(TriggerPosition_1);
95 | JailbreakV2Arena_GateTriggers_2.add(TriggerPosition_2);
96 | }
97 | }
98 |
99 | // ---------------------------------- //
100 | /// Check if the map is valid
101 | Void UpdateValidability() {
102 | SaveGateTriggers();
103 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
104 | InitAnchors();
105 | Anchor::UpdateAnchorCounts();
106 |
107 | // ---------------------------------- //
108 | // Get the amount of Gates
109 | declare ClansNbGates = [1 => 0, 2 => 0];
110 | foreach (Data in AnchorData)
111 | if (Data.Tag == "Gate" && ClansNbGates.existskey(Data.Order)) ClansNbGates[Data.Order] += 1;
112 |
113 | // ---------------------------------- //
114 | // Check if map has exactly one landmark type per team
115 | for (I, 1, 2) {
116 | if (
117 | !Anchor::HasExactlyOneAnchor("Spawn", I, TL::Compose(_("You must place exactly one Spawn #%1"), ""^I)) ||
118 | !Anchor::HasExactlyOneAnchor("JailSpawn", I, TL::Compose(_("You must place exactly one JailSpawn #%1"), ""^I)) ||
119 | !Anchor::HasExactlyOneAnchor("Goal", I, TL::Compose(_("You must place exactly one Goal #%1"), ""^I))
120 | ) return;
121 | }
122 |
123 | // ---------------------------------- //
124 | // Gates amount doesn't match
125 | if (ClansNbGates[1] != ClansNbGates[2]) {
126 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
127 | ValidabilityRequirementsMessage = _("You must place the same number of Gate #1 and Gate #2");
128 | return;
129 | }
130 |
131 | // Map is valid
132 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
133 | }
134 |
135 | // ---------------------------------- //
136 | /// Show the anchor edition manialink
137 | Void EditAnchorData(Ident _EditedAnchorDataId) {
138 | if (_EditedAnchorDataId == NullId) return;
139 | UpdateValidability();
140 | EditAnchors::EditAnchor(_EditedAnchorDataId);
141 | UpdateValidability();
142 | }
143 |
144 | // ---------------------------------- //
145 | // Main
146 | // ---------------------------------- //
147 | main() {
148 | MapType::SetVersion(MapTypeVersion);
149 | UpdateValidability();
150 | CustomEditAnchorData = True;
151 |
152 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
153 | EditAnchors::SetAvailableTags([
154 | "Spawn" => ["Spawn #1", "Spawn #2", "JailSpawn #1", "JailSpawn #2"],
155 | "Goal" => ["Goal #1", "Goal #2"],
156 | "Gate" => ["Gate #1", "Gate #2"],
157 | "Checkpoint" => ["Goal #1", "Goal #2"]
158 | ]);
159 |
160 | // ---------------------------------- //
161 | // Yield
162 | // ---------------------------------- //
163 | while (True) {
164 | yield;
165 |
166 | // ---------------------------------- //
167 | // Events management
168 | foreach (Event in PendingEvents) {
169 | switch (Event.Type) {
170 | case CPluginEvent::Type::MapModified : UpdateValidability();
171 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
172 | }
173 | }
174 | }
175 | }
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/Blacklist.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY BLACKLIST by domino54 //
3 | // script version: 2016-06-23 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * This library is connecting to a blacklist shared between
8 | * all modes created by domino54 to automatically kick users
9 | * reported and banned for bad behaviour.
10 | */
11 |
12 | #Const Version "2016-06-23"
13 | #Const ScriptName "Blacklist.Script.txt"
14 |
15 | #Include "Libs/domino54/Translations.Script.txt" as Translations
16 |
17 | // ---------------------------------- //
18 | // Constants
19 | // ---------------------------------- //
20 | #Const C_LibBlacklist_DefaultListURL "https://raw.githubusercontent.com/domino54/title-packs/master/blacklist.xml"
21 | #Const C_LibBlacklist_UserMessage "You have been kicked due your GalaxyTitles ban. Ban reason: %1."
22 | #Const C_LibBlacklist_ChatMessage "User $<%1$> was kicked due their GalaxyTitles ban. Ban reason: %2."
23 | #Const C_LibBlacklist_DefaultReason "not specified"
24 | #Const C_LibBlacklist_CheckInterval 60000
25 | #Const C_LibBlacklist_HttpReqInterval 300000
26 | #Const C_LibBlacklist_HttpReqTimeout 15000
27 |
28 | // ---------------------------------- //
29 | // Global variables
30 | // ---------------------------------- //
31 | declare Text G_LibBlacklist_BlacklistURL; ///< URL of the blacklist file
32 | declare Text[Text] G_LibBlacklist_BannedUsers; ///< List of all banned users with their ban reason
33 | declare Text[] G_LibBlacklist_ShownReasons; ///< List with logins of users kicked at least once per map
34 | declare Integer G_LibBlacklist_NextUsersCheck; ///< Time of the users next validation
35 | declare Integer G_LibBlacklist_PrevUsersCount; ///< Previous amount of connected users
36 | declare Integer G_LibBlacklist_NextRequestTime; ///< Time of the next blacklist update
37 | declare CHttpRequest G_LibBlacklist_Request; ///< Blacklist document request
38 | declare Integer G_LibBlacklist_RequestStartTime; ///< Request start time
39 | declare Boolean G_LibBlacklist_PrevMapLoaded; ///< Previous loaded map status
40 | declare Text G_LibBlacklist_PrevURLSetting; ///< Previous URL specified in main loop
41 |
42 | // ---------------------------------- //
43 | // Functions
44 | // ---------------------------------- //
45 |
46 | // ---------------------------------- //
47 | // Private
48 | // ---------------------------------- //
49 |
50 | // ---------------------------------- //
51 | /** Update blacklist data from XML file
52 | *
53 | * @param _Result Request result
54 | */
55 | Void Private_UpdateBlacklistFromXML(Text _Result) {
56 | if (_Result == "") return;
57 | declare Document = Xml.Create(_Result);
58 | if (Document == Null || Document.Root == Null || Document.Root.Name != "blacklist") return;
59 |
60 | // Clear existing blacklist array
61 | G_LibBlacklist_BannedUsers.clear();
62 |
63 | // Read information about banned players
64 | foreach (Node in Document.Root.Children) {
65 | if (Node.Name == "player") {
66 | declare Login = Node.GetAttributeText("login", "");
67 | declare Reason = Node.GetAttributeText("reason", C_LibBlacklist_DefaultReason);
68 | if (Login != "") G_LibBlacklist_BannedUsers[Login] = Reason;
69 | }
70 | }
71 |
72 | // Destroy document
73 | Xml.Destroy(Document);
74 | }
75 |
76 | // ---------------------------------- //
77 | /** Change blacklist file URL
78 | *
79 | * @param _URL New blacklist file address
80 | */
81 | Void Private_ChangeBlacklistURL(Text _URL) {
82 | if (_URL == "" || !Http.IsValidUrl(_URL)) {
83 | G_LibBlacklist_BlacklistURL = C_LibBlacklist_DefaultListURL;
84 | return;
85 | }
86 | G_LibBlacklist_BlacklistURL = _URL;
87 | }
88 |
89 | // ---------------------------------- //
90 | // Public
91 | // ---------------------------------- //
92 |
93 | // ---------------------------------- //
94 | /** Return the version number of the script
95 | *
96 | * @return The version number of the script
97 | */
98 | Text GetScriptVersion() { return Version; }
99 |
100 | // ---------------------------------- //
101 | /** Return the name of the script
102 | *
103 | * @return The name of the script
104 | */
105 | Text GetScriptName() { return ScriptName; }
106 |
107 | // ---------------------------------- //
108 | /** Library loop
109 | *
110 | * @param _BlacklistURL Blacklist file address
111 | */
112 | Void Loop(Text _BlacklistURL) {
113 | // ---------------------------------- //
114 | // Update blacklist URL
115 | if (G_LibBlacklist_PrevURLSetting != _BlacklistURL) {
116 | G_LibBlacklist_PrevURLSetting = _BlacklistURL;
117 | Private_ChangeBlacklistURL(_BlacklistURL);
118 | }
119 |
120 | // ---------------------------------- //
121 | // Update blacklist data
122 | if (Now >= G_LibBlacklist_NextRequestTime) {
123 | G_LibBlacklist_NextRequestTime = Now + C_LibBlacklist_HttpReqInterval;
124 |
125 | if (G_LibBlacklist_Request != Null) Http.Destroy(G_LibBlacklist_Request);
126 | G_LibBlacklist_Request = Null;
127 |
128 | if (G_LibBlacklist_BlacklistURL == "") G_LibBlacklist_BlacklistURL = C_LibBlacklist_DefaultListURL;
129 |
130 | if (Http.IsValidUrl(G_LibBlacklist_BlacklistURL)) {
131 | G_LibBlacklist_Request = Http.CreateGet(G_LibBlacklist_BlacklistURL, False);
132 | G_LibBlacklist_RequestStartTime = Now;
133 | }
134 | }
135 |
136 | if (G_LibBlacklist_Request != Null) {
137 | // ---------------------------------- //
138 | // Request finished
139 | if (G_LibBlacklist_Request.IsCompleted) {
140 | Private_UpdateBlacklistFromXML(G_LibBlacklist_Request.Result);
141 | Http.Destroy(G_LibBlacklist_Request);
142 | G_LibBlacklist_Request = Null;
143 | }
144 |
145 | // ---------------------------------- //
146 | // Request timed out
147 | else if (Now >= G_LibBlacklist_RequestStartTime + C_LibBlacklist_HttpReqTimeout) {
148 | Http.Destroy(G_LibBlacklist_Request);
149 | G_LibBlacklist_Request = Null;
150 | }
151 | }
152 |
153 | // ---------------------------------- //
154 | // Kick banned users trying to connect or already connected
155 | if (Users.count > 0 && (Now >= G_LibBlacklist_NextUsersCheck || G_LibBlacklist_PrevUsersCount != Users.count)) {
156 | G_LibBlacklist_PrevUsersCount = Users.count;
157 |
158 | foreach (User in Users) {
159 | if (User.Login != ServerLogin && G_LibBlacklist_BannedUsers.existskey(User.Login)) {
160 | declare Reason = G_LibBlacklist_BannedUsers[User.Login];
161 |
162 | // Notify all players on the server about kick
163 | if (!G_LibBlacklist_ShownReasons.exists(User.Login)) {
164 | G_LibBlacklist_ShownReasons.add(User.Login);
165 | Translations::SendChat([C_LibBlacklist_ChatMessage, User.Name, Reason]);
166 | }
167 |
168 | // Kick the user
169 | Admin_KickUser(User, Translations::Compose(User.Language, "", [C_LibBlacklist_UserMessage, Reason], ""));
170 | }
171 | }
172 |
173 | // Set next validation time
174 | G_LibBlacklist_NextUsersCheck = Now + C_LibBlacklist_CheckInterval;
175 | }
176 |
177 | // ---------------------------------- //
178 | // Clear displayed reason on map change
179 | if (G_LibBlacklist_PrevMapLoaded != MapLoaded) {
180 | G_LibBlacklist_PrevMapLoaded = MapLoaded;
181 | if (!MapLoaded) G_LibBlacklist_ShownReasons.clear();
182 | }
183 | }
184 |
185 | // ---------------------------------- //
186 | /// Loop using default blacklist file
187 | Void Loop() { Loop(C_LibBlacklist_DefaultListURL); }
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/Openplanet.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY OPENPLANET by Dommy //
3 | // script version: 2018-05-31 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * A simple framework library automating the process
8 | * of detecting Openplanet in game modes and game mode
9 | * manialinks.
10 | *
11 | * Learn more about Openplanet platform by Miss here:
12 | * https://openplanet.nl/
13 | */
14 |
15 | #Const Version "2018-05-31"
16 | #Const ScriptName "Libs/domino54/Openplanet.Script.txt"
17 |
18 | // ---------------------------------- //
19 | // Global variables
20 | // ---------------------------------- //
21 | declare CUILayer G_LibOpenplanet_TransportLayer; ///< Layer used to send user Openplanet status to the server.
22 |
23 | // ---------------------------------- //
24 | // Functions
25 | // ---------------------------------- //
26 |
27 | // ---------------------------------- //
28 | // Private
29 | // ---------------------------------- //
30 |
31 | // ---------------------------------- //
32 | /** Create manialink for the Openplanet library.
33 | *
34 | * @return Openplanet lib manialink.
35 | */
36 | Text Private_CreateManialinkOpenplanet() {
37 | return """
38 |
39 |
51 |
52 | """;
53 | }
54 |
55 | // ---------------------------------- //
56 | // Public
57 | // ---------------------------------- //
58 |
59 | // ---------------------------------- //
60 | /** Return the version number of the script.
61 | *
62 | * @return The version number of the script.
63 | */
64 | Text GetScriptVersion() {
65 | return Version;
66 | }
67 |
68 | // ---------------------------------- //
69 | /** Return the name of the script.
70 | *
71 | * @return The name of the script.
72 | */
73 | Text GetScriptName() {
74 | return ScriptName;
75 | }
76 |
77 | // ---------------------------------- //
78 | /** Get a player by their login.
79 | *
80 | * @param _Login Login of the player to find.
81 | *
82 | * @return Matching player.
83 | */
84 | CPlayer GetPlayer(Text _Login) {
85 | if (_Login == "") return Null;
86 |
87 | foreach (Player in Players) {
88 | if (Player.Login == _Login) return Player;
89 | }
90 |
91 | return Null;
92 | }
93 |
94 | // ---------------------------------- //
95 | /** Check if user has Openplanet installed.
96 | *
97 | * @param _UI The UI to check.
98 | *
99 | * @return True, if the user has Openplanet installed.
100 | */
101 | Boolean HasOpenplanet(CUIConfig _UI) {
102 | if (_UI == Null) return False;
103 |
104 | declare netread Boolean Net_LibOpenplanet_HasOpenplanet for _UI;
105 | return Net_LibOpenplanet_HasOpenplanet;
106 | }
107 |
108 | // ---------------------------------- //
109 | /** Check if user has Openplanet installed.
110 | *
111 | * @param _Player The player to check.
112 | *
113 | * @return True, if the user has Openplanet installed.
114 | */
115 | Boolean HasOpenplanet(CPlayer _Player) {
116 | if (_Player == Null) return False;
117 |
118 | declare UI <=> UIManager.GetUI(_Player);
119 | if (UI == Null) return False;
120 |
121 | return HasOpenplanet(UI);
122 | }
123 |
124 | // ---------------------------------- //
125 | /** Check if user has Openplanet installed.
126 | *
127 | * @param _Login The login to check.
128 | *
129 | * @return True, if the user has Openplanet installed.
130 | */
131 | Boolean HasOpenplanet(Text _Login) {
132 | if (_Login == "") return False;
133 |
134 | declare Player <=> GetPlayer(_Login);
135 | if (Player == Null) return False;
136 |
137 | return HasOpenplanet(Player);
138 | }
139 |
140 | // ---------------------------------- //
141 | /** Check if user has Openplanet installed.
142 | *
143 | * @param _User The user to check.
144 | *
145 | * @return True, if the user has Openplanet installed.
146 | */
147 | Boolean HasOpenplanet(CUser _User) {
148 | if (_User == Null) return False;
149 |
150 | declare UI <=> UIManager.GetUI(_User);
151 | if (UI == Null) return False;
152 |
153 | return HasOpenplanet(UI);
154 | }
155 |
156 | // ---------------------------------- //
157 | /** Check if user has Openplanet installed.
158 | *
159 | * @param _Score The score to check.
160 | *
161 | * @return True, if the user has Openplanet installed.
162 | */
163 | Boolean HasOpenplanet(CScore _Score) {
164 | if (_Score == Null || _Score.User == Null) return False;
165 |
166 | return HasOpenplanet(_Score.User.Login);
167 | }
168 |
169 | // ---------------------------------- //
170 | /** Get the number of connected Openplanet users.
171 | *
172 | * @return Number of connected users with Openplanet installed.
173 | */
174 | Integer NbOpenplanetUsers() {
175 | declare NbOpenplanetUsers = 0;
176 |
177 | foreach (Player in AllPlayers) {
178 | if (HasOpenplanet(Player)) NbOpenplanetUsers += 1;
179 | }
180 |
181 | return NbOpenplanetUsers;
182 | }
183 |
184 | // ---------------------------------- //
185 | /// Unload the library.
186 | Void Unload() {
187 | if (G_LibOpenplanet_TransportLayer != Null) {
188 | declare Removed = UIManager.UIAll.UILayers.remove(G_LibOpenplanet_TransportLayer);
189 | UIManager.UILayerDestroy(G_LibOpenplanet_TransportLayer);
190 | G_LibOpenplanet_TransportLayer = Null;
191 | }
192 | }
193 |
194 | // ---------------------------------- //
195 | /// Load the library.
196 | Void Load() {
197 | Unload();
198 |
199 | G_LibOpenplanet_TransportLayer = UIManager.UILayerCreate();
200 | G_LibOpenplanet_TransportLayer.ManialinkPage = Private_CreateManialinkOpenplanet();
201 | UIManager.UIAll.UILayers.add(G_LibOpenplanet_TransportLayer);
202 | }
203 |
204 | // ---------------------------------- //
205 | /// Library loop.
206 | Void Loop() {
207 | if (G_LibOpenplanet_TransportLayer == Null) return;
208 |
209 | // Players Openplanet status
210 | foreach (Player in AllPlayers) {
211 | declare netwrite Boolean Net_LibOpenplanet_HasOpenplanet_Server for Player.Score;
212 | Net_LibOpenplanet_HasOpenplanet_Server = HasOpenplanet(Player);
213 | }
214 | }
215 |
216 | // ---------------------------------- //
217 | /** Insert Openplanet detection methods to a manialink.
218 | *
219 | * @return Text body of methods returning Openplanet presence status.
220 | */
221 | Text IntoManialink() {
222 | return """
223 | Boolean HasOpenplanet() {
224 | return SystemSkuIdentifier == CMlScript::ESystemSkuIdentifier::EU;
225 | }
226 |
227 | Boolean HasOpenplanet(CScore _Score) {
228 | if (_Score == Null) return False;
229 |
230 | declare netread Boolean Net_LibOpenplanet_HasOpenplanet_Server for _Score;
231 | return Net_LibOpenplanet_HasOpenplanet_Server;
232 | }
233 |
234 | Boolean HasOpenplanet(CPlayer _Player) {
235 | if (_Player == Null) return False;
236 |
237 | switchtype (_Player) {
238 | case CTmMlPlayer : return HasOpenplanet((_Player as CTmMlPlayer).Score);
239 | case CSmPlayer : return HasOpenplanet((_Player as CSmPlayer).Score);
240 | }
241 |
242 | return False;
243 | }
244 |
245 | Integer NbOpenplanetUsers() {
246 | declare NbOpenplanetUsers = 0;
247 |
248 | foreach (Player in Players) {
249 | if (HasOpenplanet(Player)) NbOpenplanetUsers += 1;
250 | }
251 |
252 | return NbOpenplanetUsers;
253 | }
254 | """;
255 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/PayloadArena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // JAILBREAK V2 ARENA by domino54 //
3 | // script version: 2017-06-14 //
4 | // -------------------------------------- //
5 |
6 | #RequireContext CSmMapType
7 |
8 | #Const Version "2017-06-14"
9 | #Const MapTypeVersion 1
10 | #Const ScriptName "MapTypes/ShootMania/PayloadArena.Script.txt"
11 |
12 | #Include "MathLib" as ML
13 | #Include "TextLib" as TL
14 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
15 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
16 | // Custom libraries
17 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
18 |
19 | // ---------------------------------- //
20 | // Constants
21 | // ---------------------------------- //
22 | #Const C_PayloadArena_MaxNbSectors 9 ///< Maximum number of sectors the player can split the map to
23 |
24 | #Const C_PayloadArena_Rules "$<%11.$> Your map must be split into Sectors in number of between 1 and 9.\n$<%12.$> Each Sector must consist of exactly one SpawnAtk, SpawnDef and Checkpoint.\n$<%13.$> First Sector's SpawnAtk must be in a separate room with at least one Gate being the only way out.\n$<%14.$> Draw a BotPath named Payload, which will define the Payload route. Keep in mind that Payload moves in a straight line between points in the BotPath, so the actual route will be different than line shown in editor. Put a point at start and end of every slope to avoid Payload clipping into ground or flying in air.\n$<%15.$> Gates separating next Sectors can be placed, but are not required."
25 |
26 | // ---------------------------------- //
27 | // Functions
28 | // ---------------------------------- //
29 |
30 | // ---------------------------------- //
31 | /// Update the map's validation status
32 | Void UpdateValidability() {
33 | foreach (Anchor in AnchorData) {
34 | declare MinOrder = 0;
35 | if (
36 | Anchor.DefaultTag == "Spawn" || Anchor.DefaultTag == "Goal" ||
37 | Anchor.DefaultTag == "Gate" || Anchor.DefaultTag == "Checkpoint"
38 | )
39 | MinOrder = 1;
40 |
41 | Anchor.Order = ML::Clamp(Anchor.Order, MinOrder, C_PayloadArena_MaxNbSectors);
42 |
43 | if (Anchor.DefaultTag == "Spawn") {
44 | if (Anchor.Tag != "SpawnAtk" && Anchor.Tag != "SpawnDef") Anchor.Tag = "SpawnAtk";
45 | }
46 | else if (Anchor.DefaultTag == "BotPath") {
47 | if (Anchor.Tag != "BotPath" && Anchor.Tag != "Payload") Anchor.Tag = Anchor.DefaultTag;
48 | }
49 | else if (Anchor.DefaultTag == "Goal") Anchor.Tag = "Checkpoint";
50 |
51 | else Anchor.Tag = Anchor.DefaultTag;
52 | }
53 |
54 | // ---------------------------------- //
55 | // Compute total amount of anchors on the map
56 | declare MaxOrder = 1;
57 | declare Integer[] AvailableOrders;
58 |
59 | declare Integer[Integer] NbSpawnsAtk;
60 | declare Integer[Integer] NbSpawnsDef;
61 | declare Integer[Integer] NbCheckpoints;
62 |
63 | foreach (Anchor in AnchorData) {
64 | // ---------------------------------- //
65 | // Get Ids of sectors the player has created
66 | if (!AvailableOrders.exists(Anchor.Order)) {
67 | AvailableOrders.add(Anchor.Order);
68 | AvailableOrders.sort();
69 | }
70 |
71 | // Update the highest sector order on the map
72 | if (Anchor.Order > MaxOrder) MaxOrder = Anchor.Order;
73 |
74 | // ---------------------------------- //
75 | // Get amount of SpawnAtk for every sector
76 | if (Anchor.Tag == "SpawnAtk") {
77 | if (!NbSpawnsAtk.existskey(Anchor.Order)) NbSpawnsAtk[Anchor.Order] = 0;
78 | NbSpawnsAtk[Anchor.Order] += 0;
79 | }
80 |
81 | // ---------------------------------- //
82 | // Get amount of SpawnDef for every sector
83 | if (Anchor.Tag == "SpawnDef") {
84 | if (!NbSpawnsDef.existskey(Anchor.Order)) NbSpawnsDef[Anchor.Order] = 0;
85 | NbSpawnsDef[Anchor.Order] += 0;
86 | }
87 |
88 | // ---------------------------------- //
89 | // Get amount of Checkpoints for every sector
90 | if (Anchor.Tag == "Checkpoint") {
91 | if (!NbCheckpoints.existskey(Anchor.Order)) NbCheckpoints[Anchor.Order] = 0;
92 | NbCheckpoints[Anchor.Order] += 0;
93 | }
94 | }
95 |
96 | // ---------------------------------- //
97 | // Player exceeded the maximum accepted number of sectors
98 | if (MaxOrder > C_PayloadArena_MaxNbSectors) {
99 | ValidationStatus = CMapType::ValidationStatus::NotValidable;
100 | ValidabilityRequirementsMessage = TL::Compose(_("You can split your map only up to %1 sectors!"), "9");
101 | return;
102 | }
103 |
104 | // ---------------------------------- //
105 | // Player missed at least one sector in the chain
106 | declare Text[] MissedSectors;
107 | for (I, 1, MaxOrder) if (!AvailableOrders.exists(I)) MissedSectors.add(TL::ToText(I));
108 |
109 | if (MissedSectors.count > 0) {
110 | ValidationStatus = CMapType::ValidationStatus::NotValidable;
111 | ValidabilityRequirementsMessage = TL::Compose(_("Your map is missing following sectors: %1."), TL::Join(", ", MissedSectors));
112 | return;
113 | }
114 |
115 | // Update amount of anchors in lib for later check
116 | Anchor::UpdateAnchorCounts();
117 |
118 | // ---------------------------------- //
119 | // Check if every sector has exactly one SpawnAtk, SpawnDef and Checkpoint
120 | for (I, 1, MaxOrder) {
121 | if (!Anchor::HasExactlyOneAnchor("SpawnAtk", I, TL::Compose(_("You must place exactly one SpawnAtk #1!"), TL::ToText(I)))) return;
122 | if (!Anchor::HasExactlyOneAnchor("SpawnDef", I, TL::Compose(_("You must place exactly one SpawnDef #1!"), TL::ToText(I)))) return;
123 | if (!Anchor::HasExactlyOneAnchor("Checkpoint", I, TL::Compose(_("You must place exactly one Checkpoint #1!"), TL::ToText(I)))) return;
124 | }
125 |
126 | // ---------------------------------- //
127 | // Map must have exactly one Payload BotPath
128 |
129 | // Ommited: BotPaths don't have an anchor, yet
130 | // if (!Anchor::HasAtLeastOneAnchor("Payload", 0, _("You must draw the Payload path!"))) return;
131 |
132 | // ---------------------------------- //
133 | // Map must have at least one jail Gate in the first sector
134 | if (!Anchor::HasAtLeastOneAnchor("Gate", 1, _("You must place at least one Gate #1"))) return;
135 |
136 | // ---------------------------------- //
137 | // Force player to place exactly one podium
138 | declare NbPodiums = 0;
139 | foreach (Block in Blocks) if (Block.BlockModel.Name == "Podium") NbPodiums += 1;
140 |
141 | if (NbPodiums != 1) {
142 | ValidationStatus = CMapType::ValidationStatus::NotValidable;
143 | ValidabilityRequirementsMessage = _("You must place exactly one Podium!");
144 | return;
145 | }
146 | }
147 |
148 | // ---------------------------------- //
149 | /// Show the anchor edition manialink
150 | Void EditAnchorData(Ident _EditedAnchorDataId) {
151 | if (_EditedAnchorDataId == NullId) return;
152 | UpdateValidability();
153 | EditAnchors::EditAnchor(_EditedAnchorDataId);
154 | UpdateValidability();
155 | }
156 |
157 | // ---------------------------------- //
158 | // Main
159 | // ---------------------------------- //
160 | main() {
161 | MapType::SetVersion(MapTypeVersion);
162 | UpdateValidability();
163 | CustomEditAnchorData = True;
164 |
165 | declare CpList = ["Checkpoint #1", "Checkpoint #2", "Checkpoint #3", "Checkpoint #4", "Checkpoint #5", "Checkpoint #6", "Checkpoint #7", "Checkpoint #8", "Checkpoint #9"];
166 |
167 | EditAnchors::SetRulesText(TL::Compose(C_PayloadArena_Rules, "$o$070"));
168 | EditAnchors::SetAvailableTags([
169 | "Spawn" => ["SpawnAtk #1", "SpawnAtk #2", "SpawnAtk #3", "SpawnAtk #4", "SpawnAtk #5", "SpawnAtk #6", "SpawnAtk #7", "SpawnAtk #8", "SpawnAtk #9", "SpawnDef #1", "SpawnDef #2", "SpawnDef #3", "SpawnDef #4", "SpawnDef #5", "SpawnDef #6", "SpawnDef #7", "SpawnDef #8", "SpawnDef #9"],
170 | "Goal" => CpList,
171 | "Checkpoint" => CpList,
172 | "Gate" => ["Gate #1", "Gate #2", "Gate #3", "Gate #4", "Gate #5", "Gate #6", "Gate #7", "Gate #8", "Gate #9"],
173 | "Laser" => ["Laser #0", "Laser #1", "Laser #2", "Laser #3", "Laser #4", "Laser #5", "Laser #6", "Laser #7", "Laser #8", "Laser #9"],
174 | "Nucleus" => ["Nucleus #0", "Nucleus #1", "Nucleus #2", "Nucleus #3", "Nucleus #4", "Nucleus #5", "Nucleus #6", "Nucleus #7", "Nucleus #8", "Nucleus #9"],
175 | "Arrow" => ["Arrow #0", "Arrow #1", "Arrow #2", "Arrow #3", "Arrow #4", "Arrow #5", "Arrow #6", "Arrow #7", "Arrow #8", "Arrow #9"],
176 | "Rocket" => ["Rocket #0", "Rocket #1", "Rocket #2", "Rocket #3", "Rocket #4", "Rocket #5", "Rocket #6", "Rocket #7", "Rocket #8", "Rocket #9"],
177 | "Fuel" => ["Fuel #0", "Fuel #1", "Fuel #2", "Fuel #3", "Fuel #4", "Fuel #5", "Fuel #6", "Fuel #7", "Fuel #8", "Fuel #9"],
178 | "Replie" => ["Replie #0", "Replie #1", "Replie #2", "Replie #3", "Replie #4", "Replie #5", "Replie #6", "Replie #7", "Replie #8", "Replie #9"],
179 | "Armor" => ["Armor #0", "Armor #1", "Armor #2", "Armor #3", "Armor #4", "Armor #5", "Armor #6", "Armor #7", "Armor #8", "Armor #9"]
180 | ]);
181 |
182 | // ---------------------------------- //
183 | // Yield
184 | // ---------------------------------- //
185 | while (True) {
186 | yield;
187 |
188 | // ---------------------------------- //
189 | // Events management
190 | foreach (Event in PendingEvents) {
191 | switch (Event.Type) {
192 | case CPluginEvent::Type::MapModified : UpdateValidability();
193 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
194 | }
195 | }
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/Media/Characters/GalaxyDefault.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Arena Player
18 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/ArenaPlayer_IconColor.png
19 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/ArenaPlayer_IconNormal.png
20 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/ArenaPlayer_ImageColor.png
21 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/ArenaPlayer_ImageNormal.png
22 | The main protagonist of ShootMania. Equipped with the original loadout of Galaxy.
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | Full access to the basic ShootMania arsenal.
37 |
38 |
39 | Doesn't offer any special abilities.
40 |
41 |
42 |
43 | Sintel
44 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Sintel_IconColor.png
45 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Sintel_IconNormal.png
46 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Sintel_ImageColor.png
47 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Sintel_ImageNormal.png
48 | In some situations the key is to move quickly eneough. Sintel may know something about that.
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | Missile
61 | file://Media/Manialinks/ShootMania/GalaxyTitles/Icons/Missile.png
62 | Can use the Missile weapon. Bullets follow nearest enemy, no matter how far away they are.
63 |
64 |
65 | Weapon with homing functionality.
66 | Increased movement speed.
67 |
68 |
69 | Can't pick up weapon items, with exception of Rocket.
70 | Reloading only currently used weapon at time.
71 | Armor reduced by 1 unit.
72 |
73 |
74 |
75 | Susu
76 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Susu_IconColor.png
77 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Susu_IconNormal.png
78 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Susu_ImageColor.png
79 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Susu_ImageNormal.png
80 | They say it's always better together. A good example can be Susu and her well trained Toad.
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | Toad Assist
95 | file://Media/Manialinks/ShootMania/GalaxyTitles/Icons/Toad.png
96 | Can summon a Toad assisting the player during the game. Toad is attacking nearby opponents and picking up items within a small radius.
97 |
98 |
99 | Toad helping the player in game.
100 | Toad can be healed with Replie and boosted with Fuel.
101 |
102 |
103 | Reduced ammo reload speed.
104 | Need to wait 8 seconds before another Toad can be summoned.
105 |
106 |
107 |
108 | Constructor
109 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/TronMan_IconColor.png
110 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/TronMan_ImageColor.png
111 | If you're one of these people, who wanna play but are too lazy, a Turret is perfect solution for you.
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Sentry Turret
126 | file://Media/Manialinks/ShootMania/GalaxyTitles/Icons/Turret.png
127 | Can deploy a Sentry Turret attacking approaching opponents within certain radius. Turret has 4 Armors.
128 |
129 |
130 | Turret guarding small area on the map.
131 | Turret can be repaired with Replie.
132 |
133 |
134 | Reduced ammo reload speed.
135 | Need to wait 8 seconds before another Turret can be deployed.
136 |
137 |
138 |
139 | Medic
140 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/StormWoman_IconColor.png
141 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/StormWoman_IconNormal.png
142 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/StormWoman_ImageColor.png
143 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/StormWoman_ImageNormal.png
144 | There is always need for someone to keep the team alive. If you're kind enough, it can be you.
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 | Infinite supplies
159 | file://Media/Manialinks/ShootMania/GalaxyTitles/Icons/ArmorBoost.png
160 | Infinite supply of Replie and Fuel in the inventory. Enough for keeping teammates healthy and effective.
161 |
162 |
163 | Infinite Replie and Fuel supply.
164 | Fuel accessible as inventory item.
165 |
166 |
167 | Can't pick up Replie and Fuel.
168 | Fuel affects only other players and can be used only if teammates are nearby.
169 | At least 5 seconds cooldown between each supply use.
170 |
171 |
172 |
173 | Toad
174 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Toad_IconColor.png
175 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Toad_IconNormal.png
176 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Toad_ImageColor.png
177 | file://Media/Manialinks/ShootMania/GalaxyTitles/Characters/Toad_ImageNormal.png
178 | Always wondered how the world of ShootMania looks like from a Toad's perspective? Now you can check it yourself.
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 | Small and hard to hit.
193 |
194 |
195 | Reduced movement speed and stamina amount.
196 | Can use Stamina only when touching ground.
197 | Can't walljump and use grappling hooks.
198 |
199 |
200 |
201 |
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/MarkersPro.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY MARKERS PRO by domino54 //
3 | // script version: 2017-07-19 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * This library allows you to create UI markers for
8 | * both everyone and a specific player, without the
9 | * problem of player's markers overriding global ones.
10 | */
11 |
12 | #Const Version "2017-07-19"
13 | #Const ScriptName "Libs/domino54/MarkersPro.Script.txt"
14 |
15 | #Include "Libs/Nadeo/Layers2.Script.txt" as Layers
16 |
17 | // ---------------------------------- //
18 | // Constants
19 | // ---------------------------------- //
20 | #Const C_LibProMarkers_ControllerLayerId "LibProMarkers:Controller"
21 |
22 | // ---------------------------------- //
23 | // Global variables
24 | // ---------------------------------- //
25 | declare Text[Text] G_LibProMarkers_GlobalMarkers;
26 |
27 | // ---------------------------------- //
28 | // Functions
29 | // ---------------------------------- //
30 |
31 | // ---------------------------------- //
32 | // Private
33 | // ---------------------------------- //
34 |
35 | // ---------------------------------- //
36 | /** Create manialink for the markers controller module.
37 | *
38 | * @return The markers controller manialink.
39 | */
40 | Text Private_CreateManialinkController() {
41 | return """
42 |
43 |
118 |
119 | """;
120 | }
121 |
122 | // ---------------------------------- //
123 | /** Check if the marker's tag is correctly formatted.
124 | *
125 | * @param _MarkerTag The marker tag to check.
126 | *
127 | * @return True, if the marker tag is correct.
128 | */
129 | Boolean Private_CheckMarkerIntegrity(Text _MarkerTag) {
130 | if (_MarkerTag == "") return False;
131 |
132 | declare Document <=> Xml.Create(_MarkerTag);
133 | if (Document == Null) return False;
134 |
135 | declare IsValid = Document.Root != Null && Document.Root.Name == "marker";
136 | Xml.Destroy(Document);
137 | return IsValid;
138 | }
139 |
140 | // ---------------------------------- //
141 | /// Update the global set of markers.
142 | Void Private_UpdateGlobal() {
143 | declare netwrite Integer Net_LibProMarkers_GlobalMarkersUpdate for Teams[0];
144 | declare netwrite Text Net_LibProMarkers_GlobalMarkersXML for Teams[0];
145 |
146 | Net_LibProMarkers_GlobalMarkersUpdate = Now;
147 | Net_LibProMarkers_GlobalMarkersXML = "";
148 | foreach (MarkerId => MarkerTag in G_LibProMarkers_GlobalMarkers)
149 | Net_LibProMarkers_GlobalMarkersXML ^= MarkerTag;
150 | }
151 |
152 | // ---------------------------------- //
153 | /** Update a player's set of markers.
154 | *
155 | * @param _Player The player to update.
156 | */
157 | Void Private_UpdatePlayer(CPlayer _Player) {
158 | if (_Player == Null) return;
159 |
160 | declare netwrite Integer Net_LibProMarkers_PlayerMarkersUpdate for _Player;
161 | declare netwrite Text Net_LibProMarkers_PlayerMarkersXML for _Player;
162 | declare Text[Text] LibProMarkers_PlayerMarkers for _Player;
163 |
164 | Net_LibProMarkers_PlayerMarkersUpdate = Now;
165 | Net_LibProMarkers_PlayerMarkersXML = "";
166 | foreach (MarkerId => MarkerTag in LibProMarkers_PlayerMarkers)
167 | Net_LibProMarkers_PlayerMarkersXML ^= MarkerTag;
168 | }
169 |
170 | // ---------------------------------- //
171 | // Public
172 | // ---------------------------------- //
173 |
174 | // ---------------------------------- //
175 | /** Return the version number of the script.
176 | *
177 | * @return The version number of the script.
178 | */
179 | Text GetScriptVersion() { return Version; }
180 |
181 | // ---------------------------------- //
182 | /** Return the name of the script.
183 | *
184 | * @return The name of the script.
185 | */
186 | Text GetScriptName() { return ScriptName; }
187 |
188 | // ---------------------------------- //
189 | /** Add a new global marker.
190 | *
191 | * @param _MarkerId Id of the new marker to add.
192 | * @param _MarkerTag The marker tag itself.
193 | */
194 | Void AddMarker(Text _MarkerId, Text _MarkerTag) {
195 | if (_MarkerId == "" || !Private_CheckMarkerIntegrity(_MarkerTag)) return;
196 | G_LibProMarkers_GlobalMarkers[_MarkerId] = _MarkerTag;
197 | Private_UpdateGlobal();
198 | }
199 |
200 | // ---------------------------------- //
201 | /** Add a marker for a player.
202 | *
203 | * @param _MarkerId Id of the new marker to add.
204 | * @param _MarkerTag The marker tag itself.
205 | * @param _Player The player to add a new marker.
206 | */
207 | Void AddMarker(Text _MarkerId, Text _MarkerTag, CPlayer _Player) {
208 | if (_MarkerId == "" || !Private_CheckMarkerIntegrity(_MarkerTag) || _Player == Null) return;
209 | declare Text[Text] LibProMarkers_PlayerMarkers for _Player;
210 | LibProMarkers_PlayerMarkers[_MarkerId] = _MarkerTag;
211 | Private_UpdatePlayer(_Player);
212 | }
213 |
214 | // ---------------------------------- //
215 | /** Remove a global marker.
216 | *
217 | * @param _MarkerId Id of the marker to remove.
218 | */
219 | Void RemoveMarker(Text _MarkerId) {
220 | if (!G_LibProMarkers_GlobalMarkers.existskey(_MarkerId)) return;
221 | declare Removed = G_LibProMarkers_GlobalMarkers.removekey(_MarkerId);
222 | Private_UpdateGlobal();
223 | }
224 |
225 | // ---------------------------------- //
226 | /** Remove player's marker.
227 | *
228 | * @param _MarkerId Id of the marker to remove.
229 | * @param _Player The player to remove their marker.
230 | */
231 | Void RemoveMarker(Text _MarkerId, CPlayer _Player) {
232 | if (_Player == Null) return;
233 | declare Text[Text] LibProMarkers_PlayerMarkers for _Player;
234 | if (!LibProMarkers_PlayerMarkers.existskey(_MarkerId)) return;
235 | declare Removed = LibProMarkers_PlayerMarkers.removekey(_MarkerId);
236 | Private_UpdatePlayer(_Player);
237 | }
238 |
239 | // ---------------------------------- //
240 | /// Reset global markers.
241 | Void ResetGlobal() {
242 | G_LibProMarkers_GlobalMarkers.clear();
243 | Private_UpdateGlobal();
244 | }
245 |
246 | // ---------------------------------- //
247 | /* Reset markers of a player.
248 | *
249 | * @param _Player The player to reset their markers.
250 | */
251 | Void ResetPlayer(CPlayer _Player) {
252 | if (_Player == Null) return;
253 | declare Text[Text] LibProMarkers_PlayerMarkers for _Player;
254 | LibProMarkers_PlayerMarkers.clear();
255 | Private_UpdatePlayer(_Player);
256 | }
257 |
258 | // ---------------------------------- //
259 | /// Reset all players' markers.
260 | Void ResetAllPlayers() {
261 | foreach (Player in AllPlayers) ResetPlayer(Player);
262 | }
263 |
264 | // ---------------------------------- //
265 | /// Reset the library.
266 | Void Reset() {
267 | ResetGlobal();
268 | ResetAllPlayers();
269 | }
270 |
271 | // ---------------------------------- //
272 | /// Unload the library.
273 | Void Unload() {
274 | Reset();
275 | Layers::Detach(C_LibProMarkers_ControllerLayerId);
276 | Layers::Destroy(C_LibProMarkers_ControllerLayerId);
277 | }
278 |
279 | // ---------------------------------- //
280 | /// Load the library.
281 | Void Load() {
282 | Unload();
283 | Layers::Create(C_LibProMarkers_ControllerLayerId, Private_CreateManialinkController());
284 | Layers::Attach(C_LibProMarkers_ControllerLayerId);
285 | }
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/EditAnchors.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY EDIT ANCHORS by domino54 //
3 | // script version: 2017-07-14 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * Used in maptypes to easily create anchor edit manialinks.
8 | */
9 |
10 | #Const Version "2017-07-14"
11 | #Const ScriptName "Libs/domino54/EditAnchors.Script.txt"
12 |
13 | #Include "MathLib" as ML
14 | #Include "TextLib" as TL
15 |
16 | // ---------------------------------- //
17 | // Constants
18 | // ---------------------------------- //
19 | #Const C_LibEditAnchors_WindowWidth 70.
20 | #Const C_LibEditAnchors_WindowPosnX 124.
21 |
22 | // ---------------------------------- //
23 | // Global variables
24 | // ---------------------------------- //
25 | declare Text G_LibEditAnchors_Rules;
26 | declare Text[][Text] G_LibEditAnchors_AvailableTags;
27 |
28 | // ---------------------------------- //
29 | // Functions
30 | // ---------------------------------- //
31 |
32 | // ---------------------------------- //
33 | // Public
34 | // ---------------------------------- //
35 |
36 | // ---------------------------------- //
37 | /** Return the version number of the script
38 | *
39 | * @return The version number of the script
40 | */
41 | Text GetScriptVersion() { return Version; }
42 |
43 | // ---------------------------------- //
44 | /** Return the name of the script
45 | *
46 | * @return The name of the script
47 | */
48 | Text GetScriptName() { return ScriptName; }
49 |
50 | // ---------------------------------- //
51 | /** Set the maptype rules
52 | *
53 | * @param _Rules Rules of the anchors placement
54 | */
55 | Void SetRulesText(Text _Rules) { G_LibEditAnchors_Rules = _Rules; }
56 |
57 | // ---------------------------------- //
58 | /** Set available tags for anchors
59 | *
60 | * @param _AvailableTags Available tags for anchors
61 | */
62 | Void SetAvailableTags(Text[][Text] _AvailableTags) { G_LibEditAnchors_AvailableTags = _AvailableTags; }
63 |
64 | // ---------------------------------- //
65 | /** Edit specific anchor data
66 | *
67 | * @param _AnchorId Id of the anchor to edit
68 | * @param _DefaultTag Default tag of the anchor
69 | * @param _AvailableTags Available tags to set on anchor
70 | */
71 | Void EditAnchor(Ident _AnchorId, Text _DefaultTag, Text[] _AvailableTags) {
72 | if (_AnchorId == NullId || _DefaultTag == "" || !AnchorData.existskey(_AnchorId)) return;
73 |
74 | declare Anchor <=> AnchorData[_AnchorId];
75 | declare Text TagsLabels;
76 |
77 | // Get the currently choosen tag
78 | declare SelectedTag = Anchor.Tag^" #"^Anchor.Order;
79 |
80 | // Selected anchor is not editable
81 | if (_AvailableTags.count <= 0)
82 | TagsLabels = """""";
83 |
84 | // Show available tags to set
85 | else foreach (I => Tag in _AvailableTags)
86 | TagsLabels ^= """""";
91 |
92 | // ---------------------------------- //
93 | // Create anchor edit manialink
94 | declare EditAnchorLayer <=> UILayerCreate();
95 |
96 | declare SelectTagHeight = ML::Max(1, _AvailableTags.count) * 5 + 12;
97 |
98 | EditAnchorLayer.ManialinkPage = """
99 |
100 |
101 |
102 |
106 |
110 |
114 | {{{TagsLabels}}}
115 |
119 |
123 |
124 |
125 |
129 |
133 |
137 |
141 |
142 |
143 |
144 |
228 |
229 | """;
230 |
231 | // ---------------------------------- //
232 | // Communication between the manialink and the maptype
233 | declare Boolean CloseManialink for EditAnchorLayer.LocalPage;
234 | declare Integer SelectedOption for EditAnchorLayer.LocalPage;
235 | CloseManialink = False;
236 | SelectedOption = 0;
237 |
238 | if (_AvailableTags.exists(SelectedTag)) SelectedOption = _AvailableTags.keyof(SelectedTag);
239 |
240 | // ---------------------------------- //
241 | // Pause script until user selectes an option in the manialink
242 | while (!CloseManialink) yield;
243 |
244 | if (_AvailableTags.count <= 0 || !_AvailableTags.existskey(SelectedOption)) {
245 | UILayerDestroy(EditAnchorLayer);
246 | return;
247 | }
248 |
249 | // ---------------------------------- //
250 | // Update the anchor data
251 | declare TagData = TL::Split(" #", _AvailableTags[SelectedOption]);
252 | Anchor.Tag = _DefaultTag;
253 | Anchor.Order = 0;
254 |
255 | if (TagData.existskey(0)) Anchor.Tag = TagData[0];
256 | if (TagData.existskey(1)) Anchor.Order = TL::ToInteger(TagData[1]);
257 |
258 | // Destroy interface layer
259 | UILayerDestroy(EditAnchorLayer);
260 | }
261 |
262 | // ---------------------------------- //
263 | /** Automatically create manialink from previously specified data
264 | *
265 | * @param _AnchorId Anchor to edit
266 | */
267 | Void EditAnchor(Ident _AnchorId) {
268 | if (_AnchorId == NullId || !AnchorData.existskey(_AnchorId)) return;
269 | declare Anchor <=> AnchorData[_AnchorId];
270 |
271 | declare Text[] AvailableTags;
272 | if (G_LibEditAnchors_AvailableTags.existskey(Anchor.DefaultTag))
273 | AvailableTags = G_LibEditAnchors_AvailableTags[Anchor.DefaultTag];
274 |
275 | EditAnchor(_AnchorId, Anchor.DefaultTag, AvailableTags);
276 | }
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/TrackMania/Checkpoints.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY CHECKPOINTS by domino54 //
3 | // script version: 2018-04-06 //
4 | // -------------------------------------- //
5 |
6 | #Const Version "2018-04-06"
7 | #Const ScriptName "Libs/domino54/TrackMania/Checkpoints.Script.txt"
8 |
9 | #Include "MathLib" as ML
10 |
11 | // ---------------------------------- //
12 | // Constants
13 | // ---------------------------------- //
14 | #Const C_LibCheckpoints_SafeOffsetY 1.
15 |
16 | // ---------------------------------- //
17 | // Global variables
18 | // ---------------------------------- //
19 | declare Integer[] G_LibCheckpoints_TriggersList;
20 | declare Vec3[] G_LibCheckpoints_Position;
21 | declare Vec3[] G_LibCheckpoints_Size;
22 | declare Integer[] G_LibCheckpoints_Direction;
23 | declare Integer[] G_LibCheckpoints_Type;
24 |
25 | declare Integer[Ident] G_LibCheckpoints_PendingEvents;
26 |
27 | // ---------------------------------- //
28 | // Functions
29 | // ---------------------------------- //
30 |
31 | // ---------------------------------- //
32 | // Private
33 | // ---------------------------------- //
34 |
35 | // ---------------------------------- //
36 | /** Distance to the center of a horizontal tube (X axis).
37 | *
38 | * @param _1 First position.
39 | * @param _2 Second position.
40 | *
41 | * @return The distance.
42 | */
43 | Real Private_Distance2DX(Vec3 _1, Vec3 _2) {
44 | return ML::Sqrt(ML::Pow(_1.Z - _2.Z, 2.) + ML::Pow(_1.Y - _2.Y, 2.));
45 | }
46 |
47 | // ---------------------------------- //
48 | /** Distance to the center of a vertical tube.
49 | *
50 | * @param _1 First position.
51 | * @param _2 Second position.
52 | *
53 | * @return The distance.
54 | */
55 | Real Private_Distance2DY(Vec3 _1, Vec3 _2) {
56 | return ML::Sqrt(ML::Pow(_1.X - _2.X, 2.) + ML::Pow(_1.Z - _2.Z, 2.));
57 | }
58 |
59 | // ---------------------------------- //
60 | /** Distance to the center of a vertical tube (Z axis).
61 | *
62 | * @param _1 First position.
63 | * @param _2 Second position.
64 | *
65 | * @return The distance.
66 | */
67 | Real Private_Distance2DZ(Vec3 _1, Vec3 _2) {
68 | return ML::Sqrt(ML::Pow(_1.X - _2.X, 2.) + ML::Pow(_1.Y - _2.Y, 2.));
69 | }
70 |
71 | // ---------------------------------- //
72 | // Public
73 | // ---------------------------------- //
74 |
75 | // ---------------------------------- //
76 | /** Return the version number of the script.
77 | *
78 | * @return The version number of the script.
79 | */
80 | Text GetScriptVersion() { return Version; }
81 |
82 | // ---------------------------------- //
83 | /** Return the name of the script.
84 | *
85 | * @return The name of the script.
86 | */
87 | Text GetScriptName() { return ScriptName; }
88 |
89 | // ---------------------------------- //
90 | /// Load the map checkpoints info.
91 | Void LoadMap() {
92 | if (Map == Null) return;
93 |
94 | // Reset the data
95 | G_LibCheckpoints_TriggersList .clear();
96 | G_LibCheckpoints_Position .clear();
97 | G_LibCheckpoints_Size .clear();
98 | G_LibCheckpoints_Direction .clear();
99 | G_LibCheckpoints_Type .clear();
100 |
101 | // Obtain checkpoints data from the map file
102 | declare metadata Vec3[] Metadata_Lib_Checkpoints_Position for Map;
103 | declare metadata Vec3[] Metadata_Lib_Checkpoints_Size for Map;
104 | declare metadata Integer[] Metadata_Lib_Checkpoints_Direction for Map;
105 | declare metadata Integer[] Metadata_Lib_Checkpoints_Type for Map;
106 | declare metadata Integer Metadata_Lib_Checkpoints_NbTotal for Map;
107 |
108 | for (I, 0, Metadata_Lib_Checkpoints_NbTotal - 1) {
109 | declare Vec3 Position;
110 | declare Vec3 Size;
111 | declare Direction = 0;
112 | declare Type = 0;
113 |
114 | if (Metadata_Lib_Checkpoints_Position.existskey(I)) {
115 | Position = Metadata_Lib_Checkpoints_Position[I];
116 | }
117 |
118 | if (Metadata_Lib_Checkpoints_Size.existskey(I)) {
119 | Size = Metadata_Lib_Checkpoints_Size[I];
120 | }
121 |
122 | if (Metadata_Lib_Checkpoints_Direction.existskey(I)) {
123 | Direction = Metadata_Lib_Checkpoints_Direction[I];
124 | }
125 |
126 | if (Metadata_Lib_Checkpoints_Type.existskey(I)) {
127 | Type = Metadata_Lib_Checkpoints_Type[I];
128 | }
129 |
130 | // Save the checkpoint
131 | G_LibCheckpoints_TriggersList .add(I);
132 | G_LibCheckpoints_Position .add(Position);
133 | G_LibCheckpoints_Size .add(Size);
134 | G_LibCheckpoints_Direction .add(Direction);
135 | G_LibCheckpoints_Type .add(Type);
136 | }
137 | }
138 |
139 | // ---------------------------------- //
140 | /** Get the position of the checkpoint.
141 | *
142 | * @param _CheckpointId Id of the checkpoint to get its position.
143 | *
144 | * @return Position of the checkpoint.
145 | */
146 | Vec3 GetPosition(Integer _CheckpointId) {
147 | if (!G_LibCheckpoints_Position.existskey(_CheckpointId)) return Vec3;
148 | return G_LibCheckpoints_Position[_CheckpointId];
149 | }
150 |
151 | // ---------------------------------- //
152 | /** Get the size of the checkpoint.
153 | *
154 | * @param _CheckpointId Id of the checkpoint to get its size.
155 | *
156 | * @return Size of the checkpoint.
157 | */
158 | Vec3 GetSize(Integer _CheckpointId) {
159 | if (!G_LibCheckpoints_Size.existskey(_CheckpointId)) return Vec3;
160 | return G_LibCheckpoints_Size[_CheckpointId];
161 | }
162 |
163 | // ---------------------------------- //
164 | /** Get the direction of the checkpoint.
165 | *
166 | * @param _CheckpointId Id of the checkpoint to get its direction.
167 | *
168 | * @return Direction of the checkpoint.
169 | */
170 | Integer GetDirection(Integer _CheckpointId) {
171 | if (!G_LibCheckpoints_Direction.existskey(_CheckpointId)) return 0;
172 | return G_LibCheckpoints_Direction[_CheckpointId];
173 | }
174 |
175 | // ---------------------------------- //
176 | /** Get the type of the checkpoint.
177 | *
178 | * @param _CheckpointId Id of the checkpoint to get its type.
179 | *
180 | * @return Type of the checkpoint.
181 | */
182 | Integer GetType(Integer _CheckpointId) {
183 | if (!G_LibCheckpoints_Type.existskey(_CheckpointId)) return 0;
184 | return G_LibCheckpoints_Type[_CheckpointId];
185 | }
186 |
187 | // ---------------------------------- //
188 | /** Check if the player is in a given checkpoint.
189 | *
190 | * @param _Player The player to check.
191 | * @param _TriggerId Id of the trigger to check.
192 | *
193 | * @return True, if the player is in this checkpoint.
194 | */
195 | Boolean IsInTrigger(CTmPlayer _Player, Integer _TriggerId) {
196 | if (_Player == Null || !_Player.IsSpawned || !G_LibCheckpoints_TriggersList.exists(_TriggerId)) return False;
197 |
198 | // Get the trigger info
199 | declare TriggerPosition = GetPosition(_TriggerId);
200 | declare TriggerSize = GetSize(_TriggerId);
201 | declare TriggerDirection = GetDirection(_TriggerId);
202 | declare TriggerType = GetType(_TriggerId);
203 |
204 | switch (TriggerType) {
205 | // Horizontal ring
206 | case 1 : {
207 | // Horizontal
208 | if (Private_Distance2DY(_Player.Position, TriggerPosition) > TriggerSize.X) return False;
209 |
210 | // Vertical
211 | if (ML::Abs(_Player.Position.Y - TriggerPosition.Y) > TriggerSize.Y / 2) return False;
212 |
213 | return True;
214 | }
215 |
216 | // Vertical ring
217 | case 2 : {
218 | // Z axis
219 | if (TriggerDirection == 0 || TriggerDirection == 2) {
220 | if (Private_Distance2DZ(_Player.Position, TriggerPosition) > TriggerSize.X) return False;
221 | if (ML::Abs(_Player.Position.Z - TriggerPosition.Z) > TriggerSize.Y / 2) return False;
222 | }
223 |
224 | // X axis
225 | else {
226 | if (Private_Distance2DX(_Player.Position, TriggerPosition) > TriggerSize.X) return False;
227 | if (ML::Abs(_Player.Position.X - TriggerPosition.X) > TriggerSize.Y / 2) return False;
228 | }
229 |
230 | return True;
231 | }
232 |
233 | // Prism trigger
234 | default : {
235 | // Horizontal
236 | if (ML::Abs(_Player.Position.X - TriggerPosition.X) > TriggerSize.X / 2) return False;
237 | if (ML::Abs(_Player.Position.Z - TriggerPosition.Z) > TriggerSize.Z / 2) return False;
238 |
239 | // Vertical
240 | if (_Player.Position.Y < TriggerPosition.Y - C_LibCheckpoints_SafeOffsetY) return False;
241 | if (_Player.Position.Y > TriggerPosition.Y + TriggerSize.Y + C_LibCheckpoints_SafeOffsetY) return False;
242 |
243 | return True;
244 | }
245 | }
246 |
247 | return False;
248 | }
249 |
250 | // ---------------------------------- //
251 | /** Get the id of the checkpoint the player is in.
252 | *
253 | * @param _Player The player to get the checkpoint id.
254 | *
255 | * @return Id of the active checkpoint trigger.
256 | */
257 | Integer ActiveTrigger(CTmPlayer _Player) {
258 | if (_Player == Null || !_Player.IsSpawned) return -1;
259 |
260 | foreach (TriggerId in G_LibCheckpoints_TriggersList) {
261 | if (IsInTrigger(_Player, TriggerId)) return TriggerId;
262 | }
263 |
264 | return -1;
265 | }
266 |
267 | // ---------------------------------- //
268 | /** Get the array of all checkpoints ids.
269 | *
270 | * @return Array of all checkpoints ids.
271 | */
272 | Integer[] List() {
273 | return G_LibCheckpoints_TriggersList;
274 | }
275 |
276 | // ---------------------------------- //
277 | /** Get the number of available checkpoints.
278 | *
279 | * @return Number of available checkpoints.
280 | */
281 | Integer NbCheckpoints() {
282 | return List().count;
283 | }
284 |
285 | // ---------------------------------- //
286 | /** Pending trigger change events.
287 | *
288 | * @return Array of pending events [Ident PlayerId => Integer TriggerId].
289 | */
290 | Integer[Ident] OnTriggerChange() {
291 | return G_LibCheckpoints_PendingEvents;
292 | }
293 |
294 | // ---------------------------------- //
295 | /// Library main loop.
296 | Void Loop() {
297 | // Reset all events
298 | if (G_LibCheckpoints_PendingEvents.count > 0) {
299 | G_LibCheckpoints_PendingEvents.clear();
300 | }
301 |
302 | foreach (Player in Players) {
303 | declare LibCheckpoints_PrevTriggerId for Player = -1;
304 | declare CurTriggerId = ActiveTrigger(Player);
305 |
306 | if (LibCheckpoints_PrevTriggerId == CurTriggerId) continue;
307 | LibCheckpoints_PrevTriggerId = CurTriggerId;
308 |
309 | G_LibCheckpoints_PendingEvents[Player.Id] = CurTriggerId;
310 | }
311 | }
312 |
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/ServerAuth.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY SERVER AUTH by domino54 //
3 | // script version: 2017-10-09 //
4 | // -------------------------------------- //
5 |
6 | #Const Version "2017-10-09"
7 | #Const ScriptName "Libs/domino54/ServerAuth.Script.txt"
8 |
9 | #Include "Libs/Nadeo/Layers2.Script.txt" as Layers
10 | #Include "Libs/Nadeo/ModeInfo.Script.txt" as ModeInfo
11 |
12 | // ---------------------------------- //
13 | // Constantd
14 | // ---------------------------------- //
15 | #Const C_LibServerAuth_InterfaceLayerId "LibServerAuth:Interface"
16 | #Const C_LibServerAuth_AuthRequestTimeOut 10000
17 |
18 | // Status enumerator
19 | #Const C_LibServerAuth_StatusId_Disabled 0
20 | #Const C_LibServerAuth_StatusId_Pending 1
21 | #Const C_LibServerAuth_StatusId_Authorized 2
22 | #Const C_LibServerAuth_StatusId_Forbidden 3
23 | #Const C_LibServerAuth_StatusId_InvalidURL 4
24 | #Const C_LibServerAuth_StatusId_TimedOut 5
25 |
26 | // ---------------------------------- //
27 | // Global variables
28 | // ---------------------------------- //
29 | declare Boolean G_LibServerAuth_AuthRequired;
30 | declare Boolean G_LibServerAuth_IsAuthorized;
31 | declare Text G_LibServerAuth_AuthFileURL;
32 | declare Text G_LibServerAuth_AuthPassword;
33 | declare CHttpRequest G_LibServerAuth_AuthRequest;
34 | declare Integer G_LibServerAuth_RequestStart;
35 |
36 | // ---------------------------------- //
37 | // Functions
38 | // ---------------------------------- //
39 |
40 | // ---------------------------------- //
41 | // Private
42 | // ---------------------------------- //
43 |
44 | // ---------------------------------- //
45 | /** Create manialink for the server auth window.
46 | *
47 | * @return Server auth manialink.
48 | */
49 | Text Private_CreateManialinkServerAuth() {
50 | declare Size = <120., 16.>;
51 | return """
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
91 |
92 | """;
93 | }
94 |
95 | // ---------------------------------- //
96 | /** Set current server authorization status.
97 | *
98 | * @param _StatusId Authorization status id.
99 | */
100 | Void Private_SetAuthStatus(Integer _StatusId) {
101 | declare netwrite Integer Net_LibServerAuth_StatusId for Teams[0];
102 | Net_LibServerAuth_StatusId = _StatusId;
103 | }
104 |
105 | // ---------------------------------- //
106 | /** Check if the server exists in authorized servers list.
107 | *
108 | * @param _Document XML document generated from auth request result.
109 | *
110 | * @return True, if the server is authorized.
111 | */
112 | Boolean Private_CheckServerAuthorization(CXmlDocument _Document) {
113 | if (_Document == Null || _Document.Root == Null || _Document.Root.Name != "servers") return False;
114 | declare ModeName = ModeInfo::GetName();
115 |
116 | foreach (Server in _Document.Root.Children) {
117 | if (Server.Name != "server") continue;
118 | declare NodeLogin = Server.GetAttributeText("login", "");
119 | if (NodeLogin != ServerLogin) continue;
120 |
121 | if (Server.Children.count <= 0) return True;
122 |
123 | foreach (GameMode in Server.Children) {
124 | if (GameMode.Name != "mode") continue;
125 | if (GameMode.TextContents == ModeName) return True;
126 | }
127 | }
128 |
129 | return False;
130 | }
131 |
132 | // ---------------------------------- //
133 | // Public
134 | // ---------------------------------- //
135 |
136 | // ---------------------------------- //
137 | /** Return the version number of the script.
138 | *
139 | * @return The version number of the script.
140 | */
141 | Text GetScriptVersion() { return Version; }
142 |
143 | // ---------------------------------- //
144 | /** Return the name of the script.
145 | *
146 | * @return The name of the script.
147 | */
148 | Text GetScriptName() { return ScriptName; }
149 |
150 | // ---------------------------------- //
151 | /** Check if the server is authorized to run game mode.
152 | *
153 | * @return True, if server can run the mode.
154 | */
155 | Boolean IsAuthorized() {
156 | if (!G_LibServerAuth_AuthRequired) return True;
157 | return G_LibServerAuth_IsAuthorized;
158 | }
159 |
160 | // ---------------------------------- //
161 | /** Enable authorization in game mode.
162 | *
163 | * @param _AuthURL URL of the XML file with whitelisted servers logins.
164 | * @param _AuthPassword Optional password for manual server authorization.
165 | */
166 | Void EnableAuth(Text _AuthURL, Text _AuthPassword) {
167 | if (G_LibServerAuth_AuthRequired) return;
168 | G_LibServerAuth_AuthRequired = True;
169 | G_LibServerAuth_AuthFileURL = _AuthURL;
170 | G_LibServerAuth_AuthPassword = _AuthPassword;
171 | }
172 |
173 | // ---------------------------------- //
174 | /** Begin server authorization process.
175 | *
176 | * @param _UserPassword Password entered by server owner.
177 | */
178 | Void CheckAuth(Text _UserPassword) {
179 | if (IsAuthorized()) return;
180 |
181 | // Authorize in-game servers
182 | foreach (Player in AllPlayers) {
183 | if (Player.User.Login != ServerLogin) continue;
184 | Private_SetAuthStatus(C_LibServerAuth_StatusId_Authorized);
185 | G_LibServerAuth_IsAuthorized = True;
186 | return;
187 | }
188 |
189 | // Skip online permissions check if server owner entered correct passcode
190 | if (_UserPassword != "" && _UserPassword == G_LibServerAuth_AuthPassword) {
191 | Private_SetAuthStatus(C_LibServerAuth_StatusId_Authorized);
192 | G_LibServerAuth_IsAuthorized = True;
193 | return;
194 | }
195 |
196 | // Invalid data file URL
197 | if (!Http.IsValidUrl(G_LibServerAuth_AuthFileURL)) {
198 | Private_SetAuthStatus(C_LibServerAuth_StatusId_InvalidURL);
199 | G_LibServerAuth_RequestStart = Now;
200 | return;
201 | }
202 |
203 | // Start the request
204 | Private_SetAuthStatus(C_LibServerAuth_StatusId_Pending);
205 | G_LibServerAuth_AuthRequest = Http.CreateGet(G_LibServerAuth_AuthFileURL, False);
206 | G_LibServerAuth_RequestStart = Now;
207 |
208 | // Create authorization interface
209 | Layers::Create(C_LibServerAuth_InterfaceLayerId, Private_CreateManialinkServerAuth());
210 | Layers::Attach(C_LibServerAuth_InterfaceLayerId);
211 | }
212 |
213 | // ---------------------------------- //
214 | /** Wait for the authorization to be completed.
215 | *
216 | * @param _UserPassword Password entered by server owner.
217 | *
218 | * @return True, if request is being processed.
219 | */
220 | Boolean AuthLoop(Text _UserPassword) {
221 | if (IsAuthorized()) return False;
222 | if (G_LibServerAuth_RequestStart <= 0) return False;
223 |
224 | // Server owner entered correct passcode
225 | if (_UserPassword != "" && _UserPassword == G_LibServerAuth_AuthPassword) {
226 | Private_SetAuthStatus(C_LibServerAuth_StatusId_Authorized);
227 | G_LibServerAuth_IsAuthorized = True;
228 | }
229 |
230 | // ---------------------------------- //
231 | // Handle ongoing request
232 | if (G_LibServerAuth_AuthRequest != Null) {
233 | declare StopRequest = G_LibServerAuth_IsAuthorized;
234 |
235 | // Read the result
236 | if (!StopRequest && G_LibServerAuth_AuthRequest.IsCompleted) {
237 | declare Document = Xml.Create(G_LibServerAuth_AuthRequest.Result);
238 | G_LibServerAuth_IsAuthorized = Private_CheckServerAuthorization(Document);
239 | if (G_LibServerAuth_IsAuthorized) Private_SetAuthStatus(C_LibServerAuth_StatusId_Authorized);
240 | else Private_SetAuthStatus(C_LibServerAuth_StatusId_Forbidden);
241 | Xml.Destroy(Document);
242 | StopRequest = True;
243 | }
244 |
245 | // Request timed out
246 | if (Now >= G_LibServerAuth_RequestStart + C_LibServerAuth_AuthRequestTimeOut) {
247 | Private_SetAuthStatus(C_LibServerAuth_StatusId_TimedOut);
248 | StopRequest = True;
249 | }
250 |
251 | // Destroy the request
252 | if (StopRequest) {
253 | Http.Destroy(G_LibServerAuth_AuthRequest);
254 | G_LibServerAuth_AuthRequest = Null;
255 | StopRequest = False;
256 | }
257 | }
258 |
259 | // Authorization pending
260 | if (!IsAuthorized()) return True;
261 |
262 | // Destroy authorization interface
263 | Layers::Detach(C_LibServerAuth_InterfaceLayerId);
264 | Layers::Destroy(C_LibServerAuth_InterfaceLayerId);
265 |
266 | // Finish authorization
267 | G_LibServerAuth_RequestStart = -1;
268 | return False;
269 | }
270 |
--------------------------------------------------------------------------------
/Scripts/Libs/domino54/LeaderDisplay.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // LIBRARY LEADER DISPLAY by domino54 //
3 | // script version: 2018-04-21 //
4 | // -------------------------------------- //
5 |
6 | /**
7 | * Create a simple overlay displaying the current match leader
8 | * compared to the player. If the player is leading, 2nd player
9 | * in the ranking is shown.
10 | */
11 |
12 | #Const Version "2018-04-21"
13 | #Const ScriptName "Libs/domino54/LeaderDisplay.Script.txt"
14 |
15 | #Include "Libs/Nadeo/Layers2.Script.txt" as Layers
16 |
17 | // ---------------------------------- //
18 | // Constants
19 | // ---------------------------------- //
20 | #Const C_LibLeaderDisplay_ManialinkLayerId "LibLeaderDisplay"
21 | #Const C_LibLeaderDisplay_DefaultPosition <0., 74.>
22 |
23 | // ---------------------------------- //
24 | // Functions
25 | // ---------------------------------- //
26 |
27 | // ---------------------------------- //
28 | // Private
29 | // ---------------------------------- //
30 |
31 | // ---------------------------------- //
32 | /** Create manialink of the Leader Display library.
33 | *
34 | * @param _Font The font applied to all texts.
35 | *
36 | * @return Leader Display manialink.
37 | */
38 | Text Private_CreateManialinkLeaderDisplay(Text _Font) {
39 | declare Pos = C_LibLeaderDisplay_DefaultPosition;
40 | return """
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
254 |
255 | """;
256 | }
257 |
258 | // ---------------------------------- //
259 | // Public
260 | // ---------------------------------- //
261 |
262 | // ---------------------------------- //
263 | /** Return the version number of the script.
264 | *
265 | * @return The version number of the script.
266 | */
267 | Text GetScriptVersion() { return Version; }
268 |
269 | // ---------------------------------- //
270 | /** Return the name of the script.
271 | *
272 | * @return The name of the script.
273 | */
274 | Text GetScriptName() { return ScriptName; }
275 |
276 | // ---------------------------------- //
277 | /** Set the Leader Display visibility.
278 | *
279 | * @param _Visible Leader Display visibility.
280 | */
281 | Void SetVisibility(Boolean _Visible) {
282 | declare netwrite Boolean Net_LibLeaderDisplay_LayerVisible for Teams[0];
283 | Net_LibLeaderDisplay_LayerVisible = _Visible;
284 | }
285 |
286 | // ---------------------------------- //
287 | /// Hide the Leader Display.
288 | Void Hide() {
289 | SetVisibility(False);
290 | }
291 |
292 | // ---------------------------------- //
293 | /// Show the Leader Display.
294 | Void Show() {
295 | SetVisibility(True);
296 | }
297 |
298 | // ---------------------------------- //
299 | /// Unload the library.
300 | Void Unload() {
301 | Hide();
302 |
303 | Layers::Detach(C_LibLeaderDisplay_ManialinkLayerId);
304 | Layers::Destroy(C_LibLeaderDisplay_ManialinkLayerId);
305 | }
306 |
307 | // ---------------------------------- //
308 | /** Load the library.
309 | *
310 | * @param _Font The font used for all texts.
311 | */
312 | Void Load(Text _Font) {
313 | Unload();
314 |
315 | Layers::Create(C_LibLeaderDisplay_ManialinkLayerId, Private_CreateManialinkLeaderDisplay(_Font));
316 | Layers::Attach(C_LibLeaderDisplay_ManialinkLayerId);
317 | }
318 |
319 | // ---------------------------------- //
320 | /// Load the library with default font.
321 | Void Load() {
322 | Load("RajdhaniMono");
323 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/GoldenDunkV2Arena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // GOLDEN DUNK V2 ARENA by domino54 //
3 | // script version: 2016-07-01 //
4 | // original concept by Steeffeen //
5 | // -------------------------------------- //
6 |
7 | #RequireContext CSmMapType
8 |
9 | #Const Version "2016-07-01"
10 | #Const MapTypeVersion 1
11 | #Const ScriptName "GoldenDunkV2Arena.Script.txt"
12 |
13 | #Include "TextLib" as TL
14 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
15 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
16 | // Custom libraries
17 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
18 |
19 | // ---------------------------------- //
20 | // Constants
21 | // ---------------------------------- //
22 | #Const C_Rules "$<%11.$> Place exactly one Spawn #1 and one Spawn #2.\n$<%12.$> Place one Checkpoint in the middle - here balls will be spawned.\n$<%13.$> Click the icon next to block properties button and edit hoop areas for both sides.\n$<%14.$> Hoop areas must be marked with OffZone as well.\n$<%15.$> You can optionally place Goal #1 and Goal #2 to let the players construct OffZone shield."
23 |
24 | // ---------------------------------- //
25 | // Functions
26 | // ---------------------------------- //
27 |
28 | // ---------------------------------- //
29 | /// Initialize the anchors
30 | Void InitAnchors() {
31 | foreach (Anchor in AnchorData) {
32 | if (Anchor.DefaultTag == "Spawn") {
33 | Anchor.Tag = Anchor.DefaultTag;
34 | if (Anchor.Order < 1 && Anchor.Order > 2) Anchor.Order = 1;
35 | } else if (Anchor.DefaultTag == "Goal") {
36 | if (Anchor.Tag != "Goal" && Anchor.Tag != "Checkpoint") Anchor.Tag = Anchor.DefaultTag;
37 | if (Anchor.Tag == "Goal" && Anchor.Order < 1 && Anchor.Order > 2) Anchor.Order = 1;
38 | if (Anchor.Tag == "Checkpoint" && Anchor.Order != 0) Anchor.Order = 0;
39 | } else if (Anchor.DefaultTag == "Checkpoint") {
40 | if (Anchor.Tag != "Checkpoint" && Anchor.Tag != "Checkpoint") Anchor.Tag = "Checkpoint";
41 | if (Anchor.Tag == "Checkpoint" && Anchor.Order != 0) Anchor.Order = 0;
42 | if (Anchor.Tag == "Goal" && Anchor.Order < 1 && Anchor.Order > 2) Anchor.Order = 1;
43 | } else {
44 | Anchor.Tag = Anchor.DefaultTag;
45 | Anchor.Order = Anchor.DefaultOrder;
46 | }
47 | }
48 | }
49 |
50 | // ---------------------------------- //
51 | /// Check if the map is valid
52 | Void UpdateValidability() {
53 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
54 | InitAnchors();
55 | Anchor::UpdateAnchorCounts();
56 |
57 | // ---------------------------------- //
58 | // Get the amount of Goals
59 | declare ClansNbGoals = [1 => 0, 2 => 0];
60 | foreach (Data in AnchorData)
61 | if (Data.Tag == "Goal" && ClansNbGoals.existskey(Data.Order)) ClansNbGoals[Data.Order] += 1;
62 |
63 | // ---------------------------------- //
64 | // Check if map has exactly one landmark type per team
65 | for (I, 1, 2)
66 | if (!Anchor::HasExactlyOneAnchor("Spawn", I, TL::Compose(_("You must place exactly one Spawn #%1"), ""^I))) return;
67 |
68 | // ---------------------------------- //
69 | // Check if map has exactly one checkpoint
70 | if (!Anchor::HasExactlyOneAnchor("Checkpoint", 0, _("You must place exactly one Checkpoint"))) return;
71 |
72 | // ---------------------------------- //
73 | // Goals amount doesn't match
74 | if ((ClansNbGoals[1] > 0 || ClansNbGoals[2] > 0) && (ClansNbGoals[1] != 1 || ClansNbGoals[2] != 1)) {
75 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
76 | ValidabilityRequirementsMessage = _("If your map is using Goals, you must place exactly one Goal #1 and Goal #2");
77 | return;
78 | }
79 |
80 | // ---------------------------------- //
81 | // Check if the map has correct dunk positions
82 | declare metadata MetaData_DunkPositions for Map = [1 => <0., 0., 0.>, 2 => <0., 0., 0.>];
83 | for (I, 1, 2) for (J, 0, 1) if (MetaData_DunkPositions[I][J*2] <= 0 || MetaData_DunkPositions[I][J*2] > 47) {
84 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
85 | ValidabilityRequirementsMessage = _("You must specify valid dunk areas positions");
86 | return;
87 | }
88 |
89 | // Map is valid
90 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
91 | }
92 |
93 |
94 | // ---------------------------------- //
95 | /// Show the anchor edition manialink
96 | Void EditAnchorData(Ident _EditedAnchorDataId) {
97 | if (_EditedAnchorDataId == NullId) return;
98 | UpdateValidability();
99 | EditAnchors::EditAnchor(_EditedAnchorDataId);
100 | UpdateValidability();
101 | }
102 |
103 | Text CreateManialinkEditDunkLocations() {
104 | return """
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 | """;
135 | }
136 |
137 | // ---------------------------------- //
138 | // Main
139 | // ---------------------------------- //
140 | main() {
141 | MapType::SetVersion(MapTypeVersion);
142 | UpdateValidability();
143 | CustomEditAnchorData = True;
144 |
145 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
146 | EditAnchors::SetAvailableTags([
147 | "Spawn" => ["Spawn #1", "Spawn #2"],
148 | "Goal" => ["Goal #1", "Goal #2", "Checkpoint"],
149 | "Checkpoint" => ["Checkpoint", "Goal #1", "Goal #2"]
150 | ]);
151 |
152 | // ---------------------------------- //
153 | // Save additional data in the map file
154 | declare metadata MetaData_DunkPositions for Map = [1 => <0., 0., 0.>, 2 => <0., 0., 0.>];
155 |
156 | // ---------------------------------- //
157 | // Create layer for editing dunk locations
158 | declare LayerEditDunkPositions = UILayerCreate();
159 | LayerEditDunkPositions.ManialinkPage = CreateManialinkEditDunkLocations();
160 | declare LayerPage <=> LayerEditDunkPositions.LocalPage;
161 | yield;
162 |
163 | // ---------------------------------- //
164 | // Load manialink elements
165 | declare Label_CursorPositionX <=> (LayerPage.GetFirstChild("Label_CursorPositionX") as CMlLabel);
166 | declare Label_CursorPositionZ <=> (LayerPage.GetFirstChild("Label_CursorPositionZ") as CMlLabel);
167 | declare Entry_Side1DunkX <=> (LayerPage.GetFirstChild("Entry_Side1DunkX") as CMlEntry);
168 | declare Entry_Side1DunkZ <=> (LayerPage.GetFirstChild("Entry_Side1DunkZ") as CMlEntry);
169 | declare Entry_Side2DunkX <=> (LayerPage.GetFirstChild("Entry_Side2DunkX") as CMlEntry);
170 | declare Entry_Side2DunkZ <=> (LayerPage.GetFirstChild("Entry_Side2DunkZ") as CMlEntry);
171 |
172 | // Init dunk positions
173 | Entry_Side1DunkX.Value = TL::FormatReal(MetaData_DunkPositions[1].X, 0, True, True);
174 | Entry_Side1DunkZ.Value = TL::FormatReal(MetaData_DunkPositions[1].Z, 0, True, True);
175 | Entry_Side2DunkX.Value = TL::FormatReal(MetaData_DunkPositions[2].X, 0, True, True);
176 | Entry_Side2DunkZ.Value = TL::FormatReal(MetaData_DunkPositions[2].Z, 0, True, True);
177 |
178 | declare PrevEntry_Side1DunkXValue = Entry_Side1DunkX.Value;
179 | declare PrevEntry_Side1DunkZValue = Entry_Side1DunkZ.Value;
180 | declare PrevEntry_Side2DunkXValue = Entry_Side2DunkX.Value;
181 | declare PrevEntry_Side2DunkZValue = Entry_Side2DunkZ.Value;
182 |
183 | // ---------------------------------- //
184 | // Yield
185 | // ---------------------------------- //
186 | while (True) {
187 | yield;
188 |
189 | // ---------------------------------- //
190 | // Events management
191 | foreach (Event in PendingEvents) {
192 | switch (Event.Type) {
193 | case CPluginEvent::Type::MapModified : UpdateValidability();
194 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
195 | }
196 | }
197 |
198 | // ---------------------------------- //
199 | // Display current position of the cursor
200 | Label_CursorPositionX.Value = TL::ToText(CursorCoord.X);
201 | Label_CursorPositionZ.Value = TL::ToText(CursorCoord.Z);
202 |
203 | // ---------------------------------- //
204 | // Update Side 1 X position
205 | if (PrevEntry_Side1DunkXValue != Entry_Side1DunkX.Value) {
206 | MetaData_DunkPositions[1].X = TL::ToReal(Entry_Side1DunkX.Value);
207 | Entry_Side1DunkX.Value = TL::FormatReal(MetaData_DunkPositions[1].X, 5, True, True);
208 | PrevEntry_Side1DunkXValue = Entry_Side1DunkX.Value;
209 | UpdateValidability();
210 | }
211 |
212 | // ---------------------------------- //
213 | // Update Side 1 Z position
214 | if (PrevEntry_Side1DunkZValue != Entry_Side1DunkZ.Value) {
215 | MetaData_DunkPositions[1].Z = TL::ToReal(Entry_Side1DunkZ.Value);
216 | Entry_Side1DunkZ.Value = TL::FormatReal(MetaData_DunkPositions[1].Z, 5, True, True);
217 | PrevEntry_Side1DunkZValue = Entry_Side1DunkZ.Value;
218 | UpdateValidability();
219 | }
220 |
221 | // ---------------------------------- //
222 | // Update Side 2 X position
223 | if (PrevEntry_Side2DunkXValue != Entry_Side2DunkX.Value) {
224 | MetaData_DunkPositions[2].X = TL::ToReal(Entry_Side2DunkX.Value);
225 | Entry_Side2DunkX.Value = TL::FormatReal(MetaData_DunkPositions[2].X, 5, True, True);
226 | PrevEntry_Side1DunkXValue = Entry_Side1DunkX.Value;
227 | UpdateValidability();
228 | }
229 |
230 | // ---------------------------------- //
231 | // Update Side 2 Z position
232 | if (PrevEntry_Side2DunkZValue != Entry_Side2DunkZ.Value) {
233 | MetaData_DunkPositions[2].Z = TL::ToReal(Entry_Side1DunkZ.Value);
234 | Entry_Side2DunkZ.Value = TL::FormatReal(MetaData_DunkPositions[2].Z, 5, True, True);
235 | PrevEntry_Side2DunkZValue = Entry_Side2DunkZ.Value;
236 | UpdateValidability();
237 | }
238 | }
239 | }
--------------------------------------------------------------------------------
/Scripts/MapTypes/ShootMania/HungerGamesV2Arena.Script.txt:
--------------------------------------------------------------------------------
1 | // -------------------------------------- //
2 | // HUNGER GAMES V2 ARENA by domino54 //
3 | // script version: 2016-12-05 //
4 | // -------------------------------------- //
5 |
6 | #RequireContext CSmMapType
7 |
8 | #Const Version "2016-12-05"
9 | #Const MapTypeVersion 1
10 | #Const ScriptName "HungerGamesV2Arena.Script.txt"
11 |
12 | #Include "TextLib" as TL
13 | #Include "Libs/Nadeo/Anchor.Script.txt" as Anchor
14 | #Include "Libs/Nadeo/MapType.Script.txt" as MapType
15 | #Include "Libs/domino54/EditAnchors.Script.txt" as EditAnchors
16 |
17 | // ---------------------------------- //
18 | // Constants
19 | // ---------------------------------- //
20 | #Const C_Rules "$<%11.$> Place exactly one Goal.\n$<%12.$> Place at least one Spawn around the Goal (recommended: 8 - 12).\n$<%13.$> Place 8 Checkpoints, where players can respawn.\n$<%14.$> Place enough items to fill up counters in top left corner.\n$<%15.$> Place up to 14 BotPaths where Toads will be spawned."
21 |
22 | #Const C_RequiredNbCheckpoints 8 ///< Required Checkpoints amount on map
23 |
24 | /// Maximum amount of every object
25 | #Const C_MaxObjectsCount ["Weapon" => 12, "Charge" => 36, "Mini" => 24, "Replie" => 24, "Armor" => 36, "Fuel" => 12]
26 |
27 | // ---------------------------------- //
28 | // Functions
29 | // ---------------------------------- //
30 |
31 | // ---------------------------------- //
32 | /// Initialize the anchors
33 | Void InitAnchors() {
34 | foreach (Anchor in AnchorData) {
35 | Anchor.Tag = Anchor.DefaultTag;
36 | Anchor.Order = Anchor.DefaultOrder;
37 | }
38 | }
39 |
40 | // ---------------------------------- //
41 | /// Check if the map is valid
42 | Void UpdateValidability() {
43 | ValidationStatus = CSmMapType::ValidationStatus::NotValidable;
44 | InitAnchors();
45 | Anchor::UpdateAnchorCounts();
46 |
47 | // ---------------------------------- //
48 | // Podium block is forbidden
49 | foreach (Block in Blocks) {
50 | if (!TL::Find("Podium", Block.BlockModel.Name, False, False)) continue;
51 | Anchor::Private_SetAsNotValid(_("You cannot place a podium block!"));
52 | return;
53 | }
54 |
55 | // ---------------------------------- //
56 | // Check if the map has Goal and Spawns
57 | if (!Anchor::HasExactlyOneAnchor("Goal", 0, _("You must place exactly one Goal."))) return;
58 | if (!Anchor::HasAtLeastOneAnchor("Spawn", 0, _("You must place at least one Spawn"))) return;
59 | if (!Anchor::HasExactlyXAnchor("Checkpoint", 0, C_RequiredNbCheckpoints, TL::Compose(_("You must place exactly %1 Checkpoints"), TL::ToText(C_RequiredNbCheckpoints)))) return;
60 |
61 | foreach (Tag => MaxAmount in C_MaxObjectsCount) {
62 | if (Anchor::GetCount(Tag) <= MaxAmount) continue;
63 | Anchor::Private_SetAsNotValid(TL::Compose(_("You cannot place more than %1 %2!"), TL::ToText(MaxAmount), Tag^"s"));
64 | return;
65 | }
66 |
67 | // Map is valid
68 | ValidationStatus = CSmMapType::ValidationStatus::Validated;
69 | }
70 |
71 | // ---------------------------------- //
72 | /// Show the anchor edition manialink
73 | Void EditAnchorData(Ident _EditedAnchorDataId) {
74 | if (_EditedAnchorDataId == NullId) return;
75 | UpdateValidability();
76 | EditAnchors::EditAnchor(_EditedAnchorDataId);
77 | UpdateValidability();
78 | }
79 |
80 | // ---------------------------------- //
81 | /** Get amount of every anchor
82 | *
83 | * @return Array of anchors amount
84 | */
85 | Integer[Text] GetAnchorsAmount() {
86 | declare Integer[Text] AnchorsAmount;
87 | foreach (Anchor in AnchorData) {
88 | if (!AnchorsAmount.existskey(Anchor.Tag)) AnchorsAmount[Anchor.Tag] = 0;
89 | AnchorsAmount[Anchor.Tag] += 1;
90 | }
91 | return AnchorsAmount;
92 | }
93 |
94 | // ---------------------------------- //
95 | /** Create manialin kfor the objects counter module
96 | *
97 | * @return The objects counter module
98 | */
99 | Text CreateManialinkObjectsCounter() {
100 | return """
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
238 | """;
239 | }
240 |
241 | // ---------------------------------- //
242 | // Main
243 | // ---------------------------------- //
244 | main() {
245 | MapType::SetVersion(MapTypeVersion);
246 | UpdateValidability();
247 | CustomEditAnchorData = True;
248 |
249 | EditAnchors::SetRulesText(TL::Compose(C_Rules, "$o$070"));
250 | EditAnchors::SetAvailableTags(Text[][Text]);
251 |
252 | // ---------------------------------- //
253 | // Create layer for editing dunk locations
254 | declare LayerObjectsCounter = UILayerCreate();
255 | LayerObjectsCounter.ManialinkPage = CreateManialinkObjectsCounter();
256 | declare ObjectsCounterPage <=> LayerObjectsCounter.LocalPage;
257 |
258 | // ---------------------------------- //
259 | // Variables
260 | declare ObjectsAmount for ObjectsCounterPage = GetAnchorsAmount();
261 | declare ObjectsNbMax for ObjectsCounterPage = C_MaxObjectsCount;
262 | declare AmountUpdate for ObjectsCounterPage = Now;
263 |
264 | yield;
265 |
266 | // ---------------------------------- //
267 | // Yield
268 | // ---------------------------------- //
269 | while (True) {
270 | yield;
271 |
272 | // ---------------------------------- //
273 | // Events management
274 | foreach (Event in PendingEvents) {
275 | switch (Event.Type) {
276 | case CPluginEvent::Type::MapModified : {
277 | UpdateValidability();
278 | ObjectsAmount = GetAnchorsAmount();
279 | AmountUpdate = Now;
280 | }
281 | case CPluginEvent::Type::EditAnchor : EditAnchorData(Event.EditedAnchorDataId);
282 | }
283 | }
284 | }
285 | }
--------------------------------------------------------------------------------