Postado Maio 4, 2020 5 anos Este é um post popular. Esse sistema foi feito utilizando a source disponibilizada neste link Pode funcionar em TFS 0.4, OTX 2.X e, talvez, em TFS 0.4 só que a probabilidade erros é maior por ter diferentes nomes de funções e variáveis. Fiz um vídeo seguindo o passo a passo abaixo para facilitar o processo de instalação do sistema. Hoje estarei ensinando a instalar os seguintes novos atributos/sistemas em sua source CriticalHitChance e DodgeChance -- (Funciona da mesma maneira que o critical básico de script, porém sem bugs de callstack) Life e Mana Absorb -- (Regenera, de acordo com a % atribuida, a partir de dano recebido) Life e Mana Leech -- (Regenera, de acordo com a % atribuida, a partir do dano causado) Exemplo de como vai ficar Spoiler Primeiro e antes de tudo, você terá de desativar o critical padrão do Tibia (Você pode pular essa parte se quiser) Spoiler Vá em configmanager.cpp e procure por: m_confNumber[CRITICAL_HIT_CHANCE] = getGlobalNumber("criticalHitChance", 5); Apague e depois procure por: m_confBool[DISPLAY_CRITICAL_HIT] = getGlobalBool("displayCriticalHitNotify", false); Apague também e, ainda no mesmo arquivo, procure por: m_confDouble[CRITICAL_HIT_MUL] = getGlobalDouble("criticalHitMultiplier", 1); Apague! Agora em configmanager.h e procure por: CRITICAL_HIT_CHANCE, // APAGUE CRITICAL_HIT_MUL, // APAGUE DISPLAY_CRITICAL_HIT, // APAGUE Apague todos citados acima! Agora em player.cpp procure por: void Player::sendCritical() const { if(g_config.getBool(ConfigManager::DISPLAY_CRITICAL_HIT)) g_game.addAnimatedText(getPosition(), COLOR_DARKRED, "CRITICAL!"); } Substitua por: /*void Player::sendCritical() const { if(g_config.getBool(ConfigManager::DISPLAY_CRITICAL_HIT)) g_game.addAnimatedText(getPosition(), COLOR_DARKRED, "CRITICAL!"); }*/ Depois em player.h procure por: void sendCritical() const; Substitua por: /*void sendCritical() const;*/ Por último vá em weapons.cpp e procure por: if(g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE) >= random_range(1, 100)) { maxDamage = std::pow(maxDamage, g_config.getDouble(ConfigManager::CRITICAL_HIT_MUL)); player->sendCritical(); } Substitua por: /* if(g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE) >= random_range(1, 100)) { maxDamage = std::pow(maxDamage, g_config.getDouble(ConfigManager::CRITICAL_HIT_MUL)); player->sendCritical(); }*/ Procure novamente por: if(g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE) >= random_range(1, 100)) { maxValue = std::pow(maxValue, g_config.getDouble(ConfigManager::CRITICAL_HIT_MUL)); player->sendCritical(); } Substitua por: /* if(g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE) >= random_range(1, 100)) { maxValue = std::pow(maxValue, g_config.getDouble(ConfigManager::CRITICAL_HIT_MUL)); player->sendCritical(); }*/ Procure por: if(g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE) >= random_range(1, 100)) { maxValue *= g_config.getDouble(ConfigManager::CRITICAL_HIT_MUL); player->sendCritical(); } Substitua por: /* if(g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE) >= random_range(1, 100)) { maxValue *= g_config.getDouble(ConfigManager::CRITICAL_HIT_MUL); player->sendCritical(); }*/ Agora, por último, procure por: if(maxDamage) { player->sendCritical(); return -maxValue; } Substitua por: if(maxDamage) { //player->sendCritical(); return -maxValue; } Vamos lá! Vá em items.cpp e procure por: attackSpeed = 0; Abaixo coloque: criticalHitChance = dodgeChance = lifeAbsorb = manaAbsorb = lifeLeech = manaLeech = 0; Depois, ainda em items.cpp, procure por: else if(tmpStrValue == "extradefense" || tmpStrValue == "extradef") { if(readXMLInteger(itemAttributesNode, "chance", intValue)) it.extraDefenseChance = intValue; if(readXMLInteger(itemAttributesNode, "value", intValue)) it.extraDefense = intValue; if(readXMLInteger(itemAttributesNode, "random_min", intValue)) it.extraDefenseRndMin = intValue; if(readXMLInteger(itemAttributesNode, "random_max", intValue)) it.extraDefenseRndMax = intValue; } Abaixo coloque: else if(tmpStrValue == "criticalhitchance") { if(readXMLInteger(itemAttributesNode, "value", intValue)) it.criticalHitChance = intValue; } else if(tmpStrValue == "dodgechance") { if(readXMLInteger(itemAttributesNode, "value", intValue)) it.dodgeChance = intValue; } else if(tmpStrValue == "lifeabsorb") { if(readXMLInteger(itemAttributesNode, "value", intValue)) it.lifeAbsorb = intValue; } else if(tmpStrValue == "manaabsorb") { if(readXMLInteger(itemAttributesNode, "value", intValue)) it.manaAbsorb = intValue; } else if(tmpStrValue == "lifeleech") { if(readXMLInteger(itemAttributesNode, "value", intValue)) it.lifeLeech = intValue; } else if(tmpStrValue == "manaleech") { if(readXMLInteger(itemAttributesNode, "value", intValue)) it.manaLeech = intValue; } Agora vá em items.h e procure por: int32_t attack, extraAttack, defense, extraDefense, armor, breakChance, hitChance, maxHitChance, runeLevel, runeMagLevel, lightLevel, lightColor, decayTo, rotateTo, alwaysOnTopOrder; Abaixo coloque: int32_t criticalHitChance, dodgeChance, lifeAbsorb, manaAbsorb, lifeLeech, manaLeech; Agora vá em item.cpp e procure por: case ATTR_ATTACK: { int32_t attack; if(!propStream.getLong((uint32_t&)attack)) return ATTR_READ_ERROR; setAttribute("attack", attack); break; } Acima coloque: case ATTR_CRITICALHITCHANCE: { int32_t criticalHitChance; if(!propStream.getLong((uint32_t&)criticalHitChance)) return ATTR_READ_ERROR; setAttribute("criticalhitchance", criticalHitChance); break; } case ATTR_DODGECHANCE: { int32_t dodgeChance; if(!propStream.getLong((uint32_t&)dodgeChance)) return ATTR_READ_ERROR; setAttribute("dodgechance", dodgeChance); break; } case ATTR_LIFEABSORB: { int32_t lifeAbsorb; if(!propStream.getLong((uint32_t&)lifeAbsorb)) return ATTR_READ_ERROR; setAttribute("lifeabsorb", lifeAbsorb); break; } case ATTR_MANAABSORB: { int32_t manaAbsorb; if(!propStream.getLong((uint32_t&)manaAbsorb)) return ATTR_READ_ERROR; setAttribute("manaabsorb", manaAbsorb); break; } case ATTR_LIFELEECH: { int32_t lifeLeech; if(!propStream.getLong((uint32_t&)lifeLeech)) return ATTR_READ_ERROR; setAttribute("lifeleech", lifeLeech); break; } case ATTR_MANALEECH: { int32_t manaLeech; if(!propStream.getLong((uint32_t&)manaLeech)) return ATTR_READ_ERROR; setAttribute("manaleech", manaLeech); break; } Procure por: if(it.weaponType == WEAPON_DIST && it.ammoType != AMMO_NONE) { begin = false; s << " (Range:" << int32_t(item ? item->getShootRange() : it.shootRange); if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack()))) { s << ", Atk " << std::showpos << int32_t(item ? item->getAttack() : it.attack); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; } if(it.hitChance != -1 || (item && item->getHitChance() != -1)) s << ", Hit% " << std::showpos << (item ? item->getHitChance() : it.hitChance) << std::noshowpos; } else if(it.weaponType != WEAPON_AMMO && it.weaponType != WEAPON_WAND) { if(it.attack || it.extraAttack || (item && (item->getAttack() || item->getExtraAttack()))) { begin = false; s << " (Atk:"; if(it.abilities.elementType != COMBAT_NONE && it.decayTo < 1) { s << std::max((int32_t)0, int32_t((item ? item->getAttack() : it.attack) - it.abilities.elementDamage)); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; s << " physical + " << it.abilities.elementDamage << " " << getCombatName(it.abilities.elementType); } else { s << int32_t(item ? item->getAttack() : it.attack); if(it.extraAttack || (item && item->getExtraAttack())) s << " " << std::showpos << int32_t(item ? item->getExtraAttack() : it.extraAttack) << std::noshowpos; } } if(it.defense || it.extraDefense || (item && (item->getDefense() || item->getExtraDefense()))) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Def:" << int32_t(item ? item->getDefense() : it.defense); if(it.extraDefense || (item && item->getExtraDefense())) s << " " << std::showpos << int32_t(item ? item->getExtraDefense() : it.extraDefense) << std::noshowpos; } } Abaixo coloque: if(it.criticalHitChance || (item && item->getCriticalHitChance())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Crit Chance:" << std::showpos << int32_t(item ? item->getCriticalHitChance() : it.criticalHitChance) << "%"<< std::noshowpos; } if(it.dodgeChance || (item && item->getDodgeChance())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Dodge Chance:" << std::showpos << int32_t(item ? item->getDodgeChance() : it.dodgeChance) << "%"<< std::noshowpos; } if(it.lifeAbsorb || (item && item->getLifeAbsorb())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Life Absorb:" << std::showpos << int32_t(item ? item->getLifeAbsorb() : it.lifeAbsorb) << "%"<< std::noshowpos; } if(it.manaAbsorb || (item && item->getManaAbsorb())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Mana Absorb:" << std::showpos << int32_t(item ? item->getManaAbsorb() : it.manaAbsorb) << "%"<< std::noshowpos; } if(it.lifeLeech || (item && item->getLifeLeech())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Life Leech:" << std::showpos << int32_t(item ? item->getLifeLeech() : it.lifeLeech) << "%"<< std::noshowpos; } if(it.manaLeech || (item && item->getManaLeech())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Mana Leech:" << std::showpos << int32_t(item ? item->getManaLeech() : it.manaLeech) << "%"<< std::noshowpos; } Procure por: int32_t tmp = it.armor; if(item) tmp = item->getArmor(); bool begin = true; if(tmp) { s << " (Arm:" << tmp; begin = false; } Abaixo coloque: if(it.criticalHitChance || (item && item->getCriticalHitChance())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Crit Chance:" << std::showpos << int32_t(item ? item->getCriticalHitChance() : it.criticalHitChance) << "%"<< std::noshowpos; } if(it.dodgeChance || (item && item->getDodgeChance())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Dodge Chance:" << std::showpos << int32_t(item ? item->getDodgeChance() : it.dodgeChance) << "%"<< std::noshowpos; } if(it.lifeAbsorb || (item && item->getLifeAbsorb())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Life Absorb:" << std::showpos << int32_t(item ? item->getLifeAbsorb() : it.lifeAbsorb) << "%"<< std::noshowpos; } if(it.manaAbsorb || (item && item->getManaAbsorb())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Mana Absorb:" << std::showpos << int32_t(item ? item->getManaAbsorb() : it.manaAbsorb) << "%"<< std::noshowpos; } if(it.lifeLeech || (item && item->getLifeLeech())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Life Leech:" << std::showpos << int32_t(item ? item->getLifeLeech() : it.lifeLeech) << "%"<< std::noshowpos; } if(it.manaLeech || (item && item->getManaLeech())) { if(begin) { begin = false; s << " ("; } else s << ", "; s << "Mana Leech:" << std::showpos << int32_t(item ? item->getManaLeech() : it.manaLeech) << "%"<< std::noshowpos; } Agora vá em item.h e procure por: ATTR_DUALWIELD = 43, Abaixo coloque: ATTR_CRITICALHITCHANCE = 44, ATTR_DODGECHANCE = 45, ATTR_LIFEABSORB = 46, ATTR_MANAABSORB = 47, ATTR_LIFELEECH = 48, ATTR_MANALEECH = 49, Procure por: int32_t getExtraDefense() const; Abaixo coloque: int32_t getCriticalHitChance() const; int32_t getDodgeChance() const; int32_t getLifeAbsorb() const; int32_t getManaAbsorb() const; int32_t getLifeLeech() const; int32_t getManaLeech() const; Procure por: inline int32_t Item::getExtraDefense() const { bool ok; int32_t v = getIntegerAttribute("extradefense", ok); if(ok) return v; return items[id].extraDefense; } Abaixo coloque: inline int32_t Item::getCriticalHitChance() const { bool ok; int32_t v = getIntegerAttribute("criticalhitchance", ok); if(ok) return v; return items[id].criticalHitChance; } inline int32_t Item::getDodgeChance() const { bool ok; int32_t v = getIntegerAttribute("dodgechance", ok); if(ok) return v; return items[id].dodgeChance; } inline int32_t Item::getLifeAbsorb() const { bool ok; int32_t v = getIntegerAttribute("lifeabsorb", ok); if(ok) return v; return items[id].lifeAbsorb; } inline int32_t Item::getManaAbsorb() const { bool ok; int32_t v = getIntegerAttribute("manaabsorb", ok); if(ok) return v; return items[id].manaAbsorb; } inline int32_t Item::getLifeLeech() const { bool ok; int32_t v = getIntegerAttribute("lifeleech", ok); if(ok) return v; return items[id].lifeLeech; } inline int32_t Item::getManaLeech() const { bool ok; int32_t v = getIntegerAttribute("manaleech", ok); if(ok) return v; return items[id].manaLeech; } Agora vá em player.cpp e procure por: int32_t Player::getArmor() const { int32_t i = SLOT_FIRST, armor = 0; for(; i < SLOT_LAST; ++i) { if(Item* item = getInventoryItem((slots_t)i)) armor += item->getArmor(); } if(vocation->getMultiplier(MULTIPLIER_ARMOR) != 1.0) return int32_t(armor * vocation->getMultiplier(MULTIPLIER_ARMOR)); return armor; } Abaixo coloque: int32_t Player::getCriticalHitChance() const { int32_t i = SLOT_FIRST, crit = 0; for(; i < SLOT_LAST; ++i) { if(Item* item = getInventoryItem((slots_t)i)) crit += item->getCriticalHitChance(); } return crit; } int32_t Player::getDodgeChance() const { int32_t i = SLOT_FIRST, dodge = 0; for(; i < SLOT_LAST; ++i) { if(Item* item = getInventoryItem((slots_t)i)) dodge += item->getDodgeChance(); } return dodge; } int32_t Player::getLifeAbsorb() const { int32_t i = SLOT_FIRST, life = 0; for(; i < SLOT_LAST; ++i) { if(Item* item = getInventoryItem((slots_t)i)) life += item->getLifeAbsorb(); } return life; } int32_t Player::getManaAbsorb() const { int32_t i = SLOT_FIRST, mana = 0; for(; i < SLOT_LAST; ++i) { if(Item* item = getInventoryItem((slots_t)i)) mana += item->getManaAbsorb(); } return mana; } int32_t Player::getLifeLeech() const { int32_t i = SLOT_FIRST, life = 0; for(; i < SLOT_LAST; ++i) { if(Item* item = getInventoryItem((slots_t)i)) life += item->getLifeLeech(); } return life; } int32_t Player::getManaLeech() const { int32_t i = SLOT_FIRST, mana = 0; for(; i < SLOT_LAST; ++i) { if(Item* item = getInventoryItem((slots_t)i)) mana += item->getManaLeech(); } return mana; } Agora vá em player.h e procure por: virtual int32_t getDefense() const; Abaixo coloque: virtual int32_t getCriticalHitChance() const; virtual int32_t getDodgeChance() const; virtual int32_t getLifeAbsorb() const; virtual int32_t getManaAbsorb() const; virtual int32_t getLifeLeech() const; virtual int32_t getManaLeech() const; Agora vá em luascript.cpp e procure por: //getCreatureHealth(cid) lua_register(m_luaState, "getCreatureHealth", LuaInterface::luaGetCreatureHealth); Abaixo coloque: //getPlayerCriticalHitChance(cid) lua_register(m_luaState, "getPlayerCriticalHitChance", LuaInterface::luaGetPlayerCriticalHitChance); //getPlayerDodgeChance(cid) lua_register(m_luaState, "getPlayerDodgeChance", LuaInterface::luaGetPlayerDodgeChance); //getPlayerLifeAbsorb(cid) lua_register(m_luaState, "getPlayerLifeAbsorb", LuaInterface::luaGetPlayerLifeAbsorb); //getPlayerManaAbsorb(cid) lua_register(m_luaState, "getPlayerManaAbsorb", LuaInterface::luaGetPlayerManaAbsorb); //getPlayerLifeLeech(cid) lua_register(m_luaState, "getPlayerLifeLeech", LuaInterface::luaGetPlayerLifeLeech); //getPlayerManaLeech(cid) lua_register(m_luaState, "getPlayerManaLeech", LuaInterface::luaGetPlayerManaLeech); Procure por: int32_t LuaInterface::luaGetCreatureMaxHealth(lua_State* L) { //getCreatureMaxHealth(cid[, ignoreModifiers = false]) bool ignoreModifiers = false; if(lua_gettop(L) > 1) ignoreModifiers = popBoolean(L); ScriptEnviroment* env = getEnv(); if(Creature* creature = env->getCreatureByUID(popNumber(L))) lua_pushnumber(L, creature->getPlayer() && ignoreModifiers ? creature->healthMax : creature->getMaxHealth()); else { errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushboolean(L, false); } return 1; } Abaixo coloque: int32_t LuaInterface::luaGetPlayerCriticalHitChance(lua_State* L) { //getPlayerCriticalHitChance(cid) ScriptEnviroment* env = getEnv(); if(Player* player = env->getPlayerByUID(popNumber(L))) lua_pushnumber(L, player->getCriticalHitChance()); else { errorEx(getError(LUA_ERROR_PLAYER_NOT_FOUND)); lua_pushboolean(L, false); } return 1; } int32_t LuaInterface::luaGetPlayerDodgeChance(lua_State* L) { //getPlayerDodgeChance(cid) ScriptEnviroment* env = getEnv(); if(Player* player = env->getPlayerByUID(popNumber(L))) lua_pushnumber(L, player->getDodgeChance()); else { errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushboolean(L, false); } return 1; } int32_t LuaInterface::luaGetPlayerLifeAbsorb(lua_State* L) { //getPlayerLifeAbsorb(cid) ScriptEnviroment* env = getEnv(); if(Player* player = env->getPlayerByUID(popNumber(L))) lua_pushnumber(L, player->getLifeAbsorb()); else { errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushboolean(L, false); } return 1; } int32_t LuaInterface::luaGetPlayerManaAbsorb(lua_State* L) { //getPlayerManaAbsorb(cid) ScriptEnviroment* env = getEnv(); if(Player* player = env->getPlayerByUID(popNumber(L))) lua_pushnumber(L, player->getManaAbsorb()); else { errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushboolean(L, false); } return 1; } int32_t LuaInterface::luaGetPlayerLifeLeech(lua_State* L) { //getPlayerLifeLeech(cid) ScriptEnviroment* env = getEnv(); if(Player* player = env->getPlayerByUID(popNumber(L))) lua_pushnumber(L, player->getLifeLeech()); else { errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushboolean(L, false); } return 1; } int32_t LuaInterface::luaGetPlayerManaLeech(lua_State* L) { //getPlayerManaLeech(cid) ScriptEnviroment* env = getEnv(); if(Player* player = env->getPlayerByUID(popNumber(L))) lua_pushnumber(L, player->getManaLeech()); else { errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND)); lua_pushboolean(L, false); } return 1; } Agora vá em luascript.h e procure por: static int32_t luaGetPlayerSpentMana(lua_State* L); Abaixo coloque: static int32_t luaGetPlayerCriticalHitChance(lua_State* L); static int32_t luaGetPlayerDodgeChance(lua_State* L); static int32_t luaGetPlayerLifeAbsorb(lua_State* L); static int32_t luaGetPlayerManaAbsorb(lua_State* L); static int32_t luaGetPlayerLifeLeech(lua_State* L); static int32_t luaGetPlayerManaLeech(lua_State* L); As funções Lua adicionadas foram getPlayerCriticalHitChance(cid) getPlayerDodgeChance(cid) getPlayerLifeAbsorb(cid) getPlayerManaAbsorb(cid) getPlayerLifeLeech(cid) getPlayerManaLeech(cid) Agora a parte do game.cpp. (Esta é uma parte opcional, você pode optar por não adicioná-la) Spoiler Agora vá em game.cpp e procure por: bool Game::combatChangeHealth(const CombatParams& params, Creature* attacker, Creature* target, int32_t healthChange, bool force) Dentro do escopo procure por: const Position& targetPos = target->getPosition(); Adicione logo abaixo: int32_t lifeLeech, manaLeech, lifeAbsorb, manaAbsorb = 0; Ainda dentro do escopo procure por: damage = std::min(target->getHealth(), damage); if(damage > 0) { Adicione abaixo: Player* player = NULL; if(attacker && (player = attacker->getPlayer())) { if(random_range(1,100) < attacker->getPlayer()->getCriticalHitChance()) { damage = damage * 2; addAnimatedText(attacker->getPosition(), COLOR_DARKRED, "Critical!"); } } if((player = target->getPlayer()) && (attacker != target) && target == player) { if(random_range(1,100) < target->getPlayer()->getDodgeChance()) { damage = damage * 0.5; addAnimatedText(target->getPosition(), COLOR_BLUE, "Dodge!"); } } Dentro do escopo procure por: if((player = target->getPlayer()) && attacker != target) { if(attacker) ss << "You lose " << totalDamage << " hitpoint" << plural << " due to an attack by " << attacker->getNameDescription() << "."; else ss << "You lose " << totalDamage << " hitpoint" << plural << "."; player->sendStatsMessage(MSG_DAMAGE_RECEIVED, ss.str(), targetPos, details); } Adicione abaixo: if(attacker && (player = attacker->getPlayer())) { if(attacker->getPlayer()->getLifeLeech() > 0) { lifeLeech = damage * (attacker->getPlayer()->getLifeLeech() * 0.01); if(damage > 0) { combatChangeHealth(params, target, attacker, lifeLeech, true); } } if(attacker->getPlayer()->getManaLeech() > 0) { manaLeech = damage * (attacker->getPlayer()->getManaLeech() * 0.01); if(damage > 0) { combatChangeMana(target, attacker, manaLeech, params.combatType, true); } } } // Absorb if((player = target->getPlayer()) && (attacker != target)) { if(target->getPlayer()->getLifeAbsorb() > 0) { lifeAbsorb = damage * (target->getPlayer()->getLifeAbsorb() * 0.01); if(damage > 0) { combatChangeHealth(params, attacker, target, lifeAbsorb, true); } } if(target->getPlayer()->getManaAbsorb() > 0) { manaAbsorb = damage * (target->getPlayer()->getManaAbsorb() * 0.01); if(damage > 0) { combatChangeMana(attacker, target, manaAbsorb, params.combatType, true); } } } Ainda em game.cpp e procure por: bool Game::combatChangeMana(Creature* attacker, Creature* target, int32_t manaChange, CombatType_t combatType/* = COMBAT_MANADRAIN*/, bool inherited/* = false*/) Dentro do escopo procure por: const Position& targetPos = target->getPosition(); Adicione logo abaixo: int32_t lifeLeech, manaLeech, lifeAbsorb, manaAbsorb = 0; Depois, dentro do escopo, procure por: if((player = target->getPlayer()) && attacker != target) { if(attacker) ss << "You lose " << manaLoss << " mana due to an attack by " << attacker->getNameDescription(); else ss << "You lose " << manaLoss << " mana."; player->sendStatsMessage(MSG_DAMAGE_RECEIVED, ss.str(), targetPos, details); } Abaixo coloque: // Life e Mana Leech if(attacker && (player = attacker->getPlayer())) { if(attacker->getPlayer()->getLifeLeech() > 0) { lifeLeech = manaLoss * (attacker->getPlayer()->getLifeLeech() * 0.01); if(manaLoss > 0) { combatChangeHealth(manaLoss < 1 ? COMBAT_UNDEFINEDDAMAGE : COMBAT_HEALING, target, attacker, lifeLeech, MAGIC_EFFECT_UNKNOWN, COLOR_UNKNOWN, false); } } if(attacker->getPlayer()->getManaLeech() > 0) { manaLeech = manaLoss * (attacker->getPlayer()->getManaLeech() * 0.01); if(manaLoss > 0) { combatChangeMana(target, attacker, manaLeech, combatType, true); } } } // Life e Mana Absorb if((player = target->getPlayer()) && (attacker != target)) { if(target->getPlayer()->getLifeAbsorb() > 0) { lifeAbsorb = manaLoss * (target->getPlayer()->getLifeAbsorb() * 0.01); if(manaLoss > 0) { combatChangeHealth(manaLoss < 1 ? COMBAT_UNDEFINEDDAMAGE : COMBAT_HEALING, attacker, target, lifeAbsorb, MAGIC_EFFECT_UNKNOWN, COLOR_UNKNOWN, false); } } if(target->getPlayer()->getManaAbsorb() > 0) { manaAbsorb = manaLoss * (target->getPlayer()->getManaAbsorb() * 0.01); if(manaLoss > 0) { combatChangeMana(attacker, target, manaAbsorb, combatType, true); } } } Créditos: ~Mathias Kenfi Editado Dezembro 17, 2020 4 anos por Mathias Kenfi Deixando mais simples do que já estava (veja o histórico de edições)
Postado Maio 4, 2020 5 anos @Mathias Kenfi dúvida o que acontece se adicionar esse critical e deixar o outro padrão ativo??? os dois se somam ou buga ? Projeto ATS (Naruto)Informações AbaixoFacebookYoutubeDiscord Tutoriais / ConteúdosClique Aqui
Postado Maio 4, 2020 5 anos Autor 6 minutos atrás, LeoTK disse: @Mathias Kenfi dúvida o que acontece se adicionar esse critical e deixar o outro padrão ativo??? os dois se somam ou buga ? Eles somam
Postado Maio 4, 2020 5 anos É muito bom ver que ainda temos alguns realmente contribuindo com a ideia de OpenSource.. Apesar de do Dodge e Critical serem sistemas que todo mundo já possui de alguma forma, se conseguíssemos padronizar todo mundo pra usar esse seria mais fácil pra todos.
Postado Maio 4, 2020 5 anos Muito obrigado por compartilhar, com certeza irei utilizar! Editado Maio 4, 2020 5 anos por One Punch Man (veja o histórico de edições)
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.