[Scummvm-git-logs] scummvm master -> 99cc27e840b59a84e1804dda2619ecd67891cdfb

dreammaster noreply at scummvm.org
Tue Apr 19 02:31:45 UTC 2022


This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
8be58d3de2 AGS: Store game events in std::vector, remove event cap
af079a9c45 AGS: Handle all the buffered key events in one game frame
2e24e08d5b AGS: Brought few "run script" functions to similar arg list
b2d8bcad75 AGS: Refactor RunTextScript* functions for the purpose of clarity
c0010986ac AGS: Implemented `on_text_input(int chr)` callback
09da0fbf5d AGS: Implemented `dialog_options_text_input(int chr)` callback
dec92f05ea AGS: Support passing partial argument list to a script callback
99cc27e840 AGS: Fixed few comments in ccInstance::Run()


Commit: 8be58d3de20ab96c300fcfcaa94546fee15bf5fe
    https://github.com/scummvm/scummvm/commit/8be58d3de20ab96c300fcfcaa94546fee15bf5fe
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:29-07:00

Commit Message:
AGS: Store game events in std::vector, remove event cap

>From upstream a2f9a5ba94377686762b2828df4fccbe661d2b03

Changed paths:
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/event.h
    engines/ags/engine/ac/room.cpp
    engines/ags/engine/main/game_run.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h
    engines/ags/lib/std/utility.h


diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index 0f0e64942b8..f6dc82c3a3b 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -110,13 +110,13 @@ void run_event_block_inv(int invNum, int event) {
 
 // event list functions
 void setevent(int evtyp, int ev1, int ev2, int ev3) {
-	_G(event)[_G(numevents)].type = evtyp;
-	_G(event)[_G(numevents)].data1 = ev1;
-	_G(event)[_G(numevents)].data2 = ev2;
-	_G(event)[_G(numevents)].data3 = ev3;
-	_G(event)[_G(numevents)].player = _GP(game).playercharacter;
-	_G(numevents)++;
-	if (_G(numevents) >= MAXEVENTS) quit("too many events posted");
+	EventHappened evt;
+	evt.type = evtyp;
+	evt.data1 = ev1;
+	evt.data2 = ev2;
+	evt.data3 = ev3;
+	evt.player = _GP(game).playercharacter;
+	_GP(events).push_back(evt);
 }
 
 // TODO: this is kind of a hack, which forces event to be processed even if
@@ -129,7 +129,7 @@ void force_event(int evtyp, int ev1, int ev2, int ev3) {
 		setevent(evtyp, ev1, ev2, ev3);
 }
 
-void process_event(EventHappened *evp) {
+void process_event(const EventHappened *evp) {
 	RuntimeScriptValue rval_null;
 	if (evp->type == EV_TEXTSCRIPT) {
 		_G(ccError) = 0;
@@ -340,41 +340,34 @@ void runevent_now(int evtyp, int ev1, int ev2, int ev3) {
 	process_event(&evh);
 }
 
-void processallevents(int numev, EventHappened *evlist) {
-	int dd;
-
+void processallevents() {
 	if (_G(inside_processevent))
 		return;
 
-	// make a copy of the events - if processing an event includes
-	// a blocking function it will continue to the next game loop
-	// and wipe out the event pointer we were passed
-	EventHappened copyOfList[MAXEVENTS];
-	memcpy(&copyOfList[0], &evlist[0], sizeof(EventHappened) * numev);
+	// Take ownership of the pending events
+	// Note: upstream AGS used std::move, which I haven't been able
+	// to properly implement in ScummVM. Luckily, our events are
+	// a pointer, so I could get the same result swapping them
+	std::vector<EventHappened> *evtCopy = new std::vector<EventHappened>();
+	SWAP(evtCopy, _G(events));
 
 	int room_was = _GP(play).room_changes;
 
 	_G(inside_processevent)++;
 
-	for (dd = 0; dd < numev; dd++) {
-
-		process_event(&copyOfList[dd]);
+	for (size_t i = 0; i < evtCopy->size(); ++i) {
+		process_event(&(*evtCopy)[i]);
 
-		if (room_was != _GP(play).room_changes || _G(abort_engine))
+		if (room_was != _GP(play).room_changes)
 			break;  // changed room, so discard other events
 	}
 
+	delete evtCopy;
 	_G(inside_processevent)--;
 }
 
-void update_events() {
-	processallevents(_G(numevents), &_G(event)[0]);
-	_G(numevents) = 0;
-}
-
 // end event list functions
 
-
 void ClaimEvent() {
 	if (_G(eventClaimed) == EVENT_NONE)
 		quit("!ClaimEvent: no event to claim");
diff --git a/engines/ags/engine/ac/event.h b/engines/ags/engine/ac/event.h
index ed361b15e54..2596054cc35 100644
--- a/engines/ags/engine/ac/event.h
+++ b/engines/ags/engine/ac/event.h
@@ -38,8 +38,6 @@ namespace AGS3 {
 #define GE_LOSE_INV      8
 #define GE_RESTORE_GAME  9
 
-#define MAXEVENTS 15
-
 #define EV_TEXTSCRIPT 1
 #define EV_RUNEVBLOCK 2
 #define EV_FADEIN     3
@@ -52,9 +50,9 @@ namespace AGS3 {
 #define EVB_ROOM    2
 
 struct EventHappened {
-	int type;
-	int data1, data2, data3;
-	int player;
+	int type = 0;
+	int data1 = 0, data2 = 0, data3 = 0;
+	int player = -1;
 };
 
 int run_claimable_event(const char *tsname, bool includeRoom, int numParams, const RuntimeScriptValue *params, bool *eventWasClaimed);
@@ -65,10 +63,9 @@ void run_event_block_inv(int invNum, int event);
 // event list functions
 void setevent(int evtyp, int ev1 = 0, int ev2 = -1000, int ev3 = 0);
 void force_event(int evtyp, int ev1 = 0, int ev2 = -1000, int ev3 = 0);
-void process_event(EventHappened *evp);
+void process_event(const EventHappened *evp);
 void runevent_now(int evtyp, int ev1, int ev2, int ev3);
-void processallevents(int numev, EventHappened *evlist);
-void update_events();
+void processallevents();
 // end event list functions
 void ClaimEvent();
 
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index ec9e464c5e8..6a60c83ee5a 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -245,7 +245,7 @@ void unload_old_room() {
 	}
 
 	cancel_all_scripts();
-	_G(numevents) = 0;  // cancel any pending room events
+	_GP(events).clear();  // cancel any pending room events
 
 	if (_G(roomBackgroundBmp) != nullptr) {
 		_G(gfxDriver)->DestroyDDB(_G(roomBackgroundBmp));
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 6957ad27aef..07f26a1862d 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -158,7 +158,7 @@ static int game_loop_check_ground_level_interactions() {
 		if ((_G(restrict_until)) && (!ShouldStayInWaitMode())) {
 			// cancel the Rep Exec and Stands on Hotspot events that
 			// we just added -- otherwise the event queue gets huge
-			_G(numevents) = _G(numEventsAtStartOfFunction);
+			_GP(events).resize(_G(numEventsAtStartOfFunction));
 			return 0;
 		}
 	} // end if checking ground level interactions
@@ -516,14 +516,14 @@ static void check_controls() {
 	check_keyboard_controls();
 }
 
-static void check_room_edges(int numevents_was) {
+static void check_room_edges(size_t numevents_was) {
 	if ((IsInterfaceEnabled()) && (IsGamePaused() == 0) &&
 	        (_G(in_new_room) == 0) && (_G(new_room_was) == 0)) {
 		// Only allow walking off edges if not in wait mode, and
 		// if not in Player Enters Screen (allow walking in from off-screen)
 		int edgesActivated[4] = { 0, 0, 0, 0 };
 		// Only do it if nothing else has happened (eg. mouseclick)
-		if ((_G(numevents) == numevents_was) &&
+		if ((_GP(events).size() == numevents_was) &&
 		        ((_GP(play).ground_level_areas_disabled & GLED_INTERACTION) == 0)) {
 
 			if (_G(playerchar)->x <= _GP(thisroom).Edges.Left)
@@ -558,7 +558,7 @@ static void game_loop_check_controls(bool checkControls) {
 	// don't let the player do anything before the screen fades in
 	if ((_G(in_new_room) == 0) && (checkControls)) {
 		int inRoom = _G(displayed_room);
-		int numevents_was = _G(numevents);
+		size_t numevents_was = _GP(events).size();
 		check_controls();
 		check_room_edges(numevents_was);
 
@@ -631,7 +631,7 @@ static void game_loop_update_events() {
 	if (_G(in_new_room) > 0)
 		setevent(EV_FADEIN, 0, 0, 0);
 	_G(in_new_room) = 0;
-	update_events();
+	processallevents();
 	if (!_G(abort_engine) && (_G(new_room_was) > 0) && (_G(in_new_room) == 0)) {
 		// if in a new room, and the room wasn't just changed again in update_events,
 		// then queue the Enters Screen scripts
@@ -704,7 +704,7 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
 
 	sys_evt_process_pending();
 
-	_G(numEventsAtStartOfFunction) = _G(numevents);
+	_G(numEventsAtStartOfFunction) = _GP(events).size();
 
 	if (_G(want_exit)) {
 		ProperExit();
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index bc226ee9b56..73dab86f469 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -196,7 +196,7 @@ Globals::Globals() {
 	_ResPaths = new ResourcePaths();
 
 	// event.cpp globals
-	_event = new EventHappened[MAXEVENTS + 1];
+	_events = new std::vector<EventHappened>();
 
 	// fonts.cpp globals
 	_fonts = new std::vector<AGS::Shared::Font>();
@@ -443,7 +443,7 @@ Globals::~Globals() {
 	delete _ResPaths;
 
 	// event.cpp globals
-	delete[] _event;
+	delete _events;
 
 	// fonts.cpp globals
 	delete _fonts;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index c656b992117..f5ad1ec7fbe 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -667,8 +667,7 @@ public:
 	int _in_enters_screen = 0, _done_es_error = 0;
 	int _in_leaves_screen = -1;
 
-	EventHappened *_event;
-	int _numevents = 0;
+	std::vector<EventHappened> *_events;
 
 	const char *_evblockbasename = nullptr;
 	int _evblocknum = 0;
diff --git a/engines/ags/lib/std/utility.h b/engines/ags/lib/std/utility.h
index 7fe1f595467..d701a3c3dd5 100644
--- a/engines/ags/lib/std/utility.h
+++ b/engines/ags/lib/std/utility.h
@@ -22,6 +22,8 @@
 #ifndef AGS_STD_UTILITY_H
 #define AGS_STD_UTILITY_H
 
+#include "common/textconsole.h"
+
 namespace AGS3 {
 namespace std {
 
@@ -41,9 +43,21 @@ pair<T1, T2> make_pair(T1 first, T2 second) {
 	return pair<T1, T2>(first, second);
 }
 
-template<class T>
-T move(const T &v) {
-	return v;
+// STRUCT TEMPLATE remove_reference
+template <class _Ty>
+struct remove_reference {
+	using type = _Ty;
+};
+
+template <class _Ty>
+using remove_reference_t = typename remove_reference<_Ty>::type;
+
+// FUNCTION TEMPLATE move
+// TODO: Haven't been able to get this to properly work to reset
+// the source when moving the contents of std::vector arrays
+template <class _Ty>
+constexpr remove_reference_t<_Ty> &&move(_Ty &&_Arg) noexcept {
+	return static_cast<remove_reference_t<_Ty> &&>(_Arg);
 }
 
 } // namespace std


Commit: af079a9c452b0e537eac1c7a781640d74c89e4cb
    https://github.com/scummvm/scummvm/commit/af079a9c452b0e537eac1c7a781640d74c89e4cb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:38-07:00

Commit Message:
AGS: Handle all the buffered key events in one game frame

>From upstream e489e187e88071c15fa64351852b8ede45f9f7ac

Changed paths:
    engines/ags/engine/main/game_run.cpp


diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 07f26a1862d..7190f51ff06 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -502,8 +502,6 @@ static void check_keyboard_controls() {
 		debug_script_log("Running on_key_press keycode %d", sckey);
 		setevent(EV_TEXTSCRIPT, TS_KEYPRESS, sckey);
 	}
-
-	// RunTextScriptIParam(_G(gameinst),"on_key_press",kgn);
 }
 
 // check_controls: checks mouse & keyboard interface
@@ -513,7 +511,9 @@ static void check_controls() {
 	sys_evt_process_pending();
 
 	check_mouse_controls();
-	check_keyboard_controls();
+	// Handle all the buffered key events
+	while (ags_keyevent_ready())
+		check_keyboard_controls();
 }
 
 static void check_room_edges(size_t numevents_was) {


Commit: 2e24e08d5ba87ef5ecfa3ff1e4e4389176ad44d3
    https://github.com/scummvm/scummvm/commit/2e24e08d5ba87ef5ecfa3ff1e4e4389176ad44d3
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:39-07:00

Commit Message:
AGS: Brought few "run script" functions to similar arg list

>From upstream 78163a07400353013dd939ca86f5513f3196394a

Changed paths:
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/global_room.cpp
    engines/ags/engine/ac/gui.cpp
    engines/ags/engine/script/executing_script.cpp
    engines/ags/engine/script/executing_script.h
    engines/ags/engine/script/script.cpp
    engines/ags/engine/script/script.h
    engines/ags/plugins/ags_plugin.cpp


diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index f6dc82c3a3b..ddcc7ab3ee4 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -85,7 +85,8 @@ int run_claimable_event(const char *tsname, bool includeRoom, int numParams, con
 
 // runs the global script on_event function
 void run_on_event(int evtype, RuntimeScriptValue &wparam) {
-	QueueScriptFunction(kScInstGame, "on_event", 2, RuntimeScriptValue().SetInt32(evtype), wparam);
+	RuntimeScriptValue params[]{ evtype , wparam };
+	QueueScriptFunction(kScInstGame, "on_event", 2, params);
 }
 
 void run_room_event(int id) {
@@ -134,7 +135,8 @@ void process_event(const EventHappened *evp) {
 	if (evp->type == EV_TEXTSCRIPT) {
 		_G(ccError) = 0;
 		if (evp->data2 > -1000) {
-			QueueScriptFunction(kScInstGame, _G(tsnames)[evp->data1], 1, RuntimeScriptValue().SetInt32(evp->data2));
+			RuntimeScriptValue params[]{ evp->data2 };
+			QueueScriptFunction(kScInstGame, _G(tsnames)[evp->data1], 1, params);
 		} else {
 			QueueScriptFunction(kScInstGame, _G(tsnames)[evp->data1]);
 		}
diff --git a/engines/ags/engine/ac/global_room.cpp b/engines/ags/engine/ac/global_room.cpp
index fd1a7b15366..121962c9733 100644
--- a/engines/ags/engine/ac/global_room.cpp
+++ b/engines/ags/engine/ac/global_room.cpp
@@ -177,8 +177,8 @@ void CallRoomScript(int value) {
 		quit("!CallRoomScript: not inside a script???");
 
 	_GP(play).roomscript_finished = 0;
-	RuntimeScriptValue rval_null;
-	_G(curscript)->run_another("on_call", kScInstRoom, 1, RuntimeScriptValue().SetInt32(value), rval_null);
+	RuntimeScriptValue params[]{ value , RuntimeScriptValue() };
+	_G(curscript)->run_another("on_call", kScInstRoom, 1, params);
 }
 
 int HasBeenToRoom(int roomnum) {
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index d3908450c68..0506dc9f356 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -311,9 +311,9 @@ void remove_popup_interface(int ifacenum) {
 void process_interface_click(int ifce, int btn, int mbut) {
 	if (btn < 0) {
 		// click on GUI background
-		QueueScriptFunction(kScInstGame, _GP(guis)[ifce].OnClickHandler.GetCStr(), 2,
-		                    RuntimeScriptValue().SetDynamicObject(&_G(scrGui)[ifce], &_GP(ccDynamicGUI)),
-		                    RuntimeScriptValue().SetInt32(mbut));
+		RuntimeScriptValue params[]{ RuntimeScriptValue().SetDynamicObject(&_G(scrGui)[ifce], &_GP(ccDynamicGUI)),
+					RuntimeScriptValue().SetInt32(mbut) };
+		QueueScriptFunction(kScInstGame, _GP(guis)[ifce].OnClickHandler.GetCStr(), 2, params);
 		return;
 	}
 
@@ -335,24 +335,24 @@ void process_interface_click(int ifce, int btn, int mbut) {
 		// if the object has a special handler script then run it;
 		// otherwise, run interface_click
 		if ((theObj->GetEventCount() > 0) &&
-		        (!theObj->EventHandlers[0].IsEmpty()) &&
-		        (!_G(gameinst)->GetSymbolAddress(theObj->EventHandlers[0].GetCStr()).IsNull())) {
+			(!theObj->EventHandlers[0].IsEmpty()) &&
+			(!_G(gameinst)->GetSymbolAddress(theObj->EventHandlers[0].GetCStr()).IsNull())) {
 			// control-specific event handler
-			if (strchr(theObj->GetEventArgs(0).GetCStr(), ',') != nullptr)
-				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0].GetCStr(), 2,
-				                    RuntimeScriptValue().SetDynamicObject(theObj, &_GP(ccDynamicGUIObject)),
-				                    RuntimeScriptValue().SetInt32(mbut));
-			else
-				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0].GetCStr(), 1,
-				                    RuntimeScriptValue().SetDynamicObject(theObj, &_GP(ccDynamicGUIObject)));
-		} else
-			QueueScriptFunction(kScInstGame, "interface_click", 2,
-			                    RuntimeScriptValue().SetInt32(ifce),
-			                    RuntimeScriptValue().SetInt32(btn));
+			if (theObj->GetEventArgs(0).FindChar(',') != -1) {
+				RuntimeScriptValue params[]{ RuntimeScriptValue().SetDynamicObject(theObj, &_GP(ccDynamicGUIObject)),
+					RuntimeScriptValue().SetInt32(mbut) };
+				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0].GetCStr(), 2, params);
+			} else {
+				RuntimeScriptValue params[]{ RuntimeScriptValue().SetDynamicObject(theObj, &_GP(ccDynamicGUIObject)) };
+				QueueScriptFunction(kScInstGame, theObj->EventHandlers[0].GetCStr(), 1, params);
+			}
+		} else {
+			RuntimeScriptValue params[]{ ifce , btn };
+			QueueScriptFunction(kScInstGame, "interface_click", 2, params);
+		}
 	}
 }
 
-
 void replace_macro_tokens(const char *text, String &fixed_text) {
 	const char *curptr = &text[0];
 	char tmpm[3];
diff --git a/engines/ags/engine/script/executing_script.cpp b/engines/ags/engine/script/executing_script.cpp
index 2a1b3a597bb..0222546c91f 100644
--- a/engines/ags/engine/script/executing_script.cpp
+++ b/engines/ags/engine/script/executing_script.cpp
@@ -60,7 +60,7 @@ int ExecutingScript::queue_action(PostScriptAction act, int data, const char *an
 	return numPostScriptActions - 1;
 }
 
-void ExecutingScript::run_another(const char *namm, ScriptInstType scinst, size_t param_count, const RuntimeScriptValue &p1, const RuntimeScriptValue &p2) {
+void ExecutingScript::run_another(const char *namm, ScriptInstType scinst, size_t param_count, const RuntimeScriptValue *params) {
 	if (numanother < MAX_QUEUED_SCRIPTS)
 		numanother++;
 	else {
@@ -73,8 +73,8 @@ void ExecutingScript::run_another(const char *namm, ScriptInstType scinst, size_
 	script.FnName.SetString(namm, MAX_FUNCTION_NAME_LEN);
 	script.Instance = scinst;
 	script.ParamCount = param_count;
-	script.Param1 = p1;
-	script.Param2 = p2;
+	for (size_t p = 0; p < MAX_QUEUED_PARAMS && p < param_count; ++p)
+		script.Params[p] = params[p];
 }
 
 void ExecutingScript::init() {
diff --git a/engines/ags/engine/script/executing_script.h b/engines/ags/engine/script/executing_script.h
index 36363b6a747..938d0213108 100644
--- a/engines/ags/engine/script/executing_script.h
+++ b/engines/ags/engine/script/executing_script.h
@@ -41,6 +41,7 @@ enum PostScriptAction {
 #define MAX_QUEUED_SCRIPTS 4
 #define MAX_QUEUED_ACTIONS 5
 #define MAX_FUNCTION_NAME_LEN 60
+#define MAX_QUEUED_PARAMS  4
 
 enum ScriptInstType {
 	kScInstGame,
@@ -51,8 +52,7 @@ struct QueuedScript {
 	Shared::String     FnName;
 	ScriptInstType     Instance;
 	size_t             ParamCount;
-	RuntimeScriptValue Param1;
-	RuntimeScriptValue Param2;
+	RuntimeScriptValue Params[MAX_QUEUED_PARAMS];
 
 	QueuedScript();
 };
@@ -70,7 +70,7 @@ struct ExecutingScript {
 	int8 forked;
 
 	int queue_action(PostScriptAction act, int data, const char *aname);
-	void run_another(const char *namm, ScriptInstType scinst, size_t param_count, const RuntimeScriptValue &p1, const RuntimeScriptValue &p2);
+	void run_another(const char *namm, ScriptInstType scinst, size_t param_count, const RuntimeScriptValue *params);
 	void init();
 	ExecutingScript();
 };
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index e458ab3a1fa..5f1190fb8f7 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -271,22 +271,22 @@ ccInstance *GetScriptInstanceByType(ScriptInstType sc_inst) {
 	return nullptr;
 }
 
-void QueueScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count, const RuntimeScriptValue &p1, const RuntimeScriptValue &p2) {
+void QueueScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count, const RuntimeScriptValue *params) {
 	if (_G(inside_script))
 		// queue the script for the run after current script is finished
-		_G(curscript)->run_another(fn_name, sc_inst, param_count, p1, p2);
+		_G(curscript)->run_another(fn_name, sc_inst, param_count, params);
 	else
 		// if no script is currently running, run the requested script right away
-		RunScriptFunction(sc_inst, fn_name, param_count, p1, p2);
+		RunScriptFunction(sc_inst, fn_name, param_count, params);
 }
 
-void RunScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count, const RuntimeScriptValue &p1, const RuntimeScriptValue &p2) {
+void RunScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count, const RuntimeScriptValue *params) {
 	ccInstance *sci = GetScriptInstanceByType(sc_inst);
 	if (sci) {
 		if (param_count == 2)
-			RunTextScript2IParam(sci, fn_name, p1, p2);
+			RunTextScript2IParam(sci, fn_name, params[0], params[1]);
 		else if (param_count == 1)
-			RunTextScriptIParam(sci, fn_name, p1);
+			RunTextScriptIParam(sci, fn_name, params[0]);
 		else if (param_count == 0)
 			RunTextScript(sci, fn_name);
 	}
@@ -361,7 +361,7 @@ int PrepareTextScript(ccInstance *sci, const char **tsname) {
 	return 0;
 }
 
-int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, int numParam, const RuntimeScriptValue *params) {
+int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, size_t numParam, const RuntimeScriptValue *params) {
 	int oldRestoreCount = _G(gameHasBeenRestored);
 	// First, save the current ccError state
 	// This is necessary because we might be attempting
@@ -573,7 +573,7 @@ void post_script_cleanup() {
 	for (jj = 0; jj < copyof.numanother; jj++) {
 		old_room_number = _G(displayed_room);
 		QueuedScript &script = copyof.ScFnQueue[jj];
-		RunScriptFunction(script.Instance, script.FnName.GetCStr(), script.ParamCount, script.Param1, script.Param2);
+		RunScriptFunction(script.Instance, script.FnName.GetCStr(), script.ParamCount, script.Params);
 		if (script.Instance == kScInstRoom && script.ParamCount == 1) {
 			// some bogus hack for "on_call" event handler
 			_GP(play).roomscript_finished = 1;
@@ -899,8 +899,8 @@ void run_unhandled_event(int evnt) {
 	else if ((evtype == 3) & (evnt == 4));  // any click on character
 	else if (evtype > 0) {
 		can_run_delayed_command();
-
-		QueueScriptFunction(kScInstGame, "unhandled_event", 2, RuntimeScriptValue().SetInt32(evtype), RuntimeScriptValue().SetInt32(evnt));
+		RuntimeScriptValue params[] = { evtype, evnt };
+		QueueScriptFunction(kScInstGame, "unhandled_event", 2, params);
 	}
 }
 
diff --git a/engines/ags/engine/script/script.h b/engines/ags/engine/script/script.h
index 3dcd52bf355..a81aead095d 100644
--- a/engines/ags/engine/script/script.h
+++ b/engines/ags/engine/script/script.h
@@ -53,12 +53,12 @@ void    cancel_all_scripts();
 ccInstance *GetScriptInstanceByType(ScriptInstType sc_inst);
 // Queues a script function to be run either called by the engine or from another script
 void    QueueScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count = 0,
-                            const RuntimeScriptValue &p1 = RuntimeScriptValue(), const RuntimeScriptValue &p2 = RuntimeScriptValue());
+	const RuntimeScriptValue *params = nullptr);
 // Try to run a script function right away
 void    RunScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count = 0,
-                          const RuntimeScriptValue &p1 = RuntimeScriptValue(), const RuntimeScriptValue &p2 = RuntimeScriptValue());
+	const RuntimeScriptValue *params = nullptr);
 
-int     RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, int numParam, const RuntimeScriptValue *params);
+int     RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, size_t param_count, const RuntimeScriptValue *params);
 int     RunTextScript(ccInstance *sci, const char *tsname);
 int     RunTextScriptIParam(ccInstance *sci, const char *tsname, const RuntimeScriptValue &iparam);
 int     RunTextScript2IParam(ccInstance *sci, const char *tsname, const RuntimeScriptValue &iparam, const RuntimeScriptValue &param2);
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 9b497229820..4991f168e9a 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -612,11 +612,12 @@ int IAGSEngine::CallGameScriptFunction(const char *name, int32 globalScript, int
 
 	ccInstance *toRun = GetScriptInstanceByType(globalScript ? kScInstGame : kScInstRoom);
 
-	RuntimeScriptValue params[3];
-	params[0].SetPluginArgument(arg1);
-	params[1].SetPluginArgument(arg2);
-	params[2].SetPluginArgument(arg3);
-	int toret = RunScriptFunctionIfExists(toRun, name, numArgs, params);
+	RuntimeScriptValue params[]{
+		   RuntimeScriptValue().SetPluginArgument(arg1),
+		   RuntimeScriptValue().SetPluginArgument(arg2),
+		   RuntimeScriptValue().SetPluginArgument(arg3),
+	};
+	int toret = RunScriptFunctionIfExists(toRun, (char *)name, numArgs, params);
 	return toret;
 }
 
@@ -641,8 +642,9 @@ void IAGSEngine::QueueGameScriptFunction(const char *name, int32 globalScript, i
 	if (numArgs < 0 || numArgs > 2)
 		quit("IAGSEngine::QueueGameScriptFunction: invalid number of arguments");
 
-	_G(curscript)->run_another(name, globalScript ? kScInstGame : kScInstRoom, numArgs,
-	                           RuntimeScriptValue().SetPluginArgument(arg1), RuntimeScriptValue().SetPluginArgument(arg2));
+	RuntimeScriptValue params[]{ RuntimeScriptValue().SetPluginArgument(arg1),
+		RuntimeScriptValue().SetPluginArgument(arg2) };
+	_G(curscript)->run_another(name, globalScript ? kScInstGame : kScInstRoom, numArgs, params);
 }
 
 int IAGSEngine::RegisterManagedObject(const void *object, IAGSScriptManagedObject *callback) {


Commit: b2d8bcad753468e53e74823292a73c5b60d44031
    https://github.com/scummvm/scummvm/commit/b2d8bcad753468e53e74823292a73c5b60d44031
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:39-07:00

Commit Message:
AGS: Refactor RunTextScript* functions for the purpose of clarity

>From upstream 17af6ca2cb1fba310900f5189da788fa52ef7dab

Changed paths:
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/event.cpp
    engines/ags/engine/ac/event.h
    engines/ags/engine/main/game_run.cpp
    engines/ags/engine/main/game_start.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/engine/script/script.h
    engines/ags/globals.h
    engines/ags/plugins/ags_plugin.cpp


diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 2d5725974d2..9720c213bdb 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -173,7 +173,8 @@ int run_dialog_script(DialogTopic *dtpp, int dialogID, int offse, int optionInde
 	if (_G(dialogScriptsInst)) {
 		char funcName[100];
 		sprintf(funcName, "_run_dialog%d", dialogID);
-		RunTextScriptIParam(_G(dialogScriptsInst), funcName, RuntimeScriptValue().SetInt32(optionIndex));
+		RuntimeScriptValue params[]{ optionIndex };
+		RunScriptFunction(_G(dialogScriptsInst), funcName, 1, params);
 		result = _G(dialogScriptsInst)->returnValue;
 	} else {
 		// old dialog format
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index ddcc7ab3ee4..75a8e7e15aa 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -58,7 +58,7 @@ int run_claimable_event(const char *tsname, bool includeRoom, int numParams, con
 	int toret;
 
 	if (includeRoom && _G(roominst)) {
-		toret = RunScriptFunctionIfExists(_G(roominst), tsname, numParams, params);
+		toret = RunScriptFunction(_G(roominst), tsname, numParams, params);
 		if (_G(abort_engine))
 			return -1;
 
@@ -70,7 +70,7 @@ int run_claimable_event(const char *tsname, bool includeRoom, int numParams, con
 
 	// run script modules
 	for (int kk = 0; kk < _G(numScriptModules); kk++) {
-		toret = RunScriptFunctionIfExists(_GP(moduleInst)[kk], tsname, numParams, params);
+		toret = RunScriptFunction(_GP(moduleInst)[kk], tsname, numParams, params);
 
 		if (_G(eventClaimed) == EVENT_CLAIMED) {
 			_G(eventClaimed) = eventClaimedOldValue;
diff --git a/engines/ags/engine/ac/event.h b/engines/ags/engine/ac/event.h
index 2596054cc35..7df4f619c06 100644
--- a/engines/ags/engine/ac/event.h
+++ b/engines/ags/engine/ac/event.h
@@ -46,6 +46,7 @@ namespace AGS3 {
 #define TS_REPEAT   1
 #define TS_KEYPRESS 2
 #define TS_MCLICK   3
+#define TS_NUM      4
 #define EVB_HOTSPOT 1
 #define EVB_ROOM    2
 
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 7190f51ff06..0e2dd3fe3a0 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -222,8 +222,8 @@ static void check_mouse_controls() {
 			}
 			_G(wasongui) = mongu;
 			_G(wasbutdown) = mbut + 1;
-		} else setevent(EV_TEXTSCRIPT, TS_MCLICK, mbut + 1);
-		//    else RunTextScriptIParam(_G(gameinst),"on_mouse_click",aa+1);
+		} else
+			setevent(EV_TEXTSCRIPT, TS_MCLICK, mbut + 1);
 	}
 
 	if (mwheelz < 0)
diff --git a/engines/ags/engine/main/game_start.cpp b/engines/ags/engine/main/game_start.cpp
index 00c2f3014fa..a8f6aa28a7b 100644
--- a/engines/ags/engine/main/game_start.cpp
+++ b/engines/ags/engine/main/game_start.cpp
@@ -83,10 +83,7 @@ void start_game() {
 	// skip ticks to account for initialisation or a restored _GP(game).
 	skipMissedTicks();
 
-	for (int kk = 0; kk < _G(numScriptModules); kk++)
-		RunTextScript(_GP(moduleInst)[kk], "game_start");
-
-	RunTextScript(_G(gameinst), "game_start");
+	RunScriptFunctionInModules("game_start");
 
 	_G(our_eip) = -43;
 
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 5f1190fb8f7..3cebf13b503 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -19,7 +19,6 @@
  *
  */
 
-//include <string.h>
 #include "ags/engine/script/script.h"
 #include "ags/shared/ac/common.h"
 #include "ags/engine/ac/character.h"
@@ -55,9 +54,13 @@
 
 namespace AGS3 {
 
+static bool DoRunScriptFuncCantBlock(ccInstance *sci, NonBlockingScriptFunction *funcToRun, bool hasTheFunc);
+static char scfunctionname[MAX_FUNCTION_NAME_LEN + 1];
+
 int run_dialog_request(int parmtr) {
 	_GP(play).stop_dialog_at_end = DIALOG_RUNNING;
-	RunTextScriptIParam(_G(gameinst), "dialog_request", RuntimeScriptValue().SetInt32(parmtr));
+	RuntimeScriptValue params[]{ parmtr };
+	RunScriptFunction(_G(gameinst), "dialog_request", 1, params);
 
 	if (_GP(play).stop_dialog_at_end == DIALOG_STOP) {
 		_GP(play).stop_dialog_at_end = DIALOG_NONE;
@@ -277,22 +280,10 @@ void QueueScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t par
 		_G(curscript)->run_another(fn_name, sc_inst, param_count, params);
 	else
 		// if no script is currently running, run the requested script right away
-		RunScriptFunction(sc_inst, fn_name, param_count, params);
-}
-
-void RunScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count, const RuntimeScriptValue *params) {
-	ccInstance *sci = GetScriptInstanceByType(sc_inst);
-	if (sci) {
-		if (param_count == 2)
-			RunTextScript2IParam(sci, fn_name, params[0], params[1]);
-		else if (param_count == 1)
-			RunTextScriptIParam(sci, fn_name, params[0]);
-		else if (param_count == 0)
-			RunTextScript(sci, fn_name);
-	}
+		RunScriptFunctionAuto(sc_inst, fn_name, param_count, params);
 }
 
-bool DoRunScriptFuncCantBlock(ccInstance *sci, NonBlockingScriptFunction *funcToRun, bool hasTheFunc) {
+static bool DoRunScriptFuncCantBlock(ccInstance *sci, NonBlockingScriptFunction *funcToRun, bool hasTheFunc) {
 	if (!hasTheFunc)
 		return (false);
 
@@ -324,8 +315,7 @@ bool DoRunScriptFuncCantBlock(ccInstance *sci, NonBlockingScriptFunction *funcTo
 	return (hasTheFunc);
 }
 
-char scfunctionname[MAX_FUNCTION_NAME_LEN + 1];
-int PrepareTextScript(ccInstance *sci, const char **tsname) {
+static int PrepareTextScript(ccInstance *sci, const char **tsname) {
 	_G(ccError) = 0;
 	// FIXME: try to make it so this function is not called with NULL sci
 	if (sci == nullptr) return -1;
@@ -361,7 +351,7 @@ int PrepareTextScript(ccInstance *sci, const char **tsname) {
 	return 0;
 }
 
-int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, size_t numParam, const RuntimeScriptValue *params) {
+int RunScriptFunction(ccInstance *sci, const char *tsname, size_t numParam, const RuntimeScriptValue *params) {
 	int oldRestoreCount = _G(gameHasBeenRestored);
 	// First, save the current ccError state
 	// This is necessary because we might be attempting
@@ -381,10 +371,7 @@ int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, size_t numPar
 	// Clear the error message
 	_G(ccErrorString) = "";
 
-	if (numParam < 3) {
-		toret = _G(curscript)->inst->CallScriptFunction(tsname, numParam, params);
-	} else
-		quit("Too many parameters to RunScriptFunctionIfExists");
+	toret = _G(curscript)->inst->CallScriptFunction(tsname, numParam, params);
 
 	if (_G(abort_engine))
 		return -1;
@@ -413,64 +400,70 @@ int RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, size_t numPar
 	return toret;
 }
 
-int RunTextScript(ccInstance *sci, const char *tsname) {
-	if (strcmp(tsname, REP_EXEC_NAME) == 0) {
-		// run module rep_execs
-		// FIXME: in theory the function may be already called for _GP(moduleInst)[i],
-		// in which case this should not be executed; need to rearrange the code somehow
-		int room_changes_was = _GP(play).room_changes;
-		int restore_game_count_was = _G(gameHasBeenRestored);
-
-		for (int kk = 0; kk < _G(numScriptModules); kk++) {
-			if (!_GP(moduleRepExecAddr)[kk].IsNull())
-				RunScriptFunctionIfExists(_GP(moduleInst)[kk], tsname, 0, nullptr);
-
-			if ((room_changes_was != _GP(play).room_changes) ||
-			        (restore_game_count_was != _G(gameHasBeenRestored)))
-				return 0;
-		}
-	}
+void RunScriptFunctionInModules(const char *tsname, size_t param_count, const RuntimeScriptValue *params) {
+	for (int i = 0; i < _G(numScriptModules); ++i)
+		RunScriptFunction(_GP(moduleInst)[i], tsname, param_count, params);
+	RunScriptFunction(_G(gameinst), tsname, param_count, params);
+}
 
-	int toret = RunScriptFunctionIfExists(sci, tsname, 0, nullptr);
-	if ((toret == -18) && (sci == _G(roominst))) {
-		// functions in room script must exist
-		quitprintf("prepare_script: error %d (%s) trying to run '%s'   (Room %d)", toret, _G(ccErrorString).GetCStr(), tsname, _G(displayed_room));
-	}
+int RunScriptFunctionInRoom(const char *tsname, size_t param_count, const RuntimeScriptValue *params) {
+	// Some room callbacks are considered to be obligatory; for historical reasons these are
+	// identified by having no parameters;
+	// TODO: this is a hack, this should be defined either by function type, or as an arg
+	const bool strict_room_event = (param_count == 0);
+	int toret = RunScriptFunction(_G(roominst), tsname, param_count, params);
+	// If it's a obligatory room event, and return code means missing function - error
+	if (strict_room_event && (toret == -18))
+		quitprintf("RunScriptFunction: error %d (%s) trying to run '%s'   (Room %d)",
+			toret, _G(ccErrorString).GetCStr(), tsname, _G(displayed_room));
 	return toret;
 }
 
-int RunTextScriptIParam(ccInstance *sci, const char *tsname, const RuntimeScriptValue &iparam) {
-	if ((strcmp(tsname, "on_key_press") == 0) || (strcmp(tsname, "on_mouse_click") == 0)) {
-		bool eventWasClaimed;
-		int toret = run_claimable_event(tsname, true, 1, &iparam, &eventWasClaimed);
-
-		if (eventWasClaimed)
-			return toret;
+// Run non-claimable event in all script modules, except room, break if certain events occured
+static int RunUnclaimableEvent(const char *tsname) {
+	const int room_changes_was = _GP(play).room_changes;
+	const int restore_game_count_was = _G(gameHasBeenRestored);
+	for (int i = 0; i < _G(numScriptModules); ++i) {
+		if (!_GP(moduleRepExecAddr)[i].IsNull())
+			RunScriptFunction(_GP(moduleInst)[i], tsname);
+		// Break on room change or save restoration
+		if ((room_changes_was != _GP(play).room_changes) ||
+			(restore_game_count_was != _G(gameHasBeenRestored)))
+			return 0;
 	}
-
-	return RunScriptFunctionIfExists(sci, tsname, 1, &iparam);
+	return RunScriptFunction(_G(gameinst), tsname);
 }
 
-int RunTextScript2IParam(ccInstance *sci, const char *tsname, const RuntimeScriptValue &iparam, const RuntimeScriptValue &param2) {
-	RuntimeScriptValue params[2];
-	params[0] = iparam;
-	params[1] = param2;
-
-	if (strcmp(tsname, "on_event") == 0) {
-		bool eventWasClaimed;
-		int toret = run_claimable_event(tsname, true, 2, params, &eventWasClaimed);
+static int RunClaimableEvent(const char *tsname, size_t param_count, const RuntimeScriptValue *params) {
+	// Run claimable event chain in script modules and room script
+	bool eventWasClaimed;
+	int toret = run_claimable_event(tsname, true, param_count, params, &eventWasClaimed);
+	// Break on event claim
+	if (eventWasClaimed)
+		return toret;
+	return RunScriptFunction(_G(gameinst), tsname, param_count, params);
+}
 
-		if (eventWasClaimed || _G(abort_engine))
-			return toret;
+int RunScriptFunctionAuto(ScriptInstType sc_inst, const char *tsname, size_t param_count, const RuntimeScriptValue *params) {
+	// If told to use a room instance, then run only there
+	if (sc_inst == kScInstRoom)
+		return RunScriptFunctionInRoom(tsname, param_count, params);
+	// Rep-exec is only run in script modules, but not room script
+	// (because room script has its own callback, attached to event slot)
+	if (strcmp(tsname, REP_EXEC_NAME) == 0) {
+		return RunUnclaimableEvent(REP_EXEC_NAME);
 	}
-
-	// response to a button click, better update guis
-	if (ags_strnicmp(tsname, "interface_click", 15) == 0) {
-		// interface_click(int interface, int button)
-		_GP(guis)[iparam.IValue].MarkChanged();
+	// Claimable event is run in all the script modules and room script,
+	// before running in the globalscript instance
+	if ((strcmp(tsname, _G(tsnames)[TS_KEYPRESS]) == 0) || (strcmp(tsname, _G(tsnames)[TS_MCLICK]) == 0) ||
+		(strcmp(tsname, "on_event") == 0)) {
+		return RunClaimableEvent(tsname, param_count, params);
 	}
-
-	return RunScriptFunctionIfExists(sci, tsname, 2, params);
+	// Else run on the single chosen script instance
+	ccInstance *sci = GetScriptInstanceByType(sc_inst);
+	if (!sci)
+		return 0;
+	return RunScriptFunction(sci, tsname, param_count, params);
 }
 
 String GetScriptName(ccInstance *sci) {
@@ -573,7 +566,7 @@ void post_script_cleanup() {
 	for (jj = 0; jj < copyof.numanother; jj++) {
 		old_room_number = _G(displayed_room);
 		QueuedScript &script = copyof.ScFnQueue[jj];
-		RunScriptFunction(script.Instance, script.FnName.GetCStr(), script.ParamCount, script.Params);
+		RunScriptFunctionAuto(script.Instance, script.FnName.GetCStr(), script.ParamCount, script.Params);
 		if (script.Instance == kScInstRoom && script.ParamCount == 1) {
 			// some bogus hack for "on_call" event handler
 			_GP(play).roomscript_finished = 1;
diff --git a/engines/ags/engine/script/script.h b/engines/ags/engine/script/script.h
index a81aead095d..e0b0f3af4eb 100644
--- a/engines/ags/engine/script/script.h
+++ b/engines/ags/engine/script/script.h
@@ -54,17 +54,20 @@ ccInstance *GetScriptInstanceByType(ScriptInstType sc_inst);
 // Queues a script function to be run either called by the engine or from another script
 void    QueueScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count = 0,
 	const RuntimeScriptValue *params = nullptr);
-// Try to run a script function right away
-void    RunScriptFunction(ScriptInstType sc_inst, const char *fn_name, size_t param_count = 0,
+// Try to run a script function on a given script instance
+int     RunScriptFunction(ccInstance *sci, const char *tsname, size_t param_count = 0,
+	const RuntimeScriptValue *params = nullptr);
+// Run a script function in all the regular script modules, in order, where available
+// includes globalscript, but not the current room script.
+void    RunScriptFunctionInModules(const char *tsname, size_t param_count = 0,
+	const RuntimeScriptValue *params = nullptr);
+// Run an obligatory script function in the current room script
+int     RunScriptFunctionInRoom(const char *tsname, size_t param_count = 0,
+	const RuntimeScriptValue *params = nullptr);
+// Try to run a script function, guessing the behavior by its name and script instance type;
+// depending on the type may run a claimable callback chain
+int     RunScriptFunctionAuto(ScriptInstType sc_inst, const char *fn_name, size_t param_count = 0,
 	const RuntimeScriptValue *params = nullptr);
-
-int     RunScriptFunctionIfExists(ccInstance *sci, const char *tsname, size_t param_count, const RuntimeScriptValue *params);
-int     RunTextScript(ccInstance *sci, const char *tsname);
-int     RunTextScriptIParam(ccInstance *sci, const char *tsname, const RuntimeScriptValue &iparam);
-int     RunTextScript2IParam(ccInstance *sci, const char *tsname, const RuntimeScriptValue &iparam, const RuntimeScriptValue &param2);
-
-int     PrepareTextScript(ccInstance *sci, const char **tsname);
-bool    DoRunScriptFuncCantBlock(ccInstance *sci, NonBlockingScriptFunction *funcToRun, bool hasTheFunc);
 
 AGS::Shared::String GetScriptName(ccInstance *sci);
 
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index f5ad1ec7fbe..3a41fc21223 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -32,6 +32,7 @@
 #include "ags/shared/util/version.h"
 #include "ags/shared/gui/gui_main.h"
 #include "ags/shared/script/cc_script.h"
+#include "ags/engine/ac/event.h"
 #include "ags/engine/ac/runtime_defines.h"
 #include "ags/engine/ac/walk_behind.h"
 #include "ags/engine/main/engine.h"
@@ -675,7 +676,7 @@ public:
 	int _inside_processevent = 0;
 	int _eventClaimed = 0;
 
-	const char *_tsnames[4] = { nullptr, REP_EXEC_NAME, "on_key_press", "on_mouse_click" };
+	const char *_tsnames[TS_NUM] = { nullptr, REP_EXEC_NAME, "on_key_press", "on_mouse_click" };
 
 	/**@}*/
 
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 4991f168e9a..8276c8d87ce 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -617,7 +617,7 @@ int IAGSEngine::CallGameScriptFunction(const char *name, int32 globalScript, int
 		   RuntimeScriptValue().SetPluginArgument(arg2),
 		   RuntimeScriptValue().SetPluginArgument(arg3),
 	};
-	int toret = RunScriptFunctionIfExists(toRun, (char *)name, numArgs, params);
+	int toret = RunScriptFunction(toRun, (char *)name, numArgs, params);
 	return toret;
 }
 


Commit: c0010986ac6bb709285ada648aec8d55ff39d098
    https://github.com/scummvm/scummvm/commit/c0010986ac6bb709285ada648aec8d55ff39d098
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:39-07:00

Commit Message:
AGS: Implemented `on_text_input(int chr)` callback

>From upstream ba866abab0ba5a48b8577c4a01f0533a2d7e68de

Changed paths:
    engines/ags/engine/ac/event.h
    engines/ags/engine/main/game_run.cpp
    engines/ags/engine/script/script.cpp
    engines/ags/globals.h
    engines/ags/shared/ac/keycode.h


diff --git a/engines/ags/engine/ac/event.h b/engines/ags/engine/ac/event.h
index 7df4f619c06..a795c7a88de 100644
--- a/engines/ags/engine/ac/event.h
+++ b/engines/ags/engine/ac/event.h
@@ -43,12 +43,13 @@ namespace AGS3 {
 #define EV_FADEIN     3
 #define EV_IFACECLICK 4
 #define EV_NEWROOM    5
-#define TS_REPEAT   1
-#define TS_KEYPRESS 2
-#define TS_MCLICK   3
-#define TS_NUM      4
-#define EVB_HOTSPOT 1
-#define EVB_ROOM    2
+#define TS_REPEAT     1
+#define TS_KEYPRESS   2
+#define TS_MCLICK     3
+#define TS_TEXTINPUT  4
+#define TS_NUM        5
+#define EVB_HOTSPOT   1
+#define EVB_ROOM      2
 
 struct EventHappened {
 	int type = 0;
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 0e2dd3fe3a0..0981fb9e672 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -501,6 +501,10 @@ static void check_keyboard_controls() {
 		int sckey = AGSKeyToScriptKey(kgn);
 		debug_script_log("Running on_key_press keycode %d", sckey);
 		setevent(EV_TEXTSCRIPT, TS_KEYPRESS, sckey);
+		if (ki.UChar > 0) {
+			debug_script_log("Running on_text_input char %s (%d)", ki.Text, ki.UChar);
+			setevent(EV_TEXTSCRIPT, TS_TEXTINPUT, ki.UChar);
+		}
 	}
 }
 
diff --git a/engines/ags/engine/script/script.cpp b/engines/ags/engine/script/script.cpp
index 3cebf13b503..e995563ac9f 100644
--- a/engines/ags/engine/script/script.cpp
+++ b/engines/ags/engine/script/script.cpp
@@ -456,7 +456,7 @@ int RunScriptFunctionAuto(ScriptInstType sc_inst, const char *tsname, size_t par
 	// Claimable event is run in all the script modules and room script,
 	// before running in the globalscript instance
 	if ((strcmp(tsname, _G(tsnames)[TS_KEYPRESS]) == 0) || (strcmp(tsname, _G(tsnames)[TS_MCLICK]) == 0) ||
-		(strcmp(tsname, "on_event") == 0)) {
+		(strcmp(tsname, _G(tsnames)[TS_TEXTINPUT]) == 0) || (strcmp(tsname, "on_event") == 0)) {
 		return RunClaimableEvent(tsname, param_count, params);
 	}
 	// Else run on the single chosen script instance
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 3a41fc21223..c8327d7049a 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -676,7 +676,7 @@ public:
 	int _inside_processevent = 0;
 	int _eventClaimed = 0;
 
-	const char *_tsnames[TS_NUM] = { nullptr, REP_EXEC_NAME, "on_key_press", "on_mouse_click" };
+	const char *_tsnames[TS_NUM] = { nullptr, REP_EXEC_NAME, "on_key_press", "on_mouse_click", "on_text_input" };
 
 	/**@}*/
 
diff --git a/engines/ags/shared/ac/keycode.h b/engines/ags/shared/ac/keycode.h
index cdfd97fa80d..d14e6b6fabb 100644
--- a/engines/ags/shared/ac/keycode.h
+++ b/engines/ags/shared/ac/keycode.h
@@ -255,8 +255,9 @@ enum eAGSKeyCode {
 struct KeyInput {
 	const static size_t UTF8_ARR_SIZE = 5;
 
-	eAGSKeyCode Key = eAGSKeyCodeNone;
-	char        Text[UTF8_ARR_SIZE] = { 0 };
+	eAGSKeyCode Key = eAGSKeyCodeNone; // actual key code
+	int         UChar = 0; // full character value (supports unicode)
+	char        Text[UTF8_ARR_SIZE]{}; // character in a string format
 
 	KeyInput() = default;
 };


Commit: 09da0fbf5db836d94a95ecaae844eb19449ec58e
    https://github.com/scummvm/scummvm/commit/09da0fbf5db836d94a95ecaae844eb19449ec58e
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:39-07:00

Commit Message:
AGS: Implemented `dialog_options_text_input(int chr)` callback

>From upstream 76db49c6189810faa467b00c1aef9e78c526876d

Changed paths:
    engines/ags/engine/ac/dialog.cpp
    engines/ags/engine/ac/game.cpp
    engines/ags/engine/game/game_init.cpp
    engines/ags/globals.cpp
    engines/ags/globals.h


diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 9720c213bdb..bf0f18ebd52 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -851,6 +851,9 @@ bool DialogOptions::Run() {
 			_GP(runDialogOptionKeyPressHandlerFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
 			_GP(runDialogOptionKeyPressHandlerFunc).params[1].SetInt32(AGSKeyToScriptKey(gkey));
 			run_function_on_non_blocking_thread(&_GP(runDialogOptionKeyPressHandlerFunc));
+			_GP(runDialogOptionTextInputHandlerFunc).params[0].SetDynamicObject(&_GP(ccDialogOptionsRendering), &_GP(ccDialogOptionsRendering));
+			_GP(runDialogOptionTextInputHandlerFunc).params[1].SetInt32(ki.UChar);
+			run_function_on_non_blocking_thread(&_GP(runDialogOptionKeyPressHandlerFunc));
 		}
 		// Allow selection of options by keyboard shortcuts
 		else if (_GP(game).options[OPT_DIALOGNUMBERED] >= kDlgOptKeysOnly &&
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 124331b6e0d..f94b2a25e32 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -409,6 +409,7 @@ void unload_game_file() {
 	_GP(getDialogOptionUnderCursorFunc).moduleHasFunction.resize(0);
 	_GP(runDialogOptionMouseClickHandlerFunc).moduleHasFunction.resize(0);
 	_GP(runDialogOptionKeyPressHandlerFunc).moduleHasFunction.resize(0);
+	_GP(runDialogOptionTextInputHandlerFunc).moduleHasFunction.resize(0);
 	_GP(runDialogOptionRepExecFunc).moduleHasFunction.resize(0);
 	_G(numScriptModules) = 0;
 
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index d899185258e..7670891971f 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -327,6 +327,7 @@ void AllocScriptModules() {
 	_GP(getDialogOptionUnderCursorFunc).moduleHasFunction.resize(_G(numScriptModules), true);
 	_GP(runDialogOptionMouseClickHandlerFunc).moduleHasFunction.resize(_G(numScriptModules), true);
 	_GP(runDialogOptionKeyPressHandlerFunc).moduleHasFunction.resize(_G(numScriptModules), true);
+	_GP(runDialogOptionTextInputHandlerFunc).moduleHasFunction.resize(_G(numScriptModules), true);
 	_GP(runDialogOptionRepExecFunc).moduleHasFunction.resize(_G(numScriptModules), true);
 	for (int i = 0; i < _G(numScriptModules); ++i) {
 		_GP(moduleRepExecAddr)[i].Invalidate();
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index 73dab86f469..9a7902cffff 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -334,6 +334,7 @@ Globals::Globals() {
 	_getDialogOptionUnderCursorFunc = new NonBlockingScriptFunction("dialog_options_get_active", 1);
 	_runDialogOptionMouseClickHandlerFunc = new NonBlockingScriptFunction("dialog_options_mouse_click", 2);
 	_runDialogOptionKeyPressHandlerFunc = new NonBlockingScriptFunction("dialog_options_key_press", 2);
+	_runDialogOptionTextInputHandlerFunc = new NonBlockingScriptFunction("dialog_options_text_input", 2);
 	_runDialogOptionRepExecFunc = new NonBlockingScriptFunction("dialog_options_repexec", 1);
 	_scsystem = new ScriptSystem();
 	_scriptModules = new std::vector<PScript>();
@@ -570,6 +571,7 @@ Globals::~Globals() {
 	delete _getDialogOptionUnderCursorFunc;
 	delete _runDialogOptionMouseClickHandlerFunc;
 	delete _runDialogOptionKeyPressHandlerFunc;
+	delete _runDialogOptionTextInputHandlerFunc;
 	delete _runDialogOptionRepExecFunc;
 	delete _scsystem;
 	delete _scriptModules;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index c8327d7049a..65ef6b648aa 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -1256,6 +1256,7 @@ public:
 	NonBlockingScriptFunction *_getDialogOptionUnderCursorFunc;
 	NonBlockingScriptFunction *_runDialogOptionMouseClickHandlerFunc;
 	NonBlockingScriptFunction *_runDialogOptionKeyPressHandlerFunc;
+	NonBlockingScriptFunction *_runDialogOptionTextInputHandlerFunc;
 	NonBlockingScriptFunction *_runDialogOptionRepExecFunc;
 
 	ScriptSystem *_scsystem;


Commit: dec92f05ea9156961d17d9a7f62f11d73b8dba07
    https://github.com/scummvm/scummvm/commit/dec92f05ea9156961d17d9a7f62f11d73b8dba07
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:40-07:00

Commit Message:
AGS: Support passing partial argument list to a script callback

>From upstream e38df03c5d1658a2c44a26ba4ee6f22663c1e701

Changed paths:
    engines/ags/engine/script/cc_instance.cpp


diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 29aab984b13..19eca09f2a7 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -284,22 +284,25 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
 	int32_t startat = -1;
 	int k;
 	char mangledName[200];
-	sprintf(mangledName, "%s$", funcname);
+	size_t mangled_len = snprintf(mangledName, sizeof(mangledName), "%s$", funcname);
+	int export_args = 0;
 
 	for (k = 0; k < instanceof->numexports; k++) {
 		char *thisExportName = instanceof->exports[k];
 		int match = 0;
 
 		// check for a mangled name match
-		if (strncmp(thisExportName, mangledName, strlen(mangledName)) == 0) {
+		if (strncmp(thisExportName, mangledName, mangled_len) == 0) {
 			// found, compare the number of parameters
-			char *numParams = thisExportName + strlen(mangledName);
-			if (atoi(numParams) != numargs) {
-				cc_error("wrong number of parameters to exported function '%s' (expected %d, supplied %d)", funcname, atoi(numParams), numargs);
+			export_args = atoi(thisExportName + mangled_len);
+			if (export_args > numargs) {
+				cc_error("wrong number of parameters to exported function '%s' (expected %d, supplied %d)",
+					funcname, export_args, numargs);
 				return -1;
 			}
 			match = 1;
 		}
+
 		// check for an exact match (if the script was compiled with
 		// an older version)
 		if ((match == 1) || (strcmp(thisExportName, funcname) == 0)) {
@@ -318,6 +321,9 @@ int ccInstance::CallScriptFunction(const char *funcname, int32_t numargs, const
 		return -2;
 	}
 
+	// Allow to pass less parameters if script callback has less declared args
+	numargs = std::min(numargs, export_args);
+
 	//numargs++;                    // account for return address
 	flags &= ~INSTF_ABORTED;
 


Commit: 99cc27e840b59a84e1804dda2619ecd67891cdfb
    https://github.com/scummvm/scummvm/commit/99cc27e840b59a84e1804dda2619ecd67891cdfb
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-04-18T19:10:40-07:00

Commit Message:
AGS: Fixed few comments in ccInstance::Run()

>From upstream 109346cf4cc747c9a3bef72c234a18a5f63d30fe

Changed paths:
    engines/ags/engine/script/cc_instance.cpp


diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 19eca09f2a7..23766968dd7 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -694,7 +694,7 @@ int ccInstance::Run(int32_t curpc) {
 			reg1 = !(reg1);
 			break;
 		case SCMD_CALL:
-			// CallScriptFunction another function within same script, just save PC
+			// Call another function within same script, just save PC
 			// and continue from there
 			if (curnest >= MAXNEST - 1) {
 				cc_error("!call stack overflow, recursive call problem?");
@@ -920,7 +920,7 @@ int ccInstance::Run(int32_t curpc) {
 		case SCMD_CALLAS: {
 			PUSH_CALL_STACK;
 
-			// CallScriptFunction to a function in another script
+			// Call to a function in another script
 
 			// If there are nested CALLAS calls, the stack might
 			// contain 2 calls worth of parameters, so only
@@ -977,7 +977,7 @@ int ccInstance::Run(int32_t curpc) {
 			break;
 		}
 		case SCMD_CALLEXT: {
-			// CallScriptFunction to a real 'C' code function
+			// Call to a real 'C' code function
 			was_just_callas = -1;
 			if (num_args_to_func < 0) {
 				num_args_to_func = func_callstack.Count;




More information about the Scummvm-git-logs mailing list