1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20  *
21  */
22 
23 #include "ags/engine/ac/global_region.h"
24 #include "ags/shared/ac/common.h"
25 #include "ags/shared/ac/game_version.h"
26 #include "ags/engine/ac/game_state.h"
27 #include "ags/engine/ac/region.h"
28 #include "ags/engine/ac/room.h"
29 #include "ags/engine/ac/room_status.h"
30 #include "ags/engine/debugging/debug_log.h"
31 #include "ags/shared/game/room_struct.h"
32 #include "ags/shared/gfx/bitmap.h"
33 #include "ags/engine/script/script.h"
34 #include "ags/globals.h"
35 
36 namespace AGS3 {
37 
38 using namespace AGS::Shared;
39 
GetRegionIDAtRoom(int xxx,int yyy)40 int GetRegionIDAtRoom(int xxx, int yyy) {
41 	// if the co-ordinates are off the edge of the screen,
42 	// correct them to be just within
43 	// this fixes walk-off-screen problems
44 	xxx = room_to_mask_coord(xxx);
45 	yyy = room_to_mask_coord(yyy);
46 
47 	if (_G(loaded_game_file_version) >= kGameVersion_262) { // Version 2.6.2+
48 		if (xxx >= _GP(thisroom).RegionMask->GetWidth())
49 			xxx = _GP(thisroom).RegionMask->GetWidth() - 1;
50 		if (yyy >= _GP(thisroom).RegionMask->GetHeight())
51 			yyy = _GP(thisroom).RegionMask->GetHeight() - 1;
52 		if (xxx < 0)
53 			xxx = 0;
54 		if (yyy < 0)
55 			yyy = 0;
56 	}
57 
58 	int hsthere = _GP(thisroom).RegionMask->GetPixel(xxx, yyy);
59 	if (hsthere <= 0 || hsthere >= MAX_ROOM_REGIONS) return 0;
60 	if (_G(croom)->region_enabled[hsthere] == 0) return 0;
61 	return hsthere;
62 }
63 
SetAreaLightLevel(int area,int brightness)64 void SetAreaLightLevel(int area, int brightness) {
65 	if ((area < 0) || (area > MAX_ROOM_REGIONS))
66 		quit("!SetAreaLightLevel: invalid region");
67 	if (brightness < -100) brightness = -100;
68 	if (brightness > 100) brightness = 100;
69 	_GP(thisroom).Regions[area].Light = brightness;
70 	// disable RGB tint for this area
71 	_GP(thisroom).Regions[area].Tint = 0;
72 	debug_script_log("Region %d light level set to %d", area, brightness);
73 }
74 
SetRegionTint(int area,int red,int green,int blue,int amount,int luminance)75 void SetRegionTint(int area, int red, int green, int blue, int amount, int luminance) {
76 	if ((area < 0) || (area > MAX_ROOM_REGIONS))
77 		quit("!SetRegionTint: invalid region");
78 
79 	if ((red < 0) || (red > 255) || (green < 0) || (green > 255) ||
80 	        (blue < 0) || (blue > 255)) {
81 		quit("!SetRegionTint: RGB values must be 0-255");
82 	}
83 
84 	// originally the value was passed as 0
85 	// TODO: find out which versions had this; fixup only for past versions in the future!
86 	if (amount == 0)
87 		amount = 100;
88 
89 	if ((amount < 1) || (amount > 100))
90 		quit("!SetRegionTint: amount must be 1-100");
91 	if ((luminance < 0) || (luminance > 100))
92 		quit("!SetRegionTint: luminance must be 0-100");
93 
94 	debug_script_log("Region %d tint set to %d,%d,%d", area, red, green, blue);
95 
96 	/*red -= 100;
97 	green -= 100;
98 	blue -= 100;*/
99 
100 	_GP(thisroom).Regions[area].Tint = (red & 0xFF) |
101 	                                   ((green & 0xFF) << 8) |
102 	                                   ((blue & 0XFF) << 16) |
103 	                                   ((amount & 0xFF) << 24);
104 	_GP(thisroom).Regions[area].Light = (luminance * 25) / 10;
105 }
106 
DisableRegion(int hsnum)107 void DisableRegion(int hsnum) {
108 	if ((hsnum < 0) || (hsnum >= MAX_ROOM_REGIONS))
109 		quit("!DisableRegion: invalid region specified");
110 
111 	_G(croom)->region_enabled[hsnum] = 0;
112 	debug_script_log("Region %d disabled", hsnum);
113 }
114 
EnableRegion(int hsnum)115 void EnableRegion(int hsnum) {
116 	if ((hsnum < 0) || (hsnum >= MAX_ROOM_REGIONS))
117 		quit("!EnableRegion: invalid region specified");
118 
119 	_G(croom)->region_enabled[hsnum] = 1;
120 	debug_script_log("Region %d enabled", hsnum);
121 }
122 
DisableGroundLevelAreas(int alsoEffects)123 void DisableGroundLevelAreas(int alsoEffects) {
124 	if ((alsoEffects < 0) || (alsoEffects > 1))
125 		quit("!DisableGroundLevelAreas: invalid parameter: must be 0 or 1");
126 
127 	_GP(play).ground_level_areas_disabled = GLED_INTERACTION;
128 
129 	if (alsoEffects)
130 		_GP(play).ground_level_areas_disabled |= GLED_EFFECTS;
131 
132 	debug_script_log("Ground-level areas disabled");
133 }
134 
EnableGroundLevelAreas()135 void EnableGroundLevelAreas() {
136 	_GP(play).ground_level_areas_disabled = 0;
137 
138 	debug_script_log("Ground-level areas re-enabled");
139 }
140 
RunRegionInteraction(int regnum,int mood)141 void RunRegionInteraction(int regnum, int mood) {
142 	if ((regnum < 0) || (regnum >= MAX_ROOM_REGIONS))
143 		quit("!RunRegionInteraction: invalid region speicfied");
144 	if ((mood < 0) || (mood > 2))
145 		quit("!RunRegionInteraction: invalid event specified");
146 
147 	// We need a backup, because region interactions can run
148 	// while another interaction (eg. hotspot) is in a Wait
149 	// command, and leaving our basename would call the wrong
150 	// script later on
151 	const char *oldbasename = _G(evblockbasename);
152 	int   oldblocknum = _G(evblocknum);
153 
154 	_G(evblockbasename) = "region%d";
155 	_G(evblocknum) = regnum;
156 
157 	if (_GP(thisroom).Regions[regnum].EventHandlers != nullptr) {
158 		run_interaction_script(_GP(thisroom).Regions[regnum].EventHandlers.get(), mood);
159 	} else {
160 		run_interaction_event(&_G(croom)->intrRegion[regnum], mood);
161 	}
162 
163 	_G(evblockbasename) = oldbasename;
164 	_G(evblocknum) = oldblocknum;
165 }
166 
167 } // namespace AGS3
168