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 #ifndef NUVIE_USECODE_USECODE_H
24 #define NUVIE_USECODE_USECODE_H
25 
26 #include "ultima/shared/std/string.h"
27 #include "ultima/nuvie/misc/call_back.h"
28 #include "ultima/nuvie/misc/map_entity.h"
29 #include "ultima/nuvie/core/obj_manager.h"
30 #include "ultima/nuvie/core/player.h"
31 
32 namespace Ultima {
33 namespace Nuvie {
34 
35 // The game triggers one of these events on an object to activate its UseCode
36 // function(s). The return value meaning is different for each event.
37 #define USE_EVENT_USE     0x01 /* return value undefined */
38 #define USE_EVENT_LOOK    0x02 /* true: allow search, false: disallow search */
39 #define USE_EVENT_PASS    0x04 /* true: do normal move, false: object blocks */
40 #define USE_EVENT_MESSAGE 0x08 /* internal message or data return */
41 #define USE_EVENT_SEARCH  0x10 /*undefined (true = had objects?); might remove*/
42 //#define USE_EVENT_ON      0x20 /* post-move/idle */
43 #define USE_EVENT_MOVE    0x40 /* true: move object, false: don't move object */
44 #define USE_EVENT_LOAD    0x80 /* return value undefined */
45 #define USE_EVENT_READY   0x0100 /* true: object may be equipped */
46 #define USE_EVENT_GET     0x0200 /* true: do normal get */
47 #define USE_EVENT_DROP    0x0400 /* true: do normal drop */
48 #define USE_EVENT_INPUT_CANCEL 0x501 /* note this shares a bit with USE_EVENT_USE so it can pass through uc_event(). return undefined */
49 //#define USE_EVENT_NEAR    0x00 /* mirrors; might use ON with distance val */
50 //#define USE_EVENT_ATTACK  0x00 /* doors, chests, mirrors */
51 //#define USE_EVENT_ENTER   0x00 /* object enters view (clocks) */
52 //#define USE_EVENT_LEAVE   0x00 /* object leaves view */
53 
54 typedef uint16 UseCodeEvent;
55 
56 /* Events:
57  * USE
58  * Returns: undefined
59  * Use the object.
60  * actor_ref - the actor using it (the player actor typically)
61  *
62  * PASS (Quest Barrier)
63  * Returns: True if actor may move, False if object blocks
64  * Called when an actor attempts to step onto an object.
65  * actor_ref - actor trying to pass
66  * mapcoord_ref - location the actor is trying to pass (for multi-tile objects)
67  *
68  * LOOK (signs)
69  * Returns: True if an object can be searched
70  * Called when someone looks at the object. Some objects aren't searched (books
71  * for example) and should return false.
72  *
73  * MESSAGE (fumaroles, earthquakes?, powder kegs, clocks)
74  * An internal event from the engine. It must have been previously requested.
75  * Includes TIMED events, and DATA returns. Be careful that the object still
76  * exists.
77  *
78  * MOVE (cannons)
79  * Returns: True to push object to the new position
80  * Use this to perform special move functions for some objects. A cannon can be
81  * aimed with MOVE.
82  * mapcoord_ref - target location
83  *
84  * (UN)LOAD unimplemented (fumaroles)
85  * Returns: undefined
86  * Called when the object is cached in or out (or when it would have been in the
87  * original game... about 16 to 32 spaces away), and when new objects are created.
88  * It can be used to start timers, or to hatch eggs.
89  *
90  * Actor NEAR unimplemented (mirrors)
91  * Set something to happen when an actor moves close to or away from object.
92  * Distance will be used.
93  *
94  * Actor ON (chairs, traps) unimplemented
95  * Returns: undefined
96  * Called each turn for any objects in the view-area with actors standing on
97  * them.
98  *
99  * ENTER view-area unimplemented
100  *
101  * LEAVE view-area unimplemented
102  * Enter and leave will be used to start and stop sound effects. Distance will
103  * be used.
104  *
105  * (UN)READY (Amulet of Submission)
106  * Returns: True if the object may be worn, or removed
107  * This is called before the object is is equipped or removed. Check the
108  * object's flags to determine if it is being equipped or not. (if its readied
109  * flag is set it is being removed). Special un/ready functions can be created
110  * with this.
111  * actor_ref - the actor un/readying it
112  *
113  * ATTACK (doors, chests)
114  *
115  * DROP (breakables, torches)
116  * Returns: True to allow normal drop at the target.
117  * Special drop functions can be created with this.
118  * actor_ref - the actor dropping it
119  * mapcoord_ref - the desired drop target
120  *
121  * GET (torches, runes?)
122  * Returns: True if the actor can get the object.
123  * Special get functions can be created with this.
124  * actor_ref - the actor getting it
125  *
126  * SEARCH (graves, secret doors)
127  * Returns: True if the object contained other objects.
128  * FIXME: might remove this and add as a player action
129  *
130  */
131 
132 typedef enum {
133 	USE,
134 	GET,
135 	MOVE
136 } UseCodeType;
137 
138 const char *useCodeTypeToString(UseCodeType type);
139 
140 class ActorManager;
141 class Configuration;
142 class Events;
143 class Game;
144 class Map;
145 class MsgScroll;
146 class MapCoord;
147 class Party;
148 class Player;
149 class Script;
150 class ScriptThread;
151 
152 class UseCode {
153 private:
154 	ScriptThread *script_thread;
155 
156 protected:
157 	Game *game;
158 	Configuration *config;
159 	ObjManager *obj_manager;
160 	Map *map;
161 	Player *player;
162 	MsgScroll *scroll;
163 	ActorManager *actor_manager;
164 	Party *party;
165 	Script *script;
166 
167 // pass parameters to usecode functions via items (NULL itemref is unset)
168 	struct {
169 		uint32 *uint_ref;
170 		sint32 *sint_ref;
171 		Obj *obj_ref;
172 		Actor *actor_ref, *actor2_ref;
173 		MapCoord *mapcoord_ref;
174 		CallbackMessage *msg_ref;
175 		Std::string *string_ref;
176 		MapEntity *ent_ref;
177 		char *data_ref;
178 	} items;
179 	void clear_items();
180 
181 public:
182 
183 	UseCode(Game *g, Configuration *cfg);
184 	virtual ~UseCode();
185 
186 	virtual bool init(ObjManager *om, Map *m, Player *p, MsgScroll *ms);
187 
188 	bool use_obj(uint16 x, uint16 y, uint8 z, Obj *src_obj = NULL);
189 	bool use_obj(Obj *obj, Obj *src_obj = NULL) {
190 		return (use_obj(obj, player->get_actor()));    // ??
191 	}
192 
193 	virtual bool use_obj(Obj *obj, Actor *actor);
look_obj(Obj * obj,Actor * actor)194 	virtual bool look_obj(Obj *obj, Actor *actor)   {
195 		return (false);
196 	}
pass_obj(Obj * obj,Actor * actor,uint16 x,uint16 y)197 	virtual bool pass_obj(Obj *obj, Actor *actor, uint16 x, uint16 y) {
198 		return (false);
199 	}
search_obj(Obj * obj,Actor * actor)200 	virtual bool search_obj(Obj *obj, Actor *actor) {
201 		return (false);
202 	}
203 	virtual bool move_obj(Obj *obj, sint16 rel_x, sint16 rel_y);
load_obj(Obj * obj)204 	virtual bool load_obj(Obj *obj)                 {
205 		return (false);
206 	}
message_obj(Obj * obj,CallbackMessage msg,void * msg_data)207 	virtual bool message_obj(Obj *obj, CallbackMessage msg, void *msg_data) {
208 		return (false);
209 	}
210 	virtual bool ready_obj(Obj *obj, Actor *actor);
get_obj(Obj * obj,Actor * actor)211 	virtual bool get_obj(Obj *obj, Actor *actor)    {
212 		return (false);
213 	}
214 	virtual bool drop_obj(Obj *obj, Actor *actor, uint16 x, uint16 y, uint16 qty = 0) {
215 		return (false);
216 	}
217 
218 	virtual bool has_usecode(Obj *obj, UseCodeEvent ev = USE_EVENT_USE);
219 	virtual bool has_usecode(Actor *actor, UseCodeEvent ev = USE_EVENT_USE)  {
220 		return (false);
221 	}
has_lookcode(Obj * obj)222 	virtual bool has_lookcode(Obj *obj) {
223 		return (has_usecode(obj, USE_EVENT_LOOK));
224 	}
has_passcode(Obj * obj)225 	virtual bool has_passcode(Obj *obj) {
226 		return (has_usecode(obj, USE_EVENT_PASS));
227 	}
has_movecode(Obj * obj)228 	virtual bool has_movecode(Obj *obj) {
229 		return (has_usecode(obj, USE_EVENT_MOVE));
230 	}
has_loadcode(Obj * obj)231 	virtual bool has_loadcode(Obj *obj) {
232 		return (has_usecode(obj, USE_EVENT_LOAD));
233 	}
has_readycode(Obj * obj)234 	virtual bool has_readycode(Obj *obj) {
235 		return (has_usecode(obj, USE_EVENT_READY));
236 	}
cannot_unready(Obj * obj)237 	virtual bool cannot_unready(Obj *obj) {
238 		return false;
239 	}
has_getcode(Obj * obj)240 	virtual bool has_getcode(Obj *obj)  {
241 		return (has_usecode(obj, USE_EVENT_GET));
242 	}
has_dropcode(Obj * obj)243 	virtual bool has_dropcode(Obj *obj) {
244 		return (has_usecode(obj, USE_EVENT_DROP));
245 	}
246 
is_door(Obj * obj)247 	bool is_door(Obj *obj) {
248 		return (is_locked_door(obj) || is_unlocked_door(obj));
249 	}
is_locked_door(Obj * obj)250 	virtual bool is_locked_door(Obj *obj)   {
251 		return (false);
252 	}
is_unlocked_door(Obj * obj)253 	virtual bool is_unlocked_door(Obj *obj) {
254 		return (false);
255 	}
is_closed_door(Obj * obj)256 	virtual bool is_closed_door(Obj *obj)   {
257 		return (false);
258 	}
process_effects(Obj * container_obj,Actor * actor)259 	virtual bool process_effects(Obj *container_obj, Actor *actor) {
260 		return (false);
261 	}
is_food(Obj * obj)262 	virtual bool is_food(Obj *obj)          {
263 		return (false);
264 	}
265 	virtual bool is_container(Obj *obj);
is_container(uint16 obj_n,uint8 frame_n)266 	virtual bool is_container(uint16 obj_n, uint8 frame_n) {
267 		return (false);
268 	}
is_readable(Obj * obj)269 	virtual bool is_readable(Obj *obj)      {
270 		return (false);
271 	}
is_chest(Obj * obj)272 	virtual bool is_chest(Obj *obj)         {
273 		return (false);
274 	}
275 
set_itemref(sint32 * val)276 	void set_itemref(sint32 *val) {
277 		items.sint_ref = val;
278 	}
set_itemref(Obj * val)279 	void set_itemref(Obj *val)   {
280 		items.obj_ref = val;
281 	}
282 	void set_itemref(Actor *val, Actor *val2 = NULL) {
283 		items.actor_ref = val;
284 		items.actor2_ref = val2;
285 	}
set_itemref(MapCoord * val)286 	void set_itemref(MapCoord *val)   {
287 		items.mapcoord_ref = val;
288 	}
289 
290 	Obj *get_obj_from_container(Obj *obj);
291 	bool search_container(Obj *obj, bool show_string = true);
292 	Obj *destroy_obj(Obj *obj, uint32 count = 0, bool run_usecode = true);
293 	bool out_of_use_range(Obj *obj, bool check_enemies);
294 
295 	ScriptThread *get_running_script();
296 	bool is_script_running();
297 
298 protected:
299 
300 	void toggle_frame(Obj *obj);
301 	void dbg_print_event(UseCodeEvent event, Obj *obj);
302 
303 };
304 
305 } // End of namespace Nuvie
306 } // End of namespace Ultima
307 
308 #endif
309