ON

Monster Level

Por Oneshot, 30 de out. de 2013 em Linguagens de Programação

oneshot
monster
level
otserv
tibia
script
39
7.8k
OneshotO
30 de outubro de 2013 às 22:27

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.

Editado Novembro 6 por Oneshot

LuckOakeL
30 de outubro de 2013 às 22:36

Nice system.

 

Rep+

KluivertK
30 de outubro de 2013 às 22:41

Sistema muito bom One gostei!

 

 

Rep+

caoticC
31 de outubro de 2013 às 14:52

Além de desenvolver um otimo sistema não tem a limitação do client.

 

Parabéns

BeekiB
31 de outubro de 2013 às 14:59

Muito bom o código, obrigado mesmo, uma sugestão, seria legal você fazer o Race System, seria útil para muitos membros.

 

 

Obrigado novamente, REP+

 

Beeki XTibia.

OneshotO
31 de outubro de 2013 às 15:13

Muito bom o código, obrigado mesmo, uma sugestão, seria legal você fazer o Race System, seria útil para muitos membros.

 

 

Obrigado novamente, REP+

 

Beeki XTibia.

 

Como funcionaria esse Race System? Pode passar mais detalhes por PM? rs

 

Abraços.

Nu77N
31 de outubro de 2013 às 15:19

Ficou bem legal o código, com certeza no 0.3.6 não ira funcionar, pois tem alguns detalhes que precisarão ser mudados, como string do storage para integer entre outras pequenas coisas, mas nada complicado, rep+.

Editado Outubro 31 por SUJA

31 de outubro de 2013 às 15:30

ótimo sistema oneshot, parabéns!

Seria possível uma configuração extra onde pudesse editar as porcentagens? Colocando monstros ganhando mais que 10% de vida e outros menos?

BeekiB
31 de outubro de 2013 às 15:34

 

Muito bom o código, obrigado mesmo, uma sugestão, seria legal você fazer o Race System, seria útil para muitos membros.

 

 

Obrigado novamente, REP+

 

Beeki XTibia.

 

Como funcionaria esse Race System? Pode passar mais detalhes por PM? rs

 

Abraços.

 

 

Estilo Ragnarok, já ouviu falar?

OriGMO
31 de outubro de 2013 às 17:05

E como funciona ,o monstro passa de level ou o monstro nasce com level apenas? Tipo dá respaw e nasce com level 5. Ou da respaw com um level,e se ele mata algum player e tal,ele evolui de level ou não?

De qualquer forma NICE isso!

OneshotO
31 de outubro de 2013 às 17:24

E como funciona ,o monstro passa de level ou o monstro nasce com level apenas? Tipo dá respaw e nasce com level 5. Ou da respaw com um level,e se ele mata algum player e tal,ele evolui de level ou não?

De qualquer forma NICE isso!

 

Nasce com um level aleatório.

 

Grande abraço.

Editado Outubro 31 por Oneshot

HeelNoxH
31 de outubro de 2013 às 19:28

Adorei cara ira ajudar muita gente, REP+

 

(não tem limite de level ?)

OneshotO
31 de outubro de 2013 às 20:12

Adorei cara ira ajudar muita gente, REP+

 

(não tem limite de level ?)

 

Então, declarei as duas variáveis que controlam o level mínimo e máximo como int32_t, isso significa um valor máximo possível igual a 2147483647. rs

Editado Outubro 31 por Oneshot

MaenilseM
31 de outubro de 2013 às 22:51

funciona no tfs 0.3.6pl1, e tfs 0.3.6?

 

otimo codigo, vlw UmTiro, rep+.

Editado Outubro 31 por Maenilse

Nu77N
31 de outubro de 2013 às 23:10

funciona no tfs 0.3.6pl1, e tfs 0.3.6?

 

otimo codigo, vlw UmTiro, rep+.

 

Ficou bem legal o código, com certeza no 0.3.6 não ira funcionar, pois tem alguns detalhes que precisarão ser mudados, como string do storage para integer entre outras pequenas coisas, mas nada complicado, rep+.