add keypad to decoration objects

This can control lots of things and triggers on entering the correct code.
console-destruction
Maikel de Vries 2016-09-26 17:15:37 +02:00
parent 8a09fcc1b1
commit 32f5b1cb25
6 changed files with 430 additions and 0 deletions

View File

@ -0,0 +1,8 @@
[DefCore]
id=Keypad
Version=8,0
Category=C4D_StaticBack
Picture=0,0,112,144
Width=14
Height=18
Offset=-7,-9

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,366 @@
/**
Keypad
allows to enter digit codes to trigger an event.
@author Maikel
*/
// Background colors for hovering and bars and description.
static const KEYPADMENU_BackgroundColor = 0x77000000;
static const KEYPADMENU_HoverColor = 0x99888888;
static const KEYPADMENU_BarColor = 0x99888888;
local code, correct_code;
local target_door;
local correct_code_action, wrong_code_action;
local menu, menu_id, menu_target, menu_controller;
/*-- Script Interface --*/
public func SetKeypadCode(string to_code)
{
// Check if code contains any non-digits.
var non_digits = RegexMatch(to_code, "[^0-9]+");
if (!DeepEqual(non_digits, []))
{
Log("$WarningKeypadCode$", to_code);
return;
}
// If code is valid, set it.
correct_code = to_code;
return;
}
public func SetStoneDoor(object door)
{
target_door = door;
return true;
}
public func OpenDoor(object clonk)
{
SetPlrView(clonk->GetController(), target_door);
var y_off = target_door->~GetFloorOffset();
Global->CreateLight(target_door->GetX(), target_door->GetY() + y_off, 30, Fx_Light.LGT_Temp, clonk->GetController(), 30, 50);
target_door->OpenDoor();
return;
}
public func OnCorrectCodeEntered(object clonk)
{
// Open door if specified.
if (target_door)
OpenDoor(clonk);
// Perform user action last; it may delete the door/clonk/etc.
UserAction->EvaluateAction(correct_code_action, this, clonk);
return;
}
public func OnWrongCodeEntered(object clonk)
{
// Perform user action last; it may delete the door/clonk/etc.
UserAction->EvaluateAction(wrong_code_action, this, clonk);
return;
}
public func SetCodeActions(new_correct_action, new_wrong_action)
{
correct_code_action = new_correct_action;
wrong_code_action = new_wrong_action;
return;
}
/*-- Saving --*/
public func SaveScenarioObject(proplist props)
{
if (!_inherited(props, ...)) return false;
if (correct_code) props->AddCall("Code", this, "SetKeypadCode", Format("%v", correct_code));
if (target_door) props->AddCall("Target", this, "SetStoneDoor", target_door);
if (correct_code_action || wrong_code_action) props->AddCall("Action", this, "SetCodeActions", correct_code_action, wrong_code_action);
return true;
}
/*-- Editor --*/
public func Definition(proplist def)
{
if (!def.EditorProps)
def.EditorProps = {};
def.EditorProps.correct_code = { Name = "$KeypadCode$", Type = "string", Set="SetKeypadCode", EditorHelp = "$HelpKeypadCode$" };
def.EditorProps.target_door = { Name = "$KeypadTarget$", Type = "object", Filter = "IsSwitchTarget", EditorHelp = "$HelpKeypadTarget$" };
def.EditorProps.correct_code_action = new UserAction.Prop { Name = "$OnCorrectCodeAction$", EditorHelp = "$HelpOnCorrectCodeAction$" };
def.EditorProps.wrong_code_action = new UserAction.Prop { Name = "$OnWrongCodeAction$", EditorHelp = "$HelpOnWrongCodeAction$" };
return;
}
/*-- Interaction --*/
public func IsInteractable(object clonk)
{
return clonk->GetProcedure() == "WALK" && (!clonk->GetMenu() || clonk->GetMenu().ID != menu_id);
}
public func Interact(object clonk)
{
code = "";
OpenKeypadMenu(clonk);
return true;
}
/*-- Menu --*/
public func OpenKeypadMenu(object clonk)
{
// Only one clonk at a time can handle the keypad.
if (menu_controller)
return;
// If the menu is already open, don't open another instance.
if (clonk->GetMenu() && clonk->GetMenu().ID == menu_id)
return;
// This object functions as menu target and for visibility.
menu_target = CreateContents(Dummy);
menu_target.Visibility = VIS_Owner;
menu_target->SetOwner(clonk->GetOwner());
menu_controller = clonk;
// Make the room/credits menu.
menu =
{
Target = menu_target,
Left = "50%-6em",
Right = "50%+6em",
Top = "50%-10em",
Bottom = "50%+8em",
Decoration = GUI_MenuDeco,
BackgroundColor = {Std = KEYPADMENU_BackgroundColor},
};
menu.code =
{
Target = this,
ID = 2,
Bottom = "1.5em",
text =
{
Target = this,
ID = 21,
Right = "4em",
Style = GUI_TextVCenter,
Text = "$MsgEnterCode$"
},
value =
{
Target = this,
ID = 22,
Left = "4em",
Right = "100%-0.05em",
Style = GUI_TextVCenter | GUI_TextRight,
Text = nil
}
};
menu.bar =
{
Target = this,
ID = 3,
Top = "1.5em",
Bottom = "2em",
BackgroundColor = {Std = ROOMMENU_BarColor},
};
menu.keys =
{
Target = this,
ID = 4,
Top = "2em",
};
menu.keys.key1 = MakePadButton(0, 0, Icon_Number, "1", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 1));
menu.keys.key2 = MakePadButton(1, 0, Icon_Number, "2", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 2));
menu.keys.key3 = MakePadButton(2, 0, Icon_Number, "3", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 3));
menu.keys.key4 = MakePadButton(0, 1, Icon_Number, "4", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 4));
menu.keys.key5 = MakePadButton(1, 1, Icon_Number, "5", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 5));
menu.keys.key6 = MakePadButton(2, 1, Icon_Number, "6", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 6));
menu.keys.key7 = MakePadButton(0, 2, Icon_Number, "7", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 7));
menu.keys.key8 = MakePadButton(1, 2, Icon_Number, "8", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 8));
menu.keys.key9 = MakePadButton(2, 2, Icon_Number, "9", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 9));
menu.keys.key0 = MakePadButton(1, 3, Icon_Number, "0", "$TooltipDigit$", GuiAction_Call(this, "UpdateMenuCode", 0));
menu.keys.enter = MakePadButton(2, 3, Icon_Ok, nil, "$TooltipCheck$", GuiAction_Call(this, "EnterKeypadCode", nil));
menu.keys.clearlast = MakePadButton(0, 0, Icon_Number, "Hash", "$TooltipClearLast$", GuiAction_Call(this, "UpdateMenuCode", nil));
menu.keys.clearlast.Left = "0em"; menu.keys.clearlast.Right = "2em"; menu.keys.clearlast.Top = "12em"; menu.keys.clearlast.Bottom = "14em";
menu.keys.clearlast.image = {Left = "50%", Top = "50%", Symbol = Icon_Arrow, GraphicsName = "Left"};
menu.keys.clearcode = MakePadButton(0, 0, Icon_Number, "Hash", "$TooltipClearCode$", GuiAction_Call(this, "ClearMenuCode", nil));
menu.keys.clearcode.Left = "2em"; menu.keys.clearcode.Right = "4em"; menu.keys.clearcode.Top = "12em"; menu.keys.clearcode.Bottom = "14em";
menu.keys.clearcode.image = {Left = "50%", Top = "50%", Symbol = Icon_Cancel};
menu.keys.resetcode = MakePadButton(0, 0, Icon_Number, "Hash", "$TooltipResetCode$", GuiAction_Call(this, "ResetKeypadCode", nil));
menu.keys.resetcode.Left = "2em"; menu.keys.resetcode.Right = "4em"; menu.keys.resetcode.Top = "14em"; menu.keys.resetcode.Bottom = "16em";
menu.keys.resetcode.image = {Left = "50%", Top = "50%", Symbol = Icon_Swap};
menu.keys.close = MakePadButton(0, 0, Icon_Cancel, nil, "$TooltipClose$", GuiAction_Call(this, "CloseKeypadMenu", nil));
menu.keys.close.Left = "0em"; menu.keys.close.Right = "2em"; menu.keys.close.Top = "14em"; menu.keys.close.Bottom = "16em";
// Open the menu and store the menu ID.
menu_id = GuiOpen(menu);
// Notify the clonk and set the menu.
clonk->SetMenu(this);
return;
}
public func MakePadButton(int x, int y, id symbol, string graphics_name, string tooltip, on_click)
{
return {
Left = Format("%dem", 4 * x),
Right = Format("%dem", 4 * (x + 1)),
Top = Format("%dem", 4 * y),
Bottom = Format("%dem", 4 * (y + 1)),
Symbol = symbol,
GraphicsName = graphics_name,
BackgroundColor = {Std = 0, Hover = KEYPADMENU_HoverColor},
OnMouseIn = GuiAction_SetTag("Hover"),
OnMouseOut = GuiAction_SetTag("Std"),
OnClick = on_click,
Tooltip = tooltip
};
}
public func UpdateMenuCode(int digit_pressed)
{
if (digit_pressed == nil)
{
if (GetType(code) == C4V_String)
code = TakeString(code, 0, GetLength(code) - 1);
Sound("UI::Click?");
}
else
{
if (code == nil)
code = Format("%d", digit_pressed);
else
code = Format("%s%d", code, digit_pressed);
Sound("UI::Tick");
}
menu.code.value.Text = code;
GuiUpdate(menu.code.value, menu_id, menu.code.value.ID, this);
return;
}
public func ClearMenuCode()
{
code = nil;
Sound("UI::Click?");
menu.code.value.Text = code;
GuiUpdate(menu.code.value, menu_id, menu.code.value.ID, this);
return;
}
public func EnterKeypadCode()
{
if (menu_controller.code_reset_state == "reset")
{
correct_code = code;
code = nil;
menu.code.value.Text = "$MsgCodeReset$";
menu_controller.code_reset_state = nil;
Sound("UI::Confirmed");
menu.code.text.Text = "$MsgEnterCode$";
GuiUpdate(menu.code.text, menu_id, menu.code.text.ID, this);
}
else
{
if (correct_code == nil)
{
code = nil;
menu.code.value.Text = "$MsgNoCode$";
Sound("UI::Error");
}
else if (correct_code == code)
{
code = nil;
Sound("UI::Confirmed");
if (menu_controller.code_reset_state == "confirm")
{
menu.code.value.Text = "$MsgCodeConfirmed$";
menu_controller.code_reset_state = "reset";
menu.code.text.Text = "$MsgEnterNewCode$";
GuiUpdate(menu.code.text, menu_id, menu.code.text.ID, this);
}
else
{
menu.code.value.Text = "$MsgCorrectCode$";
// Execute the correct code trigger.
OnCorrectCodeEntered(menu_controller);
}
}
else
{
code = nil;
menu.code.value.Text = "$MsgWrongCode$";
Sound("UI::Error");
// Execute the wrong code trigger.
OnWrongCodeEntered(menu_controller);
}
}
GuiUpdate(menu.code.value, menu_id, menu.code.value.ID, this);
return;
}
public func ResetKeypadCode()
{
// Only allow resetting the code if the clonk (menu_target) has entered the correct code before.
if (correct_code == nil)
{
menu_controller.code_reset_state = "reset";
menu.code.text.Text = "$MsgEnterNewCode$";
GuiUpdate(menu.code.text, menu_id, menu.code.text.ID, this);
}
else if (menu_controller.code_reset_state != "reset" && menu_controller.code_reset_state != "confirm")
{
menu_controller.code_reset_state = "confirm";
menu.code.text.Text = "$MsgConfirmCode$";
GuiUpdate(menu.code.text, menu_id, menu.code.text.ID, this);
}
else
{
menu_controller.code_reset_state = nil;
menu.code.text.Text = "$MsgEnterCode$";
GuiUpdate(menu.code.text, menu_id, menu.code.text.ID, this);
}
Sound("UI::Tick");
return;
}
public func CloseKeypadMenu()
{
// Close the menu and inform the controller.
Sound("UI::Close");
GuiClose(menu_id, nil, this);
menu_target->RemoveObject();
menu_target = nil;
menu_id = nil;
if (menu_controller)
{
menu_controller.code_reset_state = nil;
menu_controller->MenuClosed();
}
menu_controller = nil;
return;
}
public func Close()
{
CloseKeypadMenu();
return;
}
/*-- Properties --*/
local Name = "$Name$";
local Description = "$Description$";

View File

@ -0,0 +1,28 @@
Name=Ziffernblock
Description=Richtiger Kennzahl eingeben um ein Ereignis aus zu lösen.
MsgEnterCode=Kennzahl eingeben:
MsgEnterNewCode=Neue Kennzahl:
MsgConfirmCode=Kennzahl bestätigen:
MsgNoCode=<c ffff00>Ziffernblock hat kein Kennzahl!</c>
MsgCorrectCode=<c 00ff00>Richtiger Kennzahl!</c>
MsgWrongCode=<c ff0000>Falscher Kennzahl!</c>
MsgCodeReset=<c 00ff00>Kennzahl wurde zurück gesetzt!</c>
MsgCodeConfirmed=<c 00ff00>Kennzahl bestätigt, jetzt zurücksetzen.</c>
TooltipDigit=Gebe Nummer ein.
TooltipCheck=Kontrolliere die eingebene Kennzahl.
TooltipClose=Schließe das Ziffernblock.
TooltipClearLast=Entferne die letzte Nummer.
TooltipClearCode=Eingegebene Kennzahl löschen.
TooltipResetCode=Die Kennzahl des Ziffernblocks zurücksetzen.
KeypadCode=Kennzahl
KeypadTarget=Ziel
OnCorrectCodeAction=Aktion 'richtige Kennzahl'
OnWrongCodeAction=Aktion 'falsche Kennzahl'
HelpKeypadCode=Gib den Kennzahl ein der vom Spieler eingetippt werden muss (darf nur Zahlen enthalten).
HelpKeypadTarget=Tür die geöffnet wird wenn den richtigen Kennzahl eingegeben wird.
HelpOnCorrectCodeAction=Aktion die ausgeführt wird wenn die richtige Kennzahl eingegeben wird.
HelpOnWrongCodeAction=Aktion die ausgeführt wird wenn eine falsche Kennzahl eingegeben wird.
WarningKeypadCode=WARNUNG: Kennzahl vom Ziffernblock (%s) enthält Charaktere die nicht Zahlen sind, Kennzahl wird nicht gesetzt.

View File

@ -0,0 +1,28 @@
Name=Keypad
Description=Enter the correct code to trigger an event.
MsgEnterCode=Enter code:
MsgEnterNewCode=New code:
MsgConfirmCode=Confirm code:
MsgNoCode=<c ffff00>Keypad has no code!</c>
MsgCorrectCode=<c 00ff00>Correct code!</c>
MsgWrongCode=<c ff0000>Wrong code!</c>
MsgCodeReset=<c 00ff00>Code has been reset!</c>
MsgCodeConfirmed=<c 00ff00>Code confirmed, reset now.</c>
TooltipDigit=Enter digit.
TooltipCheck=Check the entered code.
TooltipClose=Close the keypad.
TooltipClearLast=Delete the last digit.
TooltipClearCode=Clear the entered code.
TooltipResetCode=Reset the keypad code.
KeypadCode=Code
KeypadTarget=Target
OnCorrectCodeAction=Action 'correct code'
OnWrongCodeAction=Action 'wrong code'
HelpKeypadCode=Enter the keypad code the player must type in (must be digits only).
HelpKeypadTarget=Target door that will be opened when the correct has been entered.
HelpOnCorrectCodeAction=Action to be executed when the correct code has been entered.
HelpOnWrongCodeAction=Action to be executed when a wrong code has been entered.
WarningKeypadCode=WARNING: keypad code (%s) contains some non-digit characters, code will not be set.