aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Entities')
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp205
-rw-r--r--src/server/game/Entities/Creature/Creature.h7
-rw-r--r--src/server/game/Entities/Object/Object.cpp6
-rw-r--r--src/server/game/Entities/Object/Object.h9
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp13
-rw-r--r--src/server/game/Entities/Pet/Pet.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp42
-rw-r--r--src/server/game/Entities/Player/Player.h9
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp16
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp64
-rw-r--r--src/server/game/Entities/Unit/Unit.h4
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.cpp15
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.h2
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;