introduce changes from streamside fork

This commit is contained in:
ErikasKontenis
2019-09-16 20:38:16 +03:00
parent f2cbc2dc1c
commit ad03b0eb3e
162 changed files with 2485 additions and 698 deletions

View File

@@ -1,6 +1,6 @@
/**
* Tibia GIMUD Server - a free and open-source MMORPG server emulator
* Copyright (C) 2017 Alejandro Mujica <alejandrodemujica@gmail.com>
* Copyright (C) 2019 Sabrehaven and Mark Samman <mark.samman@gmail.com>
*
* 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
@@ -24,13 +24,16 @@
#include "game.h"
#include "configmanager.h"
#include "monster.h"
#include "events.h"
extern Game g_game;
extern ConfigManager g_config;
extern Events* g_events;
CombatDamage Combat::getCombatDamage(Creature* creature) const
{
CombatDamage damage;
damage.origin = params.origin;
damage.type = params.combatType;
if (formulaType == COMBAT_FORMULA_DAMAGE) {
damage.min = static_cast<int32_t>(mina);
@@ -175,11 +178,7 @@ ReturnValue Combat::canDoCombat(Creature* caster, Tile* tile, bool aggressive)
return RETURNVALUE_NOTENOUGHROOM;
}
/*if (tile->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) && tile->hasProperty(CONST_PROP_UNLAY)) {
return RETURNVALUE_NOTENOUGHROOM;
}*/
if (tile->hasProperty(CONST_PROP_IMMOVABLEBLOCKPATH) && tile->hasProperty(CONST_PROP_IMMOVABLENOFIELDBLOCKPATH)) {
if (tile->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) && tile->hasProperty(CONST_PROP_UNLAY)) {
return RETURNVALUE_NOTENOUGHROOM;
}
@@ -192,7 +191,8 @@ ReturnValue Combat::canDoCombat(Creature* caster, Tile* tile, bool aggressive)
const Position& tilePosition = tile->getPosition();
if (casterPosition.z < tilePosition.z) {
return RETURNVALUE_FIRSTGODOWNSTAIRS;
} else if (casterPosition.z > tilePosition.z) {
}
else if (casterPosition.z > tilePosition.z) {
return RETURNVALUE_FIRSTGOUPSTAIRS;
}
@@ -208,7 +208,7 @@ ReturnValue Combat::canDoCombat(Creature* caster, Tile* tile, bool aggressive)
return RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE;
}
return RETURNVALUE_NOERROR;
return g_events->eventCreatureOnAreaCombat(caster, tile, aggressive);
}
bool Combat::isInPvpZone(const Creature* attacker, const Creature* target)
@@ -232,74 +232,78 @@ bool Combat::isProtected(const Player* attacker, const Player* target)
ReturnValue Combat::canDoCombat(Creature* attacker, Creature* target)
{
if (attacker) {
if (const Player* targetPlayer = target->getPlayer()) {
if (targetPlayer->hasFlag(PlayerFlag_CannotBeAttacked)) {
if (!attacker) {
return g_events->eventCreatureOnTargetCombat(attacker, target);
}
if (const Player* targetPlayer = target->getPlayer()) {
if (targetPlayer->hasFlag(PlayerFlag_CannotBeAttacked)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
if (const Player* attackerPlayer = attacker->getPlayer()) {
if (attackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
if (const Player* attackerPlayer = attacker->getPlayer()) {
if (attackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
if (isProtected(attackerPlayer, targetPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
//nopvp-zone
const Tile* targetPlayerTile = targetPlayer->getTile();
if (targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE)) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
} else if (attackerPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE) && !targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE | TILESTATE_PROTECTIONZONE)) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
}
if (isProtected(attackerPlayer, targetPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
if (attacker->isSummon()) {
if (const Player* masterAttackerPlayer = attacker->getMaster()->getPlayer()) {
if (masterAttackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
if (targetPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE)) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
}
if (isProtected(masterAttackerPlayer, targetPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
}
//nopvp-zone
const Tile* targetPlayerTile = targetPlayer->getTile();
if (targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE)) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
}
} else if (target->getMonster()) {
if (const Player* attackerPlayer = attacker->getPlayer()) {
if (attackerPlayer->hasFlag(PlayerFlag_CannotAttackMonster)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE;
}
if (target->isSummon() && target->getMaster()->getPlayer() && target->getZone() == ZONE_NOPVP) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
}
else if (attackerPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE) && !targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE | TILESTATE_PROTECTIONZONE)) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
}
}
if (g_game.getWorldType() == WORLD_TYPE_NO_PVP) {
if (attacker->getPlayer() || (attacker->isSummon() && attacker->getMaster()->getPlayer())) {
if (target->getPlayer()) {
if (!isInPvpZone(attacker, target)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
if (attacker->isSummon()) {
if (const Player* masterAttackerPlayer = attacker->getMaster()->getPlayer()) {
if (masterAttackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
if (target->isSummon() && target->getMaster()->getPlayer()) {
if (!isInPvpZone(attacker, target)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE;
}
if (targetPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE)) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
}
if (isProtected(masterAttackerPlayer, targetPlayer)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
}
}
}
return RETURNVALUE_NOERROR;
else if (target->getMonster()) {
if (const Player* attackerPlayer = attacker->getPlayer()) {
if (attackerPlayer->hasFlag(PlayerFlag_CannotAttackMonster)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE;
}
if (target->isSummon() && target->getMaster()->getPlayer() && target->getZone() == ZONE_NOPVP) {
return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE;
}
}
}
if (g_game.getWorldType() == WORLD_TYPE_NO_PVP) {
if (attacker->getPlayer() || (attacker->isSummon() && attacker->getMaster()->getPlayer())) {
if (target->getPlayer()) {
if (!isInPvpZone(attacker, target)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER;
}
}
if (target->isSummon() && target->getMaster()->getPlayer()) {
if (!isInPvpZone(attacker, target)) {
return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE;
}
}
}
}
return g_events->eventCreatureOnTargetCombat(attacker, target);
}
void Combat::setPlayerCombatValues(formulaType_t formulaType, double mina, double minb, double maxa, double maxb)
@@ -422,7 +426,7 @@ CallBack* Combat::getCallback(CallBackParam_t key)
return nullptr;
}
bool Combat::CombatHealthFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data)
void Combat::CombatHealthFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data)
{
assert(data);
CombatDamage damage = *data;
@@ -439,18 +443,16 @@ bool Combat::CombatHealthFunc(Creature* caster, Creature* target, const CombatPa
}
if (g_game.combatBlockHit(damage, caster, target, params.blockedByShield, params.blockedByArmor, params.itemId != 0)) {
return false;
return;
}
if (g_game.combatChangeHealth(caster, target, damage)) {
CombatConditionFunc(caster, target, params, nullptr);
CombatConditionFunc(caster, target, params, &damage);
CombatDispelFunc(caster, target, params, nullptr);
}
return true;
}
bool Combat::CombatManaFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data)
void Combat::CombatManaFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data)
{
assert(data);
CombatDamage damage = *data;
@@ -465,16 +467,18 @@ bool Combat::CombatManaFunc(Creature* caster, Creature* target, const CombatPara
}
}
if (g_game.combatChangeMana(caster, target, damage.value)) {
if (g_game.combatChangeMana(caster, target, damage)) {
CombatConditionFunc(caster, target, params, nullptr);
CombatDispelFunc(caster, target, params, nullptr);
}
return true;
}
bool Combat::CombatConditionFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage*)
void Combat::CombatConditionFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data)
{
if (params.origin == ORIGIN_MELEE && data && data->value == 0) {
return;
}
for (const auto& condition : params.conditionList) {
if (caster == target || !target->isImmune(condition->getType())) {
Condition* conditionCopy = condition->clone();
@@ -486,21 +490,17 @@ bool Combat::CombatConditionFunc(Creature* caster, Creature* target, const Comba
target->addCombatCondition(conditionCopy);
}
}
return true;
}
bool Combat::CombatDispelFunc(Creature*, Creature* target, const CombatParams& params, CombatDamage*)
void Combat::CombatDispelFunc(Creature*, Creature* target, const CombatParams& params, CombatDamage*)
{
target->removeCombatCondition(params.dispelType);
return true;
}
bool Combat::CombatNullFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage*)
void Combat::CombatNullFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage*)
{
CombatConditionFunc(caster, target, params, nullptr);
CombatDispelFunc(caster, target, params, nullptr);
return true;
}
void Combat::combatTileEffects(const SpectatorVec& list, Creature* caster, Tile* tile, const CombatParams& params)
@@ -632,6 +632,8 @@ void Combat::CombatFunc(Creature* caster, const Position& pos, const AreaCombat*
const int32_t rangeY = maxY + Map::maxViewportY;
g_game.map.getSpectators(list, pos, true, true, rangeX, rangeX, rangeY, rangeY);
postCombatEffects(caster, pos, params);
uint16_t decreasedDamage = 0;
const uint16_t maximumDecreasedDamage = params.maximumDecreasedDamage;
@@ -721,6 +723,8 @@ void Combat::CombatFunc(Creature* caster, const Position& pos, const AreaCombat*
continue;
}
combatTileEffects(list, caster, tile, params);
if (CreatureVector* creatures = tile->getCreatures()) {
const Creature* topCreature = tile->getTopCreature();
for (Creature* creature : *creatures) {
@@ -746,9 +750,7 @@ void Combat::CombatFunc(Creature* caster, const Position& pos, const AreaCombat*
}
}
}
combatTileEffects(list, caster, tile, params);
}
postCombatEffects(caster, pos, params);
}
void Combat::doCombat(Creature* caster, Creature* target) const
@@ -834,7 +836,7 @@ bool Combat::attack(Creature* attacker, Creature* target)
return false;
}
bool Combat::closeAttack(Creature* attacker, Creature* target, fightMode_t fightMode, bool fist)
bool Combat::closeAttack(Creature* attacker, Creature* target, fightMode_t fightMode)
{
const Position& attackerPos = attacker->getPosition();
const Position& targetPos = target->getPosition();
@@ -859,7 +861,7 @@ bool Combat::closeAttack(Creature* attacker, Creature* target, fightMode_t fight
uint32_t skillValue = 0;
uint8_t skill = SKILL_FIST;
Combat::getAttackValue(attacker, attackValue, skillValue, skill, fist);
Combat::getAttackValue(attacker, attackValue, skillValue, skill);
int32_t defense = target->getDefense();
@@ -876,6 +878,7 @@ bool Combat::closeAttack(Creature* attacker, Creature* target, fightMode_t fight
combatDamage.type = combatParams.combatType;
int32_t totalDamage = Combat::getTotalDamage(skillValue, attackValue, fightMode);
combatDamage.value = totalDamage;
combatDamage.origin = ORIGIN_MELEE;
bool hit = Combat::doCombatHealth(attacker, target, combatDamage, combatParams);
@@ -884,7 +887,7 @@ bool Combat::closeAttack(Creature* attacker, Creature* target, fightMode_t fight
if (poison) {
int32_t randTest = rand();
if (hit || -totalDamage > defense && (randTest == 5 * (randTest / 5))) {
if (hit || ((-totalDamage > defense) && (randTest == 5 * (randTest / 5)))) {
poison = normal_random(poison / 2, poison);
if (poison) {
ConditionDamage* condition = static_cast<ConditionDamage*>(Condition::createCondition(CONDITIONID_COMBAT, CONDITION_POISON, 0, 0));
@@ -962,9 +965,9 @@ bool Combat::rangeAttack(Creature* attacker, Creature* target, fightMode_t fight
if (weapon->getWeaponType() == WEAPON_DISTANCE) {
ammunition = player->getAmmunition();
if (weapon->getAmmoType() != AMMO_NONE) {
if (!ammunition || ammunition->getWeaponType() != WEAPON_AMMO || weapon->getAmmoType() != ammunition->getAmmoType()) {
if (!ammunition || weapon->getAmmoType() != ammunition->getAmmoType()) {
// redirect to fist fighting
return closeAttack(attacker, target, fightMode, true);
return closeAttack(attacker, target, fightMode);
}
distanceEffect = ammunition->getMissileType();
@@ -991,6 +994,7 @@ bool Combat::rangeAttack(Creature* attacker, Creature* target, fightMode_t fight
CombatDamage combatDamage;
combatDamage.type = combatParams.combatType;
combatDamage.value = Combat::getTotalDamage(skillValue, attackValue, fightMode);
combatDamage.origin = ORIGIN_RANGED;
if (weapon) {
hitChance = 75; // throwables and such
@@ -1011,7 +1015,7 @@ bool Combat::rangeAttack(Creature* attacker, Creature* target, fightMode_t fight
}
}
if (ammunition && ammunition->getWeaponType() == WEAPON_AMMO && weapon->getAmmoType() != AMMO_NONE && weapon->getAmmoType() == ammunition->getAmmoType()) {
if (ammunition && weapon->getAmmoType() != AMMO_NONE && weapon->getAmmoType() == ammunition->getAmmoType()) {
hitChance = 90; // bows and crossbows
specialEffect = ammunition->getWeaponSpecialEffect();
attackStrength = ammunition->getAttackStrength();
@@ -1037,10 +1041,12 @@ bool Combat::rangeAttack(Creature* attacker, Creature* target, fightMode_t fight
bool hit = false;
if (rand() % distance <= skillValue) {
hit = rand() % 100 <= hitChance;
int32_t random = rand();
if (random % distance <= static_cast<int32_t>(skillValue)) {
hit = random % 100 <= hitChance;
}
if (Player* player = attacker->getPlayer()) {
if (player->getAddAttackSkill()) {
switch (player->getLastAttackBlockType()) {
@@ -1130,6 +1136,7 @@ bool Combat::rangeAttack(Creature* attacker, Creature* target, fightMode_t fight
CombatDamage combatDamage;
combatDamage.type = combatParams.combatType;
combatDamage.value = -(variation + weapon->getAttackStrength());
combatDamage.origin = ORIGIN_RANGED;
g_game.addDistanceEffect(attackerPos, targetPos, distanceEffect);
Combat::doCombatHealth(attacker, target, combatDamage, combatParams);
@@ -1182,13 +1189,13 @@ void Combat::circleShapeSpell(Creature* attacker, const Position& toPos, int32_t
}
}
void Combat::getAttackValue(Creature* creature, uint32_t& attackValue, uint32_t& skillValue, uint8_t& skill, bool fist)
void Combat::getAttackValue(Creature* creature, uint32_t& attackValue, uint32_t& skillValue, uint8_t& skill)
{
skill = SKILL_FIST;
if (Player* player = creature->getPlayer()) {
Item* weapon = player->getWeapon();
if (weapon && !fist) {
if (weapon) {
switch (weapon->getWeaponType()) {
case WEAPON_AXE: {
skill = SKILL_AXE;
@@ -1243,7 +1250,7 @@ bool Combat::canUseWeapon(Player* player, Item* weapon)
return false;
}
if (!player->hasFlag(PlayerFlag_HasInfiniteMana) && player->getMana() < weapon->getManaConsumption()) {
if (!player->hasFlag(PlayerFlag_HasInfiniteMana) && static_cast<int32_t>(player->getMana()) < weapon->getManaConsumption()) {
return false;
}
@@ -1278,14 +1285,14 @@ bool Combat::doCombatHealth(Creature* caster, Creature* target, CombatDamage& da
}
if (canCombat) {
canCombat = CombatHealthFunc(caster, target, params, &damage);
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, target);
}
if (caster && params.distanceEffect != CONST_ANI_NONE) {
addDistanceEffect(caster->getPosition(), target->getPosition(), params.distanceEffect);
}
CombatHealthFunc(caster, target, params, &damage);
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, target);
}
}
return canCombat;
@@ -1304,14 +1311,14 @@ void Combat::doCombatMana(Creature* caster, Creature* target, CombatDamage& dama
}
if (canCombat) {
if (caster && params.distanceEffect != CONST_ANI_NONE) {
addDistanceEffect(caster->getPosition(), target->getPosition(), params.distanceEffect);
}
CombatManaFunc(caster, target, params, &damage);
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, target);
}
if (caster && params.distanceEffect != CONST_ANI_NONE) {
addDistanceEffect(caster->getPosition(), target->getPosition(), params.distanceEffect);
}
}
}
@@ -1333,14 +1340,14 @@ void Combat::doCombatCondition(Creature* caster, Creature* target, const CombatP
}
if (canCombat) {
if (caster && params.distanceEffect != CONST_ANI_NONE) {
addDistanceEffect(caster->getPosition(), target->getPosition(), params.distanceEffect);
}
CombatConditionFunc(caster, target, params, nullptr);
if (params.targetCallback) {
params.targetCallback->onTargetCombat(caster, target);
}
if (caster && params.distanceEffect != CONST_ANI_NONE) {
addDistanceEffect(caster->getPosition(), target->getPosition(), params.distanceEffect);
}
}
}