/* 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 2 * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #ifndef XEEN_COMBAT_H #define XEEN_COMBAT_H #include "common/scummsys.h" #include "common/rect.h" #include "xeen/files.h" #include "xeen/sprites.h" namespace Xeen { #define MAX_NUM_MONSTERS 107 #define PARTY_AND_MONSTERS 12 #define POW_COUNT 12 #define ATTACK_MONSTERS_COUNT 26 enum DamageType { DT_PHYSICAL = 0, DT_MAGICAL = 1, DT_FIRE = 2, DT_ELECTRICAL = 3, DT_COLD = 4, DT_POISON = 5, DT_ENERGY = 6, DT_SLEEP = 7, DT_FINGEROFDEATH = 8, DT_HOLYWORD = 9, DT_MASS_DISTORTION = 10, DT_UNDEAD = 11, DT_BEASTMASTER = 12, DT_DRAGONSLEEP = 13, DT_GOLEMSTOPPER = 14, DT_HYPNOTIZE = 15, DT_INSECT_SPRAY = 16, DT_POISON_VOLLEY = 17, DT_MAGIC_ARROW = 18 }; enum SpecialAttack { SA_NONE = 0, SA_MAGIC = 1, SA_FIRE = 2, SA_ELEC = 3, SA_COLD = 4, SA_POISON = 5, SA_ENERGY = 6, SA_DISEASE = 7, SA_INSANE = 8, SA_SLEEP = 9, SA_CURSEITEM = 10, SA_INLOVE = 11, SA_DRAINSP = 12, SA_CURSE = 13, SA_PARALYZE = 14, SA_UNCONSCIOUS = 15, SA_CONFUSE = 16, SA_BREAKWEAPON = 17, SA_WEAKEN = 18, SA_ERADICATE = 19, SA_AGING = 20, SA_DEATH = 21, SA_STONE = 22 }; enum ShootType { ST_0 = 0, ST_1 = 1 }; enum CombatMode { COMBATMODE_STARTUP = 0, COMBATMODE_INTERACTIVE = 1, COMBATMODE_2 = 2 }; enum PowType { POW_INVALID = -1, POW_FIREBALL = 0, POW_INCINERATE = 1, POW_FIERY_FLAIL = 2, POW_LIGHTNING = 3, POW_MEGAVOLTS = 4, POW_SPARKS = 5, POW_STOPPER = 6, POW_MAGIC_ORB = 7, POW_COLD_RAY = 8, POW_FROST_WAVE = 9, POW_SPRAY = 10, POW_ARROW = 11, POW_MAGIC_ARROW = 12, POW_ENERGY_BLAST = 13, POW_SPARKLES = 14, POW_DEADLY_SWARM = 15 }; enum RangeType { RT_SINGLE = 0, RT_GROUP = 1, RT_ALL = 2, RT_HIT = 3 }; class XeenEngine; class Character; class XeenItem; class MonsterStruct; struct PowSlot { bool _active; int _duration; int _scale; int _elemFrame; int _elemScale; PowSlot() : _active(false), _duration(0), _scale(0), _elemFrame(0), _elemScale(0) {} }; class PowSlots { private: PowSlot _data[POW_COUNT]; public: /** * Gets a slot entry */ PowSlot &operator[](uint idx) { assert(idx < POW_COUNT); return _data[idx]; } /** * Resets the elemental frame used in all the slots */ void resetElementals() { for (int idx = 0; idx < POW_COUNT; ++idx) _data[idx]._elemFrame = 0; } }; class Combat { private: XeenEngine *_vm; /** * Handles the logic for attacking with a given amount of damage */ void attack2(int damage, RangeType rangeType); /** * Returns true if the character successfully hits the monster */ bool hitMonster(Character &c, RangeType rangeType); /** * Gets the damage a given character's equipped weapon will do */ void getWeaponDamage(Character &c, RangeType rangeType); /** * Returns how much damage will be done to a monster */ int getMonsterDamage(Character &c); /** * Gets the scale of damage, used for sprite display in the scene */ int getDamageScale(int v); /** * Gets the current monster's damage resistance to the currently set damage type */ int getMonsterResistence(RangeType rangeType); /** * Distribute experience between active party members */ void giveExperience(int experience); public: Common::Array _combatParty; bool _charsBlocked[PARTY_AND_MONSTERS]; int _charsGone[PARTY_AND_MONSTERS]; SpriteResource _powSprites; int _attackMonsters[ATTACK_MONSTERS_COUNT]; int _monster2Attack; PowSlots _pow; int _missedShot[8]; Common::Array _speedTable; int _shootingRow[8]; int _globalCombat; int _whosTurn; bool _itemFlag; int _monsterMap[32][32]; bool _monsterMoved[MAX_NUM_MONSTERS]; bool _rangeAttacking[MAX_NUM_MONSTERS]; int _gmonHit[36]; bool _monstersAttacking; CombatMode _combatMode; int _attackDurationCtr; bool _partyRan; int _whosSpeed; DamageType _damageType; Character *_oldCharacter; int _monsterDamage; int _weaponDamage; int _weaponDie, _weaponDice; int _weaponElemMaterial; XeenItem *_attackWeapon; int _attackWeaponId; File _missVoc; int _hitChanceBonus; bool _dangerPresent; bool _moveMonsters; RangeType _rangeType; ShootType _shootType; int _combatTarget; public: Combat(XeenEngine *vm); /** * Clear the list of attacking monsters */ void clearAttackers(); /** * Clear the list of blocked characters */ void clearBlocked(); /** * Clear the list of ros projectiles are on headed for part members */ void clearShooting(); /** * Resets all combat related data */ void reset(); /** * Gives damage to character or characters in the party */ void giveCharDamage(int damage, DamageType attackType, int charIndex); /** * Do damage to a specific character */ void doCharDamage(Character &c, int charNum, int monsterDataIndex); /** * Handles moving monsters by a space between game turns */ void moveMonsters(); /** * Setup the combat party with a copy of the currently active party */ void setupCombatParty(); /** * Sets up a table of speeds to determine the order in which characters and monsters fight */ void setSpeedTable(); /** * Returns true if all participants in the combat are disabled */ bool allHaveGone() const; /** * Returns true if all the characters of the party are disabled */ bool charsCantAct() const; /** * Return a description of the monsters being faced */ Common::String getMonsterDescriptions(); /** * Main method for characters to attack */ void attack(Character &c, RangeType rangeType); /** * Flag the currently active character as blocking/defending */ void block(); /** * Perform whatever the current combat character's quick action is */ void quickFight(); /** * Current selected character is trying to run away */ void run(); /** * Called to handle monsters doing ranged attacks against the party */ void monstersAttack(); void setupMonsterAttack(int monsterDataIndex, const Common::Point &pt); /** * Determines whether a given monster can move * @param pt Monster position * @param wallShift Shift mask for determining direction being moved * @param xDiff X Delta for move * @param yDiff Y Delta for move * @param monsterId Monster number being tested */ bool canMonsterMove(const Common::Point &pt, int wallShift, int xDiff, int yDiff, int monsterId); /** * Moves a monster by a given delta amount if it's a valid move */ void moveMonster(int monsterId, const Common::Point &moveDelta); /** * Handle a monster's turn at attacking combat party members */ void doMonsterTurn(int monsterId); /** * Handles a monster's turn at attacking a specific member of the combat party */ void doMonsterTurn(int monsterId, int charNum); /** * Called when combat has ended */ void endAttack(); void monsterOvercome(); /** * Checks whether a given position on the map will stop a ranged attack */ int stopAttack(const Common::Point &diffPt); /** * Called to do ranged attacks, both with bows or using a spell */ void rangedAttack(PowType powNum); /** * Fires off a ranged attack at all oncoming monsters */ void shootRangedWeapon(); /** * Returns true if there are any monsters in the vacinity */ bool areMonstersPresent() const; }; } // End of namespace Xeen #endif /* XEEN_COMBAT_H */