/* ScummVM - Graphic Adventure Engine * * ScummVM is the legal property of its developers, whose names * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * * Based on the original sources * Faery Tale II -- The Halls of the Dead * (c) 1993-1996 The Wyrmkeep Entertainment Co. */ #ifndef SAGA2_SENSOR_H #define SAGA2_SENSOR_H namespace Saga2 { const uint32 kNonActorSenseFlags = kActorSeeInvis; //const size_t maxSensorSize = 24; const size_t kMaxSensorSize = 48; // This constant represents the maximum sense range for an object. // Zero means an infinite range. const int16 kMaxSenseRange = 0; // Integers representing sensor types enum SensorType { kProtaganistSensor, kSpecificObjectSensor, kObjectPropertySensor, kSpecificActorSensor, kActorPropertySensor, kEventSensor }; // Sensors will be checked every 5 frames const int16 kSensorCheckRate = 5; /* ===================================================================== * Function prototypes * ===================================================================== */ struct GameEvent; // Allocate a new SensorList void newSensorList(SensorList *s); // Deallocate a SensorList void deleteSensorList(SensorList *p); // Fetch a specified object's SensorList SensorList *fetchSensorList(GameObject *obj); // Allocate a new Sensor void newSensor(Sensor *s); // Allocate a new Sensor with a specified starting check counter void newSensor(Sensor *s, int16 ctr); // Deallocate a Sensor void deleteSensor(Sensor *p); // Check all active sensors void checkSensors(); // Evaluate an event for all active sensors void assertEvent(const GameEvent &ev); // Initialize the sensors void initSensors(); void saveSensors(Common::OutSaveFile *outS); void loadSensors(Common::InSaveFile *in); // Cleanup the active sensors void cleanupSensors(); /* ===================================================================== * GameEvent struct * ===================================================================== */ struct GameEvent { int16 type; GameObject *directObject, *indirectObject; }; /* ===================================================================== * SenseInfo struct * ===================================================================== */ struct SenseInfo { GameObject *sensedObject; }; /* ===================================================================== * SensorList Class * ===================================================================== */ class SensorList { GameObject *_obj; public: Common::List _list; public: // Constructor -- initial construction SensorList(GameObject *o) : _obj(o) { newSensorList(this); debugC(1, kDebugSensors, "Adding SensorList %p to %d (%s) (total %d)", (void *)this, o->thisID(), o->objName(), _list.size()); } ~SensorList() { deleteSensorList(this); debugC(1, kDebugSensors, "Deleting SensorList %p of %d (%s) (total %d)", (void *)this, _obj->thisID(), _obj->objName(), _list.size()); } SensorList(Common::InSaveFile *in); // Return the number of bytes needed to archive this object in // a buffer static int32 archiveSize() { return sizeof(ObjectID); } void write(Common::MemoryWriteStreamDynamic *out); GameObject *getObject() { return _obj; } }; /* ===================================================================== * Sensor Class * ===================================================================== */ class Sensor { public: GameObject *_obj; SensorID _id; int16 _range; int16 _checkCtr; bool _active; public: // Constructor -- initial construction Sensor(GameObject *o, SensorID sensorID, int16 rng) : _obj(o), _id(sensorID), _range(rng), _active(true) { newSensor(this); SensorList *sl = fetchSensorList(o); debugC(1, kDebugSensors, "Adding Sensor %p to %d (%s) (list = %p, total = %d)", (void *)this, o->thisID(), o->objName(), (void *)sl, (sl != nullptr) ? sl->_list.size() : -1); } Sensor(Common::InSaveFile *in, int16 ctr); // Virtural destructor virtual ~Sensor() { deleteSensor(this); SensorList *sl = fetchSensorList(_obj); debugC(1, kDebugSensors, "Deleting Sensor %p of %d (%s) (list = %p, total = %d)", (void *)this, _obj->thisID(), _obj->objName(), (void *)sl, (sl != nullptr) ? sl->_list.size() : -1); } virtual void write(Common::MemoryWriteStreamDynamic *out); // Return an integer representing the type of this sensor virtual int16 getType() = 0; GameObject *getObject() { return _obj; } SensorID thisID() { return _id; } int16 getRange() { return _range; } // Determine if the object can sense what it's looking for virtual bool check(SenseInfo &info, uint32 senseFlags) = 0; // Evaluate an event to determine if the object is waiting for it virtual bool evaluateEvent(const GameEvent &event) = 0; }; /* ===================================================================== * ProtaganistSensor Class * ===================================================================== */ class ProtaganistSensor : public Sensor { public: // Constructor -- initial construction ProtaganistSensor(GameObject *o, SensorID sensorID, int16 rng) : Sensor(o, sensorID, rng) { } ProtaganistSensor(Common::InSaveFile *in, int16 ctr) : Sensor(in, ctr) { debugC(3, kDebugSaveload, "Loading ProtagonistSensor"); } // Return an integer representing the type of this sensor int16 getType(); // Determine if the object can sense what it's looking for bool check(SenseInfo &info, uint32 senseFlags); // Evaluate an event to determine if the object is waiting for it bool evaluateEvent(const GameEvent &event); }; /* ===================================================================== * ObjectSensor Class * ===================================================================== */ class ObjectSensor : public Sensor { public: // Constructor -- initial construction ObjectSensor(GameObject *o, SensorID sensorID, int16 rng) : Sensor(o, sensorID, rng) { } ObjectSensor(Common::InSaveFile *in, int16 ctr) : Sensor(in, ctr) {} // Determine if the object can sense what it's looking for bool check(SenseInfo &info, uint32 senseFlags); // Evaluate an event to determine if the object is waiting for it bool evaluateEvent(const GameEvent &event); private: // Determine if an object meets the search criteria virtual bool isObjectSought(GameObject *obj) = 0; }; /* ===================================================================== * SpecificObjectSensor Class * ===================================================================== */ class SpecificObjectSensor : public ObjectSensor { ObjectID _soughtObjID; public: // Constructor -- initial construction SpecificObjectSensor( GameObject *o, SensorID sensorID, int16 rng, ObjectID objToSense) : ObjectSensor(o, sensorID, rng), _soughtObjID(objToSense) { } SpecificObjectSensor(Common::InSaveFile *in, int16 ctr); // Return the number of bytes needed to archive this object in // a buffer int32 archiveSize(); void write(Common::MemoryWriteStreamDynamic *out); // Return an integer representing the type of this sensor int16 getType(); // Determine if the object can sense what it's looking for bool check(SenseInfo &info, uint32 senseFlags); private: // Determine if an object meets the search criteria bool isObjectSought(GameObject *obj); }; /* ===================================================================== * ObjectPropertySensor Class * ===================================================================== */ class ObjectPropertySensor : public ObjectSensor { ObjectPropertyID _objectProperty; public: // Constructor -- initial construction ObjectPropertySensor( GameObject *o, SensorID sensorID, int16 rng, ObjectPropertyID propToSense) : ObjectSensor(o, sensorID, rng), _objectProperty(propToSense) { } ObjectPropertySensor(Common::InSaveFile *in, int16 ctr); // Return the number of bytes needed to archive this object in // a buffer int32 archiveSize(); void write(Common::MemoryWriteStreamDynamic *out); // Return an integer representing the type of this sensor int16 getType(); private: // Determine if an object meets the search criteria bool isObjectSought(GameObject *obj); }; /* ===================================================================== * ActorSensor Class * ===================================================================== */ class ActorSensor : public ObjectSensor { public: // Constructor -- initial construction ActorSensor(GameObject *o, SensorID sensorID, int16 rng) : ObjectSensor(o, sensorID, rng) { } ActorSensor(Common::InSaveFile *in, int16 ctr) : ObjectSensor(in, ctr) {} private: // Determine if an object meets the search criteria bool isObjectSought(GameObject *obj); // Determine if an actor meets the search criteria virtual bool isActorSought(Actor *a) = 0; }; /* ===================================================================== * SpecificActorSensor Class * ===================================================================== */ class SpecificActorSensor : public ActorSensor { Actor *_soughtActor; public: // Constructor -- initial construction SpecificActorSensor( GameObject *o, SensorID sensorID, int16 rng, Actor *actorToSense) : ActorSensor(o, sensorID, rng), _soughtActor(actorToSense) { } SpecificActorSensor(Common::InSaveFile *in, int16 ctr); // Return the number of bytes needed to archive this object in // a buffer int32 archiveSize(); void write(Common::MemoryWriteStreamDynamic *out); // Return an integer representing the type of this sensor int16 getType(); // Determine if the object can sense what it's looking for bool check(SenseInfo &info, uint32 senseFlags); private: // Determine if an actor meets the search criteria bool isActorSought(Actor *a); }; /* ===================================================================== * ActorPropertySensor Class * ===================================================================== */ class ActorPropertySensor : public ActorSensor { ActorPropertyID _actorProperty; public: // Constructor -- initial construction ActorPropertySensor( GameObject *o, SensorID sensorID, int16 rng, ActorPropertyID propToSense) : ActorSensor(o, sensorID, rng), _actorProperty(propToSense) { } ActorPropertySensor(Common::InSaveFile *in, int16 ctr); // Return the number of bytes needed to archive this object in // a buffer int32 archiveSize(); void write(Common::MemoryWriteStreamDynamic *out); // Return an integer representing the type of this sensor int16 getType(); private: // Determine if an actor meets the search criteria bool isActorSought(Actor *a); }; /* ===================================================================== * EventSensor Class * ===================================================================== */ class EventSensor : public Sensor { int16 _eventType; public: // Constructor -- initial construction EventSensor( GameObject *o, SensorID sensorID, int16 rng, int16 type); EventSensor(Common::InSaveFile *in, int16 ctr); // Return the number of bytes needed to archive this object in // a buffer int32 archiveSize(); void write(Common::MemoryWriteStreamDynamic *out); // Return an integer representing the type of this sensor int16 getType(); // Determine if the object can sense what it's looking for bool check(SenseInfo &info, uint32 senseFlags); // Evaluate an event to determine if the object is waiting for it bool evaluateEvent(const GameEvent &event); }; } // end of namespace Saga2 #endif