forked from Mirrors/openclonk
306 lines
7.2 KiB
C
306 lines
7.2 KiB
C
/**
|
|
Tutorial Guide
|
|
The tutorial guide can be clicked by the player, it supplies the player with information and hints.
|
|
The following callbacks are made to the scenario script:
|
|
* OnGuideMessageShown(int plr, int index) when a message is shown
|
|
* OnGuideMessageRemoved(int plr, int index) when a message is removed, all events
|
|
|
|
@author Maikel
|
|
*/
|
|
|
|
|
|
local messages; // A container to hold all messages.
|
|
local message_open; // Currently open message.
|
|
local close_on_last; // Close guide on after last message.
|
|
|
|
protected func Initialize()
|
|
{
|
|
// Visibility
|
|
this.Visibility = VIS_Owner;
|
|
messages = [];
|
|
message_open = nil;
|
|
close_on_last = false;
|
|
|
|
// Initialize menu properties.
|
|
InitializeMenu();
|
|
|
|
// create the main menu
|
|
UpdateGuideMenu("");
|
|
return;
|
|
}
|
|
|
|
/* Adds a message to the guide. The internal index is set to this message meaning that this message will
|
|
* be shown if the player clicks the guide.
|
|
* @param msg Message that should be added to the message stack.
|
|
*/
|
|
public func AddGuideMessage(string msg)
|
|
{
|
|
// Add message to list.
|
|
messages[GetLength(messages)] = msg;
|
|
// Update the menu, because of the next button.
|
|
if (message_open != nil)
|
|
ShowGuideMenu(message_open);
|
|
return;
|
|
}
|
|
|
|
/* Shows a guide message to the player, also resets the internal index to that point.
|
|
* @param show_index The message corresponding to this index will be shown, if nil the last message will be shown.
|
|
*/
|
|
public func ShowGuideMessage(int show_index)
|
|
{
|
|
// If the index is not specified show last message, index must be between first and last message.
|
|
if (show_index == nil)
|
|
show_index = GetLength(messages) - 1;
|
|
show_index = BoundBy(show_index, 0, GetLength(messages) - 1);
|
|
// Show the guide message.
|
|
ShowGuideMenu(show_index);
|
|
return;
|
|
}
|
|
|
|
// Hides the guide and its menu to the player.
|
|
public func HideGuide()
|
|
{
|
|
if (this.Visibility == VIS_Owner)
|
|
{
|
|
// Change visibility and do script callback.
|
|
this.Visibility = VIS_None;
|
|
GameCall("OnGuideMessageRemoved", GetOwner(), message_open);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Shows the guide and its menu to the player, if it was hidden before.
|
|
public func ShowGuide()
|
|
{
|
|
if (this.Visibility == VIS_None)
|
|
{
|
|
// Change visibility and do script callback.
|
|
this.Visibility = VIS_Owner;
|
|
GameCall("OnGuideMessageShown", GetOwner(), message_open);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Returns whether the guide is currently hidden.
|
|
public func IsHidden()
|
|
{
|
|
return this.Visibility == VIS_None;
|
|
}
|
|
|
|
public func EnableCloseOnLastMessage(bool disable)
|
|
{
|
|
close_on_last = !disable;
|
|
return;
|
|
}
|
|
|
|
public func GetMessageCount()
|
|
{
|
|
return GetLength(messages);
|
|
}
|
|
|
|
protected func Destruction()
|
|
{
|
|
CloseGuideMenu();
|
|
return;
|
|
}
|
|
|
|
|
|
/*-- Menu implementation --*/
|
|
|
|
// Menu IDs.
|
|
local id_menu;
|
|
|
|
// Menu proplists.
|
|
local prop_menu;
|
|
local prop_next;
|
|
local prop_prev;
|
|
|
|
private func InitializeMenu()
|
|
{
|
|
var menu_width = 25; // in percentage of whole screen
|
|
var meny_offset = 4; // in em
|
|
var menu_height = 6; // in em, should correspond to six lines of text
|
|
var text_margin = 1; // margins in 1/10 em
|
|
|
|
// Menu proplist.
|
|
prop_menu =
|
|
{
|
|
Target = this,
|
|
Style = GUI_Multiple,
|
|
Decoration = GUI_MenuDeco,
|
|
Left = Format("%d%%", 50 - menu_width),
|
|
Right = Format("%d%%", 50 + menu_width),
|
|
Top = Format("0%%+%dem", meny_offset),
|
|
Bottom = Format("0%%+%dem", meny_offset + menu_height),
|
|
BackgroundColor = {Std = 0},
|
|
};
|
|
|
|
// Submenu proplists.
|
|
var prop_guide =
|
|
{
|
|
Target = this,
|
|
ID = 1,
|
|
Right = Format("0%%+%dem", menu_height),
|
|
Symbol = GetID(),
|
|
};
|
|
var prop_text =
|
|
{
|
|
Left = Format("0%%%s", ToEmString(10 * menu_height + text_margin)),
|
|
// 'Right' will be set on update
|
|
Target = this,
|
|
ID = 2,
|
|
Text = nil,
|
|
};
|
|
prop_next =
|
|
{
|
|
Target = this,
|
|
ID = 3,
|
|
Left = Format("100%%-%dem", menu_height / 2),
|
|
Top = Format("100%%-%dem", menu_height / 2),
|
|
Symbol = Icon_Arrow,
|
|
GraphicsName = "Down",
|
|
Text = "$MsgNext$",
|
|
Style = GUI_TextHCenter | GUI_TextVCenter,
|
|
BackgroundColor = {Std = 0, Hover = 0x50ffff00},
|
|
OnMouseIn = GuiAction_SetTag("Hover"),
|
|
OnMouseOut = GuiAction_SetTag("Std"),
|
|
OnClick = GuiAction_Call(this, "ShowNextMessage"),
|
|
};
|
|
prop_prev =
|
|
{
|
|
Target = this,
|
|
ID = 4,
|
|
Left = Format("100%%-%dem", menu_height / 2),
|
|
Bottom = Format("0%%+%dem", menu_height / 2),
|
|
Symbol = Icon_Arrow,
|
|
GraphicsName = "Up",
|
|
Text = "$MsgPrevious$",
|
|
Style = GUI_TextHCenter | GUI_TextVCenter,
|
|
BackgroundColor = {Std = 0, Hover = 0x50ffff00},
|
|
OnMouseIn = GuiAction_SetTag("Hover"),
|
|
OnMouseOut = GuiAction_SetTag("Std"),
|
|
OnClick = GuiAction_Call(this, "ShowPreviousMessage"),
|
|
};
|
|
|
|
// Add menu elements.
|
|
prop_menu.guide = prop_guide;
|
|
prop_menu.text = prop_text;
|
|
prop_menu.next = prop_next;
|
|
prop_menu.prev = prop_prev;
|
|
|
|
// Menu ID.
|
|
id_menu = GuiOpen(prop_menu);
|
|
return;
|
|
}
|
|
|
|
private func ShowGuideMenu(int index)
|
|
{
|
|
// There will always be the removal of the previous message.
|
|
if (message_open != nil && !IsHidden())
|
|
GameCall("OnGuideMessageRemoved", GetOwner(), message_open);
|
|
|
|
// Show the new message.
|
|
var message = messages[index];
|
|
if (!message)
|
|
return;
|
|
var has_next = index < GetLength(messages) - 1;
|
|
var has_prev = index > 0;
|
|
var has_close = close_on_last && !has_next;
|
|
UpdateGuideMenu(message, has_next, has_prev, has_close);
|
|
message_open = index;
|
|
|
|
// Notify the scenario script.
|
|
if (message_open != nil && !IsHidden())
|
|
GameCall("OnGuideMessageShown", GetOwner(), message_open);
|
|
return;
|
|
}
|
|
|
|
private func UpdateGuideMenu(string guide_message, bool has_next, bool has_prev, bool has_close)
|
|
{
|
|
// Update the text message entry.
|
|
prop_menu.text.Text = guide_message;
|
|
|
|
// Don't usually leave a margin for the text - just when actually showing buttons.
|
|
var is_showing_buttons = has_next || has_close || has_prev;
|
|
|
|
var text_right_side = "100%";
|
|
if (is_showing_buttons)
|
|
{
|
|
text_right_side = Format("100%-2.9em");
|
|
}
|
|
GuiUpdate({Right = text_right_side, Text = guide_message}, id_menu, prop_menu.text.ID, this);
|
|
|
|
// Update the next/close button.
|
|
if (has_next || has_close)
|
|
{
|
|
prop_menu.next = prop_next;
|
|
if (has_next)
|
|
{
|
|
prop_menu.next.Symbol = Icon_Arrow;
|
|
prop_menu.next.GraphicsName = "Down";
|
|
prop_menu.next.Text = "$MsgNext$";
|
|
}
|
|
else if (has_close)
|
|
{
|
|
prop_menu.next.Symbol = Icon_Cancel;
|
|
prop_menu.next.Text = "$MsgClose$";
|
|
}
|
|
GuiUpdate(prop_menu, id_menu, prop_menu.ID, this);
|
|
}
|
|
else if (prop_menu.next != nil)
|
|
{
|
|
GuiClose(id_menu, prop_menu.next.ID, this);
|
|
prop_menu.next = nil;
|
|
}
|
|
|
|
// Update the previous button.
|
|
if (has_prev)
|
|
{
|
|
prop_menu.prev = prop_prev;
|
|
GuiUpdate(prop_menu, id_menu, prop_menu.ID, this);
|
|
}
|
|
else if (prop_menu.prev != nil)
|
|
{
|
|
GuiClose(id_menu, prop_menu.prev.ID, this);
|
|
prop_menu.prev = nil;
|
|
}
|
|
return;
|
|
}
|
|
|
|
private func CloseGuideMenu()
|
|
{
|
|
// Gamecall on closing of the open message.
|
|
if (message_open != nil)
|
|
GameCall("OnGuideMessageRemoved", GetOwner(), message_open);
|
|
message_open = nil;
|
|
GuiClose(id_menu, nil, this);
|
|
return;
|
|
}
|
|
|
|
// Menu callback: the player has clicked on next message.
|
|
private func ShowNextMessage()
|
|
{
|
|
if (message_open >= GetLength(messages) - 1)
|
|
{
|
|
if (close_on_last)
|
|
CloseGuideMenu();
|
|
return;
|
|
}
|
|
ShowGuideMenu(message_open + 1);
|
|
return;
|
|
}
|
|
|
|
// Menu callback: the player has clicked on previous message.
|
|
private func ShowPreviousMessage()
|
|
{
|
|
if (message_open == 0)
|
|
return;
|
|
ShowGuideMenu(message_open - 1);
|
|
return;
|
|
}
|
|
|
|
|
|
/*-- Properties --*/
|
|
|
|
local Name = "$Name$";
|