diff options
Diffstat (limited to 'src/server/game/Entities')
| -rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 205 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 7 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 6 | ||||
| -rw-r--r-- | src/server/game/Entities/Object/Object.h | 9 | ||||
| -rw-r--r-- | src/server/game/Entities/Pet/Pet.cpp | 13 | ||||
| -rw-r--r-- | src/server/game/Entities/Pet/Pet.h | 2 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 42 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.h | 9 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/StatSystem.cpp | 16 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 64 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.cpp | 15 | ||||
| -rw-r--r-- | src/server/game/Entities/Vehicle/Vehicle.h | 2 |
13 files changed, 162 insertions, 232 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 79beab4f7e6..f0b21a29bd2 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -330,9 +330,6 @@ bool Creature::InitEntry(uint32 entry, uint32 /*team*/, const CreatureData* data SetName(normalInfo->Name); // at normal entry always - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, minfo->bounding_radius); - SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach); - SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f); SetFloatValue(UNIT_MOD_CAST_HASTE, 1.0f); @@ -341,6 +338,7 @@ bool Creature::InitEntry(uint32 entry, uint32 /*team*/, const CreatureData* data SetSpeed(MOVE_SWIM, 1.0f); // using 1.0 rate SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate + // Will set UNIT_FIELD_BOUNDINGRADIUS and UNIT_FIELD_COMBATREACH SetObjectScale(cinfo->scale); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, cinfo->HoverHeight); @@ -439,28 +437,7 @@ bool Creature::UpdateEntry(uint32 Entry, uint32 team, const CreatureData* data) ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); } - // Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc) - float ground = GetPositionZ(); - GetMap()->GetWaterOrGroundLevel(GetPositionX(), GetPositionY(), GetPositionZ(), &ground); - - bool isInAir = G3D::fuzzyGt(GetPositionZ(), ground + 0.05f) || G3D::fuzzyLt(GetPositionZ(), ground - 0.05f); // Can be underground too, prevent the falling - - if (cInfo->InhabitType & INHABIT_AIR && cInfo->InhabitType & INHABIT_GROUND && isInAir) - SetCanFly(true); - else if (cInfo->InhabitType & INHABIT_AIR && isInAir) - SetDisableGravity(true); - else - { - SetCanFly(false); - SetDisableGravity(false); - } - - // TODO: Shouldn't we check whether or not the creature is in water first? - if (cInfo->InhabitType & INHABIT_WATER && IsInWater()) - AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - else - RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - + UpdateMovementFlags(); return true; } @@ -474,33 +451,7 @@ void Creature::Update(uint32 diff) m_vehicleKit->Reset(); } - if (IsInWater()) - { - if (canSwim()) - AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - } - else - { - if (canWalk()) - RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - } - - // Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc) - float ground = GetPositionZ(); - GetMap()->GetWaterOrGroundLevel(GetPositionX(), GetPositionY(), GetPositionZ(), &ground); - - bool isInAir = G3D::fuzzyGt(GetPositionZ(), ground + 0.05f) || G3D::fuzzyLt(GetPositionZ(), ground - 0.05f); // Can be underground too, prevent the falling - CreatureTemplate const* cinfo = GetCreatureTemplate(); - - if (cinfo->InhabitType & INHABIT_AIR && cinfo->InhabitType & INHABIT_GROUND && isInAir) - SetCanFly(true); - else if (cinfo->InhabitType & INHABIT_AIR && isInAir) - SetDisableGravity(true); - else - { - SetCanFly(false); - SetDisableGravity(false); - } + UpdateMovementFlags(); switch (m_deathState) { @@ -870,84 +821,6 @@ void Creature::InitializeReactState() SetReactState(REACT_DEFENSIVE);*/; } -bool Creature::isCanTrainingOf(Player* player, bool msg) const -{ - if (!isTrainer()) - return false; - - TrainerSpellData const* trainer_spells = GetTrainerSpells(); - - if ((!trainer_spells || trainer_spells->spellList.empty()) && GetCreatureTemplate()->trainer_type != TRAINER_TYPE_PETS) - { - TC_LOG_ERROR(LOG_FILTER_SQL, "Creature %u (Entry: %u) have UNIT_NPC_FLAG_TRAINER but have empty trainer spell list.", - GetGUIDLow(), GetEntry()); - return false; - } - - switch (GetCreatureTemplate()->trainer_type) - { - case TRAINER_TYPE_CLASS: - if (player->getClass() != GetCreatureTemplate()->trainer_class) - { - if (msg) - { - player->PlayerTalkClass->ClearMenus(); - switch (GetCreatureTemplate()->trainer_class) - { - case CLASS_DRUID: player->PlayerTalkClass->SendGossipMenu(4913, GetGUID()); break; - case CLASS_HUNTER: player->PlayerTalkClass->SendGossipMenu(10090, GetGUID()); break; - case CLASS_MAGE: player->PlayerTalkClass->SendGossipMenu(328, GetGUID()); break; - case CLASS_PALADIN:player->PlayerTalkClass->SendGossipMenu(1635, GetGUID()); break; - case CLASS_PRIEST: player->PlayerTalkClass->SendGossipMenu(4436, GetGUID()); break; - case CLASS_ROGUE: player->PlayerTalkClass->SendGossipMenu(4797, GetGUID()); break; - case CLASS_SHAMAN: player->PlayerTalkClass->SendGossipMenu(5003, GetGUID()); break; - case CLASS_WARLOCK:player->PlayerTalkClass->SendGossipMenu(5836, GetGUID()); break; - case CLASS_WARRIOR:player->PlayerTalkClass->SendGossipMenu(4985, GetGUID()); break; - } - } - return false; - } - break; - case TRAINER_TYPE_PETS: - if (player->getClass() != CLASS_HUNTER) - { - player->PlayerTalkClass->ClearMenus(); - player->PlayerTalkClass->SendGossipMenu(3620, GetGUID()); - return false; - } - break; - case TRAINER_TYPE_MOUNTS: - if (GetCreatureTemplate()->trainer_race && player->getRace() != GetCreatureTemplate()->trainer_race) - { - if (msg) - { - player->PlayerTalkClass->ClearMenus(); - switch (GetCreatureTemplate()->trainer_race) - { - case RACE_DWARF: player->PlayerTalkClass->SendGossipMenu(5865, GetGUID()); break; - case RACE_GNOME: player->PlayerTalkClass->SendGossipMenu(4881, GetGUID()); break; - case RACE_HUMAN: player->PlayerTalkClass->SendGossipMenu(5861, GetGUID()); break; - case RACE_NIGHTELF: player->PlayerTalkClass->SendGossipMenu(5862, GetGUID()); break; - case RACE_ORC: player->PlayerTalkClass->SendGossipMenu(5863, GetGUID()); break; - case RACE_TAUREN: player->PlayerTalkClass->SendGossipMenu(5864, GetGUID()); break; - case RACE_TROLL: player->PlayerTalkClass->SendGossipMenu(5816, GetGUID()); break; - case RACE_UNDEAD_PLAYER:player->PlayerTalkClass->SendGossipMenu(624, GetGUID()); break; - case RACE_BLOODELF: player->PlayerTalkClass->SendGossipMenu(5862, GetGUID()); break; - case RACE_DRAENEI: player->PlayerTalkClass->SendGossipMenu(5864, GetGUID()); break; - } - } - return false; - } - break; - case TRAINER_TYPE_TRADESKILLS: - // There's no Blacksmith specialization on Cataclysm, conditions are not required for tradeskills - break; - default: - return false; // checked and error output at creature_template loading - } - return true; -} - bool Creature::isCanInteractWithBattleMaster(Player* player, bool msg) const { if (!isBattleMaster()) @@ -1588,30 +1461,10 @@ void Creature::setDeathState(DeathState s) SetFullHealth(); SetLootRecipient(NULL); ResetPlayerDamageReq(); - CreatureTemplate const* cinfo = GetCreatureTemplate(); - SetWalk(true); - - // Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc) - float ground = GetPositionZ(); - GetMap()->GetWaterOrGroundLevel(GetPositionX(), GetPositionY(), GetPositionZ(), &ground); - bool isInAir = G3D::fuzzyGt(GetPositionZ(), ground + 0.05f) || G3D::fuzzyLt(GetPositionZ(), ground - 0.05f); // Can be underground too, prevent the falling - - if (cinfo->InhabitType & INHABIT_AIR && cinfo->InhabitType & INHABIT_GROUND && isInAir) - SetCanFly(true); - else if (cinfo->InhabitType & INHABIT_AIR && isInAir) - SetDisableGravity(true); - else - { - SetCanFly(false); - SetDisableGravity(false); - } - - if (cinfo->InhabitType & INHABIT_WATER && IsInWater()) - AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); - else - RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); + UpdateMovementFlags(); + CreatureTemplate const* cinfo = GetCreatureTemplate(); SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); ClearUnitState(uint32(UNIT_STATE_ALL_STATE)); SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); @@ -2675,3 +2528,51 @@ Unit* Creature::SelectNearestHostileUnitInAggroRange(bool useLOS) const return target; } + +void Creature::UpdateMovementFlags() +{ + // Set the movement flags if the creature is in that mode. (Only fly if actually in air, only swim if in water, etc) + float ground = GetMap()->GetHeight(GetPositionX(), GetPositionY(), GetPositionZMinusOffset()); + + bool isInAir = !IsFalling() && (G3D::fuzzyGt(GetPositionZMinusOffset(), ground + 0.05f) || G3D::fuzzyLt(GetPositionZMinusOffset(), ground - 0.05f)); // Can be underground too, prevent the falling + + if (GetCreatureTemplate()->InhabitType & INHABIT_AIR && isInAir) + { + if (GetCreatureTemplate()->InhabitType & INHABIT_GROUND) + SetCanFly(true); + else + SetDisableGravity(true); + } + else + { + SetCanFly(false); + SetDisableGravity(false); + } + + if (GetCreatureTemplate()->InhabitType & INHABIT_WATER && IsInWater()) + AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING); + else + RemoveUnitMovementFlag(MOVEMENTFLAG_SWIMMING); +} + +void Creature::SetObjectScale(float scale) +{ + Unit::SetObjectScale(scale); + + if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(GetDisplayId())) + { + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, minfo->bounding_radius * scale); + SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach * scale); + } +} + +void Creature::SetDisplayId(uint32 modelId) +{ + Unit::SetDisplayId(modelId); + + if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId)) + { + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, minfo->bounding_radius * GetFloatValue(OBJECT_FIELD_SCALE_X)); + SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach * GetFloatValue(OBJECT_FIELD_SCALE_X)); + } +} diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 4d55b97732d..df4031f521f 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -453,6 +453,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature void AddToWorld(); void RemoveFromWorld(); + void SetObjectScale(float scale); + void SetDisplayId(uint32 modelId); + void DisappearAndDie(); bool Create(uint32 guidlow, Map* map, uint32 phaseMask, uint32 Entry, uint32 vehId, uint32 team, float x, float y, float z, float ang, const CreatureData* data = NULL); @@ -481,7 +484,6 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature void InitializeReactState(); /// @todo Rename these properly - bool isCanTrainingOf(Player* player, bool msg) const; bool isCanInteractWithBattleMaster(Player* player, bool msg) const; bool isCanTrainingAndResetTalentsOf(Player* player) const; bool canCreatureAttack(Unit const* victim, bool force = true) const; @@ -519,6 +521,9 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature bool HasSpell(uint32 spellID) const; bool UpdateEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL); + + void UpdateMovementFlags(); + bool UpdateStats(Stats stat); bool UpdateAllStats(); void UpdateResistances(uint32 school); diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index ed0ac21f6cb..96248f067de 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -761,12 +761,6 @@ void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask* { if (!target->canSeeSpellClickOn(this->ToCreature())) appendValue &= ~UNIT_NPC_FLAG_SPELLCLICK; - - if (appendValue & UNIT_NPC_FLAG_TRAINER) - { - if (!creature->isCanTrainingOf(target, false)) - appendValue &= ~(UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS | UNIT_NPC_FLAG_TRAINER_PROFESSION); - } } *data << uint32(appendValue); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 854978b921f..a72f4fcf3e4 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -518,6 +518,15 @@ struct MovementInfo void SetFallTime(uint32 time) { fallTime = time; } + void ClearTransport() + { + t_guid = 0; + t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); + t_seat = -1; + t_time = 0; + t_time2 = 0; + } + void OutDebug(); }; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 1612b45bc89..ce564bd9090 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -2038,3 +2038,16 @@ Player* Pet::GetOwner() const { return Minion::GetOwner()->ToPlayer(); } + +void Pet::SetDisplayId(uint32 modelId) +{ + Guardian::SetDisplayId(modelId); + + if (!isControlled()) + return; + + if (Unit* owner = GetOwner()) + if (Player* player = owner->ToPlayer()) + if (owner->ToPlayer()->GetGroup()) + owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); +} diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 975b97adce3..ac274e3035d 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -46,6 +46,8 @@ class Pet : public Guardian void AddToWorld(); void RemoveFromWorld(); + void SetDisplayId(uint32 modelId); + PetType getPetType() const { return m_petType; } void setPetType(PetType type) { m_petType = type; } bool isControlled() const { return getPetType() == SUMMON_PET || getPetType() == HUNTER_PET; } diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e35e4b7d505..642da3e8d95 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -978,8 +978,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) uint8 powertype = cEntry->powerType; - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); - SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); + SetObjectScale(1.0f); setFactionForRace(createInfo->Race); @@ -2136,9 +2135,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { m_transport->RemovePassenger(this); m_transport = NULL; - m_movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); - m_movementInfo.t_time = 0; - m_movementInfo.t_seat = -1; + m_movementInfo.ClearTransport(); RepopAtGraveyard(); // teleport to near graveyard if on transport, looks blizz like :) } @@ -2162,10 +2159,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati { m_transport->RemovePassenger(this); m_transport = NULL; - m_movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); - m_movementInfo.t_time = 0; - m_movementInfo.t_seat = -1; - m_movementInfo.t_guid = 0; + m_movementInfo.ClearTransport(); } } @@ -4588,16 +4582,16 @@ Mail* Player::GetMail(uint32 id) void Player::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const { - for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) + if (target == this) { - if (m_items[i] == NULL) - continue; + for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i) + { + if (m_items[i] == NULL) + continue; - m_items[i]->BuildCreateUpdateBlockForPlayer(data, target); - } + m_items[i]->BuildCreateUpdateBlockForPlayer(data, target); + } - if (target == this) - { for (uint8 i = INVENTORY_SLOT_BAG_START; i < BANK_SLOT_BAG_END; ++i) { if (m_items[i] == NULL) @@ -5158,8 +5152,6 @@ void Player::BuildPlayerRepop() StopMirrorTimers(); //disable timers(bars) - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, float(1.0f)); //see radius of death player? - // set and clear other SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND); } @@ -14419,10 +14411,6 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool } break; } - case GOSSIP_OPTION_TRAINER: - if (!creature->isCanTrainingOf(this, false)) - canTalk = false; - break; case GOSSIP_OPTION_LEARNDUALSPEC: if (!(GetSpecsCount() == 1 && creature->isCanTrainingAndResetTalentsOf(this) && !(getLevel() < sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)))) canTalk = false; @@ -14450,6 +14438,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool case GOSSIP_OPTION_QUESTGIVER: canTalk = false; break; + case GOSSIP_OPTION_TRAINER: case GOSSIP_OPTION_GOSSIP: case GOSSIP_OPTION_SPIRITGUIDE: case GOSSIP_OPTION_INNKEEPER: @@ -14463,7 +14452,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool canTalk = false; break; default: - TC_LOG_ERROR(LOG_FILTER_SQL, "Creature entry %u have unknown gossip option %u for menu %u", creature->GetEntry(), itr->second.OptionType, itr->second.MenuId); + TC_LOG_ERROR(LOG_FILTER_SQL, "Creature entry %u has unknown gossip option %u for menu %u", creature->GetEntry(), itr->second.OptionType, itr->second.MenuId); canTalk = false; break; } @@ -17088,8 +17077,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) _LoadIntoDataField(fields[55].GetCString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE); _LoadIntoDataField(fields[57].GetCString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2); - SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); - SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); + SetObjectScale(1.0f); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f); // load achievements before anything else to prevent multiple gains for the same achievement/criteria on every loading (as loading does call UpdateAchievementCriteria) @@ -18926,7 +18914,9 @@ void Player::ConvertInstancesToGroup(Player* player, Group* group, bool switchLe { for (BoundInstancesMap::iterator itr = player->m_boundInstances[i].begin(); itr != player->m_boundInstances[i].end();) { - group->BindToInstance(itr->second.save, itr->second.perm, false); + if (!switchLeader || !group->GetBoundInstance(itr->second.save->GetDifficulty(), itr->first)) + group->BindToInstance(itr->second.save, itr->second.perm, false); + // permanent binds are not removed if (switchLeader && !itr->second.perm) { diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 1dba62f1f3b..bbda2a75fba 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1214,7 +1214,7 @@ class Player : public Unit, public GridObject<Player> friend void Item::AddToUpdateQueueOf(Player* player); friend void Item::RemoveFromUpdateQueueOf(Player* player); public: - explicit Player (WorldSession* session); + explicit Player(WorldSession* session); ~Player(); void CleanupsBeforeDelete(bool finalCleanup = true); @@ -1222,6 +1222,13 @@ class Player : public Unit, public GridObject<Player> void AddToWorld(); void RemoveFromWorld(); + void SetObjectScale(float scale) + { + Unit::SetObjectScale(scale); + SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, scale * DEFAULT_WORLD_OBJECT_SIZE); + SetFloatValue(UNIT_FIELD_COMBATREACH, scale * DEFAULT_COMBAT_REACH); + } + bool TeleportTo(uint32 mapid, float x, float y, float z, float orientation, uint32 options = 0); bool TeleportTo(WorldLocation const &loc, uint32 options = 0); bool TeleportToBGEntryPoint(); diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 1f4ab95517d..ac771004096 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -24,6 +24,7 @@ #include "SpellAuras.h" #include "SpellAuraEffects.h" #include "SpellMgr.h" +#include "World.h" inline bool _ModifyUInt32(bool apply, uint32& baseValue, int32& amount) { @@ -437,6 +438,10 @@ void Player::UpdateBlockPercentage() value += GetTotalAuraModifier(SPELL_AURA_MOD_BLOCK_PERCENT); // Increase from rating value += GetRatingBonusValue(CR_BLOCK); + + if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE)) + value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_BLOCK) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_BLOCK) : value; + value = value < 0.0f ? 0.0f : value; } SetStatFloatValue(PLAYER_BLOCK_PERCENTAGE, value); @@ -471,6 +476,10 @@ void Player::UpdateCritPercentage(WeaponAttackType attType) float value = GetTotalPercentageModValue(modGroup) + GetRatingBonusValue(cr); // Modify crit from weapon skill and maximized defense skill of same level victim difference value += (int32(GetMaxSkillValueForLevel()) - int32(GetMaxSkillValueForLevel())) * 0.04f; + + if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE)) + value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_CRIT) : value; + value = value < 0.0f ? 0.0f : value; SetStatFloatValue(index, value); } @@ -570,6 +579,10 @@ void Player::UpdateParryPercentage() nondiminishing += GetTotalAuraModifier(SPELL_AURA_MOD_PARRY_PERCENT); // apply diminishing formula to diminishing parry chance value = nondiminishing + diminishing * parry_cap[pclass] / (diminishing + parry_cap[pclass] * m_diminishing_k[pclass]); + + if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE)) + value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_PARRY) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_PARRY) : value; + value = value < 0.0f ? 0.0f : value; } SetStatFloatValue(PLAYER_PARRY_PERCENTAGE, value); @@ -602,6 +615,9 @@ void Player::UpdateDodgePercentage() uint32 pclass = getClass()-1; float value = nondiminishing + (diminishing * dodge_cap[pclass] / (diminishing + dodge_cap[pclass] * m_diminishing_k[pclass])); + if (sWorld->getBoolConfig(CONFIG_STATS_LIMITS_ENABLE)) + value = value > sWorld->getFloatConfig(CONFIG_STATS_LIMITS_DODGE) ? sWorld->getFloatConfig(CONFIG_STATS_LIMITS_DODGE) : value; + value = value < 0.0f ? 0.0f : value; SetStatFloatValue(PLAYER_DODGE_PERCENTAGE, value); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 6c226693871..bda77af54ed 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -13317,16 +13317,6 @@ bool Unit::IsPolymorphed() const void Unit::SetDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId); - - if (GetTypeId() == TYPEID_UNIT && ToCreature()->isPet()) - { - Pet* pet = ToPet(); - if (!pet->isControlled()) - return; - Unit* owner = GetOwner(); - if (owner && (owner->GetTypeId() == TYPEID_PLAYER) && owner->ToPlayer()->GetGroup()) - owner->ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); - } } void Unit::RestoreDisplayId() @@ -15862,29 +15852,23 @@ void Unit::EnterVehicle(Unit* base, int8 seatId) void Unit::_EnterVehicle(Vehicle* vehicle, int8 seatId, AuraApplication const* aurApp) { // Must be called only from aura handler + ASSERT(aurApp); + if (!isAlive() || GetVehicleKit() == vehicle || vehicle->GetBase()->IsOnVehicle(this)) return; if (m_vehicle) { - if (m_vehicle == vehicle) - { - if (seatId >= 0 && seatId != GetTransSeat()) - { - TC_LOG_DEBUG(LOG_FILTER_VEHICLES, "EnterVehicle: %u leave vehicle %u seat %d and enter %d.", GetEntry(), m_vehicle->GetBase()->GetEntry(), GetTransSeat(), seatId); - ChangeSeat(seatId); - } - - return; - } - else + if (m_vehicle != vehicle) { TC_LOG_DEBUG(LOG_FILTER_VEHICLES, "EnterVehicle: %u exit %u and enter %u.", GetEntry(), m_vehicle->GetBase()->GetEntry(), vehicle->GetBase()->GetEntry()); ExitVehicle(); } + else if (seatId >= 0 && seatId == GetTransSeat()) + return; } - if (!aurApp || aurApp->GetRemoveMode()) + if (aurApp->GetRemoveMode()) return; if (Player* player = ToPlayer()) @@ -15914,16 +15898,22 @@ void Unit::ChangeSeat(int8 seatId, bool next) if (seat == m_vehicle->Seats.end() || seat->second.Passenger) return; - // Todo: the functions below could be consolidated and refactored to take - // SeatMap::const_iterator as parameter, to save redundant map lookups. - m_vehicle->RemovePassenger(this); + AuraEffect* rideVehicleEffect = NULL; + AuraEffectList const& vehicleAuras = m_vehicle->GetBase()->GetAuraEffectsByType(SPELL_AURA_CONTROL_VEHICLE); + for (AuraEffectList::const_iterator itr = vehicleAuras.begin(); itr != vehicleAuras.end(); ++itr) + { + if ((*itr)->GetCasterGUID() != GetGUID()) + continue; + + // Make sure there is only one ride vehicle aura on target cast by the unit changing seat + ASSERT(!rideVehicleEffect); + rideVehicleEffect = *itr; + } + + // Unit riding a vehicle must always have control vehicle aura on target + ASSERT(rideVehicleEffect); - // Set m_vehicle to NULL before adding passenger as adding new passengers is handled asynchronously - // and someone may call ExitVehicle again before passenger is added to new seat - Vehicle* veh = m_vehicle; - m_vehicle = NULL; - if (!veh->AddPassenger(this, seatId)) - ASSERT(false); + rideVehicleEffect->ChangeAmount(seat->first + 1); } void Unit::ExitVehicle(Position const* /*exitPosition*/) @@ -15953,7 +15943,8 @@ void Unit::_ExitVehicle(Position const* exitPosition) if (!m_vehicle) return; - m_vehicle->RemovePassenger(this); + // This should be done before dismiss, because there may be some aura removal + Vehicle* vehicle = m_vehicle->RemovePassenger(this); Player* player = ToPlayer(); @@ -15961,10 +15952,6 @@ void Unit::_ExitVehicle(Position const* exitPosition) if (player && player->duel && player->duel->isMounted) player->DuelComplete(DUEL_FLED); - // This should be done before dismiss, because there may be some aura removal - Vehicle* vehicle = m_vehicle; - m_vehicle = NULL; - SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT Position pos; @@ -16016,6 +16003,11 @@ void Unit::_ExitVehicle(Position const* exitPosition) } } +bool Unit::IsFalling() const +{ + return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FALLING | MOVEMENTFLAG_FALLING_FAR) || movespline->isFalling(); +} + void Unit::SetCanFly(bool apply) { if (apply) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 7d149332694..f164b04644b 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1931,7 +1931,7 @@ class Unit : public WorldObject void UpdateInterruptMask(); uint32 GetDisplayId() const { return GetUInt32Value(UNIT_FIELD_DISPLAYID); } - void SetDisplayId(uint32 modelId); + virtual void SetDisplayId(uint32 modelId); uint32 GetNativeDisplayId() const { return GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID); } void RestoreDisplayId(); void SetNativeDisplayId(uint32 modelId) { SetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); } @@ -2090,6 +2090,7 @@ class Unit : public WorldObject void RemoveVehicleKit(); Vehicle* GetVehicleKit()const { return m_vehicleKit; } Vehicle* GetVehicle() const { return m_vehicle; } + void SetVehicle(Vehicle* vehicle) { m_vehicle = vehicle; } bool IsOnVehicle(const Unit* vehicle) const; Unit* GetVehicleBase() const; Creature* GetVehicleCreatureBase() const; @@ -2120,6 +2121,7 @@ class Unit : public WorldObject bool isTurning() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_MASK_TURNING); } virtual bool CanFly() const = 0; bool IsFlying() const { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_DISABLE_GRAVITY); } + bool IsFalling() const; void SetCanFly(bool apply); void RewardRage(uint32 baseRage, bool attacker); diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp index 503d89a8e82..797430683f4 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.cpp +++ b/src/server/game/Entities/Vehicle/Vehicle.cpp @@ -496,10 +496,10 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId) * @param [in, out] unit The passenger to remove. */ -void Vehicle::RemovePassenger(Unit* unit) +Vehicle* Vehicle::RemovePassenger(Unit* unit) { if (unit->GetVehicle() != this) - return; + return NULL; SeatMap::iterator seat = GetSeatIteratorForPassenger(unit); ASSERT(seat != Seats.end()); @@ -517,11 +517,7 @@ void Vehicle::RemovePassenger(Unit* unit) _me->RemoveCharmedBy(unit); if (_me->IsInWorld()) - { - unit->m_movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f); - unit->m_movementInfo.t_time = 0; - unit->m_movementInfo.t_seat = 0; - } + unit->m_movementInfo.ClearTransport(); // only for flyable vehicles if (unit->IsFlying()) @@ -532,6 +528,9 @@ void Vehicle::RemovePassenger(Unit* unit) if (GetBase()->GetTypeId() == TYPEID_UNIT) sScriptMgr->OnRemovePassenger(this, unit); + + unit->SetVehicle(NULL); + return this; } /** @@ -803,7 +802,7 @@ bool VehicleJoinEvent::Execute(uint64, uint32) Target->RemovePendingEventsForSeat(Seat->first); - Passenger->m_vehicle = Target; + Passenger->SetVehicle(Target); Seat->second.Passenger = Passenger->GetGUID(); if (Seat->second.SeatInfo->CanEnterOrExit()) { diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h index c83a9fa5f33..9fb1b6614b5 100644 --- a/src/server/game/Entities/Vehicle/Vehicle.h +++ b/src/server/game/Entities/Vehicle/Vehicle.h @@ -59,7 +59,7 @@ class Vehicle : public TransportBase bool AddPassenger(Unit* passenger, int8 seatId = -1); void EjectPassenger(Unit* passenger, Unit* controller); - void RemovePassenger(Unit* passenger); + Vehicle* RemovePassenger(Unit* passenger); void RelocatePassengers(); void RemoveAllPassengers(); bool IsVehicleInUse() const; |
