1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14 
15 #include "ac/global_room.h"
16 #include "ac/common.h"
17 #include "ac/character.h"
18 #include "ac/characterinfo.h"
19 #include "ac/draw.h"
20 #include "ac/event.h"
21 #include "ac/gamesetupstruct.h"
22 #include "ac/gamestate.h"
23 #include "ac/global_character.h"
24 #include "ac/global_game.h"
25 #include "ac/movelist.h"
26 #include "ac/properties.h"
27 #include "ac/room.h"
28 #include "ac/roomstatus.h"
29 #include "debug/debug_log.h"
30 #include "debug/debugger.h"
31 #include "script/script.h"
32 #include "util/math.h"
33 
34 using namespace Common;
35 
36 extern GameState play;
37 extern GameSetupStruct game;
38 extern RoomStatus *croom;
39 extern CharacterInfo*playerchar;
40 extern int displayed_room;
41 extern int in_enters_screen;
42 extern int in_leaves_screen;
43 extern int in_inv_screen, inv_screen_newroom;
44 extern MoveList *mls;
45 extern int gs_to_newroom;
46 extern roomstruct thisroom;
47 
SetAmbientTint(int red,int green,int blue,int opacity,int luminance)48 void SetAmbientTint (int red, int green, int blue, int opacity, int luminance) {
49     if ((red < 0) || (green < 0) || (blue < 0) ||
50         (red > 255) || (green > 255) || (blue > 255) ||
51         (opacity < 0) || (opacity > 100) ||
52         (luminance < 0) || (luminance > 100))
53         quit("!SetTint: invalid parameter. R,G,B must be 0-255, opacity & luminance 0-100");
54 
55     debug_script_log("Set ambient tint RGB(%d,%d,%d) %d%%", red, green, blue, opacity);
56 
57     play.rtint_enabled = opacity > 0;
58     play.rtint_red = red;
59     play.rtint_green = green;
60     play.rtint_blue = blue;
61     play.rtint_level = opacity;
62     play.rtint_light = (luminance * 25) / 10;
63 }
64 
SetAmbientLightLevel(int light_level)65 void SetAmbientLightLevel(int light_level)
66 {
67     light_level = Math::Clamp(-100, 100, light_level);
68 
69     play.rtint_enabled = light_level != 0;
70     play.rtint_level = 0;
71     play.rtint_light = light_level;
72 }
73 
74 extern ScriptPosition last_in_dialog_request_script_pos;
NewRoom(int nrnum)75 void NewRoom(int nrnum) {
76     if (nrnum < 0)
77         quitprintf("!NewRoom: room change requested to invalid room number %d.", nrnum);
78 
79     if (displayed_room < 0) {
80         // called from game_start; change the room where the game will start
81         playerchar->room = nrnum;
82         return;
83     }
84 
85 
86     debug_script_log("Room change requested to room %d", nrnum);
87     EndSkippingUntilCharStops();
88 
89     can_run_delayed_command();
90 
91     if (play.stop_dialog_at_end != DIALOG_NONE) {
92         if (play.stop_dialog_at_end == DIALOG_RUNNING)
93             play.stop_dialog_at_end = DIALOG_NEWROOM + nrnum;
94         else {
95             quitprintf("!NewRoom: two NewRoom/RunDialog/StopDialog requests within dialog; last was called in \"%s\", line %d",
96                 last_in_dialog_request_script_pos.Section.GetCStr(), last_in_dialog_request_script_pos.Line);
97         }
98         return;
99     }
100 
101     get_script_position(last_in_dialog_request_script_pos);
102 
103     if (in_leaves_screen >= 0) {
104         // NewRoom called from the Player Leaves Screen event -- just
105         // change which room it will go to
106         in_leaves_screen = nrnum;
107     }
108     else if (in_enters_screen) {
109         setevent(EV_NEWROOM,nrnum);
110         return;
111     }
112     else if (in_inv_screen) {
113         inv_screen_newroom = nrnum;
114         return;
115     }
116     else if ((inside_script==0) & (in_graph_script==0)) {
117         new_room(nrnum,playerchar);
118         return;
119     }
120     else if (inside_script) {
121         curscript->queue_action(ePSANewRoom, nrnum, "NewRoom");
122         // we might be within a MoveCharacterBlocking -- the room
123         // change should abort it
124         if ((playerchar->walking > 0) && (playerchar->walking < TURNING_AROUND)) {
125             // nasty hack - make sure it doesn't move the character
126             // to a walkable area
127             mls[playerchar->walking].direct = 1;
128             StopMoving(game.playercharacter);
129         }
130     }
131     else if (in_graph_script)
132         gs_to_newroom = nrnum;
133 }
134 
135 
NewRoomEx(int nrnum,int newx,int newy)136 void NewRoomEx(int nrnum,int newx,int newy) {
137     Character_ChangeRoom(playerchar, nrnum, newx, newy);
138 }
139 
NewRoomNPC(int charid,int nrnum,int newx,int newy)140 void NewRoomNPC(int charid, int nrnum, int newx, int newy) {
141     if (!is_valid_character(charid))
142         quit("!NewRoomNPC: invalid character");
143     if (charid == game.playercharacter)
144         quit("!NewRoomNPC: use NewRoomEx with the player character");
145 
146     Character_ChangeRoom(&game.chars[charid], nrnum, newx, newy);
147 }
148 
ResetRoom(int nrnum)149 void ResetRoom(int nrnum) {
150     if (nrnum == displayed_room)
151         quit("!ResetRoom: cannot reset current room");
152     if ((nrnum<0) | (nrnum>=MAX_ROOMS))
153         quit("!ResetRoom: invalid room number");
154 
155     if (isRoomStatusValid(nrnum))
156     {
157         RoomStatus* roomstat = getRoomStatus(nrnum);
158         roomstat->FreeScriptData();
159         roomstat->FreeProperties();
160         roomstat->beenhere = 0;
161     }
162 
163     debug_script_log("Room %d reset to original state", nrnum);
164 }
165 
HasPlayerBeenInRoom(int roomnum)166 int HasPlayerBeenInRoom(int roomnum) {
167     if ((roomnum < 0) || (roomnum >= MAX_ROOMS))
168         return 0;
169     if (isRoomStatusValid(roomnum))
170         return getRoomStatus(roomnum)->beenhere;
171     else
172         return 0;
173 }
174 
CallRoomScript(int value)175 void CallRoomScript (int value) {
176     can_run_delayed_command();
177 
178     if (!inside_script)
179         quit("!CallRoomScript: not inside a script???");
180 
181     play.roomscript_finished = 0;
182     RuntimeScriptValue rval_null;
183     curscript->run_another("on_call", kScInstRoom, 1, RuntimeScriptValue().SetInt32(value), rval_null);
184 }
185 
HasBeenToRoom(int roomnum)186 int HasBeenToRoom (int roomnum) {
187     if ((roomnum < 0) || (roomnum >= MAX_ROOMS))
188         quit("!HasBeenToRoom: invalid room number specified");
189 
190     if (isRoomStatusValid(roomnum))
191         return getRoomStatus(roomnum)->beenhere;
192     else
193         return 0;
194 }
195 
GetRoomPropertyText(const char * property,char * bufer)196 void GetRoomPropertyText (const char *property, char *bufer)
197 {
198     get_text_property(thisroom.roomProps, croom->roomProps, property, bufer);
199 }
200 
SetBackgroundFrame(int frnum)201 void SetBackgroundFrame(int frnum) {
202     if ((frnum<-1) | (frnum>=thisroom.num_bscenes))
203         quit("!SetBackgrondFrame: invalid frame number specified");
204     if (frnum<0) {
205         play.bg_frame_locked=0;
206         return;
207     }
208 
209     play.bg_frame_locked = 1;
210 
211     if (frnum == play.bg_frame)
212     {
213         // already on this frame, do nothing
214         return;
215     }
216 
217     play.bg_frame = frnum;
218     on_background_frame_change ();
219 }
220 
GetBackgroundFrame()221 int GetBackgroundFrame() {
222     return play.bg_frame;
223 }
224