[Scummvm-git-logs] scummvm master -> cff33430a15cd84801b4de7683b8b54bb0673619

dreammaster noreply at scummvm.org
Sun May 10 09:45:53 UTC 2026


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

Summary:
f125a126dc MADS: DRAGONSPHERE: Added room 112
9c90161ff5 MADS: DRAGONSPHERE: Added room 113
9706500109 MADS: DRAGONSPHERE: Added room 114
cff33430a1 MADS: DRAGONSPHERE: Added room 115


Commit: f125a126dc3893751663b8b7579e5462a25bb56f
    https://github.com/scummvm/scummvm/commit/f125a126dc3893751663b8b7579e5462a25bb56f
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-10T18:56:03+10:00

Commit Message:
MADS: DRAGONSPHERE: Added room 112

Changed paths:
    engines/mads/madsv2/dragonsphere/rooms/room111.cpp
    engines/mads/madsv2/dragonsphere/rooms/room112.cpp


diff --git a/engines/mads/madsv2/dragonsphere/rooms/room111.cpp b/engines/mads/madsv2/dragonsphere/rooms/room111.cpp
index d9300fe9f36..59688a9b2c9 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/room111.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/room111.cpp
@@ -246,7 +246,12 @@ done:
 }
 
 void room_111_synchronize(Common::Serializer &s) {
-	
+	for (int16 &v : scratch.sprite)    s.syncAsSint16LE(v);
+	for (int16 &v : scratch.sequence)  s.syncAsSint16LE(v);
+	for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+	s.syncAsSint16LE(scratch.dragon_frame);
+	s.syncAsSint16LE(scratch.done_with_conv);
+	s.syncAsSint16LE(scratch.prev_room);
 }
 
 void room_111_preload() {
diff --git a/engines/mads/madsv2/dragonsphere/rooms/room112.cpp b/engines/mads/madsv2/dragonsphere/rooms/room112.cpp
index 6307350c986..e9423b51560 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/room112.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/room112.cpp
@@ -22,7 +22,9 @@
 #include "mads/madsv2/core/conv.h"
 #include "mads/madsv2/core/game.h"
 #include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
 #include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/matte.h"
 #include "mads/madsv2/core/sound.h"
 #include "mads/madsv2/core/text.h"
 #include "mads/madsv2/dragonsphere/mads/conv.h"
@@ -39,6 +41,9 @@ namespace Dragonsphere {
 namespace Rooms {
 
 struct Scratch {
+	int16 sprite[15];       /* Sprite series handles */
+	int16 sequence[15];     /* Sequence handles      */
+	int16 animation[4];     /* Animation handles     */
 };
 
 #define local (&scratch)
@@ -46,26 +51,60 @@ struct Scratch {
 #define seq   local->sequence
 #define aa    local->animation
 
-//static Scratch scratch;
+static Scratch scratch;
 
-void room_112_init() {
+/* ======================== Triggers ========================= */
 
-}
+#define ROOM_112_DONE_HEALING      60
+#define ROOM_112_DONE_UNHEALING    62
 
-void room_112_daemon() {
 
-}
+static void room_112_init(void) {
+	viewing_at_y = ((video_y - display_y) >> 1);
+	kernel_init_dialog();  /* clear interface */
+	kernel_set_interface_mode(INTER_LIMITED_SENTENCES);
 
-void room_112_pre_parser() {
+	player.commands_allowed = false;
+	player.walker_visible = false;
 
+	if (player.x == 0) {
+		aa[0] = kernel_run_animation(kernel_name('g', 1), ROOM_112_DONE_HEALING);
+		global[player_score] += 5;
+	} else {
+		aa[0] = kernel_run_animation(kernel_name('g', 2), ROOM_112_DONE_UNHEALING);
+	}
+
+	section_1_music();
 }
 
-void room_112_parser() {
+static void room_112_daemon() {
+	if (kernel.trigger == ROOM_112_DONE_HEALING) {
+		global[guard_pid_status] = GUARD_IS_HEALED;
+		player.x = 0;
+		text_show(11027);
+		new_room = 110;
+	}
+
+	if (kernel.trigger == ROOM_112_DONE_UNHEALING) {
+		global[guard_pid_status] = GUARD_IS_UNHEALED;
+		player.x = 100;
+		new_room = 110;
+	}
+}
 
+static void room_112_pre_parser() {
+	player.need_to_walk = false;
 }
 
+static void room_112_parser() {
+	// No implementation
+}
+
+
 void room_112_synchronize(Common::Serializer &s) {
-	
+	for (int16 &v : scratch.sprite)    s.syncAsSint16LE(v);
+	for (int16 &v : scratch.sequence)  s.syncAsSint16LE(v);
+	for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
 }
 
 void room_112_preload() {


Commit: 9c90161ff5042782bdd22e6f249ad677c44f6294
    https://github.com/scummvm/scummvm/commit/9c90161ff5042782bdd22e6f249ad677c44f6294
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-10T19:20:14+10:00

Commit Message:
MADS: DRAGONSPHERE: Added room 113

Changed paths:
    engines/mads/madsv2/dragonsphere/mads/inventory.h
    engines/mads/madsv2/dragonsphere/mads/sounds.h
    engines/mads/madsv2/dragonsphere/mads/words.h
    engines/mads/madsv2/dragonsphere/rooms/room113.cpp


diff --git a/engines/mads/madsv2/dragonsphere/mads/inventory.h b/engines/mads/madsv2/dragonsphere/mads/inventory.h
index 66a26ad2733..a6dc4438649 100644
--- a/engines/mads/madsv2/dragonsphere/mads/inventory.h
+++ b/engines/mads/madsv2/dragonsphere/mads/inventory.h
@@ -37,6 +37,7 @@ enum {
 	fruit           =  7,
 	pid_doll        =  8,
 	magic_belt      = 18,
+	crystal_ball    = 29,
 	shifter_ring    = 32,
 	rare_coin       = 38,
 	crystal_flower  = 39,
diff --git a/engines/mads/madsv2/dragonsphere/mads/sounds.h b/engines/mads/madsv2/dragonsphere/mads/sounds.h
index 0719d4aa3d4..3ba66ac57e1 100644
--- a/engines/mads/madsv2/dragonsphere/mads/sounds.h
+++ b/engines/mads/madsv2/dragonsphere/mads/sounds.h
@@ -29,17 +29,22 @@ namespace MADSV2 {
 namespace Dragonsphere {
 
 enum {
-	N_DoorOpens       =  24,
-	N_DoorCloses      =  25,
-	N_TakeObjectSnd   =  26,
-	N_WayStationMus   =  37,
-	N_QueenMother     =  45,
-	N_TurnDiaryPage   =  65,
-	N_WallGrinds      =  67,
-	N_DragonInWater   =  72,
-	N_JumpDownWell    =  93,
-	N_BooksRumble     =  94,
-	N_McMornTipsTable = 100
+	N_DoorOpens          =  24,
+	N_DoorCloses         =  25,
+	N_TakeObjectSnd      =  26,
+	N_PlayerDies         =  27,
+	N_InvokeCrystalBall  =  28,
+	N_SealMus            =  35,
+	N_UnderGroundMus     =  36,
+	N_WayStationMus      =  37,
+	N_QueenMother        =  45,
+	N_TurnDiaryPage      =  65,
+	N_WallGrinds         =  67,
+	N_DragonInWater      =  72,
+	N_OldMachinery       =  74,
+	N_JumpDownWell       =  93,
+	N_BooksRumble        =  94,
+	N_McMornTipsTable    = 100
 };
 
 } // namespace Dragonsphere
diff --git a/engines/mads/madsv2/dragonsphere/mads/words.h b/engines/mads/madsv2/dragonsphere/mads/words.h
index 80a096e4029..605627b01a1 100644
--- a/engines/mads/madsv2/dragonsphere/mads/words.h
+++ b/engines/mads/madsv2/dragonsphere/mads/words.h
@@ -37,6 +37,7 @@ enum {
 	words_pull                 =  10,
 	words_walk_to              =  13,
 	words_floor                =  16,
+	words_walk_across          =  17,
 	words_rug                  =  18,
 	words_carpet               =  19,
 	words_wall                 =  20,
@@ -60,12 +61,21 @@ enum {
 	words_tie                  = 102,
 	words_crystal_ball         = 109,
 	words_gaze_into            = 110,
+	words_invoke_power_of      = 111,
+	words_shift_into_bear      = 116,
+	words_shift_into_seal      = 117,
+	words_shift_into_snake     = 118,
+	words_revert               = 119,
 	words_tentacle_parts       = 125,
 	words_rare_coin            = 129,
+	words_emerald              = 136,
 	words_touch                = 146,
 	words_throne_room          = 147,
+	words_cave_floor           = 152,
 	words_castle               = 156,
+	words_stairs               = 168,
 	words_walk_down            = 169,
+	words_cave_wall            = 174,
 	words_brazier              = 175,
 	words_door_to_throne_room  = 176,
 	words_dining_table         = 178,
@@ -114,8 +124,12 @@ enum {
 	words_step                 = 256,
 	words_king_s_throne        = 258,
 	words_queen_s_throne       = 260,
+	words_grate                = 262,
+	words_river                = 263,
 	words_diaries              = 264,
+	words_swim_down            = 265,
 	words_scullery_maid        = 266,
+	words_ward                 = 268,
 	words_doorway              = 277,
 	words_faerie               = 278,
 	words_guard_captain        = 280,
@@ -123,6 +137,11 @@ enum {
 	words_shapechanger         = 282,
 	words_king                 = 291,
 	words_sconce               = 329,
+	words_trap_door            = 334,
+	words_swim_up              = 337,
+	words_shore                = 339,
+	words_swim_to              = 340,
+	words_swim_towards         = 341,
 	words_Queen_Mother         = 347,
 	words_sit_on               = 363,
 	words_Soptus_Ecliptus      = 448,
diff --git a/engines/mads/madsv2/dragonsphere/rooms/room113.cpp b/engines/mads/madsv2/dragonsphere/rooms/room113.cpp
index d2e51a2810e..84e5e31813c 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/room113.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/room113.cpp
@@ -22,7 +22,9 @@
 #include "mads/madsv2/core/conv.h"
 #include "mads/madsv2/core/game.h"
 #include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
 #include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/object.h"
 #include "mads/madsv2/core/sound.h"
 #include "mads/madsv2/core/text.h"
 #include "mads/madsv2/dragonsphere/mads/conv.h"
@@ -39,6 +41,18 @@ namespace Dragonsphere {
 namespace Rooms {
 
 struct Scratch {
+	int16 sprite[15];       /* Sprite series handles */
+	int16 sequence[15];     /* Sequence handles      */
+	int16 animation[4];     /* Animation handles     */
+
+	int16 side_of_room;     /* indicates if Pid on left or right side of room */
+	int16 stairs_id[5];     /* Handles for stairs hotspots */
+
+	int16 seal_frame;       /* animation frame being held for seal stuff */
+	int16 seal_action;      /* Type of action to run for seal animation */
+	int16 anim_0_running;
+
+	int16 clicked_on;
 };
 
 #define local (&scratch)
@@ -46,26 +60,842 @@ struct Scratch {
 #define seq   local->sequence
 #define aa    local->animation
 
-//static Scratch scratch;
+static Scratch scratch;
+
+
+/* ========================= Sprites ========================= */
+
+#define fx_pid_descends      1  /* rm113b2 */
+#define fx_rare_coin         2  /* rm113p0 */
+#define fx_emerald           3  /* rm113p1 */
+#define fx_ward              4  /* rm113y  */    
+#define fx_take_coin         5  /* pddrl_9 */
+#define fx_take_emerald      6  /* rm113g  */  
+#define fx_trap_door         7  /* rm113x  */
+#define fx_dead_king         8  /* rm113a  */
+#define fx_down_stairs       9  /* rm113b1 */
+#define fx_pid_floats        10  /* rm113z0 */
+#define fx_dead_pid          11  /* rm113z1 */
+
+
+/* ======================== Triggers ========================= */
+
+#define ROOM_113_RESTART     70
+#define ROOM_113_PID_APPEARS 80
+
+
+/* walk points */
+#define START_X_ROOM_114     127
+#define START_Y_ROOM_114     73
+#define START_X_ROOM_117     227
+#define START_Y_ROOM_117     118
+#define START_X_ROOM_110     254
+#define START_Y_ROOM_110     117
+
+#define WALK_TO_STAIRS_X     127
+#define WALK_TO_STAIRS_Y     73
+
+/* cursor points */
+#define FLOOR_WITH_TRAP_X    203
+#define FLOOR_WITH_TRAP_Y    103
+
+/* absolute series points */
+#define DEAD_KING_X          255
+#define DEAD_KING_Y          123
+
+#define SEAL_TREAD           0
+#define SEAL_LEAVE           1
+#define SEAL_GET_OUT_FAR     2
+#define SEAL_GET_OUT_NEAR    3
+
+#define OUT_OF_WATER_FAR_X   122
+#define OUT_OF_WATER_FAR_Y   81
+
+#define OUT_OF_WATER_NEAR_X  183
+#define OUT_OF_WATER_NEAR_Y  130
+
+#define INTO_SEAL_NEAR_X     213
+#define INTO_SEAL_NEAR_Y     127
+
+#define INTO_SEAL_FAR_X      107
+#define INTO_SEAL_FAR_Y      81
+
+#define LEFT_SIDE            0
+#define RIGHT_SIDE           1 
+
+#define SEAL                 0
+#define HUMAN                1
+
+#define RIVER_X              132
+#define RIVER_Y              94
+
+
+
+void room_113_alter_hotspots(int state) {
+	int count;
+
+	if (state == SEAL) {
+		kernel_flip_hotspot(words_river, true);
+
+		for (count = 0; count < room_num_spots; count++) {
+
+			if (room_spots[count].vocab == words_river) {
+				if (room_spots[count].verb != words_swim_up) {
+					room_spots[count].verb = words_swim_down;
+				}
+			}
+			if (room_spots[count].vocab == words_cave_floor) {
+				room_spots[count].vocab = words_shore;
+				room_spots[count].verb = words_swim_to;
+			}
+			if (room_spots[count].vocab == words_grate) {
+				room_spots[count].verb = words_swim_to;
+			}
+			if (room_spots[count].vocab == words_trap_door) {
+				room_spots[count].cursor_number = 1;
+			}
+			if ((room_spots[count].vocab == words_cave_wall) || (room_spots[count].vocab == words_stairs) ||
+				(room_spots[count].vocab == words_trap_door) || (room_spots[count].vocab == words_ward) ||
+				(room_spots[count].vocab == words_rare_coin) || (room_spots[count].vocab == words_emerald)) {
+				room_spots[count].verb = words_swim_towards;
+			}
+		}
+
+	} else {
+
+		kernel_flip_hotspot(words_river, false);
+		kernel_flip_hotspot_loc(words_river, true, RIVER_X, RIVER_Y);
 
-void room_113_init() {
+		for (count = 0; count < room_num_spots; count++) {
 
+			if (room_spots[count].vocab == words_river) {
+				if (room_spots[count].verb != words_swim_up && room_spots[count].cursor_number != 5) {
+					room_spots[count].verb = words_walk_to;
+				}
+			}
+			if (room_spots[count].vocab == words_shore) {
+				room_spots[count].verb = words_walk_across;
+				room_spots[count].vocab = words_cave_floor;
+			}
+			if (room_spots[count].vocab == words_stairs) {
+				room_spots[count].verb = words_walk_down;
+			}
+			if (room_spots[count].vocab == words_trap_door) {
+				room_spots[count].cursor_number = 3;
+			}
+			if (room_spots[count].vocab == words_trap_door) {
+				room_spots[count].verb = words_walk_across;
+			}
+			if (room_spots[count].vocab == words_trap_door || room_spots[count].vocab == words_grate ||
+				room_spots[count].vocab == words_ward || room_spots[count].vocab == words_emerald ||
+				room_spots[count].vocab == words_rare_coin || room_spots[count].vocab == words_cave_wall) {
+				room_spots[count].verb = words_walk_to;
+			}
+		}
+	}
 }
 
-void room_113_daemon() {
+static void room_113_init() {
+	if (previous_room != KERNEL_RESTORING_GAME) {
+		local->anim_0_running = false;
+	}
 
+	/* Load sprite series */
+
+	if (global[player_persona] == PLAYER_IS_PID) {
+		if (global[statue_is_on_stairway_114]) {
+			ss[fx_down_stairs] = kernel_load_series(kernel_name('b', 1), false);
+		} else {
+			ss[fx_pid_descends] = kernel_load_series(kernel_name('b', 2), false);
+		}
+	}
+
+	if (object_is_here(rare_coin)) {
+		ss[fx_rare_coin] = kernel_load_series(kernel_name('p', 0), false);
+		if (global[player_persona] == PLAYER_IS_PID) {
+			ss[fx_take_coin] = kernel_load_series("*PDDRL_9", false);
+		}
+		seq[fx_rare_coin] = kernel_seq_stamp(ss[fx_rare_coin], false, KERNEL_FIRST);
+		kernel_seq_depth(seq[fx_rare_coin], 6);
+	} else {
+		kernel_flip_hotspot(words_rare_coin, false);
+	}
+
+	if (global[ward_status] == WARD_PRESENT) {
+		ss[fx_ward] = kernel_load_series(kernel_name('y', -1), false);
+		seq[fx_ward] = kernel_seq_stamp(ss[fx_ward], false, KERNEL_FIRST);
+		kernel_seq_depth(seq[fx_ward], 12);
+		kernel_flip_hotspot(words_emerald, false);
+	} else {
+		kernel_flip_hotspot(words_ward, false);
+	}
+
+
+	if (object_is_here(emerald)) {
+		ss[fx_emerald] = kernel_load_series(kernel_name('p', 1), false);
+		if (global[player_persona] == PLAYER_IS_PID) {
+			ss[fx_take_emerald] = kernel_load_series(kernel_name('g', -1), false);
+		}
+		if (global[ward_status] == WARD_GONE) {
+			seq[fx_emerald] = kernel_seq_stamp(ss[fx_emerald], false, KERNEL_FIRST);
+			kernel_seq_depth(seq[fx_emerald], 12);
+		}
+	} else {
+		kernel_flip_hotspot(words_emerald, false);
+	}
+
+
+	/* if statue on stairs in rm114 show stairs hotspots else show trap_door */
+
+	if (global[statue_is_on_stairway_114]) {
+		kernel_flip_hotspot(words_trap_door, false);
+
+	} else {
+		kernel_flip_hotspot(words_trap_door, true);
+		kernel_flip_hotspot(words_stairs, false);
+		ss[fx_trap_door] = kernel_load_series(kernel_name('x', -1), false);
+		seq[fx_trap_door] = kernel_seq_stamp(ss[fx_trap_door], false, KERNEL_FIRST);
+		kernel_seq_depth(seq[fx_trap_door], 14);
+	}
+
+	if (local->anim_0_running) {
+		aa[0] = kernel_run_animation(kernel_name('s', 1), 0);
+		player.walker_visible = false;
+		local->seal_action = SEAL_TREAD;
+		kernel_reset_animation(aa[0], 187);
+		/* player is a seal */
+
+	} else if (previous_room == 114) {       /* Player comes from Stair Trap */
+		player.x = START_X_ROOM_114;
+		player.y = START_Y_ROOM_114;
+		player.facing = FACING_SOUTHEAST;
+		local->side_of_room = LEFT_SIDE;
+
+	} else if (previous_room == 117) {  /* Player comes from Swimming Cutaway */
+		aa[0] = kernel_run_animation(kernel_name('s', 1), 0);
+		player.walker_visible = false;
+		player.commands_allowed = false;
+		local->seal_action = SEAL_TREAD;
+		local->anim_0_running = true;
+		kernel_reset_animation(aa[0], 84);
+
+	} else if (previous_room != KERNEL_RESTORING_GAME) {  /* Player comes from Way Station rm110 */
+		local->side_of_room = RIGHT_SIDE;
+		player.commands_allowed = false;
+		if (global[player_persona] == PLAYER_IS_PID) {
+			player.walker_visible = false;
+			if (!player_has(magic_belt)) {
+				sound_play(N_PlayerDies);
+				ss[fx_dead_pid] = kernel_load_series(kernel_name('z', 1), false);
+				seq[fx_dead_pid] = kernel_seq_stamp(ss[fx_dead_pid], false, KERNEL_FIRST);
+				kernel_seq_loc(seq[fx_dead_pid], DEAD_KING_X, DEAD_KING_Y);
+				kernel_seq_depth(seq[fx_dead_pid], 5);
+				kernel_timing_trigger(TWO_SECONDS, ROOM_113_RESTART);
+
+			} else {
+				ss[fx_pid_floats] = kernel_load_series(kernel_name('z', 0), false);
+				seq[fx_pid_floats] = kernel_seq_forward(ss[fx_pid_floats], false,
+					8, 0, 0, 1);
+				kernel_seq_depth(seq[fx_pid_floats], 8);
+				kernel_seq_range(seq[fx_pid_floats], KERNEL_FIRST, KERNEL_LAST);
+				kernel_seq_trigger(seq[fx_pid_floats],
+					KERNEL_TRIGGER_EXPIRE, 0, ROOM_113_PID_APPEARS);
+			}
+
+		} else {
+			sound_play(N_PlayerDies);
+			ss[fx_dead_king] = kernel_load_series(kernel_name('a', -1), false);
+			seq[fx_dead_king] = kernel_seq_stamp(ss[fx_dead_king], false, KERNEL_FIRST);
+			kernel_seq_loc(seq[fx_dead_king], DEAD_KING_X, DEAD_KING_Y);
+			kernel_seq_depth(seq[fx_dead_king], 5);
+			kernel_seq_scale(seq[fx_dead_king], 85);
+			kernel_timing_trigger(TWO_SECONDS, ROOM_113_RESTART);
+		}
+	}
+
+	if (local->anim_0_running) {
+		room_113_alter_hotspots(SEAL);
+	} else {
+		room_113_alter_hotspots(HUMAN);
+	}
+
+	section_1_music();
 }
 
-void room_113_pre_parser() {
+static void handle_animation_seal() {
+	int seal_reset_frame;
+
+	if (kernel_anim[aa[0]].frame != local->seal_frame) {
+		local->seal_frame = kernel_anim[aa[0]].frame;
+		seal_reset_frame = -1;
+
+		switch (local->seal_frame) {
+		case 37:  /* end of Pid getting out of water far side */
+			room_113_alter_hotspots(HUMAN);
+			player_demand_location(OUT_OF_WATER_FAR_X, OUT_OF_WATER_FAR_Y);
+			player_demand_facing(FACING_NORTHWEST);
+			global[player_is_seal] = false;
+			sound_play(N_UnderGroundMus);
+			player.walker_visible = true;
+			kernel_abort_animation(aa[0]);
+			kernel_synch(KERNEL_PLAYER, 0, KERNEL_NOW, 0);
+			seal_reset_frame = -1;
+			local->side_of_room = LEFT_SIDE;
+			player.commands_allowed = true;
+			local->anim_0_running = false;
+			break;
+
+		case 72:  /* end of Pid getting out of water near side */
+			room_113_alter_hotspots(HUMAN);
+			player_demand_location(OUT_OF_WATER_NEAR_X, OUT_OF_WATER_NEAR_Y);
+			player_demand_facing(FACING_SOUTHEAST);
+			player.walker_visible = true;
+			global[player_is_seal] = false;
+			sound_play(N_UnderGroundMus);
+			kernel_abort_animation(aa[0]);
+			kernel_synch(KERNEL_PLAYER, 0, KERNEL_NOW, 0);
+			seal_reset_frame = -1;
+			local->side_of_room = RIGHT_SIDE;
+			player.commands_allowed = true;
+			local->anim_0_running = false;
+			break;
+
+		case 101:
+		case 136:
+		case 177:
+			player.commands_allowed = true;
+			break;
+
+		case 102: /* end Pid coming from room 117 */
+		case 137: /* end Pid on far side to seal  */
+		case 178: /* end Pid on near side to seal */
+		case 186: /* end of 360  */
+		case 187: /* tread water */
+		case 188: /* tread water */
+		case 189: /* tread water */
+		case 190: /* tread water */
+		case 191: /* tread water */
+		case 192: /* tread water */
+		case 193: /* tread water */
+		case 194: /* tread water */
+		case 195: /* tread water */
+			switch (local->seal_action) {
+			case SEAL_TREAD:
+				seal_reset_frame = imath_random(186, 194);
+				if (imath_random(1, 60) == 1) {
+					seal_reset_frame = 178;  /* do a 360 */
+				}
+				break;
+
+			case SEAL_LEAVE:
+				seal_reset_frame = 72; /* seal swim down stream */
+				break;
 
+			case SEAL_GET_OUT_FAR:
+				seal_reset_frame = 0; /* seal get out of water on far side */
+				break;
+
+			case SEAL_GET_OUT_NEAR:
+				seal_reset_frame = 37; /* seal get out of water on near side */
+				break;
+			}
+			break;
+
+		case 83: /* end of swimming off screen */
+			new_room = 117;
+			break;
+		}
+
+		if (seal_reset_frame >= 0) {
+			kernel_reset_animation(aa[0], seal_reset_frame);
+			local->seal_frame = seal_reset_frame;
+		}
+	}
 }
 
-void room_113_parser() {
+static void room_113_daemon(void) {
+	if (local->anim_0_running) {
+		handle_animation_seal();
+	}
+
+	if (kernel.trigger == ROOM_113_RESTART) {
+		if (game.difficulty == EASY_MODE) {
+			text_show(11336);
+		} else {
+			text_show(45);
+		}
+		new_room = 110;
+	}
 
+	if (kernel.trigger == ROOM_113_PID_APPEARS) {
+		player_demand_facing(FACING_SOUTH);
+		player.x = START_X_ROOM_110;
+		player.y = START_Y_ROOM_110;
+		player.commands_allowed = true;
+		player.walker_visible = true;
+		kernel_synch(KERNEL_PLAYER, 0, KERNEL_SERIES, seq[fx_pid_floats]);
+	}
+}
+
+static void room_113_pre_parser() {
+	if (inter_point_y >= 100 || inter_point_x > 221) {
+		local->clicked_on = RIGHT_SIDE;
+	} else {
+		local->clicked_on = LEFT_SIDE;
+	}
+
+	if (local->side_of_room == RIGHT_SIDE && !local->anim_0_running) {
+		if (local->clicked_on == LEFT_SIDE) {
+			player.need_to_walk = false;
+			if (player_said_1(walk_to) || player_said_1(walk_across)) {
+				if (!player_said_1(river)) {
+					text_show(11304);
+					player_cancel_command();
+				}
+			}
+		}
+	}
+
+	if (local->side_of_room == LEFT_SIDE && !local->anim_0_running) {
+		if (local->clicked_on == RIGHT_SIDE) {
+			player.need_to_walk = false;
+			if (player_said_1(walk_to) || player_said_1(walk_across)) {
+				if (!player_said_1(river)) {
+					text_show(11304);
+					player_cancel_command();
+				}
+			}
+		}
+	}
+
+	if (player_said_1(shift_into_seal) && !local->anim_0_running) {
+		if (local->side_of_room == RIGHT_SIDE) {
+			player_walk(INTO_SEAL_NEAR_X, INTO_SEAL_NEAR_Y, FACING_NORTHWEST);
+		} else {
+			player_walk(INTO_SEAL_FAR_X, INTO_SEAL_FAR_Y, FACING_SOUTHEAST);
+		}
+	}
+
+	if (local->anim_0_running) {  /* player is Seal */
+		player.need_to_walk = false;
+	}
+}
+
+static void room_113_parser() {
+	int count;
+	int ok = false;
+
+	if (player.look_around) {
+		text_show(11301);
+		goto handled;
+	}
+
+	if (local->anim_0_running) {  /* player is Seal */
+		if (player_said_2(swim_down, river)) {
+			for (count = 0; count < room_num_spots; count++) {
+				if (room_spots[count].verb == words_swim_down) {
+					if (room_spots[count].cursor_number == 5) {
+						if ((inter_point_x >= room_spots[count].ul_x) &&
+							(inter_point_x <= room_spots[count].lr_x) &&
+							(inter_point_y >= room_spots[count].ul_y) &&
+							(inter_point_y <= room_spots[count].lr_y)) {
+							ok = true;
+						}
+					}
+				}
+			}
+
+			if (!ok) {
+				text_show(11332);
+				goto handled;
+			}
+
+			if (player_has_been_in_room(117)) {
+				text_show(11317);
+			} else {
+				local->seal_action = SEAL_LEAVE;
+				player.commands_allowed = false;
+			}
+			goto handled;
+		}
+
+		if (player_said_1(revert)) {
+			if (local->side_of_room == RIGHT_SIDE) {
+				local->seal_action = SEAL_GET_OUT_NEAR;
+			} else {
+				local->seal_action = SEAL_GET_OUT_FAR;
+			}
+			goto handled;
+		}
+
+		if (player_said_2(swim_up, river)) {
+			text_show(11331);
+			goto handled;
+		}
+
+		if (player_said_2(swim_to, grate)) {
+			text_show(11330);
+			goto handled;
+		}
+
+		if (player_said_1(swim_towards) || player_said_1(swim_to) ||
+			(player_said_2(take, emerald) && !player_has(emerald)) ||
+			(player_said_2(take, rare_coin) && !player_has(rare_coin))) {
+			if (local->clicked_on == RIGHT_SIDE) {
+				local->seal_action = SEAL_GET_OUT_NEAR;
+			} else {
+				local->seal_action = SEAL_GET_OUT_FAR;
+			}
+			player.commands_allowed = false;
+			goto handled;
+		}
+	}
+
+	if (player_said_2(walk_to, trap_door) || player_said_2(swim_towards, trap_door)) {
+		if (local->side_of_room == LEFT_SIDE) {
+			switch (kernel.trigger) {
+			case 0:
+				player.commands_allowed = false;
+				player.walker_visible = false;
+				kernel_seq_delete(seq[fx_trap_door]);
+				seq[fx_pid_descends] = kernel_seq_forward(ss[fx_pid_descends],
+					false, 8, 0, 0, 1);
+				kernel_seq_depth(seq[fx_pid_descends], 14);
+				kernel_synch(KERNEL_PLAYER, 0, KERNEL_SERIES, seq[fx_pid_descends]);
+				kernel_seq_trigger(seq[fx_pid_descends],
+					KERNEL_TRIGGER_EXPIRE, 0, 1);
+				sound_play(N_OldMachinery);
+				break;
+
+			case 1:
+				new_room = 114;
+				break;
+			}
+		}
+		goto handled;
+	}
+
+	if (player_said_2(walk_down, stairs) || player_said_2(swim_towards, stairs)) {
+		if (local->side_of_room == LEFT_SIDE) {
+			switch (kernel.trigger) {
+			case 0:
+				player.commands_allowed = false;
+				player.walker_visible = false;
+				seq[fx_down_stairs] = kernel_seq_forward(ss[fx_down_stairs],
+					false, 7, 0, 0, 1);
+				kernel_seq_depth(seq[fx_down_stairs], 11);
+				kernel_synch(KERNEL_SERIES, seq[fx_down_stairs], KERNEL_PLAYER, 0);
+				kernel_seq_trigger(seq[fx_down_stairs],
+					KERNEL_TRIGGER_EXPIRE, 0, 1);
+				break;
+
+			case 1:
+				new_room = 114;
+				break;
+			}
+
+		} else {
+			text_show(11304);
+		}
+		goto handled;
+	}
+
+
+	if (player_said_2(take, rare_coin)) {
+		if (kernel.trigger || !player_has(rare_coin)) {
+			if (local->side_of_room == RIGHT_SIDE) {
+				switch (kernel.trigger) {
+				case 0:
+					player.commands_allowed = false;
+					player.walker_visible = false;
+					seq[fx_take_coin] = kernel_seq_pingpong(ss[fx_take_coin],
+						false, 6, 0, 0, 2);
+					kernel_seq_player(seq[fx_take_coin], true);
+					kernel_seq_trigger(seq[fx_take_coin],
+						KERNEL_TRIGGER_SPRITE, 5, 1);
+					kernel_seq_trigger(seq[fx_take_coin],
+						KERNEL_TRIGGER_EXPIRE, 0, 2);
+					break;
+
+				case 1:
+					/* sound_queue (N_PickUpObject006);*/
+					kernel_seq_delete(seq[fx_rare_coin]);
+					kernel_flip_hotspot(words_rare_coin, false);
+					sound_play(N_TakeObjectSnd);
+					inter_give_to_player(rare_coin);
+					global[player_score] += 5;
+					object_examine(rare_coin, 11318, 0);
+					break;
+
+				case 2:
+					kernel_synch(KERNEL_PLAYER, 0, KERNEL_SERIES, seq[fx_take_coin]);
+					player.walker_visible = true;
+					player.commands_allowed = true;
+					break;
+				}
+
+			} else {
+				text_show(11304);
+			}
+			goto handled;
+		}
+	}
+
+	if (player_said_2(invoke_power_of, crystal_ball)) {
+		if (global[ward_status] == WARD_PRESENT) {
+			if (local->anim_0_running) {
+				text_show(32);
+				goto handled;
+
+			} else if (local->side_of_room == LEFT_SIDE) {
+				switch (kernel.trigger) {
+				case 0:
+					sound_play(N_InvokeCrystalBall);
+					text_show(970);
+					player.commands_allowed = false;
+					kernel_seq_delete(seq[fx_ward]);
+					kernel_flip_hotspot(words_ward, false);
+					kernel_flip_hotspot(words_emerald, true);
+					seq[fx_emerald] = kernel_seq_stamp(ss[fx_emerald], false, KERNEL_FIRST);
+					kernel_seq_depth(seq[fx_emerald], 12);
+					kernel_timing_trigger(TENTH_SECOND, 1);
+					global[player_score] += 5;
+					goto handled;
+					break;
+
+				case 1:
+					global[ward_status] = WARD_GONE;
+					global[crystal_ball_dead] = true;
+					inter_move_object(crystal_ball, NOWHERE);
+					player.commands_allowed = true;
+					text_show(11320);
+					goto handled;
+					break;
+				}
+			} else {
+				text_show(11327);
+				goto handled;
+			}
+		}
+	}
+
+	if (player_said_2(take, emerald)) {
+		if (kernel.trigger || !player_has(emerald)) {
+			if (local->side_of_room == LEFT_SIDE) {
+				switch (kernel.trigger) {
+				case 0:
+					player.commands_allowed = false;
+					player.walker_visible = false;
+					seq[fx_take_emerald] = kernel_seq_pingpong(ss[fx_take_emerald],
+						false, 6, 0, 0, 2);
+					kernel_seq_range(seq[fx_take_emerald], 1, 2);
+					kernel_seq_player(seq[fx_take_emerald], true);
+					kernel_seq_trigger(seq[fx_take_emerald],
+						KERNEL_TRIGGER_SPRITE, 2, 1);
+					kernel_seq_trigger(seq[fx_take_emerald],
+						KERNEL_TRIGGER_EXPIRE, 0, 2);
+					break;
+
+				case 1:
+					/* sound_queue (N_PickUpObject006);*/
+					kernel_seq_delete(seq[fx_emerald]);
+					kernel_flip_hotspot(words_emerald, false);
+					sound_play(N_TakeObjectSnd);
+					inter_give_to_player(emerald);
+					global[player_score] += 5;
+					object_examine(emerald, 11319, 0);
+					break;
+
+				case 2:
+					kernel_synch(KERNEL_PLAYER, 0, KERNEL_SERIES, seq[fx_take_emerald]);
+					player.walker_visible = true;
+					player.commands_allowed = true;
+					break;
+				}
+			} else {
+				text_show(11304);
+			}
+			goto handled;
+		}
+	}
+
+	if (player_said_1(shift_into_seal)) {
+		if (local->anim_0_running) {
+			text_show(11325);
+
+		} else {
+			if (!(global[player_score_flags] & SCORE_SHIFT_INTO_SEAL_113)) {
+				global[player_score_flags] = global[player_score_flags] | SCORE_SHIFT_INTO_SEAL_113;
+				global[player_score] += 2;
+			}
+
+			global[player_is_seal] = true;
+			sound_play(N_SealMus);
+			local->anim_0_running = true;
+			aa[0] = kernel_run_animation(kernel_name('s', 1), 0);
+			if (local->side_of_room == LEFT_SIDE) {
+				kernel_reset_animation(aa[0], 103);
+			} else {
+				kernel_reset_animation(aa[0], 138);
+			}
+			player.commands_allowed = false;
+			player.walker_visible = false;
+			local->seal_action = SEAL_TREAD;
+			kernel_synch(KERNEL_ANIM, aa[0], KERNEL_PLAYER, 0);
+			room_113_alter_hotspots(SEAL);
+		}
+		goto handled;
+	}
+
+	if ((player_said_1(open) || player_said_1(pull)) &&
+		player_said_1(trap_door)) {
+		text_show(11306);
+		goto handled;
+	}
+
+	if (player_said_1(look) || player_said_1(look_at)) {
+
+		if (player_said_1(cave_floor) || player_said_1(shore)) {
+			text_show(11302);
+			goto handled;
+		}
+
+		if (player_said_1(trap_door)) {
+			text_show(11303);
+			goto handled;
+		}
+
+		if (player_said_1(river)) {
+			if (local->anim_0_running) {
+				text_show(11316);
+			} else if (global[player_persona] == PLAYER_IS_PID) {
+				text_show(11307);
+			} else {
+				text_show(11316);
+			}
+			goto handled;
+		}
+
+		if (player_said_1(cave_wall)) {
+			text_show(11308);
+			goto handled;
+		}
+
+		if (player_said_1(grate)) {
+			text_show(11310);
+			goto handled;
+		}
+
+		if (player_said_1(ward)) {
+			text_show(11312);
+			goto handled;
+		}
+
+
+		if (player_said_1(rare_coin)) {
+			if (object_is_here(rare_coin)) {
+				text_show(11315);
+				goto handled;
+			}
+		}
+
+		if (player_said_1(emerald)) {
+			if (object_is_here(emerald)) {
+				text_show(11314);
+				goto handled;
+			}
+		}
+
+		if (player_said_1(stairs)) {
+			if (global[statue_is_on_stairway_114] == STAIRWAY_STATUE) {
+				text_show(11326);
+			} else {
+				text_show(11305);
+			}
+			goto handled;
+		}
+	}
+
+	if ((player_said_1(look) || player_said_1(look_at) || player_said_1(take)) &&
+		player_said_1(bucket)) {
+		text_show(11309);
+		goto handled;
+	}
+
+	if ((player_said_1(push) || player_said_1(pull)) &&
+		player_said_1(grate)) {
+		text_show(11311);
+		goto handled;
+	}
+
+	if (player_said_1(ward)) {
+		if (local->side_of_room == RIGHT_SIDE && !local->anim_0_running) {
+			text_show(11304);
+			goto handled;
+
+		} else if (local->side_of_room == LEFT_SIDE && !local->anim_0_running) {
+			if (player_said_1(push) ||
+				player_said_1(open) ||
+				player_said_1(pull)) {
+				text_show(11313);
+				goto handled;
+			}
+		}
+	}
+
+	if (player_said_1(shift_into_bear)) {
+		text_show(11321);
+		goto handled;
+	}
+
+	if (player_said_1(shift_into_snake)) {
+		text_show(11322);
+		goto handled;
+	}
+
+	if (player_said_1(swim_to) || player_said_1(swim_towards) ||
+		player_said_1(swim_down) || player_said_1(swim_up)) {
+		goto handled;
+	}
+
+	if (player_said_2(gaze_into, crystal_ball)) {
+		if (local->anim_0_running) {
+			text_show(32);
+		} else {
+			text_show(11323);
+		}
+		goto handled;
+	}
+
+	if (local->anim_0_running) {  /* player is Seal */
+		if (!player_said_1(look) && !player_said_1(take) && !player_said_1(push) &&
+			!player_said_1(open) && !player_said_1(put) && !player_said_1(talk_to) &&
+			!player_said_1(give) && !player_said_1(pull) && !player_said_1(close) &&
+			!player_said_1(throw) && !player_said_1(swim_to) && !player_said_1(swim_towards)) {
+			text_show(32);
+			goto handled;
+		}
+	}
+
+	goto done;
+
+handled:
+	player.command_ready = false;
+
+done:
+	;
 }
 
 void room_113_synchronize(Common::Serializer &s) {
-	
+	for (int16 &v : scratch.sprite)    s.syncAsSint16LE(v);
+	for (int16 &v : scratch.sequence)  s.syncAsSint16LE(v);
+	for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+	s.syncAsSint16LE(scratch.side_of_room);
+	for (int16 &v : scratch.stairs_id) s.syncAsSint16LE(v);
+	s.syncAsSint16LE(scratch.seal_frame);
+	s.syncAsSint16LE(scratch.seal_action);
+	s.syncAsSint16LE(scratch.anim_0_running);
+	s.syncAsSint16LE(scratch.clicked_on);
 }
 
 void room_113_preload() {
@@ -74,8 +904,25 @@ void room_113_preload() {
 	room_parser_code_pointer = room_113_parser;
 	room_daemon_code_pointer = room_113_daemon;
 
+	if (kernel.teleported_in) {
+		inter_give_to_player(crystal_ball);
+		inter_give_to_player(shifter_ring);
+		inter_give_to_player(magic_belt);
+		global[player_persona] = PLAYER_IS_PID;
+	}
+
 	section_1_walker();
 	section_1_interface();
+
+	if (global[statue_is_on_stairway_114]) {
+		kernel_initial_variant = 1;
+	}
+
+	vocab_make_active(words_swim_down);
+	vocab_make_active(words_swim_up);
+	vocab_make_active(words_shore);
+	vocab_make_active(words_swim_to);
+	vocab_make_active(words_swim_towards);
 }
 
 } // namespace Rooms


Commit: 97065001099758eb64bf02303e5500ea7fac6a30
    https://github.com/scummvm/scummvm/commit/97065001099758eb64bf02303e5500ea7fac6a30
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-10T19:31:29+10:00

Commit Message:
MADS: DRAGONSPHERE: Added room 114

Changed paths:
    engines/mads/madsv2/dragonsphere/mads/inventory.h
    engines/mads/madsv2/dragonsphere/mads/words.h
    engines/mads/madsv2/dragonsphere/rooms/room114.cpp


diff --git a/engines/mads/madsv2/dragonsphere/mads/inventory.h b/engines/mads/madsv2/dragonsphere/mads/inventory.h
index a6dc4438649..16524f0832f 100644
--- a/engines/mads/madsv2/dragonsphere/mads/inventory.h
+++ b/engines/mads/madsv2/dragonsphere/mads/inventory.h
@@ -36,6 +36,7 @@ enum {
 	bone            =  6,
 	fruit           =  7,
 	pid_doll        =  8,
+	statue          = 15,
 	magic_belt      = 18,
 	crystal_ball    = 29,
 	shifter_ring    = 32,
diff --git a/engines/mads/madsv2/dragonsphere/mads/words.h b/engines/mads/madsv2/dragonsphere/mads/words.h
index 605627b01a1..ecc84dbbd36 100644
--- a/engines/mads/madsv2/dragonsphere/mads/words.h
+++ b/engines/mads/madsv2/dragonsphere/mads/words.h
@@ -57,6 +57,7 @@ enum {
 	words_bone                 =  62,
 	words_doll                 =  66,
 	words_heal                 =  68,
+	words_statue               =  79,
 	words_rope                 = 101,
 	words_tie                  = 102,
 	words_crystal_ball         = 109,
@@ -71,10 +72,12 @@ enum {
 	words_emerald              = 136,
 	words_touch                = 146,
 	words_throne_room          = 147,
+	words_passageway_to_west   = 150,
 	words_cave_floor           = 152,
 	words_castle               = 156,
 	words_stairs               = 168,
 	words_walk_down            = 169,
+	words_cave_ceiling         = 173,
 	words_cave_wall            = 174,
 	words_brazier              = 175,
 	words_door_to_throne_room  = 176,
@@ -136,12 +139,17 @@ enum {
 	words_merchant             = 281,
 	words_shapechanger         = 282,
 	words_king                 = 291,
+	words_climb_up             = 296,
 	words_sconce               = 329,
+	words_stairway             = 331,
+	words_mechanism            = 332,
+	words_spearheads           = 333,
 	words_trap_door            = 334,
 	words_swim_up              = 337,
 	words_shore                = 339,
 	words_swim_to              = 340,
 	words_swim_towards         = 341,
+	words_climb_through        = 346,
 	words_Queen_Mother         = 347,
 	words_sit_on               = 363,
 	words_Soptus_Ecliptus      = 448,
diff --git a/engines/mads/madsv2/dragonsphere/rooms/room114.cpp b/engines/mads/madsv2/dragonsphere/rooms/room114.cpp
index f366ed00312..6089f375a14 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/room114.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/room114.cpp
@@ -22,6 +22,7 @@
 #include "mads/madsv2/core/conv.h"
 #include "mads/madsv2/core/game.h"
 #include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
 #include "mads/madsv2/core/kernel.h"
 #include "mads/madsv2/core/sound.h"
 #include "mads/madsv2/core/text.h"
@@ -39,6 +40,16 @@ namespace Dragonsphere {
 namespace Rooms {
 
 struct Scratch {
+	int16 sprite[15];       /* Sprite series handles */
+	int16 sequence[15];     /* Sequence handles      */
+	int16 animation[4];     /* Animation handles     */
+
+	int16 stairway_frame;
+	int16 stairway_action;
+	int16 on_stairway;        /* T if came from under well and have choices on stairway */
+
+	int16 anim_0_running;
+	int16 anim_1_running;
 };
 
 #define local (&scratch)
@@ -46,26 +57,474 @@ struct Scratch {
 #define seq   local->sequence
 #define aa    local->animation
 
-//static Scratch scratch;
+static Scratch scratch;
+
+
+/* ========================= Sprites ========================= */
+
+#define fx_sconce_fire       1 /* rm114y */
+
+#define ROOM_114_RUN_AA_SUB_0 60
+
+#define START_X_ROOM_113     109
+#define START_Y_ROOM_113     118
+#define START_X_ROOM_115     16
+#define START_Y_ROOM_115     105
+
+#define LADDER_FREEZE        0
+#define LADDER_DIE           1
+#define LADDER_GO_UP         2
+#define LADDER_GO_DOWN       3 
+#define LADDER_PLACE_OBJECT  4
+#define LADDER_OTHER         5
+
+#define UP_LADDER_X          230
+#define UP_LADDER_Y          30
+
+
+static void room_114_init(void) {
+	/* Load sprite series */
+
+	if (previous_room != KERNEL_RESTORING_GAME) {
+		local->on_stairway = false;
+		local->anim_0_running = false;
+		local->anim_1_running = false;
+	}
+
+	kernel_flip_hotspot(words_statue, false);
+
+	ss[fx_sconce_fire] = kernel_load_series(kernel_name('y', -1), false);
+
+	/* Start continuous sequences */
+	seq[fx_sconce_fire] = kernel_seq_forward(ss[fx_sconce_fire], false, 7, 0, 0, 0);
+	kernel_seq_depth(seq[fx_sconce_fire], 15);
+
+
+	if (previous_room == KERNEL_RESTORING_GAME) {
+		aa[0] = kernel_run_animation(kernel_name('d', 1), 0);
+		local->anim_0_running = true;
+		if (global[statue_is_on_stairway_114] == STAIRWAY_STATUE) {
+			kernel_flip_hotspot(words_statue, true);
+		}
+		if (local->on_stairway) {
+			player.walker_visible = false;
+			local->stairway_action = LADDER_FREEZE;
+			kernel_reset_animation(aa[0], 49);
+
+		} else {
+			kernel_reset_animation(aa[0], 104);
+		}
+
+	} else if (previous_room == 113) { /* Player comes from under well */
+		player.x = START_X_ROOM_113;
+		player.y = START_Y_ROOM_113;
+		player.facing = FACING_WEST;
+		player.walker_visible = false;
+		player.commands_allowed = false;
+
+		if (!global[statue_is_on_stairway_114]) {
+			local->stairway_action = LADDER_FREEZE;
+			local->on_stairway = true;
+			local->anim_0_running = false;
+			aa[2] = kernel_run_animation(kernel_name('d', 3), ROOM_114_RUN_AA_SUB_0);
+
+		} else {
+			aa[0] = kernel_run_animation(kernel_name('d', 1), 0);
+			local->anim_0_running = true;
+			kernel_reset_animation(aa[0], 49);
+			kernel_reset_animation(aa[0], 210);
+			local->stairway_action = LADDER_OTHER;
+			if (global[statue_is_on_stairway_114] == STAIRWAY_STATUE) {
+				kernel_flip_hotspot(words_statue, true);
+			}
+			/* Have Pid come down into room - statue is already on stairway - or crystal ball - he is safe */
+		}
+
+	} else if (previous_room != KERNEL_RESTORING_GAME) { /* Player comes from Darkened Beast rm115 */
+		aa[0] = kernel_run_animation(kernel_name('d', 1), 0);
+		local->anim_0_running = true;
+		player.x = START_X_ROOM_115;
+		player.y = START_Y_ROOM_115;
+		player.facing = FACING_EAST;
+		local->stairway_action = LADDER_OTHER;
+		if (global[statue_is_on_stairway_114] == STAIRWAY_STATUE) {
+			kernel_flip_hotspot(words_statue, true);
+		}
+		kernel_reset_animation(aa[0], 104);
+	}
+
+	section_1_music();
+}
+
+static void handle_animation_stairway_1() {
+	int stairway_reset_frame;
+
+	if (kernel_anim[aa[1]].frame != local->stairway_frame) {
+		local->stairway_frame = kernel_anim[aa[1]].frame;
+		stairway_reset_frame = -1;
+
+		switch (local->stairway_frame) {
+		case 103:
+			if (game.difficulty == EASY_MODE) {
+				text_show(11429);
+			} else {
+				text_show(45);
+			}
+			new_room = 113;
+			break;
+		}
+
+		if (stairway_reset_frame >= 0) {
+			kernel_reset_animation(aa[1], stairway_reset_frame);
+			local->stairway_frame = stairway_reset_frame;
+		}
+	}
+}
+
+static void handle_animation_stairway() {
+	int stairway_reset_frame;
+
+	if (kernel_anim[aa[0]].frame != local->stairway_frame) {
+		local->stairway_frame = kernel_anim[aa[0]].frame;
+		stairway_reset_frame = -1;
+
+		switch (local->stairway_frame) {
+		case 144:
+		case 103:
+		case 209:
+		case 327:
+			new_room = 113;
+			break;
+
+		case 272:
+			if (global[statue_is_on_stairway_114]) {
+				stairway_reset_frame = 157;
+			}
+			break;
+
+		case 54:
+			inter_move_object(statue, NOWHERE);
+			break;
+
+		case 49: /* end of frozen on bottom of stairway - waiting for input */
+		case 59: /* end of place object */
+
+			if (local->stairway_frame == 59) {
+				text_show(11428);
+			}
+
+			if (local->stairway_action == LADDER_FREEZE) {
+				stairway_reset_frame = 48;
+				player.commands_allowed = true;
+				/* keep him on bottom of stairway waiting for user input */
+
+			} else if (local->stairway_action == LADDER_GO_UP) {
+				stairway_reset_frame = 265;
+				/* make him go up and leave room */
+
+			} else if (local->stairway_action == LADDER_PLACE_OBJECT) {
+				stairway_reset_frame = 49;
+				local->stairway_action = LADDER_FREEZE;
+				/* put object on end of stairway */
 
-void room_114_init() {
+			} else if (local->stairway_action == LADDER_GO_DOWN) {
+				if (!global[statue_is_on_stairway_114]) {
+					kernel_abort_animation(aa[0]);
+					aa[1] = kernel_run_animation(kernel_name('d', 2), 0);
+					stairway_reset_frame = -1;
+					local->anim_0_running = false;
+					local->anim_1_running = true;
+					kernel_reset_animation(aa[1], 60);
+					kernel_synch(KERNEL_ANIM, aa[1], KERNEL_NOW, 0);
 
+				} else {
+					stairway_reset_frame = 59;
+					/* make player walk off stairway */
+				}
+			}
+			break;
+
+		case 66:
+			if (!global[statue_is_on_stairway_114]) {
+				stairway_reset_frame = 66;
+				/* make player die */
+
+			} else {
+				player.walker_visible = true;
+				player.commands_allowed = true;
+				stairway_reset_frame = 103;
+				local->on_stairway = false;
+				kernel_synch(KERNEL_PLAYER, 0, KERNEL_ANIM, aa[0]);
+				player.ready_to_walk = true;
+			}
+			break;
+
+		case 104: /* end of stairway stamped down in room */
+			if (local->stairway_action == LADDER_GO_UP) {
+				stairway_reset_frame = 150;
+				player.commands_allowed = false;
+				player.walker_visible = false;
+				kernel_synch(KERNEL_PLAYER, 0, KERNEL_ANIM, aa[0]);
+				/* make Pid climb stairway */
+			} else {
+				stairway_reset_frame = 103;
+				/* keep stairway stamped down */
+			}
+			break;
+
+		case 265: /* end of coming into room - stairs already in place */
+			player.x = START_X_ROOM_113;
+			player.y = START_Y_ROOM_113;
+			player.walker_visible = true;
+			player.commands_allowed = true;
+			stairway_reset_frame = 103;
+			local->on_stairway = false;
+			player_demand_facing(FACING_WEST);
+			kernel_synch(KERNEL_PLAYER, 0, KERNEL_ANIM, aa[0]);
+			break;
+		}
+
+		if (stairway_reset_frame >= 0) {
+			kernel_reset_animation(aa[0], stairway_reset_frame);
+			local->stairway_frame = stairway_reset_frame;
+		}
+	}
 }
 
-void room_114_daemon() {
+static void room_114_daemon() {
+	if (kernel.trigger == ROOM_114_RUN_AA_SUB_0) {
+		kernel_abort_animation(aa[2]);
+		aa[0] = kernel_run_animation(kernel_name('d', 1), 0);
+		local->anim_0_running = true;
+		kernel_reset_animation(aa[0], 49);
+		kernel_synch(KERNEL_ANIM, aa[0], KERNEL_NOW, 0);
+	}
 
+	if (local->anim_1_running) {
+		handle_animation_stairway_1();
+	}
+
+	if (local->anim_0_running) {
+		handle_animation_stairway();
+	}
 }
 
-void room_114_pre_parser() {
+static void room_114_pre_parser(void) {
+	if (player_said_2(walk_down, passageway_to_west)) {
+		player.walk_off_edge_to_room = 115;
+	}
+
+	if (local->on_stairway) {
+		if (player_said_2(climb_up, stairway) || player_said_2(climb_through, trap_door)) {
+			player.need_to_walk = false;
+		}
+
+		if (player_said_1(walk_across) || player_said_1(walk_to) || player_said_1(walk_down)) {
+			local->stairway_action = LADDER_GO_DOWN;
+			player.commands_allowed = false;
+			player.ready_to_walk = false;
+		}
 
+		if (player_said_1(push) || player_said_1(pull) || player_said_1(open) ||
+			player_said_1(close) || player_said_1(give) || player_said_1(take) ||
+			player_said_1(throw) || player_said_1(put)) {
+			player.need_to_walk = false;
+		}
+	}
 }
 
-void room_114_parser() {
 
+static void room_114_parser() {
+	if (player_said_3(put, statue, stairway) && global[statue_is_on_stairway_114] == STAIRWAY_STATUE) {
+		text_show(11414);
+		goto handled;
+	}
+
+	if (player_said_2(climb_up, stairway) || player_said_2(climb_through, trap_door)) {
+		if (!local->on_stairway) {
+			local->stairway_action = LADDER_GO_UP;
+			player.commands_allowed = false;
+			goto handled;
+		}
+	}
+
+	if (local->on_stairway) {
+		if (player_said_2(climb_up, stairway) || player_said_2(climb_through, trap_door)) {
+			local->stairway_action = LADDER_GO_UP;
+			player.commands_allowed = false;
+			goto handled;
+
+		} else if (player_said_3(put, statue, stairway) ||
+			player_said_2(invoke_power_of, crystal_ball)) {
+
+			if (!global[statue_is_on_stairway_114]) {
+				if (player_said_1(statue)) {
+					global[player_score] += 3;
+					kernel_flip_hotspot(words_statue, true);
+					local->stairway_action = LADDER_PLACE_OBJECT;
+					player.commands_allowed = false;
+					global[statue_is_on_stairway_114] = STAIRWAY_STATUE;
+
+				} else {
+					global[statue_is_on_stairway_114] = STAIRWAY_CRYSTAL_BALL;
+					sound_play(N_InvokeCrystalBall);
+					text_show(11411);
+					inter_move_object(crystal_ball, NOWHERE);
+					text_show(970);
+				}
+				goto handled;
+			}
+
+		} else if (player_said_2(put, stairway)) {
+			if (!global[statue_is_on_stairway_114]) {
+				if (game.difficulty == EASY_MODE) {
+					text_show(11412);
+				} else {
+					text_show(11413);
+				}
+				goto handled;
+			}
+
+		} else if (player_said_1(walk_across) || player_said_1(walk_to) || player_said_1(walk_down)) {
+			goto handled;
+		}
+	}
+
+	if (player.look_around) {
+		if (global[statue_is_on_stairway_114]) {
+			if (local->on_stairway) {
+				text_show(11401);
+			} else {
+				text_show(11402);
+			}
+		} else {
+			text_show(11401);
+		}
+		goto handled;
+	}
+
+	if (player_said_1(look) || player_said_1(look_at)) {
+
+		if (player_said_1(statue)) {
+			if (local->on_stairway && !player_has(statue)) {
+				text_show(11409);
+				goto handled;
+			} else if (!player_has(statue)) {
+				text_show(11408);
+				goto handled;
+			}
+		}
+
+		if (player_said_1(stairway)) {
+
+			if (global[statue_is_on_stairway_114] == STAIRWAY_CRYSTAL_BALL) {
+
+				if (!local->on_stairway) {
+					text_show(11422);
+					/* crystal ball did the trick */
+				} else if (global[statue_is_on_stairway_114]) {
+					text_show(11421);
+					/* I hope the crystal ball did the trick */
+				}
+
+			} else if (global[statue_is_on_stairway_114] == STAIRWAY_STATUE) {
+
+				if (!local->on_stairway) {
+					text_show(11408);
+					/* The statue did the trick! */
+				} else if (global[statue_is_on_stairway_114]) {
+					text_show(11407);
+					/* I hope the statue will do the trick */
+				}
+
+			} else {
+				text_show(11405);
+				/* plain old look at stairway */
+			}
+			goto handled;
+		}
+
+		if (player_said_1(passageway_to_west)) {
+			text_show(11403);
+			goto handled;
+		}
+
+		if (player_said_1(mechanism)) {
+			text_show(11404);
+			goto handled;
+		}
+
+		if (player_said_1(cave_wall)) {
+			text_show(11423);
+			goto handled;
+		}
+
+		if (player_said_1(trap_door)) {
+			text_show(11427);
+			goto handled;
+		}
+
+		if (player_said_1(cave_ceiling)) {
+			text_show(11424);
+			goto handled;
+		}
+
+		if (player_said_1(floor)) {
+			text_show(11425);
+			goto handled;
+		}
+
+		if (player_said_1(sconce)) {
+			text_show(11426);
+			goto handled;
+		}
+
+		if (player_said_1(spearheads)) {
+			text_show(11406);
+			goto handled;
+		}
+	}
+
+	if (player_said_2(take, statue)) {
+		if (!player_has(statue)) {
+			text_show(11416);
+			goto handled;
+		}
+	}
+
+	if (player_said_2(open, stairway)) {
+		text_show(11418);
+		goto handled;
+	}
+
+	if (player_said_2(gaze_into, crystal_ball)) {
+		text_show(11410);
+		goto handled;
+	}
+
+	if (player_said_2(close, stairway)) {
+		text_show(11417);
+		goto handled;
+	}
+
+	goto done;
+
+handled:
+	player.command_ready = false;
+
+done:
+	;
 }
 
 void room_114_synchronize(Common::Serializer &s) {
-	
+	for (int16 &v : scratch.sprite)    s.syncAsSint16LE(v);
+	for (int16 &v : scratch.sequence)  s.syncAsSint16LE(v);
+	for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+	s.syncAsSint16LE(scratch.stairway_frame);
+	s.syncAsSint16LE(scratch.stairway_action);
+	s.syncAsSint16LE(scratch.on_stairway);
+	s.syncAsSint16LE(scratch.anim_0_running);
+	s.syncAsSint16LE(scratch.anim_1_running);
 }
 
 void room_114_preload() {


Commit: cff33430a15cd84801b4de7683b8b54bb0673619
    https://github.com/scummvm/scummvm/commit/cff33430a15cd84801b4de7683b8b54bb0673619
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-05-10T19:45:38+10:00

Commit Message:
MADS: DRAGONSPHERE: Added room 115

Changed paths:
    engines/mads/madsv2/dragonsphere/mads/inventory.h
    engines/mads/madsv2/dragonsphere/mads/sounds.h
    engines/mads/madsv2/dragonsphere/mads/words.h
    engines/mads/madsv2/dragonsphere/rooms/room115.cpp


diff --git a/engines/mads/madsv2/dragonsphere/mads/inventory.h b/engines/mads/madsv2/dragonsphere/mads/inventory.h
index 16524f0832f..0523348fba7 100644
--- a/engines/mads/madsv2/dragonsphere/mads/inventory.h
+++ b/engines/mads/madsv2/dragonsphere/mads/inventory.h
@@ -29,23 +29,24 @@ namespace MADSV2 {
 namespace Dragonsphere {
 
 enum {
-	bird_figurine   =  1,
-	shieldstone     =  3,
-	sword           =  4,
-	goblet          =  5,
-	bone            =  6,
-	fruit           =  7,
-	pid_doll        =  8,
-	statue          = 15,
-	magic_belt      = 18,
-	crystal_ball    = 29,
-	shifter_ring    = 32,
-	rare_coin       = 38,
-	crystal_flower  = 39,
-	ruby_ring       = 41,
-	gold_nugget     = 42,
-	magic_music_box = 43,
-	emerald         = 44
+	bird_figurine    =  1,
+	shieldstone      =  3,
+	sword            =  4,
+	goblet           =  5,
+	bone             =  6,
+	fruit            =  7,
+	pid_doll         =  8,
+	statue           = 15,
+	magic_belt       = 18,
+	crystal_ball     = 29,
+	shifter_ring     = 32,
+	rare_coin        = 38,
+	crystal_flower   = 39,
+	ruby_ring        = 41,
+	gold_nugget      = 42,
+	magic_music_box  = 43,
+	emerald          = 44,
+	piece_of_paper   = 45
 };
 
 } // namespace Dragonsphere
diff --git a/engines/mads/madsv2/dragonsphere/mads/sounds.h b/engines/mads/madsv2/dragonsphere/mads/sounds.h
index 3ba66ac57e1..c48ea3a0a78 100644
--- a/engines/mads/madsv2/dragonsphere/mads/sounds.h
+++ b/engines/mads/madsv2/dragonsphere/mads/sounds.h
@@ -42,6 +42,8 @@ enum {
 	N_WallGrinds         =  67,
 	N_DragonInWater      =  72,
 	N_OldMachinery       =  74,
+	N_DogWhimper         =  79,
+	N_BeastSnd           =  80,
 	N_JumpDownWell       =  93,
 	N_BooksRumble        =  94,
 	N_McMornTipsTable    = 100
diff --git a/engines/mads/madsv2/dragonsphere/mads/words.h b/engines/mads/madsv2/dragonsphere/mads/words.h
index ecc84dbbd36..df0b0b359b8 100644
--- a/engines/mads/madsv2/dragonsphere/mads/words.h
+++ b/engines/mads/madsv2/dragonsphere/mads/words.h
@@ -53,16 +53,23 @@ enum {
 	words_invoke               =  47,
 	words_shieldstone          =  55,
 	words_sword                =  56,
+	words_attack               =  57,
+	words_carve_up             =  58,
 	words_goblet               =  59,
 	words_bone                 =  62,
 	words_doll                 =  66,
 	words_heal                 =  68,
+	words_dates                =  78,
 	words_statue               =  79,
+	words_bottle_of_flies      =  80,
+	words_thrust               =  87,
+	words_torch                =  93,
 	words_rope                 = 101,
 	words_tie                  = 102,
 	words_crystal_ball         = 109,
 	words_gaze_into            = 110,
 	words_invoke_power_of      = 111,
+	words_soptus_soporific     = 113,
 	words_shift_into_bear      = 116,
 	words_shift_into_seal      = 117,
 	words_shift_into_snake     = 118,
@@ -70,13 +77,16 @@ enum {
 	words_tentacle_parts       = 125,
 	words_rare_coin            = 129,
 	words_emerald              = 136,
+	words_speak_words_on       = 138,
 	words_touch                = 146,
 	words_throne_room          = 147,
 	words_passageway_to_west   = 150,
+	words_passageway_to_east   = 151,
 	words_cave_floor           = 152,
 	words_castle               = 156,
 	words_stairs               = 168,
 	words_walk_down            = 169,
+	words_edge_of_abyss        = 170,
 	words_cave_ceiling         = 173,
 	words_cave_wall            = 174,
 	words_brazier              = 175,
@@ -133,11 +143,13 @@ enum {
 	words_swim_down            = 265,
 	words_scullery_maid        = 266,
 	words_ward                 = 268,
+	words_darkness_beast       = 269,
 	words_doorway              = 277,
 	words_faerie               = 278,
 	words_guard_captain        = 280,
 	words_merchant             = 281,
 	words_shapechanger         = 282,
+	words_parchment            = 290,
 	words_king                 = 291,
 	words_climb_up             = 296,
 	words_sconce               = 329,
@@ -149,6 +161,7 @@ enum {
 	words_shore                = 339,
 	words_swim_to              = 340,
 	words_swim_towards         = 341,
+	words_grotto               = 345,
 	words_climb_through        = 346,
 	words_Queen_Mother         = 347,
 	words_sit_on               = 363,
diff --git a/engines/mads/madsv2/dragonsphere/rooms/room115.cpp b/engines/mads/madsv2/dragonsphere/rooms/room115.cpp
index 8ba88d302a0..76a02ce0801 100644
--- a/engines/mads/madsv2/dragonsphere/rooms/room115.cpp
+++ b/engines/mads/madsv2/dragonsphere/rooms/room115.cpp
@@ -22,8 +22,10 @@
 #include "mads/madsv2/core/conv.h"
 #include "mads/madsv2/core/game.h"
 #include "mads/madsv2/core/imath.h"
+#include "mads/madsv2/core/inter.h"
 #include "mads/madsv2/core/kernel.h"
 #include "mads/madsv2/core/sound.h"
+#include "mads/madsv2/core/speech.h"
 #include "mads/madsv2/core/text.h"
 #include "mads/madsv2/dragonsphere/mads/conv.h"
 #include "mads/madsv2/dragonsphere/mads/inventory.h"
@@ -39,6 +41,18 @@ namespace Dragonsphere {
 namespace Rooms {
 
 struct Scratch {
+	int16 sprite[15];       /* Sprite series handles */
+	int16 sequence[15];     /* Sequence handles      */
+	int16 animation[4];     /* Animation handles     */
+
+	int16 beast_frame;      /* animation frame being held for beast stuff */
+	int16 beast_action;       /* Type of action to run for beast animation */
+	int16 prevent;
+	int16 prevent_2;
+	int16 say_text;
+	int16 crunch_timer;
+
+	char message[20];     /* String to say to dog */
 };
 
 #define local (&scratch)
@@ -46,26 +60,655 @@ struct Scratch {
 #define seq   local->sequence
 #define aa    local->animation
 
-//static Scratch scratch;
+static Scratch scratch;
+
+/* ========================= Sprites ========================= */
+
+#define fx_fire               1  /* rm115x0 */
+#define fx_bone               2  /* rm115x1 */
+#define fx_throw_bone         3  /* rm115b0 */
+
+
+/* ======================== Triggers ========================= */
+
+#define ROOM_115_CAN_KILL     70          
+
+
+/* walk points */
+#define START_X_ROOM_116      23
+#define START_Y_ROOM_116      91
+#define START_X_ROOM_114      305
+#define START_Y_ROOM_114      104
+#define WALK_TO_X_FROM_116    75
+#define WALK_TO_Y_FROM_116    110
+
+#define THROW_BONE_X          149
+#define THROW_BONE_Y          132
+
+#define BEAST_EAT_X           102
+#define BEAST_EAT_Y           121
+
+#define SAY_WORD_X            192
+#define SAY_WORD_Y            137
+
+/* animation controls */
+#define LOOK_AROUND           0
+#define GET_UP                1
+#define ATTACK                2
+#define REALLY_ATTACK         3
+#define SLEEP                 4
+
+#define BEAST_LAY_X           138
+#define BEAST_LAY_Y           85
+
+
+static void room_115_init() {
+	kernel.disable_fastwalk = true;
+
+	if (previous_room != KERNEL_RESTORING_GAME) {
+		local->say_text = false;
+	}
+
+	local->crunch_timer = 0;
+
+	/* Load sprite series */
+
+	ss[fx_fire] = kernel_load_series(kernel_name('x', 0), false);
+	ss[fx_bone] = kernel_load_series(kernel_name('x', 1), false);
+	ss[fx_throw_bone] = kernel_load_series(kernel_name('b', 0), false);
+
+	if (global[threw_bone]) {
+		seq[fx_bone] = kernel_seq_stamp(ss[fx_bone], false, KERNEL_FIRST);
+		kernel_seq_depth(seq[fx_bone], 11);
+	} else {
+		kernel_flip_hotspot(words_bone, false);
+	}
+
+	kernel_flip_hotspot(words_darkness_beast, false);
+	kernel_flip_hotspot_loc(words_darkness_beast, true, BEAST_LAY_X, BEAST_LAY_Y);
+
+	local->prevent = false;
+	local->prevent_2 = false;
+
+	/* Start continuous sequences */
+
+	seq[fx_fire] = kernel_seq_forward(ss[fx_fire], false, 7, 0, 0, 0);
 
-void room_115_init() {
+	if (previous_room == 116) {  /* Player comes from the Ice\King room */
+		player.x = START_X_ROOM_116;
+		player.y = START_Y_ROOM_116;
+		player.facing = FACING_SOUTHWEST;
+		player_walk(WALK_TO_X_FROM_116, WALK_TO_Y_FROM_116, FACING_SOUTHEAST);
 
+	} else if (previous_room != KERNEL_RESTORING_GAME) { /* Player comes from Stair trap rm114 */
+		player.x = START_X_ROOM_114;
+		player.y = START_Y_ROOM_114;
+		player.facing = FACING_WEST;
+	}
+
+	aa[0] = kernel_run_animation(kernel_name('d', 1), 0);
+	if (global[dog_is_asleep]) {
+		local->beast_action = SLEEP;
+	} else {
+		local->beast_action = LOOK_AROUND;
+	}
+
+	if (kernel.teleported_in) {
+		inter_give_to_player(bone);
+		inter_give_to_player(piece_of_paper);
+	}
+
+	section_1_music();
 }
 
-void room_115_daemon() {
+static void handle_animation_beast() {
+	int beast_reset_frame;
+	int random;
+
+	if (kernel_anim[aa[0]].frame != local->beast_frame) {
+		local->beast_frame = kernel_anim[aa[0]].frame;
+		beast_reset_frame = -1;
+
+		switch (local->beast_frame) {
+		case 1:   /* end of head down */
+		case 60:  /* end of head down */
+		case 80:  /* end of head down */
+
+			if (local->say_text) {
+				if (local->say_text == 1) {         /* crystal ball used */
+					text_show(11513);
+					inter_move_object(crystal_ball, NOWHERE);
+					text_show(970);
+				} else if (local->say_text == 2) {  /* parchment used */
+					text_show(11508);
+				}
+				player.commands_allowed = true;
+				local->say_text = false;
+			}
+
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				if (imath_random(1, 30) == 1) {
+					beast_reset_frame = 1;  /* put head up (new node) */
+				} else {
+					beast_reset_frame = 0;  /* keep head down */
+				}
+				break;
+
+			case GET_UP:
+			case ATTACK:
+				beast_reset_frame = 1;  /* put head up (new node) */
+				break;
+
+			case SLEEP:
+				beast_reset_frame = 0;  /* keep head down */
+				break;
+			}
+			break;
+
+		case 3:  /* end of head up */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 3;   /* mode head (new node) */
+				} else if (random == 2) {
+					beast_reset_frame = 58;  /* put head down (new node) */
+				} else {
+					beast_reset_frame = 2;   /* keep in this position */
+				}
+				break;
+
+			case GET_UP:
+			case ATTACK:
+				beast_reset_frame = 3;   /* mode head (new node) */
+				break;
+
+			case SLEEP:
+				beast_reset_frame = 58;  /* keep head down */
+				break;
+			}
+			break;
+
+		case 4:  /* end of keeping head up */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 4;   /* mode head (new node) */
+				} else if (random == 2) {
+					beast_reset_frame = 2;   /* move head (new node) */
+				} else {
+					beast_reset_frame = 3;   /* keep head where it is */
+				}
+				break;
+
+			case GET_UP:
+			case ATTACK:
+				beast_reset_frame = 5;   /* get up (new node) */
+				kernel_flip_hotspot(words_darkness_beast, true);
+				kernel_flip_hotspot_loc(words_darkness_beast, false, BEAST_LAY_X, BEAST_LAY_Y);
+				break;
+
+			case SLEEP:
+				beast_reset_frame = 2;  /* keep head down */
+				break;
+			}
+			break;
+
+		case 5:  /* end of keeping head up */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 3;   /* mode head (new node) */
+				} else {
+					beast_reset_frame = 4;   /* keep head where it is */
+				}
+				break;
+
+			case GET_UP:
+			case ATTACK:
+			case SLEEP:
+				beast_reset_frame = 3;  /* move head (new node) */
+				break;
+			}
+			break;
+
+		case 22:
+			if (!global[dog_is_asleep]) {
+				local->beast_action = LOOK_AROUND;
+			}
+			break;
+
+		case 23:  /* end of getting up */
+		case 25:  /* end of moving head */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 23;   /* move head (new node) */
+				} else if (random == 2) {
+					beast_reset_frame = 25;   /* move head (new node) */
+				} else if (random == 3) {
+					beast_reset_frame = 24;   /* keep head where it is */
+				} else if (random == 4) {
+					beast_reset_frame = 22;   /* keep head where it is */
+				} else {
+					beast_reset_frame = local->beast_frame - 1;
+				}
+				break;
+
+			case ATTACK:
+				beast_reset_frame = 25;  /* move head (new node) */
+				break;
+
+			case SLEEP:
+				kernel_flip_hotspot(words_darkness_beast, false);
+				kernel_flip_hotspot_loc(words_darkness_beast, true, BEAST_LAY_X, BEAST_LAY_Y);
+				beast_reset_frame = 60;  /* sleep (new node) */
+				break;
+			}
+			break;
+
+		case 24:  /* end of moving head */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 22;   /* move head (new node) */
+				} else {
+					beast_reset_frame = 23;   /* keep head where it is */
+				}
+				break;
+
+			case ATTACK:
+			case SLEEP:
+				beast_reset_frame = 22;  /* move head (new node) */
+				break;
+			}
+			break;
+
+		case 26:  /* end of moving head */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 24;   /* move head (new node) */
+				} else if (random == 2) {
+					beast_reset_frame = 26;   /* move head (new node) */
+				} else {
+					beast_reset_frame = 25;   /* keep head where it is */
+				}
+				break;
+
+			case ATTACK:
+				beast_reset_frame = 26;  /* move head (new node) */
+				break;
 
+			case SLEEP:
+				beast_reset_frame = 24;  /* move head (new node) */
+				break;
+			}
+			break;
+
+		case 27:  /* end of moving head */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 27;   /* move head (new node) */
+				} else if (random == 2) {
+					beast_reset_frame = 25;   /* move head (new node) */
+				} else {
+					beast_reset_frame = 26;   /* keep head where it is */
+				}
+				break;
+
+			case ATTACK:
+				beast_reset_frame = 26;  /* attack */
+				break;
+
+			case REALLY_ATTACK:
+				beast_reset_frame = 29;  /* attack */
+				break;
+
+			case SLEEP:
+				beast_reset_frame = 25;  /* move head (new node) */
+				break;
+			}
+			break;
+
+		case 28:  /* end of moving head */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 26;   /* move head (new node) */
+				} else if (random == 2) {
+					beast_reset_frame = 28;   /* move head (new node) */
+				} else {
+					beast_reset_frame = 27;   /* keep head where it is */
+				}
+				break;
+
+			case ATTACK:
+			case SLEEP:
+				beast_reset_frame = 26;  /* attack */
+				break;
+			}
+			break;
+
+		case 29:  /* end of moving head */
+			switch (local->beast_action) {
+			case LOOK_AROUND:
+				random = imath_random(1, 30);
+				if (random == 1) {
+					beast_reset_frame = 27;   /* move head (new node) */
+				} else {
+					beast_reset_frame = 28;   /* keep head where it is */
+				}
+				break;
+
+			case ATTACK:
+			case SLEEP:
+				beast_reset_frame = 27;  /* move head (new node) */
+				break;
+			}
+			break;
+
+		case 35:
+			player.walker_visible = false;
+			kernel_synch(KERNEL_PLAYER, 0, KERNEL_ANIM, aa[0]);
+			break;
+
+		case 36:
+			global_speech_go(3);
+			break;
+
+		case 57:
+			global_speech_go(4);
+			break;
+
+		case 58:
+			++local->crunch_timer;
+			if (local->crunch_timer > 20) {
+				kernel.force_restart = true;
+				sound_play(N_PlayerDies);
+				if (game.difficulty == EASY_MODE) {
+					text_show(11521);
+				} else {
+					text_show(45);
+				}
+			} else {
+				beast_reset_frame = 57;
+			}
+			break;
+		}
+
+		if (beast_reset_frame >= 0) {
+			kernel_reset_animation(aa[0], beast_reset_frame);
+			local->beast_frame = beast_reset_frame;
+		}
+	}
 }
 
-void room_115_pre_parser() {
+static void room_115_daemon() {
+	handle_animation_beast();
 
+	if (player.x <= 200 && !local->prevent && !global[dog_is_asleep]) {
+		local->beast_action = GET_UP;
+		local->prevent = true;
+	}
+
+	if (player.x <= 140 && !local->prevent_2 && !global[dog_is_asleep]) {
+		local->prevent_2 = true;
+		player.commands_allowed = false;
+		local->beast_action = ATTACK;
+		player_walk(BEAST_EAT_X, BEAST_EAT_Y, FACING_NORTHWEST);
+		player_walk_trigger(ROOM_115_CAN_KILL);
+	}
+
+	if (kernel.trigger == ROOM_115_CAN_KILL) {
+		local->beast_action = REALLY_ATTACK;
+	}
 }
 
-void room_115_parser() {
+static void room_115_pre_parser() {
+	if (player_said_2(walk_down, passageway_to_east)) {
+		player.walk_off_edge_to_room = 114;
+	}
+
+	if (player_said_2(take, bone)) {
+		if (global[threw_bone] && !global[dog_is_asleep]) {
+			player.need_to_walk = false;
+		}
+	}
 
+	if (player_said_2(speak_words_on, parchment)) {
+		if (!global[dog_is_asleep]) {
+			player_walk(SAY_WORD_X, SAY_WORD_Y, FACING_NORTHWEST);
+		}
+	}
+}
+
+static void room_115_parser() {
+	int id;
+
+	if (player.look_around) {
+		if (global[dog_is_asleep]) {
+			text_show(11519);
+		} else {
+			text_show(11501);
+		}
+		goto handled;
+	}
+
+	if (player_said_2(walk_down, passageway_to_west)) {
+		if (global[dog_is_asleep]) {
+			new_room = 116;
+		}
+		goto handled;
+	}
+
+
+	if (player_said_2(speak_words_on, parchment)) {
+		if (!global[dog_is_asleep] || kernel.trigger) {
+			switch (kernel.trigger) {
+			case 0:
+			case 1:
+				player.commands_allowed = false;
+				if ((local->beast_frame < 23) || (local->beast_frame > 35)) {
+					kernel_timing_trigger(10, 1);
+				} else {
+					sound_play(N_BeastSnd);
+					local->message[0] = '"';
+					local->message[1] = 1;
+					local->message[2] = 2;
+					local->message[3] = 3;
+					local->message[4] = 4;
+					local->message[5] = 5;
+					local->message[6] = '!';
+					local->message[7] = '"';
+					local->message[8] = 0;
+
+					id = kernel_message_add(local->message, 0, 0,
+						MESSAGE_COLOR, FOUR_SECONDS,
+						0, KERNEL_MESSAGE_PLAYER);
+					kernel_message_teletype(id, 8, true);
+
+					kernel_timing_trigger(TWO_SECONDS, 2);
+
+					player.commands_allowed = false;
+				}
+				break;
+
+			case 2:
+				global[dog_is_asleep] = true;
+				local->beast_action = SLEEP;
+				global[player_score] += 2;
+				local->say_text = 2;
+				sound_play(N_DogWhimper);
+				break;
+			}
+			goto handled;
+		}
+	}
+
+	if (player_said_2(invoke_power_of, crystal_ball) && !global[crystal_ball_dead]) {
+		sound_play(N_InvokeCrystalBall);
+		global[dog_is_asleep] = true;
+		global[crystal_ball_dead] = true;
+		local->beast_action = SLEEP;
+		local->say_text = 1;
+		sound_play(N_DogWhimper);
+		goto handled;
+	}
+
+	if (player_said_3(throw, bone, darkness_beast) ||
+		player_said_3(give, bone, darkness_beast) ||
+		player_said_3(throw, bone, grotto)) {
+		switch (kernel.trigger) {
+		case 0:
+			if (player_has(bone)) {
+				player_walk(THROW_BONE_X, THROW_BONE_Y, FACING_NORTHWEST);
+				player_walk_trigger(1);
+			}
+			break;
+
+		case 1:
+			player.commands_allowed = false;
+			player.walker_visible = false;
+			global[threw_bone] = true;
+			seq[fx_throw_bone] = kernel_seq_forward(ss[fx_throw_bone], false, 7, 0, 0, 1);
+			kernel_seq_depth(seq[fx_throw_bone], 7);
+			kernel_seq_range(seq[fx_throw_bone], KERNEL_FIRST, KERNEL_LAST);
+			kernel_seq_trigger(seq[fx_throw_bone], KERNEL_TRIGGER_EXPIRE, 0, 3);
+			kernel_seq_trigger(seq[fx_throw_bone], KERNEL_TRIGGER_SPRITE, 9, 2);
+			kernel_synch(KERNEL_SERIES, seq[fx_throw_bone], KERNEL_PLAYER, 0);
+			break;
+
+		case 2:
+			player.commands_allowed = true;
+			player.walker_visible = true;
+			kernel_synch(KERNEL_PLAYER, 0, KERNEL_SERIES, seq[fx_throw_bone]);
+			break;
+
+		case 3:
+			inter_move_object(bone, NOWHERE);
+			seq[fx_bone] = kernel_seq_stamp(ss[fx_bone], false, KERNEL_FIRST);
+			kernel_seq_depth(seq[fx_bone], 14);
+			kernel_flip_hotspot(words_bone, true);
+			if (!global[dog_is_asleep]) {
+				text_show(11507);
+			} else {
+				text_show(11518);
+			}
+			break;
+		}
+		goto handled;
+	}
+
+	if (player_said_1(look) || player_said_1(look_at)) {
+
+		if (player_said_1(torch)) {
+			text_show(11502);
+			goto handled;
+		}
+
+		if (player_said_1(edge_of_abyss)) {
+			text_show(11503);
+			goto handled;
+		}
+
+		if (player_said_1(passageway_to_east)) {
+			text_show(11504);
+			goto handled;
+		}
+
+		if (player_said_1(passageway_to_west)) {
+			text_show(11505);
+			goto handled;
+		}
+
+		if (player_said_1(grotto)) {
+			text_show(11520);
+			goto handled;
+		}
+
+		if (player_said_1(darkness_beast)) {
+			if (global[dog_is_asleep]) {
+				text_show(11508);
+			} else {
+				text_show(11506);
+			}
+			goto handled;
+		}
+
+		if (player_said_1(bone) && !player_has(bone)) {
+			text_show(11509);
+			goto handled;
+		}
+	}
+
+	if (player_said_3(throw, dates, darkness_beast)) {
+		text_show(11514);
+		goto handled;
+	}
+
+	if (player_said_2(gaze_into, crystal_ball)) {
+		if (!global[dog_is_asleep]) {
+			text_show(11512);
+			goto handled;
+		}
+	}
+
+	if (player_said_2(take, bone) && !player_has(bone)) {
+		if (global[dog_is_asleep]) {
+			text_show(11511);
+		} else {
+			text_show(11510);
+		}
+		goto handled;
+	}
+
+	if (player_said_2(open, bottle_of_flies)) {
+		text_show(11516);
+		goto handled;
+	}
+
+	if (player_said_3(give, soptus_soporific, darkness_beast)) {
+		text_show(11517);
+		goto handled;
+	}
+
+	if (player_said_3(sword, attack, darkness_beast) ||
+		player_said_3(sword, carve_up, darkness_beast) ||
+		player_said_3(sword, thrust, darkness_beast)) {
+		text_show(11515);
+		goto handled;
+	}
+
+	goto done;
+
+handled:
+	player.command_ready = false;
+
+done:
+	;
 }
 
 void room_115_synchronize(Common::Serializer &s) {
-	
+	for (int16 &v : scratch.sprite)    s.syncAsSint16LE(v);
+	for (int16 &v : scratch.sequence)  s.syncAsSint16LE(v);
+	for (int16 &v : scratch.animation) s.syncAsSint16LE(v);
+	s.syncAsSint16LE(scratch.beast_frame);
+	s.syncAsSint16LE(scratch.beast_action);
+	s.syncAsSint16LE(scratch.prevent);
+	s.syncAsSint16LE(scratch.prevent_2);
+	s.syncAsSint16LE(scratch.say_text);
+	s.syncAsSint16LE(scratch.crunch_timer);
+	s.syncBytes((byte *)scratch.message, sizeof(scratch.message));
 }
 
 void room_115_preload() {
@@ -76,6 +719,9 @@ void room_115_preload() {
 
 	section_1_walker();
 	section_1_interface();
+
+	vocab_make_active(words_darkness_beast);
+	vocab_make_active(words_walk_to);
 }
 
 } // namespace Rooms




More information about the Scummvm-git-logs mailing list