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  * Based on the original sources
23  *   Faery Tale II -- The Halls of the Dead
24  *   (c) 1993-1996 The Wyrmkeep Entertainment Co.
25  */
26 
27 #ifndef SAGA2_SENSOR_H
28 #define SAGA2_SENSOR_H
29 
30 namespace Saga2 {
31 
32 const uint32 nonActorSenseFlags = actorSeeInvis;
33 
34 //const size_t maxSensorSize = 24;
35 const size_t maxSensorSize = 48;
36 
37 //  This constant represents the maximum sense range for an object.
38 //  Zero means an infinite range.
39 const int16 maxSenseRange = 0;
40 
41 //  Integers representing sensor types
42 enum SensorType {
43 	protaganistSensor,
44 	specificObjectSensor,
45 	objectPropertySensor,
46 	specificActorSensor,
47 	actorPropertySensor,
48 	eventSensor
49 };
50 
51 //  Sensors will be checked every 5 frames
52 const int16 sensorCheckRate = 5;
53 
54 /* ===================================================================== *
55    Function prototypes
56  * ===================================================================== */
57 
58 struct GameEvent;
59 
60 //  Allocate a new SensorList
61 void newSensorList(SensorList *s);
62 //  Deallocate an SensorList
63 void deleteSensorList(SensorList *p);
64 
65 //  Fetch a specified object's SensorList
66 SensorList *fetchSensorList(GameObject *obj);
67 
68 //  Allocate a new Sensor
69 void newSensor(Sensor *s);
70 //  Allocate a new Sensor with a specified starting check counter
71 void newSensor(Sensor *s, int16 ctr);
72 //  Deallocate a Sensor
73 void deleteSensor(Sensor *p);
74 
75 //  Check all active sensors
76 void checkSensors(void);
77 //  Evaluate an event for all active sensors
78 void assertEvent(const GameEvent &ev);
79 
80 //  Initialize the sensors
81 void initSensors(void);
82 void saveSensors(Common::OutSaveFile *outS);
83 void loadSensors(Common::InSaveFile *in);
84 //  Cleanup the active sensors
85 void cleanupSensors(void);
86 
87 /* ===================================================================== *
88    GameEvent struct
89  * ===================================================================== */
90 
91 struct GameEvent {
92 	int16           type;
93 	GameObject      *directObject,
94 	                *indirectObject;
95 };
96 
97 /* ===================================================================== *
98    SenseInfo struct
99  * ===================================================================== */
100 
101 struct SenseInfo {
102 	GameObject      *sensedObject;
103 };
104 
105 /* ===================================================================== *
106    SensorList Class
107  * ===================================================================== */
108 
109 class SensorList {
110 	GameObject      *obj;
111 
112 public:
113 	Common::List<Sensor *> _list;
114 
115 public:
116 	//  Constructor -- initial construction
SensorList(GameObject * o)117 	SensorList(GameObject *o) : obj(o) {
118 		newSensorList(this);
119 		debugC(1, kDebugSensors, "Adding SensorList %p to %d (%s) (total %d)",
120 		       (void *)this, o->thisID(), o->objName(), _list.size());
121 	}
122 
~SensorList()123 	~SensorList() {
124 		deleteSensorList(this);
125 		debugC(1, kDebugSensors, "Deleting SensorList %p of %d (%s) (total %d)",
126 		       (void *)this, obj->thisID(), obj->objName(), _list.size());
127 	}
128 
129 	SensorList(Common::InSaveFile *in);
130 
131 	//  Return the number of bytes needed to archive this object in
132 	//  a buffer
archiveSize(void)133 	static int32 archiveSize(void) {
134 		return sizeof(ObjectID);
135 	}
136 
137 	void write(Common::MemoryWriteStreamDynamic *out);
138 
getObject(void)139 	GameObject *getObject(void) {
140 		return obj;
141 	}
142 };
143 
144 /* ===================================================================== *
145    Sensor Class
146  * ===================================================================== */
147 
148 class Sensor {
149 public:
150 	GameObject      *obj;
151 	SensorID        id;
152 	int16           range;
153 
154 	int16       checkCtr;
155 	bool _active;
156 
157 public:
158 	//  Constructor -- initial construction
Sensor(GameObject * o,SensorID sensorID,int16 rng)159 	Sensor(GameObject *o, SensorID sensorID, int16 rng) : obj(o), id(sensorID), range(rng), _active(true) {
160 		newSensor(this);
161 		SensorList *sl = fetchSensorList(o);
162 		debugC(1, kDebugSensors, "Adding Sensor %p to %d (%s) (list = %p, total = %d)",
163 		       (void *)this, o->thisID(), o->objName(), (void *)sl, (sl != nullptr) ? sl->_list.size() : -1);
164 	}
165 
166 	Sensor(Common::InSaveFile *in, int16 ctr);
167 
168 	//  Virtural destructor
~Sensor(void)169 	virtual ~Sensor(void) {
170 		deleteSensor(this);
171 		SensorList *sl = fetchSensorList(obj);
172 		debugC(1, kDebugSensors, "Deleting Sensor %p of %d (%s) (list = %p, total = %d)",
173 		       (void *)this, obj->thisID(), obj->objName(), (void *)sl, (sl != nullptr) ? sl->_list.size() : -1);
174 	}
175 
176 	virtual void write(Common::MemoryWriteStreamDynamic *out);
177 
178 	//  Return an integer representing the type of this sensor
179 	virtual int16 getType(void) = 0;
180 
getObject(void)181 	GameObject *getObject(void) {
182 		return obj;
183 	}
thisID(void)184 	SensorID thisID(void) {
185 		return id;
186 	}
getRange(void)187 	int16 getRange(void) {
188 		return range;
189 	}
190 
191 	//  Determine if the object can sense what it's looking for
192 	virtual bool check(SenseInfo &info, uint32 senseFlags) = 0;
193 
194 	//  Evaluate an event to determine if the object is waiting for it
195 	virtual bool evaluateEvent(const GameEvent &event) = 0;
196 };
197 
198 /* ===================================================================== *
199    ProtaganistSensor Class
200  * ===================================================================== */
201 
202 class ProtaganistSensor : public Sensor {
203 public:
204 	//  Constructor -- initial construction
ProtaganistSensor(GameObject * o,SensorID sensorID,int16 rng)205 	ProtaganistSensor(GameObject *o, SensorID sensorID, int16 rng) :
206 		Sensor(o, sensorID, rng) {
207 	}
208 
ProtaganistSensor(Common::InSaveFile * in,int16 ctr)209 	ProtaganistSensor(Common::InSaveFile *in, int16 ctr) : Sensor(in, ctr) {
210 		debugC(3, kDebugSaveload, "Loading ProtagonistSensor");
211 	}
212 
213 	//  Return an integer representing the type of this sensor
214 	int16 getType(void);
215 
216 	//  Determine if the object can sense what it's looking for
217 	bool check(SenseInfo &info, uint32 senseFlags);
218 
219 	//  Evaluate an event to determine if the object is waiting for it
220 	bool evaluateEvent(const GameEvent &event);
221 };
222 
223 /* ===================================================================== *
224    ObjectSensor Class
225  * ===================================================================== */
226 
227 class ObjectSensor : public Sensor {
228 public:
229 	//  Constructor -- initial construction
ObjectSensor(GameObject * o,SensorID sensorID,int16 rng)230 	ObjectSensor(GameObject *o, SensorID sensorID, int16 rng) :
231 		Sensor(o, sensorID, rng) {
232 	}
233 
ObjectSensor(Common::InSaveFile * in,int16 ctr)234 	ObjectSensor(Common::InSaveFile *in, int16 ctr) : Sensor(in, ctr) {}
235 
236 	//  Determine if the object can sense what it's looking for
237 	bool check(SenseInfo &info, uint32 senseFlags);
238 
239 	//  Evaluate an event to determine if the object is waiting for it
240 	bool evaluateEvent(const GameEvent &event);
241 
242 private:
243 	//  Determine if an object meets the search criteria
244 	virtual bool isObjectSought(GameObject *obj) = 0;
245 };
246 
247 /* ===================================================================== *
248    SpecificObjectSensor Class
249  * ===================================================================== */
250 
251 class SpecificObjectSensor : public ObjectSensor {
252 	ObjectID        soughtObjID;
253 
254 public:
255 	//  Constructor -- initial construction
SpecificObjectSensor(GameObject * o,SensorID sensorID,int16 rng,ObjectID objToSense)256 	SpecificObjectSensor(
257 	    GameObject  *o,
258 	    SensorID    sensorID,
259 	    int16       rng,
260 	    ObjectID    objToSense) :
261 		ObjectSensor(o, sensorID, rng),
262 		soughtObjID(objToSense) {
263 	}
264 
265 	SpecificObjectSensor(Common::InSaveFile *in, int16 ctr);
266 
267 	//  Return the number of bytes needed to archive this object in
268 	//  a buffer
269 	int32 archiveSize(void);
270 
271 	void write(Common::MemoryWriteStreamDynamic *out);
272 
273 	//  Return an integer representing the type of this sensor
274 	int16 getType(void);
275 
276 	//  Determine if the object can sense what it's looking for
277 	bool check(SenseInfo &info, uint32 senseFlags);
278 
279 private:
280 	//  Determine if an object meets the search criteria
281 	bool isObjectSought(GameObject *obj);
282 };
283 
284 /* ===================================================================== *
285    ObjectPropertySensor Class
286  * ===================================================================== */
287 
288 class ObjectPropertySensor : public ObjectSensor {
289 	ObjectPropertyID    objectProperty;
290 
291 public:
292 	//  Constructor -- initial construction
ObjectPropertySensor(GameObject * o,SensorID sensorID,int16 rng,ObjectPropertyID propToSense)293 	ObjectPropertySensor(
294 	    GameObject          *o,
295 	    SensorID            sensorID,
296 	    int16               rng,
297 	    ObjectPropertyID    propToSense) :
298 		ObjectSensor(o, sensorID, rng),
299 		objectProperty(propToSense) {
300 	}
301 
302 	ObjectPropertySensor(Common::InSaveFile *in, int16 ctr);
303 
304 	//  Return the number of bytes needed to archive this object in
305 	//  a buffer
306 	int32 archiveSize(void);
307 
308 	void write(Common::MemoryWriteStreamDynamic *out);
309 
310 	//  Return an integer representing the type of this sensor
311 	int16 getType(void);
312 
313 private:
314 	//  Determine if an object meets the search criteria
315 	bool isObjectSought(GameObject *obj);
316 };
317 
318 /* ===================================================================== *
319    ActorSensor Class
320  * ===================================================================== */
321 
322 class ActorSensor : public ObjectSensor {
323 public:
324 	//  Constructor -- initial construction
ActorSensor(GameObject * o,SensorID sensorID,int16 rng)325 	ActorSensor(GameObject *o, SensorID sensorID, int16 rng) :
326 		ObjectSensor(o, sensorID, rng) {
327 	}
328 
ActorSensor(Common::InSaveFile * in,int16 ctr)329 	ActorSensor(Common::InSaveFile *in, int16 ctr) : ObjectSensor(in, ctr) {}
330 
331 private:
332 	//  Determine if an object meets the search criteria
333 	bool isObjectSought(GameObject *obj);
334 
335 	//  Determine if an actor meets the search criteria
336 	virtual bool isActorSought(Actor *a) = 0;
337 };
338 
339 /* ===================================================================== *
340    SpecificActorSensor Class
341  * ===================================================================== */
342 
343 class SpecificActorSensor : public ActorSensor {
344 	Actor       *soughtActor;
345 
346 public:
347 	//  Constructor -- initial construction
SpecificActorSensor(GameObject * o,SensorID sensorID,int16 rng,Actor * actorToSense)348 	SpecificActorSensor(
349 	    GameObject  *o,
350 	    SensorID    sensorID,
351 	    int16       rng,
352 	    Actor       *actorToSense) :
353 		ActorSensor(o, sensorID, rng),
354 		soughtActor(actorToSense) {
355 	}
356 
357 	SpecificActorSensor(Common::InSaveFile *in, int16 ctr);
358 
359 	//  Return the number of bytes needed to archive this object in
360 	//  a buffer
361 	int32 archiveSize(void);
362 
363 	void write(Common::MemoryWriteStreamDynamic *out);
364 
365 	//  Return an integer representing the type of this sensor
366 	int16 getType(void);
367 
368 	//  Determine if the object can sense what it's looking for
369 	bool check(SenseInfo &info, uint32 senseFlags);
370 
371 private:
372 	//  Determine if an actor meets the search criteria
373 	bool isActorSought(Actor *a);
374 };
375 
376 /* ===================================================================== *
377    ActorPropertySensor Class
378  * ===================================================================== */
379 
380 class ActorPropertySensor : public ActorSensor {
381 	ActorPropertyID     actorProperty;
382 
383 public:
384 	//  Constructor -- initial construction
ActorPropertySensor(GameObject * o,SensorID sensorID,int16 rng,ActorPropertyID propToSense)385 	ActorPropertySensor(
386 	    GameObject          *o,
387 	    SensorID            sensorID,
388 	    int16               rng,
389 	    ActorPropertyID     propToSense) :
390 		ActorSensor(o, sensorID, rng),
391 		actorProperty(propToSense) {
392 	}
393 
394 	ActorPropertySensor(Common::InSaveFile *in, int16 ctr);
395 
396 	//  Return the number of bytes needed to archive this object in
397 	//  a buffer
398 	int32 archiveSize(void);
399 
400 	void write(Common::MemoryWriteStreamDynamic *out);
401 
402 	//  Return an integer representing the type of this sensor
403 	int16 getType(void);
404 
405 private:
406 	//  Determine if an actor meets the search criteria
407 	bool isActorSought(Actor *a);
408 };
409 
410 /* ===================================================================== *
411    EventSensor Class
412  * ===================================================================== */
413 
414 class EventSensor : public Sensor {
415 	int16               eventType;
416 
417 public:
418 	//  Constructor -- initial construction
419 	EventSensor(
420 	    GameObject      *o,
421 	    SensorID        sensorID,
422 	    int16           rng,
423 	    int16           type);
424 
425 	EventSensor(Common::InSaveFile *in, int16 ctr);
426 
427 	//  Return the number of bytes needed to archive this object in
428 	//  a buffer
429 	int32 archiveSize(void);
430 
431 	void write(Common::MemoryWriteStreamDynamic *out);
432 
433 	//  Return an integer representing the type of this sensor
434 	int16 getType(void);
435 
436 	//  Determine if the object can sense what it's looking for
437 	bool check(SenseInfo &info, uint32 senseFlags);
438 
439 	//  Evaluate an event to determine if the object is waiting for it
440 	bool evaluateEvent(const GameEvent &event);
441 };
442 
443 } // end of namespace Saga2
444 
445 #endif
446