Difference between revisions of "Interacting with the player: BBS forms"
m |
Zonkmachine (talk | contribs) (→Adding options to the form: fixup) |
||
(30 intermediate revisions by 2 users not shown) | |||
Line 4: | Line 4: | ||
There are two components to any mission's entry on a bulletin board: The advert and the form. The advert is the part that is displayed on the main bulletin board list, along with all the other entries. The form is the part that appears on screen when the player clicks the advert's button. | There are two components to any mission's entry on a bulletin board: The advert and the form. The advert is the part that is displayed on the main bulletin board list, along with all the other entries. The form is the part that appears on screen when the player clicks the advert's button. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
==The BBS advert== | ==The BBS advert== | ||
Line 48: | Line 19: | ||
One important thing to bear in mind is that the script cannot query a bulletin boad to find out what adverts already exist. Each script must carefully track each advert that it has created if it is to have any control over how long they remain, and to be able to re-create them after a reload. | One important thing to bear in mind is that the script cannot query a bulletin boad to find out what adverts already exist. Each script must carefully track each advert that it has created if it is to have any control over how long they remain, and to be able to re-create them after a reload. | ||
− | Here is an example of adding an advert. The effect of clicking the advert is simply to send a message to the player console with the name of the station. The advert is only added if the station is in space. There is no mission here | + | Here is an example of adding an advert. The effect of clicking the advert is simply to send a message to the player console with the name of the station and the reference number which is also the adverts place on the BBS. The advert is only added if the station is in space. There is no mission here, it is simply to illustrate the mechanics of adding an advert. Launch Pioneer and choose a new game with start on Barnard's star. |
+ | local Event = require "Event" | ||
+ | local Comms = require "Comms" | ||
+ | |||
+ | local ref -- Variable to save the advert's reference number | ||
+ | |||
local onCreateBB = function (station) | local onCreateBB = function (station) | ||
-- This function can be in any scope that's visible when AddAdvert() is called | -- This function can be in any scope that's visible when AddAdvert() is called | ||
local sendStationName = function () | local sendStationName = function () | ||
− | Comms.ImportantMessage(station.label) | + | Comms.ImportantMessage(station.label .. "\n" .. "Add ref number: " .. ref) |
end | end | ||
− | + | ||
if station.type == 'STARPORT_ORBITAL' then | if station.type == 'STARPORT_ORBITAL' then | ||
− | station:AddAdvert('Need the name of this station?',sendStationName) | + | ref = station:AddAdvert('Need the name of this station?',sendStationName) |
end | end | ||
end | end | ||
Line 66: | Line 42: | ||
This code will create an advert: | This code will create an advert: | ||
− | [[File: | + | [[File:BBS1.png]] |
+ | |||
+ | Looking at the image, you will notice that the advert has appeared at the top of the bulletin board and that only one of two fields is filled with text. The BBS ad has two components, the '''title''' on top and the '''description'''. Only the description is present and since the BBS posts are sorted on first the title and secondly on the description, since the title is blank the post will show up on top. The icon used is the default. '''AddAdvert''' has two versions and we used a simpler legacy form. See | ||
− | + | -- Legacy form | |
+ | ref = station:AddAdvert(description, onChat, onDelete) | ||
Clicking on the advert causes this to happen: | Clicking on the advert causes this to happen: | ||
− | [[File: | + | [[File:BBS2.png]] |
+ | |||
+ | Even though the only thing our function did was to send a message to the console, you can see that Pioneer automatically created a form for our advert. The only control is the 'Hang up' button. | ||
− | + | Going back to the World View you can see the message on the Comms terminal: | |
+ | |||
+ | [[File:BBS3.png]] | ||
+ | |||
+ | ==More AddAdvert()== | ||
+ | |||
+ | As we saw, the legacy form of '''AddAdvert''' created an add that lacked a title and with a default icon. Lets rewrite the example above in the full form. [https://codedoc.pioneerspacesim.net/index.html#LuaClass:SpaceStation:AddAdvert LuaClass:SpaceStation:AddAdvert]. | ||
+ | |||
+ | AddAdvert takes a table as argument. | ||
+ | ref = station:AddAdvert({ | ||
+ | description = description, | ||
+ | icon = icon, | ||
+ | onChat = onChat, | ||
+ | onDelete = onDelete, | ||
+ | isEnabled = isEnabled, | ||
+ | }) | ||
+ | |||
+ | Let's try the earlier example but simplified a bit to run on all stations. | ||
+ | local Event = require "Event" | ||
+ | local Comms = require "Comms" | ||
+ | |||
+ | local ref -- Variable to save the advert's reference number | ||
+ | |||
+ | local onCreateBB = function (station) | ||
+ | |||
+ | -- This function can be in any scope that's visible when AddAdvert() is called | ||
+ | local sendStationName = function () | ||
+ | Comms.ImportantMessage(station.label .. "\n" .. "Add ref number: " .. ref) | ||
+ | end | ||
+ | |||
+ | ref = station:AddAdvert({ | ||
+ | title = 'STATION NAME', | ||
+ | description = 'Need the name of this station?', | ||
+ | icon = 'news', | ||
+ | onChat = sendStationName, | ||
+ | onDelete = onDelete, | ||
+ | }) | ||
+ | end | ||
+ | |||
+ | Event.Register("onCreateBB", onCreateBB) | ||
+ | |||
+ | The ad now looks complete. | ||
+ | |||
+ | [[File:BBS5.png]] | ||
==The BBS form== | ==The BBS form== | ||
Line 82: | Line 106: | ||
The form itself is passed to the function specified in the <code>SpaceStation.AddAdvert()</code> method. In the example above, that function would be <code>sendStationName()</code>, which simply ignored any parameters sent to it. This resulted in the form being blank. | The form itself is passed to the function specified in the <code>SpaceStation.AddAdvert()</code> method. In the example above, that function would be <code>sendStationName()</code>, which simply ignored any parameters sent to it. This resulted in the form being blank. | ||
− | The form object which is passed to this function has methods for adding the content. <code>SetTitle()</code> and <code>SetMessage()</code> each accept a string. <code>SetFace()</code> takes a table of information which defines the photofit face on the left | + | The form object which is passed to this function has methods for adding the content. <code>SetTitle()</code> and <code>SetMessage()</code> each accept a string. <code>SetFace()</code> takes a table of information which defines the photofit face on the left but in the following example <code>SetFace()</code> is called without any arguments and the face will therefore be completely randomized. |
− | + | A minimal example without any clickable options, just the default 'Hang up': | |
+ | local Event = import("Event") | ||
+ | |||
local populateForm = function (form) | local populateForm = function (form) | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
form:SetTitle('This appears above the face picture') | form:SetTitle('This appears above the face picture') | ||
− | form:SetFace( | + | form:SetFace() |
form:SetMessage([[This is the main message. | form:SetMessage([[This is the main message. | ||
Line 101: | Line 121: | ||
local onCreateBB = function (station) | local onCreateBB = function (station) | ||
− | station:AddAdvert('This appears in the advert list',populateForm) | + | station:AddAdvert({ |
+ | title = 'AD TITLE', | ||
+ | description = 'This appears in the advert list', | ||
+ | icon = 'news', | ||
+ | onChat = populateForm, | ||
+ | onDelete = onDelete, | ||
+ | }) | ||
end | end | ||
Line 108: | Line 134: | ||
As before, an advert was created: | As before, an advert was created: | ||
− | [[File: | + | [[File:BBS4.png]] |
− | + | We have clicked on the ad and can see that <code>populateForm</code> was called, and it successfully filled the form with content. If you 'hang up' and press the ad again a completely new face is generated. Lets improve on this and make the face persistent for the existence of the advert. Making it reappear in a saved game would take some more work (see "[[Surviving a reload]]"). | |
− | + | local Character = require "Character" | |
+ | local Event = require "Event" | ||
+ | |||
+ | local client = {} | ||
+ | local message | ||
+ | |||
+ | local populateForm = function (form) | ||
+ | form:SetTitle('Pizza time!') | ||
+ | form:SetFace(client) | ||
+ | form:SetMessage(message) | ||
+ | end | ||
+ | |||
+ | local onCreateBB = function (station) | ||
+ | |||
+ | client = Character.New() | ||
+ | message = "I'm " .. client.name .. " and I need some pizza. I'm thinking pepperoni and cheeze. You feelin me?" | ||
+ | |||
+ | station:AddAdvert({ | ||
+ | title = 'PIZZA PARTY!', | ||
+ | description = 'Special delivery needed', | ||
+ | icon = 'news', | ||
+ | onChat = populateForm, | ||
+ | onDelete = onDelete, | ||
+ | }) | ||
+ | end | ||
+ | |||
+ | Event.Register("onCreateBB", onCreateBB) | ||
− | [ | + | We introduce a new module ''' '[https://pioneerspacesim.net/codedoc/files2/Character-lua.html Character]' ''' which basically is an rpg style character sheet with methods to work with it. It's a tool to generate and work with non-player characters (npc's). <code>client = Character.New()</code> sets client to an all new character with basic characteristics, name, title, and looks. A character can be sent directly to the SetFace method and that's what we're after here. We also used the 'clients' name. |
− | |||
− | |||
==Adding options to the form== | ==Adding options to the form== | ||
− | In the example above, | + | In the example above, we created a function named <code>populateForm()</code> which was run when the advert button was clicked. That's not the only time it can be run; it is also run whenever options on its form are clicked. To make use of this, it is passed two additional parameters, both of which <code>populateForm()</code> ignored. The first parameter is the form object, the second is the advert's unique reference and the third is the number of the option that was clicked. Because it handles all chat events, by convention we instead name this function <code>onChat()</code>, which is how it shall be named from now on. |
− | |||
− | To make use of this, it is passed two additional parameters, both of which <code>populateForm()</code> ignored. The first parameter is the form object, the second is the advert's unique reference and the third is the number of the option that was clicked. Because it handles all chat events, by convention we instead name this function <code>onChat()</code>, which is how it shall be named from now on. | ||
− | + | In the first example that called the function 'sendStationName' we caught the reference number from ''' 'AddAdvert()' ''' in a variable named ''' 'ref' '''. As you may remember, ''' 'AddAdvert()' ''' takes two arguments; A string and a function. The function is passed three arguments. The second of these arguments is the reference number so we could have picked it up from within ''' 'sendStationName' '''. The ''' 'ref' ''' number is useful if your script adds several adverts, each of which might have slightly differently worded content. | |
− | + | You've already learned the methods: ''' 'SetTitle()' ''', ''' 'SetMessage()' ''', and ''' 'SetFace()' '''. Let's add the rest of the form() methods:<br> | |
+ | * ''' form:AddOption() ''': adds clickable options with buttons. It takes two arguments: A string to set the text of the button and the option nr that will be sent to the form. This value is 0 when first called from the BBS by clicking the add. Every option form will have a default 'Hang up' option which returns -1.<br> | ||
+ | * ''' form:Clear() ''': removes the Message and Options, but preserves the Title and Face.<br> | ||
+ | * ''' form:Close() ''': Closes the form.<br> | ||
+ | * ''' form:RemoveAdvertOnClose() ''': Closes the form and removes the ad.<br> | ||
Form options are declared like this: | Form options are declared like this: | ||
− | + | form:AddOption('I am option one',1) | |
− | + | form:AddOption('I am option two',2) | |
− | These options will appear with the specified caption, and will call <code>onChat()</code>, which will receive the form object, the advert reference and the number that was specified after the caption in <code>AddOption()</code>. | + | These options will appear with the specified caption, and will call <code>onChat()</code>, which will receive the form object, the advert reference and the option number that was specified after the caption in <code>AddOption()</code>. |
− | The codedoc | + | The onChat function below is adapted from an earlier example from the codedoc: |
+ | local Event = require 'Event' | ||
+ | |||
local onChat = function (form, ref, option) | local onChat = function (form, ref, option) | ||
form:Clear() | form:Clear() | ||
Line 147: | Line 201: | ||
form:SetMessage("What's your favourite colour?") | form:SetMessage("What's your favourite colour?") | ||
− | form:AddOption("Red", | + | form:AddOption("Red", 1) |
− | form:AddOption("Green", | + | form:AddOption("Green", 2) |
− | form:AddOption(" | + | form:AddOption("Blue", 3) |
− | |||
− | |||
return | return | ||
Line 159: | Line 211: | ||
if option == 1 then | if option == 1 then | ||
form:SetMessage("Ahh red, the colour of raspberries.") | form:SetMessage("Ahh red, the colour of raspberries.") | ||
− | |||
return | return | ||
end | end | ||
Line 166: | Line 217: | ||
if option == 2 then | if option == 2 then | ||
form:SetMessage("Ahh green, the colour of trees.") | form:SetMessage("Ahh green, the colour of trees.") | ||
− | |||
return | return | ||
end | end | ||
− | -- option 3 - | + | -- option 3 - blue |
if option == 3 then | if option == 3 then | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
form:SetMessage("Ahh blue, the colour of the ocean.") | form:SetMessage("Ahh blue, the colour of the ocean.") | ||
− | |||
return | return | ||
end | end | ||
Line 187: | Line 229: | ||
form:Close() | form:Close() | ||
end | end | ||
+ | |||
+ | local onCreateBB = function (station) | ||
+ | station:AddAdvert({ | ||
+ | title = 'COLORS', | ||
+ | description = "Let's talk colors!", | ||
+ | icon = 'news', | ||
+ | onChat = onChat, | ||
+ | onDelete = onDelete, | ||
+ | }) | ||
+ | end | ||
+ | |||
+ | Event.Register("onCreateBB", onCreateBB) | ||
Here, every time <code>onChat()</code> is called, regardless of the specified option, the form is cleared. The option is checked, and the relevant content is added to the form. Any other functions can be called from here, and this is how the script gets input from the player. | Here, every time <code>onChat()</code> is called, regardless of the specified option, the form is cleared. The option is checked, and the relevant content is added to the form. Any other functions can be called from here, and this is how the script gets input from the player. | ||
Line 192: | Line 246: | ||
An alternative format might be this: | An alternative format might be this: | ||
+ | local Event = require 'Event' | ||
+ | |||
local onChat = function (form, ref, option) | local onChat = function (form, ref, option) | ||
form:Clear() | form:Clear() | ||
Line 200: | Line 256: | ||
form:SetMessage("What's your favourite colour?") | form:SetMessage("What's your favourite colour?") | ||
− | form:AddOption("Red", | + | form:AddOption("Red", 1) |
− | form:AddOption("Green", | + | form:AddOption("Green", 2) |
− | form:AddOption(" | + | form:AddOption("Blue", 3) |
− | |||
− | |||
end, | end, | ||
[1] = function () | [1] = function () | ||
form:SetMessage("Ahh red, the colour of raspberries.") | form:SetMessage("Ahh red, the colour of raspberries.") | ||
− | |||
end, | end, | ||
[2] = function () | [2] = function () | ||
form:SetMessage("Ahh green, the colour of trees.") | form:SetMessage("Ahh green, the colour of trees.") | ||
− | |||
end, | end, | ||
[3] = function () | [3] = function () | ||
− | |||
− | |||
− | |||
− | |||
form:SetMessage("Ahh blue, the colour of the ocean.") | form:SetMessage("Ahh blue, the colour of the ocean.") | ||
− | |||
end, | end, | ||
[-1] = function () | [-1] = function () | ||
form:Close() | form:Close() | ||
end | end | ||
− | + | } | |
− | + | options[option]() | |
end | end | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | local onCreateBB = function (station) | |
− | + | station:AddAdvert({ | |
− | + | title = 'COLORS', | |
− | + | description = "Let's talk colors!", | |
− | + | icon = 'news', | |
− | + | onChat = onChat, | |
− | + | onDelete = onDelete, | |
− | }) | + | }) |
+ | end | ||
− | + | Event.Register("onCreateBB", onCreateBB) | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Try this out: | |
− | + | * To understand what ''' 'form:Clear()' ''' does, comment out the line above containing it and restart Pioneer. As the form is no longer cleared and the 'Hang up' button is included automatically, there now appears to be only one form. The color selection buttons still works though. | |
− | [ | + | * Try adding 'Go back' buttons from the color options: |
+ | [1] = function () | ||
+ | form:SetMessage("Ahh red, the colour of raspberries.") | ||
+ | form:AddOption("Go back", 0) | ||
+ | end, | ||
− | + | * Try booth suggestions above at the same time. ''' 'form:Clear()' ''' is your friend. | |
− | + | * Stick this code into the second onChat example above (or adopt it to the first one) to try out ''' 'form:RemoveAdvertOnClose()' ''' and to test the ''' 'ref' ''' argument: | |
− | + | form:AddOption("Report post", 4) -- In option[0] | |
− | + | ||
− | + | -- ... | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | [ | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | [4] = function () | |
− | + | form:SetMessage("The ad has been reported and will not be shown on your BBS. " .. | |
− | + | "Thank you for helping us to improve 'Haber Connect'!\n" .. | |
− | + | "The ad was number " .. ref .. " from the top of the list." ) | |
− | + | form:RemoveAdvertOnClose() | |
− | + | end, | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | Please note! The '''ref''' nr and position in the '''BBS''' is not the same. It's the order in which the ad was created from the same script and the position in the BBS depends on the title and description as the posts are sorted. There are scripts that only create one ad at a time (Donate to Cranks...), and they will all have ref nr. 1. | |
− | + | ==Where to go from here== | |
+ | To see simple complete examples of BBS interaction used in the game, look in <code>data/modules/DonateToCranks/DonateToCranks.lua</code>, and its accompanying language file <code>data/lang/modules-donatetocranks/en.json</code>, or the Advice module <code>data/modules/Advice/Advice.lua</code> and <code>data/lang/modules-advice/en.json</code>. |
Latest revision as of 19:42, 25 July 2024
The bulletin board system is currently the only place where real dialogue between a script and the player can take place. Bulletin boards can exist within any SpaceStation
in the current system. They are created in a station the first time that a ship is either spawned, or lands, in that station. They continue to exist until the player leaves the system or quits the game. They are not saved in saved games, although a saved game contains information about which ones did exist.
When a bulletin board is created, the onCreateBB
event is triggered, and passes the SpaceStation
body in which that bulletin board was created. There is an exception to this: The event is not triggered after loading a game for those bulletin boards which, having existed at the time of saving, are re-created. The consequences of this will be covered later (see "Surviving a reload").
There are two components to any mission's entry on a bulletin board: The advert and the form. The advert is the part that is displayed on the main bulletin board list, along with all the other entries. The form is the part that appears on screen when the player clicks the advert's button.
Contents
The BBS advert
Adverts are placed onto a BBS by calling the station's AddAdvert()
method, once the bulletin board has been created. Depending on the nature of your script, you might want to always place one advert on every station (as seen with the Breakdowns & Servicing script), or you might want to place an arbitrary number of adverts on a given station (as seen with deliveries, or assassinations).
The opportunities to add an advert are presented by two events. onCreateBB
is the obvious one; there is also onUpdateBB
, which is called for all existing bulletin boards in the current system, approximately once every hour or two. The actual interval is not particularly predictable.
The AddAdvert()
method takes three arguments. The first is the text that will appear on the advert. The second is the function that will be called when the player clicks the advert. The third is optional, and is a function that can be called when the advert is deleted for any reason.
AddAdvert()
returns a reference number, which can subsequently be used to remove the advert using RemoveAdvert()
.
It's the job of the scripter to decide how many, if any, adverts to add to a bulletin board when onCreateBB
is triggered, and whether to add or remove any when onUpdateBB
is triggered. Tests could include the population of the system, the type of starport or the type of planet. In the future, tests will be able to include the government type of the system.
One important thing to bear in mind is that the script cannot query a bulletin boad to find out what adverts already exist. Each script must carefully track each advert that it has created if it is to have any control over how long they remain, and to be able to re-create them after a reload.
Here is an example of adding an advert. The effect of clicking the advert is simply to send a message to the player console with the name of the station and the reference number which is also the adverts place on the BBS. The advert is only added if the station is in space. There is no mission here, it is simply to illustrate the mechanics of adding an advert. Launch Pioneer and choose a new game with start on Barnard's star.
local Event = require "Event" local Comms = require "Comms" local ref -- Variable to save the advert's reference number local onCreateBB = function (station) -- This function can be in any scope that's visible when AddAdvert() is called local sendStationName = function () Comms.ImportantMessage(station.label .. "\n" .. "Add ref number: " .. ref) end if station.type == 'STARPORT_ORBITAL' then ref = station:AddAdvert('Need the name of this station?',sendStationName) end end Event.Register("onCreateBB", onCreateBB)
This code will create an advert:
Looking at the image, you will notice that the advert has appeared at the top of the bulletin board and that only one of two fields is filled with text. The BBS ad has two components, the title on top and the description. Only the description is present and since the BBS posts are sorted on first the title and secondly on the description, since the title is blank the post will show up on top. The icon used is the default. AddAdvert has two versions and we used a simpler legacy form. See
-- Legacy form ref = station:AddAdvert(description, onChat, onDelete)
Clicking on the advert causes this to happen:
Even though the only thing our function did was to send a message to the console, you can see that Pioneer automatically created a form for our advert. The only control is the 'Hang up' button.
Going back to the World View you can see the message on the Comms terminal:
More AddAdvert()
As we saw, the legacy form of AddAdvert created an add that lacked a title and with a default icon. Lets rewrite the example above in the full form. LuaClass:SpaceStation:AddAdvert.
AddAdvert takes a table as argument.
ref = station:AddAdvert({ description = description, icon = icon, onChat = onChat, onDelete = onDelete, isEnabled = isEnabled, })
Let's try the earlier example but simplified a bit to run on all stations.
local Event = require "Event" local Comms = require "Comms" local ref -- Variable to save the advert's reference number local onCreateBB = function (station) -- This function can be in any scope that's visible when AddAdvert() is called local sendStationName = function () Comms.ImportantMessage(station.label .. "\n" .. "Add ref number: " .. ref) end ref = station:AddAdvert({ title = 'STATION NAME', description = 'Need the name of this station?', icon = 'news', onChat = sendStationName, onDelete = onDelete, }) end Event.Register("onCreateBB", onCreateBB)
The ad now looks complete.
The BBS form
Once the player has clicked on an advert, they are presented with a form. Each advert has only one form. The content of the form is added by the script, and can be modified at any time. It consists of a title, a face, a message and zero or more clickable options.
The form itself is passed to the function specified in the SpaceStation.AddAdvert()
method. In the example above, that function would be sendStationName()
, which simply ignored any parameters sent to it. This resulted in the form being blank.
The form object which is passed to this function has methods for adding the content. SetTitle()
and SetMessage()
each accept a string. SetFace()
takes a table of information which defines the photofit face on the left but in the following example SetFace()
is called without any arguments and the face will therefore be completely randomized.
A minimal example without any clickable options, just the default 'Hang up':
local Event = import("Event") local populateForm = function (form) form:SetTitle('This appears above the face picture') form:SetFace() form:SetMessage([[This is the main message. It is normally a multi-line string.]]) end local onCreateBB = function (station) station:AddAdvert({ title = 'AD TITLE', description = 'This appears in the advert list', icon = 'news', onChat = populateForm, onDelete = onDelete, }) end Event.Register("onCreateBB", onCreateBB)
As before, an advert was created:
We have clicked on the ad and can see that populateForm
was called, and it successfully filled the form with content. If you 'hang up' and press the ad again a completely new face is generated. Lets improve on this and make the face persistent for the existence of the advert. Making it reappear in a saved game would take some more work (see "Surviving a reload").
local Character = require "Character" local Event = require "Event" local client = {} local message local populateForm = function (form) form:SetTitle('Pizza time!') form:SetFace(client) form:SetMessage(message) end local onCreateBB = function (station) client = Character.New() message = "I'm " .. client.name .. " and I need some pizza. I'm thinking pepperoni and cheeze. You feelin me?" station:AddAdvert({ title = 'PIZZA PARTY!', description = 'Special delivery needed', icon = 'news', onChat = populateForm, onDelete = onDelete, }) end Event.Register("onCreateBB", onCreateBB)
We introduce a new module 'Character' which basically is an rpg style character sheet with methods to work with it. It's a tool to generate and work with non-player characters (npc's). client = Character.New()
sets client to an all new character with basic characteristics, name, title, and looks. A character can be sent directly to the SetFace method and that's what we're after here. We also used the 'clients' name.
Adding options to the form
In the example above, we created a function named populateForm()
which was run when the advert button was clicked. That's not the only time it can be run; it is also run whenever options on its form are clicked. To make use of this, it is passed two additional parameters, both of which populateForm()
ignored. The first parameter is the form object, the second is the advert's unique reference and the third is the number of the option that was clicked. Because it handles all chat events, by convention we instead name this function onChat()
, which is how it shall be named from now on.
In the first example that called the function 'sendStationName' we caught the reference number from 'AddAdvert()' in a variable named 'ref' . As you may remember, 'AddAdvert()' takes two arguments; A string and a function. The function is passed three arguments. The second of these arguments is the reference number so we could have picked it up from within 'sendStationName' . The 'ref' number is useful if your script adds several adverts, each of which might have slightly differently worded content.
You've already learned the methods: 'SetTitle()' , 'SetMessage()' , and 'SetFace()' . Let's add the rest of the form() methods:
- form:AddOption() : adds clickable options with buttons. It takes two arguments: A string to set the text of the button and the option nr that will be sent to the form. This value is 0 when first called from the BBS by clicking the add. Every option form will have a default 'Hang up' option which returns -1.
- form:Clear() : removes the Message and Options, but preserves the Title and Face.
- form:Close() : Closes the form.
- form:RemoveAdvertOnClose() : Closes the form and removes the ad.
Form options are declared like this:
form:AddOption('I am option one',1) form:AddOption('I am option two',2)
These options will appear with the specified caption, and will call onChat()
, which will receive the form object, the advert reference and the option number that was specified after the caption in AddOption()
.
The onChat function below is adapted from an earlier example from the codedoc:
local Event = require 'Event' local onChat = function (form, ref, option) form:Clear() -- option 0 is called when the form is first activated from the -- bulletin board if option == 0 then form:SetTitle("Favourite colour") form:SetMessage("What's your favourite colour?") form:AddOption("Red", 1) form:AddOption("Green", 2) form:AddOption("Blue", 3) return end -- option 1 - red if option == 1 then form:SetMessage("Ahh red, the colour of raspberries.") return end -- option 2 - green if option == 2 then form:SetMessage("Ahh green, the colour of trees.") return end -- option 3 - blue if option == 3 then form:SetMessage("Ahh blue, the colour of the ocean.") return end -- only option left is -1, hang up form:Close() end local onCreateBB = function (station) station:AddAdvert({ title = 'COLORS', description = "Let's talk colors!", icon = 'news', onChat = onChat, onDelete = onDelete, }) end Event.Register("onCreateBB", onCreateBB)
Here, every time onChat()
is called, regardless of the specified option, the form is cleared. The option is checked, and the relevant content is added to the form. Any other functions can be called from here, and this is how the script gets input from the player.
An alternative format might be this:
local Event = require 'Event' local onChat = function (form, ref, option) form:Clear() local options = { [0] = function () form:SetTitle("Favourite colour") form:SetMessage("What's your favourite colour?") form:AddOption("Red", 1) form:AddOption("Green", 2) form:AddOption("Blue", 3) end, [1] = function () form:SetMessage("Ahh red, the colour of raspberries.") end, [2] = function () form:SetMessage("Ahh green, the colour of trees.") end, [3] = function () form:SetMessage("Ahh blue, the colour of the ocean.") end, [-1] = function () form:Close() end } options[option]() end local onCreateBB = function (station) station:AddAdvert({ title = 'COLORS', description = "Let's talk colors!", icon = 'news', onChat = onChat, onDelete = onDelete, }) end Event.Register("onCreateBB", onCreateBB)
Try this out:
- To understand what 'form:Clear()' does, comment out the line above containing it and restart Pioneer. As the form is no longer cleared and the 'Hang up' button is included automatically, there now appears to be only one form. The color selection buttons still works though.
- Try adding 'Go back' buttons from the color options:
[1] = function () form:SetMessage("Ahh red, the colour of raspberries.") form:AddOption("Go back", 0) end,
- Try booth suggestions above at the same time. 'form:Clear()' is your friend.
- Stick this code into the second onChat example above (or adopt it to the first one) to try out 'form:RemoveAdvertOnClose()' and to test the 'ref' argument:
form:AddOption("Report post", 4) -- In option[0] -- ... [4] = function () form:SetMessage("The ad has been reported and will not be shown on your BBS. " .. "Thank you for helping us to improve 'Haber Connect'!\n" .. "The ad was number " .. ref .. " from the top of the list." ) form:RemoveAdvertOnClose() end,
Please note! The ref nr and position in the BBS is not the same. It's the order in which the ad was created from the same script and the position in the BBS depends on the title and description as the posts are sorted. There are scripts that only create one ad at a time (Donate to Cranks...), and they will all have ref nr. 1.
Where to go from here
To see simple complete examples of BBS interaction used in the game, look in data/modules/DonateToCranks/DonateToCranks.lua
, and its accompanying language file data/lang/modules-donatetocranks/en.json
, or the Advice module data/modules/Advice/Advice.lua
and data/lang/modules-advice/en.json
.