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 ULTIMA4_GAME_CREATURE_H 24 #define ULTIMA4_GAME_CREATURE_H 25 26 #include "ultima/ultima4/game/object.h" 27 #include "ultima/ultima4/map/movement.h" 28 #include "ultima/ultima4/filesys/savegame.h" 29 #include "ultima/ultima4/core/types.h" 30 31 namespace Ultima { 32 namespace Ultima4 { 33 34 class CombatController; 35 class ConfigElement; 36 class Tile; 37 38 typedef unsigned short CreatureId; 39 typedef Std::map<CreatureId, class Creature *> CreatureMap; 40 typedef Std::vector<class Creature *> CreatureVector; 41 42 #define MAX_CREATURES 128 43 44 /* Creatures on world map */ 45 46 #define MAX_CREATURES_ON_MAP 4 47 #define MAX_CREATURE_DISTANCE 16 48 49 /* Creature ids */ 50 51 typedef enum { 52 HORSE1_ID = 0, 53 HORSE2_ID = 1, 54 55 MAGE_ID = 2, 56 BARD_ID = 3, 57 FIGHTER_ID = 4, 58 DRUID_ID = 5, 59 TINKER_ID = 6, 60 PALADIN_ID = 7, 61 RANGER_ID = 8, 62 SHEPHERD_ID = 9, 63 64 GUARD_ID = 10, 65 VILLAGER_ID = 11, 66 SINGINGBARD_ID = 12, 67 JESTER_ID = 13, 68 BEGGAR_ID = 14, 69 CHILD_ID = 15, 70 BULL_ID = 16, 71 LORDBRITISH_ID = 17, 72 73 PIRATE_ID = 18, 74 NIXIE_ID = 19, 75 GIANT_SQUID_ID = 20, 76 SEA_SERPENT_ID = 21, 77 SEAHORSE_ID = 22, 78 WHIRLPOOL_ID = 23, 79 STORM_ID = 24, 80 RAT_ID = 25, 81 BAT_ID = 26, 82 GIANT_SPIDER_ID = 27, 83 GHOST_ID = 28, 84 SLIME_ID = 29, 85 TROLL_ID = 30, 86 GREMLIN_ID = 31, 87 MIMIC_ID = 32, 88 REAPER_ID = 33, 89 INSECT_SWARM_ID = 34, 90 GAZER_ID = 35, 91 PHANTOM_ID = 36, 92 ORC_ID = 37, 93 SKELETON_ID = 38, 94 ROGUE_ID = 39, 95 PYTHON_ID = 40, 96 ETTIN_ID = 41, 97 HEADLESS_ID = 42, 98 CYCLOPS_ID = 43, 99 WISP_ID = 44, 100 EVILMAGE_ID = 45, 101 LICH_ID = 46, 102 LAVA_LIZARD_ID = 47, 103 ZORN_ID = 48, 104 DAEMON_ID = 49, 105 HYDRA_ID = 50, 106 DRAGON_ID = 51, 107 BALRON_ID = 52 108 } CreatureType; 109 110 typedef enum { 111 MATTR_STEALFOOD = 0x1, 112 MATTR_STEALGOLD = 0x2, 113 MATTR_CASTS_SLEEP = 0x4, 114 MATTR_UNDEAD = 0x8, 115 MATTR_GOOD = 0x10, 116 MATTR_WATER = 0x20, 117 MATTR_NONATTACKABLE = 0x40, 118 MATTR_NEGATE = 0x80, 119 MATTR_CAMOUFLAGE = 0x100, 120 MATTR_NOATTACK = 0x200, 121 MATTR_AMBUSHES = 0x400, 122 MATTR_RANDOMRANGED = 0x800, 123 MATTR_INCORPOREAL = 0x1000, 124 MATTR_NOCHEST = 0x2000, 125 MATTR_DIVIDES = 0x4000, 126 MATTR_SPAWNSONDEATH = 0x8000, 127 MATTR_FORCE_OF_NATURE = 0x10000 128 } CreatureAttrib; 129 130 typedef enum { 131 MATTR_STATIONARY = 0x1, 132 MATTR_WANDERS = 0x2, 133 MATTR_SWIMS = 0x4, 134 MATTR_SAILS = 0x8, 135 MATTR_FLIES = 0x10, 136 MATTR_TELEPORT = 0x20, 137 MATTR_CANMOVECREATURES = 0x40, 138 MATTR_CANMOVEAVATAR = 0x80 139 } CreatureMovementAttrib; 140 141 typedef enum { 142 MSTAT_DEAD, 143 MSTAT_FLEEING, 144 MSTAT_CRITICAL, 145 MSTAT_HEAVILYWOUNDED, 146 MSTAT_LIGHTLYWOUNDED, 147 MSTAT_BARELYWOUNDED 148 } CreatureStatus; 149 150 /** 151 * Creature Class Definition 152 * @todo 153 * <ul> 154 * <li>split into a CreatureType (all the settings for a 155 * particular creature e.g. orc) and Creature (a specific 156 * creature instance)</li> 157 * <li>creatures can be looked up by name, ids can probably go away</li> 158 * </ul> 159 */ 160 class Creature : public Object { 161 typedef Common::List<StatusType> StatusList; 162 163 public: 164 /** 165 * Creature class implementation 166 */ 167 Creature(MapTile tile = MapTile(0)); 168 169 void load(const ConfigElement &conf); 170 171 // Accessor methods getName()172 virtual Common::String getName() const { 173 return _name; 174 } getHitTile()175 virtual const Common::String &getHitTile() const { 176 return _rangedHitTile; 177 } getMissTile()178 virtual const Common::String &getMissTile() const { 179 return _rangedMissTile; 180 } getId()181 CreatureId getId() const { 182 return _id; 183 } getLeader()184 CreatureId getLeader() const { 185 return _leader; 186 } getHp()187 virtual int getHp() const { 188 return _hp; 189 } getXp()190 virtual int getXp() const { 191 return _xp; 192 } getWorldrangedtile()193 virtual const Common::String &getWorldrangedtile() const { 194 return _worldRangedTile; 195 } getSlowedType()196 SlowedType getSlowedType() const { 197 return _slowedType; 198 } getEncounterSize()199 int getEncounterSize() const { 200 return _encounterSize; 201 } getResists()202 byte getResists() const { 203 return _resists; 204 } 205 206 // Setters setName(Common::String s)207 void setName(Common::String s) { 208 _name = s; 209 } setHitTile(const Common::String & t)210 void setHitTile(const Common::String &t) { 211 _rangedHitTile = t; 212 } setMissTile(const Common::String & t)213 void setMissTile(const Common::String &t) { 214 _rangedMissTile = t; 215 } setHp(int points)216 virtual void setHp(int points) { 217 _hp = points; 218 } 219 220 // Query methods isGood()221 bool isGood() const { 222 return _mAttr & MATTR_GOOD; 223 } isEvil()224 bool isEvil() const { 225 return !isGood(); 226 } isUndead()227 bool isUndead() const { 228 return _mAttr & MATTR_UNDEAD; 229 } leavesChest()230 bool leavesChest() const { 231 return !isAquatic() && !(_mAttr & MATTR_NOCHEST); 232 } isAquatic()233 bool isAquatic() const { 234 return _mAttr & MATTR_WATER; 235 } wanders()236 bool wanders() const { 237 return _movementAttr & MATTR_WANDERS; 238 } isStationary()239 bool isStationary() const { 240 return _movementAttr & MATTR_STATIONARY; 241 } flies()242 bool flies() const { 243 return _movementAttr & MATTR_FLIES; 244 } teleports()245 bool teleports() const { 246 return _movementAttr & MATTR_TELEPORT; 247 } swims()248 bool swims() const { 249 return _movementAttr & MATTR_SWIMS; 250 } sails()251 bool sails() const { 252 return _movementAttr & MATTR_SAILS; 253 } walks()254 bool walks() const { 255 return !(flies() || swims() || sails()); 256 } divides()257 bool divides() const { 258 return _mAttr & MATTR_DIVIDES; 259 } spawnsOnDeath()260 bool spawnsOnDeath() const { 261 return _mAttr & MATTR_SPAWNSONDEATH; 262 } canMoveOntoCreatures()263 bool canMoveOntoCreatures() const { 264 return _movementAttr & MATTR_CANMOVECREATURES; 265 } canMoveOntoPlayer()266 bool canMoveOntoPlayer() const { 267 return _movementAttr & MATTR_CANMOVEAVATAR; 268 } 269 bool isAttackable() const; willAttack()270 bool willAttack() const { 271 return !(_mAttr & MATTR_NOATTACK); 272 } stealsGold()273 bool stealsGold() const { 274 return _mAttr & MATTR_STEALGOLD; 275 } stealsFood()276 bool stealsFood() const { 277 return _mAttr & MATTR_STEALFOOD; 278 } negates()279 bool negates() const { 280 return _mAttr & MATTR_NEGATE; 281 } camouflages()282 bool camouflages() const { 283 return _mAttr & MATTR_CAMOUFLAGE; 284 } ambushes()285 bool ambushes() const { 286 return _mAttr & MATTR_AMBUSHES; 287 } isIncorporeal()288 bool isIncorporeal() const { 289 return _mAttr & MATTR_INCORPOREAL; 290 } hasRandomRanged()291 bool hasRandomRanged() const { 292 return _mAttr & MATTR_RANDOMRANGED; 293 } leavesTile()294 bool leavesTile() const { 295 return _leavesTile; 296 } castsSleep()297 bool castsSleep() const { 298 return _mAttr & MATTR_CASTS_SLEEP; 299 } isForceOfNature()300 bool isForceOfNature() const { 301 return _mAttr & MATTR_FORCE_OF_NATURE; 302 } 303 int getDamage() const; getCamouflageTile()304 const Common::String &getCamouflageTile() const { 305 return _camouflageTile; 306 } 307 void setRandomRanged(); 308 int setInitialHp(int hp = -1); 309 310 /** 311 * Performs a special action for the creature 312 * Returns true if the action takes up the creatures 313 * whole turn (i.e. it cant move afterwords) 314 */ 315 bool specialAction(); 316 317 /** 318 * Performs a special effect for the creature 319 * Returns true if something special happened, 320 * or false if nothing happened 321 */ 322 bool specialEffect(); 323 324 /* combat methods */ 325 void act(CombatController *controller); 326 327 /** 328 * Add status effects to the creature, in order of importance 329 */ 330 virtual void addStatus(StatusType status); 331 void applyTileEffect(TileEffect effect); 332 virtual int getAttackBonus() const; 333 virtual int getDefense() const; 334 bool divide(); 335 bool spawnOnDeath(); 336 virtual CreatureStatus getState() const; 337 StatusType getStatus() const; 338 bool isAsleep() const; 339 340 /** 341 * Hides or shows a camouflaged creature, depending on its distance from 342 * the nearest opponent 343 */ 344 bool hideOrShow(); 345 346 Creature *nearestOpponent(int *dist, bool ranged); 347 virtual void putToSleep(); 348 virtual void removeStatus(StatusType status); 349 virtual void setStatus(StatusType status); 350 virtual void wakeUp(); 351 352 /** 353 * Applies damage to the creature. 354 * Returns true if the creature still exists after the damage has been applied 355 * or false, if the creature was destroyed 356 * 357 * If byplayer is false (when a monster is killed by walking through 358 * fire or poison, or as a result of jinx) we don't report experience 359 * on death 360 */ 361 virtual bool applyDamage(int damage, bool byplayer = true); 362 virtual bool dealDamage(Creature *m, int damage); 363 364 // Properties 365 protected: 366 Common::String _name; 367 Common::String _rangedHitTile; 368 Common::String _rangedMissTile; 369 CreatureId _id; 370 Common::String _camouflageTile; 371 CreatureId _leader; 372 int _baseHp; 373 int _hp; 374 StatusList _status; 375 int _xp; 376 byte _ranged; 377 Common::String _worldRangedTile; 378 bool _leavesTile; 379 CreatureAttrib _mAttr; 380 CreatureMovementAttrib _movementAttr; 381 SlowedType _slowedType; 382 int _encounterSize; 383 byte _resists; 384 CreatureId _spawn; 385 }; 386 387 /** 388 * CreatureMgr Class Definition 389 */ 390 class CreatureMgr { 391 public: 392 static CreatureMgr *getInstance(); 393 394 void loadAll(); 395 396 /** 397 * Returns a creature using a tile to find which one to create 398 * or nullptr if a creature with that tile cannot be found 399 */ 400 Creature *getByTile(MapTile tile); 401 402 /** 403 * Returns the creature that has the corresponding id 404 * or returns nullptr if no creature with that id could 405 * be found. 406 */ 407 Creature *getById(CreatureId id); 408 409 /** 410 * Returns the creature that has the corresponding name 411 * or returns nullptr if no creature can be found with 412 * that name (case insensitive) 413 */ 414 Creature *getByName(Common::String name); 415 416 /** 417 * Creates a random creature based on the tile given 418 */ 419 Creature *randomForTile(const Tile *tile); 420 421 /** 422 * Creates a random creature based on the dungeon level given 423 */ 424 Creature *randomForDungeon(int dnglevel); 425 426 /** 427 * Creates a random ambushing creature 428 */ 429 Creature *randomAmbushing(); 430 431 private: CreatureMgr()432 CreatureMgr() {} 433 434 // disallow assignments, copy contruction 435 CreatureMgr(const CreatureMgr &); 436 const CreatureMgr &operator=(const CreatureMgr &); 437 438 static CreatureMgr *_instance; 439 440 CreatureMap _creatures; 441 }; 442 443 bool isCreature(Object *punknown); 444 445 #define creatureMgr (CreatureMgr::getInstance()) 446 447 } // End of namespace Ultima4 448 } // End of namespace Ultima 449 450 #endif 451