Why make a player touch a sign to find the command and then say when you can have them touch an NPC and click/press button for yes instead? Chat commands for situations like that can be avoided now with elegant dialog systems.
Tutorial/examples assumes some knowledge of GUIs, catchevent, class scripts, and objects. All examples have been tested and work.
So you've reached that final critical part in your script and you need to implement a "Are you sure?" dialog. How do you do it? The way I see it there's two ways.
Without waitfor:
PHP Code:
//#CLIENTSIDE
function onCreated() {
setupFancyStuff();
promptUserToDestroy();
}
function setupFancyStuff() {
for (temp.i = 0; temp.i < 40; temp.i++) {
with (findimg(200 + temp.i)) {
x = player.x + random(-32, 32);
y = player.y + random(-32, 32);
image = "light4.png";
red = ((temp.i % 4) in {0,3} ? 1 : 0);
green = ((temp.i % 4) in {1,3} ? 1 : 0);
blue = ((temp.i % 4) == 2 ? 1 : 0);
alpha = 0.99;
}
}
}
function promptUserToDestroy() {
new GuiWindowCtrl("Window_AreUSure") {
width = 240;
height = 200;
x = (screenwidth - width) / 2;
y = (screenheight - height) / 2;
text = "Delete the pretty lights?";
visible = true;
canclose = canminimize = canmaximize = canresize = false;
new GuiButtonCtrl("Window_AreUSure_Yes") {
x = 1;
y = 20;
width = 99 + 20;
height = 178;
text = "Yes";
}
new GuiButtonCtrl("Window_AreUSure_No") {
x = 120;
y = 20;
width = 99 + 20;
height = 178;
text = "No";
}
}
}
function Window_AreUSure_Yes.onAction() {
hideimgs(200, 300);
Window_AreUSure.destroy();
}
function Window_AreUSure_No.onAction() {
Window_AreUSure.destroy();
}
With waitfor:
PHP Code:
//#CLIENTSIDE
function onCreated() {
setupFancyStuff();
if (promptUserToDestroy() == true) {
hideimgs(200,300);
}
}
function setupFancyStuff() {
for (temp.i = 0; temp.i < 40; temp.i++) {
with (findimg(200 + temp.i)) {
x = player.x + random(-32, 32);
y = player.y + random(-32, 32);
image = "light4.png";
red = ((temp.i % 4) in {0,3} ? 1 : 0);
green = ((temp.i % 4) in {1,3} ? 1 : 0);
blue = ((temp.i % 4) == 2 ? 1 : 0);
alpha = 0.99;
}
}
}
function promptUserToDestroy() {
new GuiWindowCtrl("Window_AreUSure") {
width = 240;
height = 200;
x = (screenwidth - width) / 2;
y = (screenheight - height) / 2;
text = "Delete the pretty lights?";
visible = true;
canclose = canminimize = canmaximize = canresize = false;
this.returnvalue = false;
new GuiButtonCtrl("Window_AreUSure_Yes") {
x = 1;
y = 20;
width = 99 + 20;
height = 178;
text = "Yes";
thiso.catchevent(this.name, "onAction", "onReplied");
}
new GuiButtonCtrl("Window_AreUSure_No") {
x = 120;
y = 20;
width = 99 + 20;
height = 178;
text = "No";
thiso.catchevent(this.name, "onAction", "onReplied");
}
}
// Waits for the onAnsweredDialog event to occur within the hour (3600 seconds).
// If you don't specify the timeout it will quit waiting after a while depending
// on what the script is doing.
waitfor(this, "AnsweredDialog", 3600);
// Return the value decided by the user.
return Window_AreUSure.returnvalue;
}
function onReplied(obj) {
// Set the return value of the window based on which button was pressed.
Window_AreUSure.returnvalue = (obj.text == "Yes" ? true : false);
// Hide the Window
Window_AreUSure.hide();
// Trigger AnsweredDialog to resume execution of script
this.trigger("AnsweredDialog", "");
}
Waitfor is really handy because you can have your script waitfor anything really nor do you have to define the event that has to occur. I.e:
syntax:
waitfor(receiving_object, event, timeout);
object receiving_object - The object that is going to receive the event
string event - The event the script is going to wait for the object to receive
float timeout - How long the script should waitfor (optional)
PHP Code:
//#CLIENTSIDE
function onCreated() {
// Generate Random Number for RandomEvent
temp.val = int(random(1, 3));
// Schedules RandomEvent to occur in 3 seconds.
this.scheduleevent(3, "RandomEvent_" @ temp.val);
// Waits for RandomEvent
waitfor(this, "RandomEvent_" @ temp.val);
// Success!
player.chat = "Tada!";
}
Now at first glance both scripts perform the same task except that with waitfor (with some modifications) you can re-use the code in other scripts provided you place the prompt function in a class or weapon script. Like so:
class: dialog
PHP Code:
//#CLIENTSIDE
function promptUser(txt) {
new GuiWindowCtrl("Window_AreUSure") {
width = 240;
height = 200;
x = (screenwidth - width) / 2;
y = (screenheight - height) / 2;
text = txt;
visible = true;
canclose = canminimize = canmaximize = canresize = false;
this.returnvalue = false;
new GuiButtonCtrl("Window_AreUSure_Yes") {
x = 1;
y = 20;
width = 99 + 20;
height = 178;
text = "Yes";
thiso.catchevent(this.name, "onAction", "onUserPromptReplied");
}
new GuiButtonCtrl("Window_AreUSure_No") {
x = 120;
y = 20;
width = 99 + 20;
height = 178;
text = "No";
thiso.catchevent(this.name, "onAction", "onUserPromptReplied");
}
}
// Waits for the onAnsweredDialog event to occur within the hour (3600 seconds).
// If you don't specify the timeout it will quit waiting after a while depending
// on what the script is doing.
waitfor(this, "AnsweredDialog", 3600);
// Return the value decided by the user.
return Window_AreUSure.returnvalue;
}
function onUserPromptReplied(obj) {
// Set the return value of the window based on which button was pressed.
Window_AreUSure.returnvalue = (obj.text == "Yes" ? true : false);
// Hide the Window
Window_AreUSure.hide();
// Trigger AnsweredDialog to resume execution of script
this.trigger("AnsweredDialog", "");
}
So after proper usage of class scripts and waitfor we're left with this:
PHP Code:
// Join dialog script to weapon
function onCreated() {
this.join("dialog");
}
//#CLIENTSIDE
function onCreated() {
setupFancyStuff();
if (promptUser("Destroy the pretty lights?") == true) {
hideimgs(200,300);
}
}
function setupFancyStuff() {
for (temp.i = 0; temp.i < 40; temp.i++) {
with (findimg(200 + temp.i)) {
x = player.x + random(-32, 32);
y = player.y + random(-32, 32);
image = "light4.png";
red = ((temp.i % 4) in {0,3} ? 1 : 0);
green = ((temp.i % 4) in {1,3} ? 1 : 0);
blue = ((temp.i % 4) == 2 ? 1 : 0);
alpha = 0.99;
}
}
}
As you can see the final scripts code is now much shorter, easier to read and understand logically.
Of course this is only a very basic implementation of a Dialog system, Novo has created one that's much more full-fledged it can be found
here.