Looking for an example of opening a story book
Moderator: OpenTTD Developers
-
- Engineer
- Posts: 18
- Joined: 13 Jan 2008 16:06
Looking for an example of opening a story book
Per some discussion elsewhere, it was suggested a story book could give me an option to allow players to pause and unpause on my cooperative server. I'd like to take a swing at this but I can't find a working example of a script that would open when the story book icon is clicked. For that matter, I don't even know how to make the story book icon in the main bar clickable.
The code off the main Wiki is dead so I'm at a loss at what to use as a reference. I can pull down some promising script that does this kind of thing if somebody can refer one. I am not daunted by the scripting syntax but I'm lacking on all of the OpenTTD bindings to it so I'm pretty helpless doing anything with it without some reference.
The code off the main Wiki is dead so I'm at a loss at what to use as a reference. I can pull down some promising script that does this kind of thing if somebody can refer one. I am not daunted by the scripting syntax but I'm lacking on all of the OpenTTD bindings to it so I'm pretty helpless doing anything with it without some reference.
Re: Looking for an example of opening a story book
Here is an example of creating and showing global story book page taken from RenewedVillageGrowth story.nut
Code: Select all
/* Issue an initial warning if game's cargo list doesn't match with settings. */
function StoryEditor::TownsWarningPage(num_towns)
{
// Creating the page
local sp_warning = this.NewStoryPage(GSCompany.COMPANY_INVALID, GSText(GSText.STR_SB_WARNING_TITLE));
GSStoryPage.NewElement(sp_warning, GSStoryPage.SPET_TEXT, 0, GSText(GSText.STR_SB_WARNING_1, num_towns, SELF_MAX_TOWNS));
GSStoryPage.Show(sp_warning);
}
-
- Engineer
- Posts: 18
- Joined: 13 Jan 2008 16:06
Re: Looking for an example of opening a story book
That's some useful stuff there. I'm assuming the story gets created in main.nut:
Does that story book ungray the story book icon in the toolbar? I don't understand what plumbing has to happen to make it possible to make it open there. All the stories I've tried to run so far basically create popups and stuff but I want something I can trust people to be able to click on their clients. I could just try to install and run this one but I'm not in a spot where I can try it right away.
Edit: Also, nice concept. I'd roll it out on my buddies if I didn't think it would melt their brains more than I am already hahaha.
Code: Select all
// Create and fill StoryBook. This can't be done before OTTD is ready.
local story_editor = StoryEditor();
story_editor.CreateStoryBook(this.towns.len());
Edit: Also, nice concept. I'd roll it out on my buddies if I didn't think it would melt their brains more than I am already hahaha.
Re: Looking for an example of opening a story book
Check the reference documentation of GSStoryPage. There you can find all functions and their explanations.
static StoryPageID New (GSCompany::CompanyID company, Text *title)
- create new story page for a company/all with a title, this will also ungray the button, you can create multiple pages
static StoryPageElementID NewElement (StoryPageID story_page_id, StoryPageElementType type, uint32 reference, Text *text)
- add element to a story page, this is used to add content/text to a page, you can add multiple elements to a single page
static StoryPageButtonFormatting MakePushButtonReference (StoryPageButtonColour colour, StoryPageButtonFlags flags)
- add button to the story page which creates an event upon clicking and can be used for pause/unpause action
- use GSEventController to read events and check for GSEventStoryPageButtonClick event
static StoryPageID New (GSCompany::CompanyID company, Text *title)
- create new story page for a company/all with a title, this will also ungray the button, you can create multiple pages
static StoryPageElementID NewElement (StoryPageID story_page_id, StoryPageElementType type, uint32 reference, Text *text)
- add element to a story page, this is used to add content/text to a page, you can add multiple elements to a single page
static StoryPageButtonFormatting MakePushButtonReference (StoryPageButtonColour colour, StoryPageButtonFlags flags)
- add button to the story page which creates an event upon clicking and can be used for pause/unpause action
- use GSEventController to read events and check for GSEventStoryPageButtonClick event
-
- Engineer
- Posts: 18
- Joined: 13 Jan 2008 16:06
Re: Looking for an example of opening a story book
Thanks. That should finally give me enough length of rope to shoot myself in the foot! But at least I can now!
Re: Looking for an example of opening a story book
It's worth remembering that the story book is saved in the savegame, so when your GS reloads from a saved game, you need to either be able to resume from the saved story book, or delete all pages from the story book and re-create it.
Resuming from a saved story book basically involves keeping track of, or knowing, the page and element IDs in the script's save data.
Resuming from a saved story book basically involves keeping track of, or knowing, the page and element IDs in the script's save data.
-
- Engineer
- Posts: 18
- Joined: 13 Jan 2008 16:06
Re: Looking for an example of opening a story book
Are those button events actually some kind of callback-driven event or something I have to poll? My first glance made me think I had to implement an event receiver like I'd normally expect in a GUI toolkit, but this code here:
https://github.com/MinchinWeb/openttd-g ... r/main.nut
is polling the event controller:
I saw a lot of polling in other code but I know that's something people typically do if they're not comfortable with callbacks. Well, I'm not much better in this language because I don't know how I connect to it.
https://github.com/MinchinWeb/openttd-g ... r/main.nut
is polling the event controller:
Code: Select all
if(GSEventController.IsEventWaiting())
{
local ev = GSEventController.GetNextEvent();
local ev_type = ev.GetEventType();
if(ev_type == GSEvent.ET_GOAL_QUESTION_ANSWER)
{
local click_event = GSEventGoalQuestionAnswer.Convert(ev);
if(click_event.GetUniqueID() == questionUniqueId)
return click_event.GetButton();
}
}
-
- Engineer
- Posts: 18
- Joined: 13 Jan 2008 16:06
Re: Looking for an example of opening a story book
Regarding save state: if I'm having to save any state here then I've probably done something really wrong. I am basically present a pause button in the store and having it pause/resume when pressed. Presumably that should be stateless...
Re: Looking for an example of opening a story book
Regarding polling:
The structure of a GS (and AI) is that it has a single "main" function that gets called when the script is started by the game, and this one function call lasts for the entire game. The game suspends execution of the script at certain times: When the script executes a command, which requires a simulation tick to execute. When the script calls the Delay function to request suspension for a number of ticks. And if the script runs out of execution time allotted for the current tick.
There are generally no callbacks, everything is synchronous and events are received by polling for them. You should not run the event polling in a tight loop, but make sure there is a Delay call between each poll for events. Basically the main loop of a script should look like: Poll events, perform planned actions, delay until next tick.
Regarding save state:
The script is started over when the game is loaded. In multiplayer, only the server runs the script, so this start-over only happens when the server loads the game.
If the first thing you do in the script is create a new story book page, unconditionally, then when the saved game is reloaded, the script will create a new story book page on top of the saved one, leaving you with two story book pages.
For that reason, you should at the very least store a flag in the script save data that the story book page has already been created and doesn't need to be created again.
Also consider the case of whether the script may need to support upgrades, i.e. a newer version that has more elements on pages, or more pages, and need to be able to upgrade an existing saved game's story book.
I hope this makes sense, it's a rather condensed explanation.
The structure of a GS (and AI) is that it has a single "main" function that gets called when the script is started by the game, and this one function call lasts for the entire game. The game suspends execution of the script at certain times: When the script executes a command, which requires a simulation tick to execute. When the script calls the Delay function to request suspension for a number of ticks. And if the script runs out of execution time allotted for the current tick.
There are generally no callbacks, everything is synchronous and events are received by polling for them. You should not run the event polling in a tight loop, but make sure there is a Delay call between each poll for events. Basically the main loop of a script should look like: Poll events, perform planned actions, delay until next tick.
Regarding save state:
The script is started over when the game is loaded. In multiplayer, only the server runs the script, so this start-over only happens when the server loads the game.
If the first thing you do in the script is create a new story book page, unconditionally, then when the saved game is reloaded, the script will create a new story book page on top of the saved one, leaving you with two story book pages.
For that reason, you should at the very least store a flag in the script save data that the story book page has already been created and doesn't need to be created again.
Also consider the case of whether the script may need to support upgrades, i.e. a newer version that has more elements on pages, or more pages, and need to be able to upgrade an existing saved game's story book.
I hope this makes sense, it's a rather condensed explanation.
-
- Engineer
- Posts: 18
- Joined: 13 Jan 2008 16:06
Re: Looking for an example of opening a story book
This is some meatball garbage I'm coding and hopefully posting 61 lines of code is a no-no (I can use an online code sharing portal next time if it is). I don't know if this code works at all but this is the gist of what I see. I can't figure out how I should properly detect the button I'm creating and definitely not how to rediscover that on a game load for a story book that was previously connected.
Code: Select all
class MainClass extends GSController
{
version = 1;
loaded = false;
}
function MainClass::Start()
{
if(!loaded)
{
local sp_pause = GSStoryPage.New(GSCompany.CompanyID.COMPANY_INVALID, "Cooperative Server Pause/Unpause");
GSStoryPage.NewElement(sp_pause, GSStoryPage.SPET_TEXT, 0, "Cooperative Server Pause/Unpause Script");
// I believe I need this ID to be certain with story button clicks that I'm getting the right one. I don't know how to rebind it on load.
local pauseButtonId = GSStoryPage.NewElement(sp_pause, GSStoryPage.SPET_BUTTON_PUSH, GSStoryPage.MakePushButtonReference(GSStoryPage.SPBC_RED, GSStoryPage.SPBF_FLOAT_LEFT), "Pause Toggle");
}
else
{
// TODO: Need to bind to any existing, preloaded story if we're loading from a save in order to get pauseButtonId
}
while(true)
{
if(GSEventController.IsEventWaiting())
{
local ev = GSEventController.GetNextEvent();
local ev_type = ev.GetEventType();
if(ev_type == GSEvent.ET_STORYPAGE_BUTTON_CLICK)
{
local button_event = GSEventStoryPageButtonClick.Convert(ev);
if(click_event.GetElementID() == pauseButtonId)
{
if(GSGame.IsPaused())
{
GSGame.Unpause()
}
else
{
GSGame.Pause()
}
}
}
}
this.Sleep(1);
}
}
function MainClass::Save() {
local Save = {
version = version,
};
return Save;
}
function MainClass::Load(version, data) {
if ("version" in data) version = data.version;
loaded = true;
}
Re: Looking for an example of opening a story book
You can take a look at the IntroGameTool GS I wrote: https://github.com/nielsmh/IntroGameToo ... n.nut#L217
It has versioned pages with buttons, and saves/restores button id's.
It has versioned pages with buttons, and saves/restores button id's.
Who is online
Users browsing this forum: No registered users and 2 guests