openclonk/planet/Missions.ocf/MtBrame.ocs/Dialogue.ocd/Script.c

216 lines
4.4 KiB
C

/**
Dialogue
Attach to a non player charachter to provide a message interface.
*/
local dlg_target;
local dlg_name;
local dlg_info;
local dlg_progress;
local dlg_status;
static const DLG_Status_Active = 0;
static const DLG_Status_Stop = 1;
static const DLG_Status_Remove = 2;
/*-- Dialogue creation --*/
// Sets a new dialogue for a npc.
global func SetDialogue(string name)
{
if (!this)
return;
var dialogue = CreateObject(Dialogue);
dialogue->InitDialogue(name, this);
dialogue->SetObjectLayer(nil);
return dialogue;
}
// Removes the existing dialogue of an object.
global func RemoveDialogue()
{
if (!this)
return;
var dialogue = FindObject(Find_ID(Dialogue), Find_ActionTarget(this));
if (dialogue)
dialogue->RemoveObject();
return;
}
/*-- Dialogue properties --*/
protected func Initialize()
{
// Dialogue progress to one.
dlg_progress = 1;
dlg_status = DLG_Status_Active;
return;
}
public func InitDialogue(string name, object target)
{
dlg_target = target;
dlg_name = name;
// Attach dialogue object to target.
SetAction("Dialogue", target);
// Update dialogue to target.
UpdateDialogue();
return;
}
private func UpdateDialogue()
{
// Adapt size to target and its direction.
var wdt = dlg_target->GetID()->GetDefWidth();
var hgt = dlg_target->GetID()->GetDefHeight();
var dir = dlg_target->GetDir();
SetShape(-wdt/2 + 2*(dir-1)*wdt, -hgt/2, 3*wdt, hgt);
// Transfer target name.
//SetName(Format("$MsgSpeak$", dlg_target->GetName()));
return;
}
public func SetDialogueInfo()
{
return;
}
public func SetDialogueProgress(int progress)
{
dlg_progress = Max(1, progress);
return;
}
public func SetDialogueStatus(int status)
{
dlg_status = status;
return;
}
/*-- Interaction --*/
// Players can talk to NPC via the interaction bar.
public func IsInteractable() { return true; }
// Adapt appearance in the interaction bar.
public func GetInteractionMetaInfo(object clonk)
{
if (InDialogue(clonk))
return { Description = Format("$MsgSpeak$", dlg_target->GetName()) , IconName = nil, IconID = Clonk, Selected = true };
return { Description = Format("$MsgSpeak$", dlg_target->GetName()) , IconName = nil, IconID = Clonk, Selected = false };
}
// Called on player interaction.
public func Interact(object clonk)
{
// Currently in a dialogue: abort that dialogue.
if (InDialogue(clonk))
clonk->CloseMenu();
// No conversation context: abort.
if (!dlg_name)
return true;
// Stop dialogue?
if (dlg_status == DLG_Status_Stop)
{
clonk->CloseMenu();
dlg_status = DLG_Status_Active;
return true;
}
// Remove dialogue?
if (dlg_status == DLG_Status_Remove)
{
clonk->CloseMenu();
RemoveObject();
return true;
}
// Start conversation context.
// Update dialogue progress first.
var progress = dlg_progress;
dlg_progress++;
// Then call relevant functions.
Call(Format("Dlg_%s_%d", dlg_name, progress), clonk);
return true;
}
private func InDialogue(object clonk)
{
return clonk->GetMenu() == Dialogue;
}
public func MessageBoxAll(string message, object talker)
{
for(var i = 0; i < GetPlayerCount(); ++i)
MessageBox(message, GetCursor(GetPlayerByIndex(i)), talker);
}
private func MessageBox(string message, object clonk, object talker)
{
// Use current NPC as talker if unspecified.
if (!talker)
talker = dlg_target;
// Use a menu for this dialogue.
clonk->CreateMenu(Dialogue, this, C4MN_Extra_None, nil, nil, C4MN_Style_Dialog, false, Dialogue);
// Add NPC portrait.
//var portrait = Format("%i", talker->GetID()); //, Dialogue, talker->GetColor(), "1");
clonk->AddMenuItem("", "", Dialogue, nil, nil, nil, C4MN_Add_ImgObject, talker); //TextSpec);
// Add NPC message.
var msg = Format("<c %x>%s:</c> %s", talker->GetColor(), talker->GetName(), message);
clonk->AddMenuItem(msg, "", nil, nil, nil, nil, C4MN_Add_ForceNoDesc);
// Add answers.
//for (var i = 0; i < GetLength(message.Answers); i++)
//{
// var ans = message.Answers[i][0];
// var call_back = message.Answers[i][1];
// target->AddMenuItem(ans, call_back, nil, nil, target, nil, C4MN_Add_ForceNoDesc);
//}
// Set menu decoration.
clonk->SetMenuDecoration(GUI_MenuDeco);
// Set text progress to NPC name.
var name = dlg_target->GetName();
var n_length;
while (GetChar(name, n_length))
n_length++;
clonk->SetMenuTextProgress(n_length + 1);
return;
}
local ActMap = {
Dialogue = {
Prototype = Action,
Name = "Dialogue",
Procedure = DFA_ATTACH,
Delay = 0,
NextAction = "Dialogue",
}
};
local Name = "$Name$";