Monster Level
Boa noite,
Você deve ter visto este tópico e ficado interessado na feature, afinal, seria legal monstros terem também level, não é? O sistema que desenvolvi é bem funcional, o monstro passa a ter level e ganha mais HP, dá mais dano, tem mais defesa, dependendo dele.
Como é feito em C++, a configuração é feita totalmente no XML do monstro, ficando tudo mais organizado. Há um extra no código, onde você pode manipular o level do summon do jogador, alterando o valor do storage 'monster_level'.
Bom, é isso aí, para instalar, siga os passos a seguir atentamente.
O sistema foi desenvolvido com base no The Forgotten Server 0.4_SVN r3777, não testei na versão 0.3.6, você tem a total liberdade para fazer isso.
monsters.h
Procure por:
bool isSummonable, isIllusionable, isConvinceable, isAttackable, isHostile, isLureable, isWalkable, canPushItems, canPushCreatures, pushable, hideName, hideHealth;
Substitua por:
bool isSummonable, isIllusionable, isConvinceable, isAttackable, isHostile, isLureable, isWalkable, canPushItems, canPushCreatures, pushable, hideName, hideHealth, hideLevel;
Procure por:
int32_t defense, armor, health, healthMax, baseSpeed, lookCorpse, corpseUnique, corpseAction, maxSummons, targetDistance, runAwayHealth, conditionImmunities, damageImmunities, lightLevel, lightColor, changeTargetSpeed, changeTargetChance;
Substitua por:
int32_t defense, armor, health, healthMax, baseSpeed, lookCorpse, corpseUnique, corpseAction, maxSummons, targetDistance, runAwayHealth, conditionImmunities, damageImmunities, lightLevel, lightColor, changeTargetSpeed, changeTargetChance, levelMin, levelMax;
monsters.cpp
Procure por:
canPushItems = canPushCreatures = isSummonable = isIllusionable = isConvinceable = isLureable = isWalkable = hideName = hideHealth = false;
Substitua por:
canPushItems = canPushCreatures = isSummonable = isIllusionable = isConvinceable = isLureable = isWalkable = hideName = hideHealth = hideLevel = false;
Procure por:
baseSpeed = 200;
Logo abaixo, adicione:
levelMin = levelMax = 1;
Localize:
bool Monsters::loadMonster
Dentro da função, procure por:
for(xmlNodePtr p = root->children; p; p = p->next) { if(p->type != XML_ELEMENT_NODE) continue; if(!xmlStrcmp(p->name, (const xmlChar*)"health")) { if(!readXMLInteger(p, "max", intValue)) { SHOW_XML_ERROR("Missing health.max"); monsterLoad = false; break; } mType->healthMax = intValue; if(!readXMLInteger(p, "now", intValue)) mType->health = mType->healthMax; else mType->health = intValue; }
Logo abaixo, adicione:
else if(!xmlStrcmp(p->name, (const xmlChar*)"level")) { if(!readXMLInteger(p, "max", intValue)) mType->levelMax = 1; else mType->levelMax = intValue; if(!readXMLInteger(p, "min", intValue)) mType->levelMin = mType->levelMax; else mType->levelMin = intValue; }
Procure por:
if(readXMLString(tmpNode, "emblem", strValue)) mType->guildEmblem = getEmblems(strValue);
Logo abaixo, adicione:
if(readXMLString(tmpNode, "hidelevel", strValue)) mType->hideLevel = booleanString(strValue);
monster.h
Localize:
class Monster : public Creature {
Logo abaixo de:
public: #ifdef __ENABLE_SERVER_DIAGNOSTIC__ static uint32_t monsterCount; #endif virtual ~Monster();
Adicione:
std::string name, nameDescription; int32_t level; double bonusAttack, bonusDefense;
Substitua:
virtual const std::string& getName() const {return mType->name;} virtual const std::string& getNameDescription() const {return mType->nameDescription;} virtual std::string getDescription(int32_t) const {return mType->nameDescription + ".";}
Por:
virtual const std::string& getName() const {return name;} virtual const std::string& getNameDescription() const {return nameDescription;} virtual std::string getDescription(int32_t) const {return nameDescription + ".";}
monster.cpp
Procure por:
Monster::Monster(MonsterType* _mType):
Logo abaixo de:
isIdle = true;
Adicione:
name = _mType->name; nameDescription = _mType->nameDescription; level = (int32_t)random_range(_mType->levelMin, _mType->levelMax, DISTRO_NORMAL); bonusAttack = 1.0; bonusDefense = 1.0;
Procure por:
Monster::onCreatureAppear
Substitua toda a função por:
void Monster::onCreatureAppear(const Creature* creature) { Creature::onCreatureAppear(creature); if(creature == this) { //We just spawned lets look around to see who is there. if(isSummon()) { std::string value; this->master->getStorage((std::string)"monster_level", value); uint8_t intValue = atoi(value.c_str()); if(intValue || value == "0") level = intValue; else level = 1; isMasterInRange = canSee(master->getPosition()); } if(g_config.getBool(ConfigManager::MONSTER_HAS_LEVEL)) { this->healthMax = std::floor(this->getMaxHealth() * (1. + (0.1 * (level - 1)))); this->health = this->healthMax; this->bonusAttack += (0.01 * (level - 1)); this->bonusDefense += (0.005 * (level - 1)); } updateTargetList(); updateIdleStatus(); } else onCreatureEnter(const_cast<Creature*>(creature)); }
Substitua todos:
g_config.getDouble(ConfigManager::RATE_MONSTER_DEFENSE)
Por:
g_config.getDouble(ConfigManager::RATE_MONSTER_DEFENSE) * bonusDefense
Substitua todos:
g_config.getDouble(ConfigManager::RATE_MONSTER_ATTACK)
Por:
g_config.getDouble(ConfigManager::RATE_MONSTER_ATTACK) * bonusAttack
map.cpp
Procure por:
#include "game.h"
Adicione:
#include "configmanager.h"
Procure por:
extern Game g_game;
Adicione abaixo:
extern ConfigManager g_config;
Procure pela função:
bool Map::placeCreature {
Adicione logo depois:
Monster* monster = creature->getMonster(); if(monster && g_config.getBool(ConfigManager::MONSTER_HAS_LEVEL)) { uint8_t level; if(!monster->getMonsterType()->hideLevel) { if(monster->isSummon()) { std::string value; monster->getMaster()->getStorage((std::string)"monster_level", value); uint8_t intValue = atoi(value.c_str()); if(intValue || value == "0") level = intValue; else level = 1; } else level = monster->level; char buffer [10]; monster->name = monster->getName() + " [" + itoa(level, buffer, 10) + "]"; } }
configmanager.h
Procure por:
MONSTER_SPAWN_WALKBACK,
E adicione abaixo:
MONSTER_HAS_LEVEL,
configmanager.cpp
Procure por:
m_loaded = true;
Adicione um pouco antes:
m_confBool[MONSTER_HAS_LEVEL] = getGlobalBool("monsterHasLevel", true);
config.lua
monsterHasLevel = true
Acabou, ufa, né?
São muitas modificações para fazer, mas o resultado é garantido e é uma funcionalidade a mais para seu servidor.
Como está programado, a cada level, monstros ganham 10% de HP, 1% de dano e 0.5% de defesa.
Para configurar level mínimo e máximo, é só adicionar no XML do monstro:
<level min="1" max="10"/>
E alterar a seu gosto.
trunk.r3777 (com Monster Level)
Espero que gostem, qualquer erro, só postar no tópico.
Grande abraço.