/** * Tibia GIMUD Server - a free and open-source MMORPG server emulator * Copyright (C) 2019 Sabrehaven and Mark Samman * * 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 FS_MONSTERS_H_776E8327BCE2450EB7C4A260785E6C0D #define FS_MONSTERS_H_776E8327BCE2450EB7C4A260785E6C0D #include "creature.h" #define MAX_LOOTCHANCE 1000 #define MAX_STATICWALK 100 struct LootBlock { uint16_t id; uint32_t countmax; uint32_t chance; //optional int32_t subType; int32_t actionId; std::string text; std::vector childLoot; LootBlock() { id = 0; countmax = 0; chance = 0; subType = -1; actionId = -1; } }; struct summonBlock_t { std::string name; uint32_t chance; uint32_t max; bool force = false; }; class BaseSpell; struct spellBlock_t { constexpr spellBlock_t() = default; ~spellBlock_t(); spellBlock_t(const spellBlock_t& other) = delete; spellBlock_t& operator=(const spellBlock_t& other) = delete; spellBlock_t(spellBlock_t&& other) : spell(other.spell), chance(other.chance), range(other.range), minCombatValue(other.minCombatValue), maxCombatValue(other.maxCombatValue), attack(other.attack), skill(other.skill), combatSpell(other.combatSpell) { other.spell = nullptr; } BaseSpell* spell = nullptr; uint32_t chance = 100; uint32_t range = 0; int32_t minCombatValue = 0; int32_t maxCombatValue = 0; int32_t attack = 0; int32_t skill = 0; bool combatSpell = false; }; struct voiceBlock_t { std::string text; bool yellText; }; class MonsterType { struct MonsterInfo { LuaScriptInterface* scriptInterface; std::map elementMap; std::vector voiceVector; std::vector lootItems; std::vector scripts; std::vector attackSpells; std::vector defenseSpells; std::vector summons; Skulls_t skull = SKULL_NONE; Outfit_t outfit = {}; RaceType_t race = RACE_BLOOD; LightInfo light = {}; uint16_t lookcorpse = 0; uint64_t experience = 0; uint32_t manaCost = 0; uint32_t maxSummons = 0; uint32_t changeTargetSpeed = 0; uint32_t conditionImmunities = 0; uint32_t damageImmunities = 0; uint32_t baseSpeed = 70; int32_t creatureAppearEvent = -1; int32_t creatureDisappearEvent = -1; int32_t creatureMoveEvent = -1; int32_t creatureSayEvent = -1; int32_t thinkEvent = -1; int32_t targetDistance = 1; int32_t runAwayHealth = 0; int32_t health = 100; int32_t healthMax = 100; int32_t changeTargetChance = 0; int32_t strategyNearestEnemy = 0; int32_t strategyWeakestEnemy = 0; int32_t strategyMostDamageEnemy = 0; int32_t strategyRandomEnemy = 0; int32_t armor = 0; int32_t defense = 0; int32_t attack = 0; int32_t skill = 0; int32_t poison = 0; bool canPushItems = false; bool canPushCreatures = false; bool pushable = true; bool isSummonable = false; bool isIllusionable = false; bool isConvinceable = false; bool isAttackable = true; bool isHostile = true; bool hiddenHealth = false; }; public: MonsterType() = default; // non-copyable MonsterType(const MonsterType&) = delete; MonsterType& operator=(const MonsterType&) = delete; std::string name; std::string nameDescription; MonsterInfo info; void createLoot(Container* corpse); bool createLootContainer(Container* parent, const LootBlock& lootblock); std::vector createLootItem(const LootBlock& lootBlock); }; class Monsters { public: Monsters() = default; // non-copyable Monsters(const Monsters&) = delete; Monsters& operator=(const Monsters&) = delete; bool loadFromXml(bool reloading = false); bool isLoaded() const { return loaded; } bool reload(); MonsterType* getMonsterType(const std::string& name); static uint32_t getLootRandom(); private: ConditionDamage* getDamageCondition(ConditionType_t conditionType, int32_t cycles, int32_t count, int32_t max_count); bool deserializeSpell(const pugi::xml_node& node, spellBlock_t& sb, const std::string& description = ""); bool loadMonster(const std::string& file, const std::string& monsterName, std::list>& monsterScriptList, bool reloading = false); void loadLootContainer(const pugi::xml_node& node, LootBlock&); bool loadLootItem(const pugi::xml_node& node, LootBlock&); std::map monsters; std::unique_ptr scriptInterface; bool loaded = false; }; #endif