Skip to content

Commit

Permalink
Engine: hide "stop_dialog_at_end" processing inside a function
Browse files Browse the repository at this point in the history
This picks out some logic processing code into handle_state_change_in_dialog_request() function.
Also moved run_dialog_request() to dialog.cpp for better organization.
  • Loading branch information
ivan-mogilko committed Oct 27, 2024
1 parent 39483c0 commit 4b9ede5
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 69 deletions.
65 changes: 63 additions & 2 deletions Engine/ac/dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,39 @@ const char *Dialog_GetScriptName(ScriptDialog *sd)
}

//=============================================================================
// dialog manager stuff

#define RUN_DIALOG_STAY -1
#define RUN_DIALOG_STOP_DIALOG -2
#define RUN_DIALOG_GOTO_PREVIOUS -4
// dialog manager stuff

static int run_dialog_request(int parmtr)
{
play.stop_dialog_at_end = DIALOG_RUNNING;
RuntimeScriptValue params[]{ parmtr };
RunScriptFunction(gameinst.get(), "dialog_request", 1, params);

if (play.stop_dialog_at_end == DIALOG_STOP)
{
play.stop_dialog_at_end = DIALOG_NONE;
return -2;
}
if (play.stop_dialog_at_end >= DIALOG_NEWTOPIC)
{
int tval = play.stop_dialog_at_end - DIALOG_NEWTOPIC;
play.stop_dialog_at_end = DIALOG_NONE;
return tval;
}
if (play.stop_dialog_at_end >= DIALOG_NEWROOM)
{
int roomnum = play.stop_dialog_at_end - DIALOG_NEWROOM;
play.stop_dialog_at_end = DIALOG_NONE;
NewRoom(roomnum);
return -2;
}
play.stop_dialog_at_end = DIALOG_NONE;
return -1;
}

void get_dialog_script_parameters(unsigned char* &script, unsigned short* param1, unsigned short* param2)
{
Expand Down Expand Up @@ -1292,11 +1320,18 @@ struct DialogExec
int DlgWas = -1;
// CHECKME: this may be unnecessary, investigate later
bool IsFirstEntry = true;
// nested dialogs "stack"
// Dialog topics history, used by "goto-previous" command
std::stack<int> TopicHist;
int ExecutedOption = -1; // option which is currently run (or -1)
bool AreOptionsDisplayed = false; // if dialog options are displayed on screen

// A position in script saved by certain API function calls in "dialog_request" callback;
// used purely for error reporting when the script has 2+ calls to gamestate-changing
// functions such as StartDialog or ChangeRoom.
// FIXME: this is horrible, review this and make consistent with error reporting
// for regular calls in normal script.
ScriptPosition SavedDialogRequestScriptPos;

DialogExec(int start_dlgnum) : DlgNum(start_dlgnum) {}
int HandleDialogResult(int res);
void Run();
Expand Down Expand Up @@ -1414,6 +1449,32 @@ void do_conversation(int dlgnum)
dialogExec = {};
}

bool handle_state_change_in_dialog_request(const char *apiname, int dlgreq_retval, bool expect_dialog_request)
{
// Test if we are inside a dialog state AND dialog_request callback
if ((dialogExec == nullptr) || (play.stop_dialog_at_end == DIALOG_NONE))
{
// Some command may only work inside dialog_request (?)
if (expect_dialog_request)
debug_script_warn("%s: not in a dialog_request(), ignored", apiname);
return false; // not handled, process command as normal
}

// Test if dialog result was not set yet
if (play.stop_dialog_at_end == DIALOG_RUNNING)
{
play.stop_dialog_at_end = dlgreq_retval;
get_script_position(dialogExec->SavedDialogRequestScriptPos);
}
else
{
debug_script_warn("!%s: more than one NewRoom/RunDialog/StopDialog requests within a dialog '%s' (%d), following one(s) will be ignored\n\tfirst was made in \"%s\", line %d",
apiname, game.dialogScriptNames[dialogExec->DlgNum].GetCStr(), dialogExec->DlgNum,
dialogExec->SavedDialogRequestScriptPos.Section.GetCStr(), dialogExec->SavedDialogRequestScriptPos.Line);
}
return true; // handled, state change will be taken care of by a dialog script
}

// end dialog manager


Expand Down
4 changes: 4 additions & 0 deletions Engine/ac/dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ void do_conversation(int dlgnum);
int show_dialog_options(int dlgnum, bool runGameLoopsInBackground);
// Handles a dialog option, optionally "sais" its text, optionally run corresponding dialog script's entry
int run_dialog_option(int dlgnum, int dialog_choice, int sayChosenOption, bool run_script);
// Handles a game-state changing command (such as StartDialog) inside "dialog_request" callback.
// Returns whether the change was handled in "dialog's way", and further processing is not necessary.
// Otherwise should process the command as normal.
bool handle_state_change_in_dialog_request(const char *apiname, int dlgreq_retval, bool expect_dialog_request = false);

extern std::vector<ScriptDialog> scrDialog;
extern std::vector<DialogTopic> dialog;
Expand Down
4 changes: 2 additions & 2 deletions Engine/ac/gamestate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ void GamePlayState::ReadFromSavegame(Stream *in, GameDataVersion data_ver, GameS
show_single_dialog_option = in->ReadInt32();
keep_screen_during_instant_transition = in->ReadInt32();
read_dialog_option_colour = in->ReadInt32();
stop_dialog_at_end = in->ReadInt32();
in->ReadInt32(); // was stop_dialog_at_end, which should not serialize
speech_portrait_placement = in->ReadInt32();
speech_portrait_x = in->ReadInt32();
speech_portrait_y = in->ReadInt32();
Expand Down Expand Up @@ -726,7 +726,7 @@ void GamePlayState::WriteForSavegame(Stream *out) const
out->WriteInt32(show_single_dialog_option);
out->WriteInt32(keep_screen_during_instant_transition);
out->WriteInt32(read_dialog_option_colour);
out->WriteInt32(stop_dialog_at_end);
out->WriteInt32(0); // was stop_dialog_at_end, which should not serialize
out->WriteInt32(speech_portrait_placement);
out->WriteInt32(speech_portrait_x);
out->WriteInt32(speech_portrait_y);
Expand Down
4 changes: 4 additions & 0 deletions Engine/ac/gamestate.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ struct GamePlayState
int show_single_dialog_option = 0;
int keep_screen_during_instant_transition = 0;
int read_dialog_option_colour = 0;
// stop_dialog_at_end - special value that is not supposed to be used in user script,
// but used in a generated dialogscript (when converted from dialog script slang)
// to tell how to proceed after "run-script" command ("dialog_request" callback).
// if non-0 - means that we are inside "dialog_request" callback.
int stop_dialog_at_end = 0;
int speech_portrait_placement = 0; // speech portrait placement mode (automatic/custom)
int speech_portrait_x = 0; // a speech portrait x offset from corresponding screen side
Expand Down
28 changes: 7 additions & 21 deletions Engine/ac/global_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,39 +27,25 @@ using namespace AGS::Common;

extern GameSetupStruct game;

ScriptPosition last_in_dialog_request_script_pos;
void RunDialog(int tum) {
void RunDialog(int tum)
{
if ((tum<0) | (tum>=game.numdialog))
quit("!RunDialog: invalid topic number specified");

can_run_delayed_command();

if (play.stop_dialog_at_end != DIALOG_NONE) {
if (play.stop_dialog_at_end == DIALOG_RUNNING)
play.stop_dialog_at_end = DIALOG_NEWTOPIC + tum;
else
quitprintf("!RunDialog: two NewRoom/RunDialog/StopDialog requests within dialog; last was called in \"%s\", line %d",
last_in_dialog_request_script_pos.Section.GetCStr(), last_in_dialog_request_script_pos.Line);
return;
}

get_script_position(last_in_dialog_request_script_pos);
if (handle_state_change_in_dialog_request("RunDialog", DIALOG_NEWTOPIC + tum))
return; // handled

if (inside_script)
get_executingscript()->QueueAction(PostScriptAction(ePSARunDialog, tum, "RunDialog"));
else
do_conversation(tum);
}


void StopDialog() {
if (play.stop_dialog_at_end == DIALOG_NONE) {
debug_script_warn("StopDialog called, but was not in a dialog");
debug_script_log("StopDialog called but no dialog");
return;
}
get_script_position(last_in_dialog_request_script_pos);
play.stop_dialog_at_end = DIALOG_STOP;
void StopDialog()
{
handle_state_change_in_dialog_request("StopDialog", DIALOG_STOP, true);
}

void SetDialogOption(int dlg, int opt, int onoroff, bool dlg_script)
Expand Down
15 changes: 3 additions & 12 deletions Engine/ac/global_room.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "ac/common.h"
#include "ac/character.h"
#include "ac/characterinfo.h"
#include "ac/dialog.h"
#include "ac/draw.h"
#include "ac/event.h"
#include "ac/gamesetupstruct.h"
Expand Down Expand Up @@ -68,7 +69,6 @@ void SetAmbientLightLevel(int light_level)
play.rtint_light = light_level;
}

extern ScriptPosition last_in_dialog_request_script_pos;
void NewRoom(int nrnum) {
if (nrnum < 0)
quitprintf("!NewRoom: room change requested to invalid room number %d.", nrnum);
Expand All @@ -85,17 +85,8 @@ void NewRoom(int nrnum) {

can_run_delayed_command();

if (play.stop_dialog_at_end != DIALOG_NONE) {
if (play.stop_dialog_at_end == DIALOG_RUNNING)
play.stop_dialog_at_end = DIALOG_NEWROOM + nrnum;
else {
quitprintf("!NewRoom: two NewRoom/RunDialog/StopDialog requests within dialog; last was called in \"%s\", line %d",
last_in_dialog_request_script_pos.Section.GetCStr(), last_in_dialog_request_script_pos.Line);
}
return;
}

get_script_position(last_in_dialog_request_script_pos);
if (handle_state_change_in_dialog_request("NewRoom", DIALOG_NEWROOM + nrnum))
return; // handled

if (in_leaves_screen >= 0) {
// NewRoom called from the Player Leaves Screen event -- just
Expand Down
14 changes: 9 additions & 5 deletions Engine/ac/runtime_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,6 @@
#define MAXGSVALUES 500
#define MAXGLOBALSTRINGS 51
#define MAX_INVORDER 500
#define DIALOG_NONE 0
#define DIALOG_RUNNING 1
#define DIALOG_STOP 2
#define DIALOG_NEWROOM 100
#define DIALOG_NEWTOPIC 12000
#define MAX_TIMERS 21
#define MAX_PARSED_WORDS 15

Expand Down Expand Up @@ -122,10 +117,19 @@ const int LegacyRoomVolumeFactor = 30;
// a 1-based movelist index offset for characters
#define CHMLSOFFS (1 + MAX_ROOM_OBJECTS)
#define MAX_SCRIPT_AT_ONCE 10

#define EVENT_NONE 0
#define EVENT_INPROGRESS 1
#define EVENT_CLAIMED 2

// Values for GameState::stop_dialog_at_end;
// tell what to do with the current Dialog after returning from the option script
#define DIALOG_NONE 0
#define DIALOG_RUNNING 1
#define DIALOG_STOP 2
#define DIALOG_NEWROOM 100
#define DIALOG_NEWTOPIC 12000

// Internal skip style flags, for speech/display, wait;
// theoretically correspond to InputType in script (with a 24-bit shift)
#define SKIP_NONE 0x00
Expand Down
2 changes: 0 additions & 2 deletions Engine/debug/debugger.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ extern int break_on_next_script_step;
int check_for_messages_from_debugger();
bool send_state_to_debugger(const char *msg);
bool send_exception_to_debugger(const char *qmsg);
// Returns current script's location and callstack
AGS::Common::String get_cur_script(int numberOfLinesOfCallStack);
bool get_script_position(ScriptPosition &script_pos);

void check_debug_keys();
Expand Down
24 changes: 0 additions & 24 deletions Engine/script/script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,30 +89,6 @@ size_t numScriptModules = 0;
static bool DoRunScriptFuncCantBlock(ccInstance *sci, NonBlockingScriptFunction* funcToRun, bool hasTheFunc);


int run_dialog_request (int parmtr) {
play.stop_dialog_at_end = DIALOG_RUNNING;
RuntimeScriptValue params[]{ parmtr };
RunScriptFunction(gameinst.get(), "dialog_request", 1, params);

if (play.stop_dialog_at_end == DIALOG_STOP) {
play.stop_dialog_at_end = DIALOG_NONE;
return -2;
}
if (play.stop_dialog_at_end >= DIALOG_NEWTOPIC) {
int tval = play.stop_dialog_at_end - DIALOG_NEWTOPIC;
play.stop_dialog_at_end = DIALOG_NONE;
return tval;
}
if (play.stop_dialog_at_end >= DIALOG_NEWROOM) {
int roomnum = play.stop_dialog_at_end - DIALOG_NEWROOM;
play.stop_dialog_at_end = DIALOG_NONE;
NewRoom(roomnum);
return -2;
}
play.stop_dialog_at_end = DIALOG_NONE;
return -1;
}

void run_function_on_non_blocking_thread(NonBlockingScriptFunction* funcToRun) {

update_script_mouse_coords();
Expand Down
1 change: 0 additions & 1 deletion Engine/script/script.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ struct NonBlockingScriptFunction
}
};

int run_dialog_request (int parmtr);
void run_function_on_non_blocking_thread(NonBlockingScriptFunction* funcToRun);

// TODO: run_interaction_event() and run_interaction_script()
Expand Down

0 comments on commit 4b9ede5

Please sign in to comment.