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