Custom campaigns in your title pack
Posted: 19 May 2014, 08:48
xbx wrote:Hello!
Just a quick note to hint at ways to make some kind of custom solo campaign in TM and SM.
When you create a title, instead of providing a folder with maps, and get the standard campaign menu and unlock pattern, you can provide a playlist and a script.
When the user goes into the solo campaign, the menu will be skipped and the script started with the maps provided in the playlist.
And the script can then decide which map to lead next, or display a manialink and interact with the user - before even loading the first map.
This allows for doing stuff like story mode or displaying a world map, or whatever.
Here is a very simple script with no actual gameplay that displays a list and asks which map to lead next.
Code: Select all
// *********************** ** ** * * // * Test solo campagain with map list // ******************* ** ** * * // (works for TM and SM) #RequireContext CSmMode //#RequireContext CTmMode /* in the title pack, set the solo maps as a playlist (instead of a campaign folder) <solo> <medals>12</medals> <mode name="Modes\ShootMania\TestSolo.Script.txt"/> <campaign folder=""/> <playlist name="SoloTest.txt"/> </solo> */ #Include "TextLib" as TextLib #Include "Libs/Nadeo/Mode.Script.txt" #Const Version "2014-04-07" // === Main === main() { UIManager.ResetAll(); declare LayerMapList = UIManager.UILayerCreate(); UIManager.UIAll.UILayers.add(LayerMapList); declare CurUpdateNum = 0; wait(Users.count > 0); // wait for the game to be ready declare LocalPlayerUI <=> UIManager.GetUI(Users[0]); assert(LocalPlayerUI != Null); while( !ServerShutdownRequested ) { // Manialink displayed when no map is loaded // for example: simple pick the map from list CurUpdateNum += 1; LayerMapList.ManialinkPage = """ <frame> <quad sizen="160 100" halign="center" valign="center" style="Bgs1InRace" substyle="BgWindow3"/> <label posn="-75 45 1" scale="1" halign="left" valign="center" text="Now playing: {{{MapName}}}" /> <label posn="-75 32 1" scale="2" halign="left" valign="center" text="Choose next map:" /> """; declare MapIndex = 0; foreach (CandidateMap in MapList) { declare PostFix = ""; if (MapIndex == NextMapIndex) PostFix = "$z <--- next"; LayerMapList.ManialinkPage ^= """ <label posn="-75 {{{25-5*MapIndex}}} 1" scale="1" halign="left" valign="center" text="{{{CandidateMap.Name^PostFix}}}" id="map_{{{MapIndex}}}" scriptevents="1" /> """; MapIndex += 1; } LayerMapList.ManialinkPage ^= """ </frame> <script><!-- #Include "TextLib" as TextLib main() { declare netwrite SelectedMapIndex for UI = -1; declare netwrite UpdateNum for UI = 0; SelectedMapIndex = -1; UpdateNum = {{{CurUpdateNum}}}; while (True) { yield; foreach (Event in PendingEvents) { if (Event.Type == CMlEvent::Type::MouseClick) { declare Parts = TextLib::Split("_", Event.ControlId); if (Parts.count == 2 && Parts[0] =="map") { SelectedMapIndex = TextLib::ToInteger(Parts[1]); } } } } } --></script>"""; Synchro_DoBarrier(); declare netread UpdateNum for LocalPlayerUI = 0 ; declare netread SelectedMapIndex for LocalPlayerUI = -1; wait(UpdateNum == CurUpdateNum && SelectedMapIndex != -1); NextMapIndex = SelectedMapIndex; // note: it's a good idea to set this as early as possible (in network games), // as it allows the game to pre-download the maps & stuff on the clients. LoadMap(); // === play the map UIManager.UIAll.UISequence = CUIConfig::EUISequence::RollingBackgroundIntro; sleep(10000); UIManager.UIAll.UISequence = CUIConfig::EUISequence::None; // ==== UnloadMap(); } UIManager.UILayerDestroy(LayerMapList); }