aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorVincent-Michael <Vincent_Michael@gmx.de>2013-06-11 22:07:11 +0200
committerVincent-Michael <Vincent_Michael@gmx.de>2013-06-11 22:07:11 +0200
commit0bebf40fe7fc6ffdf3e86452f14e3bf647380b15 (patch)
tree42afd9e6643b3bd3400c9f4f80fd3991748fbcd7 /src/server/game
parent93c86b0c52a99d69fd14f4904a000b6c86759c69 (diff)
parent9ec22fffa00135cd776afebe2899bf54fb52f15f (diff)
Merge branch 'master' of github.com:TrinityCore/TrinityCore into 4.3.4
Conflicts: src/server/game/AuctionHouse/AuctionHouseMgr.h src/server/game/Entities/Creature/Creature.cpp src/server/game/Entities/Player/Player.cpp src/server/game/Entities/Unit/StatSystem.cpp src/server/game/Entities/Unit/Unit.cpp src/server/game/Entities/Vehicle/Vehicle.cpp src/server/game/Handlers/NPCHandler.cpp
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp9
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.h8
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp3
-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
-rw-r--r--src/server/game/Events/GameEventMgr.cpp10
-rw-r--r--src/server/game/Groups/Group.cpp44
-rw-r--r--src/server/game/Handlers/AuctionHouseHandler.cpp3
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp4
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp10
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp11
-rw-r--r--src/server/game/Maps/Map.cpp19
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp8
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.h1
-rw-r--r--src/server/game/Scripting/ScriptMgr.h4
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp11
-rw-r--r--src/server/game/Spells/Spell.cpp21
-rw-r--r--src/server/game/Spells/SpellEffects.cpp18
-rw-r--r--src/server/game/World/World.cpp7
-rw-r--r--src/server/game/World/World.h5
31 files changed, 263 insertions, 327 deletions
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 8f0eadbe88d..6186e616928 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -256,6 +256,15 @@ void AuctionHouseMgr::LoadAuctionItems()
{
uint32 oldMSTime = getMSTime();
+ // need to clear in case we are reloading
+ if (!mAitems.empty())
+ {
+ for (ItemMap::iterator itr = mAitems.begin(); itr != mAitems.end(); ++itr)
+ delete itr->second;
+
+ mAitems.clear();
+ }
+
// data needs to be at first place for Item::LoadFromDB
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_AUCTION_ITEMS);
PreparedQueryResult result = CharacterDatabase.Query(stmt);
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h
index 7c870c20b65..5b5b172b2d4 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.h
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h
@@ -42,14 +42,14 @@ enum AuctionError
ERR_AUCTION_HIGHER_BID = 5,
ERR_AUCTION_BID_INCREMENT = 7,
ERR_AUCTION_BID_OWN = 10,
- ERR_RESTRICTED_ACCOUNT = 13,
+ ERR_AUCTION_RESTRICTED_ACCOUNT = 13
};
enum AuctionAction
{
- AUCTION_SELL_ITEM = 0,
- AUCTION_CANCEL = 1,
- AUCTION_PLACE_BID = 2
+ AUCTION_SELL_ITEM = 0,
+ AUCTION_CANCEL = 1,
+ AUCTION_PLACE_BID = 2
};
enum MailAuctionAnswers
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index a2c95c30cab..d6fb6905985 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -1674,7 +1674,8 @@ bool ConditionMgr::isConditionTypeValid(Condition* cond)
{
if (!sObjectMgr->GetQuestTemplate(cond->ConditionValue1))
{
- TC_LOG_ERROR(LOG_FILTER_SQL, "Quest condition specifies non-existing quest (%u), skipped", cond->ConditionValue1);
+ TC_LOG_ERROR(LOG_FILTER_SQL, "Quest condition (Type: %u) points to non-existing quest (%u) for Source Entry %u. SourceGroup: %u, SourceTypeOrReferenceId: %u",
+ cond->ConditionType, cond->ConditionValue1, cond->SourceEntry, cond->SourceGroup, cond->SourceType);
return false;
}
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;
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index 6f6080c8d91..54e1ca6a5d6 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -1332,13 +1332,10 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
creature->LoadEquipment(itr->second.equipment_id, true);
if (itr->second.modelid > 0 && itr->second.modelid_prev != itr->second.modelid)
{
- CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid);
- if (minfo)
+ if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid))
{
creature->SetDisplayId(itr->second.modelid);
creature->SetNativeDisplayId(itr->second.modelid);
- creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, minfo->bounding_radius);
- creature->SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach);
}
}
}
@@ -1347,13 +1344,10 @@ void GameEventMgr::ChangeEquipOrModel(int16 event_id, bool activate)
creature->LoadEquipment(itr->second.equipement_id_prev, true);
if (itr->second.modelid_prev > 0 && itr->second.modelid_prev != itr->second.modelid)
{
- CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev);
- if (minfo)
+ if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(itr->second.modelid_prev))
{
creature->SetDisplayId(itr->second.modelid_prev);
creature->SetNativeDisplayId(itr->second.modelid_prev);
- creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, minfo->bounding_radius);
- creature->SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach);
}
}
}
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index bfb0e005eda..9d27ca61511 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -646,30 +646,39 @@ bool Group::RemoveMember(uint64 guid, const RemoveMethod& method /*= GROUP_REMOV
}
}
-void Group::ChangeLeader(uint64 guid)
+void Group::ChangeLeader(uint64 newLeaderGuid)
{
- member_witerator slot = _getMemberWSlot(guid);
+ member_witerator slot = _getMemberWSlot(newLeaderGuid);
if (slot == m_memberSlots.end())
return;
- Player* player = ObjectAccessor::FindPlayer(slot->guid);
+ Player* newLeader = ObjectAccessor::FindPlayer(slot->guid);
// Don't allow switching leader to offline players
- if (!player)
+ if (!newLeader)
return;
- sScriptMgr->OnGroupChangeLeader(this, guid, m_leaderGuid);
+ sScriptMgr->OnGroupChangeLeader(this, newLeaderGuid, m_leaderGuid);
if (!isBGGroup() && !isBFGroup())
{
+ SQLTransaction trans = CharacterDatabase.BeginTransaction();
+
// Remove the groups permanent instance bindings
for (uint8 i = 0; i < MAX_DIFFICULTY; ++i)
{
for (BoundInstancesMap::iterator itr = m_boundInstances[i].begin(); itr != m_boundInstances[i].end();)
{
- if (itr->second.perm)
+ // Do not unbind saves of instances that already had map created (a newLeader entered)
+ // forcing a new instance with another leader requires group disbanding (confirmed on retail)
+ if (itr->second.perm && !sMapMgr->FindMap(itr->first, itr->second.save->GetInstanceId()))
{
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_INSTANCE_PERM_BINDING);
+ stmt->setUInt32(0, m_dbStoreId);
+ stmt->setUInt32(1, itr->second.save->GetInstanceId());
+ trans->Append(stmt);
+
itr->second.save->RemoveGroup(this);
m_boundInstances[i].erase(itr++);
}
@@ -678,29 +687,22 @@ void Group::ChangeLeader(uint64 guid)
}
}
- // Same in the database
-
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GROUP_INSTANCE_PERM_BINDING);
-
- stmt->setUInt32(0, m_dbStoreId);
- stmt->setUInt32(1, player->GetGUIDLow());
-
- CharacterDatabase.Execute(stmt);
-
// Copy the permanent binds from the new leader to the group
- Player::ConvertInstancesToGroup(player, this, true);
+ Player::ConvertInstancesToGroup(newLeader, this, true);
// Update the group leader
- stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEADER);
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GROUP_LEADER);
- stmt->setUInt32(0, player->GetGUIDLow());
+ stmt->setUInt32(0, newLeader->GetGUIDLow());
stmt->setUInt32(1, m_dbStoreId);
- CharacterDatabase.Execute(stmt);
+ trans->Append(stmt);
+
+ CharacterDatabase.CommitTransaction(trans);
}
- m_leaderGuid = player->GetGUID();
- m_leaderName = player->GetName();
+ m_leaderGuid = newLeader->GetGUID();
+ m_leaderName = newLeader->GetName();
ToggleGroupMemberFlag(slot, MEMBER_FLAG_ASSISTANT, false);
WorldPacket data(SMSG_GROUP_SET_LEADER, m_leaderName.size()+1);
diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp
index cc3b065dbe4..4ebe9a2b90d 100644
--- a/src/server/game/Handlers/AuctionHouseHandler.cpp
+++ b/src/server/game/Handlers/AuctionHouseHandler.cpp
@@ -30,9 +30,6 @@
#include "Util.h"
#include "AccountMgr.h"
-//please DO NOT use iterator++, because it is slower than ++iterator!!!
-//post-incrementation is always slower than pre-incrementation !
-
//void called when player click on auctioneer npc
void WorldSession::HandleAuctionHelloOpcode(WorldPacket& recvData)
{
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 2adc1fd2d89..2739e53b818 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -361,9 +361,7 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvPacket)
{
plrMover->m_transport->RemovePassenger(plrMover);
plrMover->m_transport = NULL;
- movementInfo.t_pos.Relocate(0.0f, 0.0f, 0.0f, 0.0f);
- movementInfo.t_time = 0;
- movementInfo.t_seat = -1;
+ movementInfo.ClearTransport();
}
// fall damage generation (ignore in flight case that can be triggered also at lags in moment teleportation to another map).
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index aebd1baa901..51533ad8a9f 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -132,10 +132,6 @@ void WorldSession::SendTrainerList(uint64 guid, const std::string& strTitle)
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- // trainer list loaded at check;
- if (!unit->isCanTrainingOf(_player, true))
- return;
-
CreatureTemplate const* ci = unit->GetCreatureTemplate();
if (!ci)
@@ -257,12 +253,6 @@ void WorldSession::HandleTrainerBuySpellOpcode(WorldPacket& recvData)
if (GetPlayer()->HasUnitState(UNIT_STATE_DIED))
GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH);
- if (!unit->isCanTrainingOf(_player, true))
- {
- SendTrainerBuyFailed(guid, spellId, 0);
- return;
- }
-
// check present spell in trainer spell list
TrainerSpellData const* trainer_spells = unit->GetTrainerSpells();
if (!trainer_spells)
diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp
index 45be13ae776..279c1392e17 100644
--- a/src/server/game/Handlers/QuestHandler.cpp
+++ b/src/server/game/Handlers/QuestHandler.cpp
@@ -499,12 +499,12 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_QUESTGIVER_COMPLETE_QUEST npc = %u, questId = %u", uint32(GUID_LOPART(playerGuid)), questId);
+ Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, playerGuid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
+ if (!object || !object->hasInvolvedQuest(questId))
+ return;
+
if (autoCompleteMode == 0)
{
- Object* object = ObjectAccessor::GetObjectByTypeMask(*_player, playerGuid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT);
- if (!object || !object->hasInvolvedQuest(questId))
- return;
-
// some kind of WPE protection
if (!_player->CanInteractWithQuestGiver(object))
return;
@@ -545,6 +545,9 @@ void WorldSession::HandleQuestgiverCompleteQuest(WorldPacket& recvData)
else // no items required
_player->PlayerTalkClass->SendQuestGiverOfferReward(quest, playerGuid, !autoCompleteMode);
}
+
+ if (Creature* creature = object->ToCreature())
+ sScriptMgr->OnQuestComplete(_player, creature, quest);
}
}
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 54a9fdea264..90e072825de 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -1934,25 +1934,14 @@ float Map::GetHeight(uint32 phasemask, float x, float y, float z, bool vmap/*=tr
bool Map::IsInWater(float x, float y, float pZ, LiquidData* data) const
{
- // Check surface in x, y point for liquid
- if (const_cast<Map*>(this)->GetGrid(x, y))
- {
- LiquidData liquid_status;
- LiquidData* liquid_ptr = data ? data : &liquid_status;
- if (getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr))
- return true;
- }
- return false;
+ LiquidData liquid_status;
+ LiquidData* liquid_ptr = data ? data : &liquid_status;
+ return getLiquidStatus(x, y, pZ, MAP_ALL_LIQUIDS, liquid_ptr) & (LIQUID_MAP_IN_WATER | LIQUID_MAP_UNDER_WATER);
}
bool Map::IsUnderWater(float x, float y, float z) const
{
- if (const_cast<Map*>(this)->GetGrid(x, y))
- {
- if (getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN)&LIQUID_MAP_UNDER_WATER)
- return true;
- }
- return false;
+ return getLiquidStatus(x, y, z, MAP_LIQUID_TYPE_WATER|MAP_LIQUID_TYPE_OCEAN) & LIQUID_MAP_UNDER_WATER;
}
bool Map::CheckGridIntegrity(Creature* c, bool moved) const
diff --git a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
index 227780daa1f..186723a1c43 100755
--- a/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/PointMovementGenerator.cpp
@@ -43,8 +43,8 @@ void PointMovementGenerator<T>::DoInitialize(T* unit)
if (speed > 0.0f)
init.SetVelocity(speed);
init.Launch();
-
- //Call for creature group update
+
+ // Call for creature group update
if (Creature* creature = unit->ToCreature())
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
creature->GetFormation()->LeaderMoveTo(i_x, i_y, i_z);
@@ -72,8 +72,8 @@ bool PointMovementGenerator<T>::DoUpdate(T* unit, uint32 /*diff*/)
if (speed > 0.0f) // Default value for point motion type is 0.0, if 0.0 spline will use GetSpeed on unit
init.SetVelocity(speed);
init.Launch();
-
- //Call for creature group update
+
+ // Call for creature group update
if (Creature* creature = unit->ToCreature())
if (creature->GetFormation() && creature->GetFormation()->getLeader() == creature)
creature->GetFormation()->LeaderMoveTo(i_x, i_y, i_z);
diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h
index b18166ea615..a76c552079b 100644
--- a/src/server/game/Movement/Spline/MoveSpline.h
+++ b/src/server/game/Movement/Spline/MoveSpline.h
@@ -115,6 +115,7 @@ namespace Movement
uint32 GetId() const { return m_Id; }
bool Finalized() const { return splineflags.done; }
bool isCyclic() const { return splineflags.cyclic; }
+ bool isFalling() const { return splineflags.falling; }
const Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); }
const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3(); }
int32 currentPathIdx() const;
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 62a53ef67f7..85797ac351b 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -687,8 +687,8 @@ class PlayerScript : public UnitScript
// Called when a player is killed by a creature
virtual void OnPlayerKilledByCreature(Creature* /*killer*/, Player* /*killed*/) { }
- // Called when a player's level changes (right before the level is applied)
- virtual void OnLevelChanged(Player* /*player*/, uint8 /*newLevel*/) { }
+ // Called when a player's level changes (after the level is applied)
+ virtual void OnLevelChanged(Player* /*player*/, uint8 /*oldLevel*/) { }
// Called when a player's free talent points change (right before the change is applied)
virtual void OnFreeTalentPointsChanged(Player* /*player*/, uint32 /*points*/) { }
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 6b14e5a8b53..6b2e67df095 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -2153,7 +2153,9 @@ void AuraEffect::HandleAuraModScale(AuraApplication const* aurApp, uint8 mode, b
Unit* target = aurApp->GetTarget();
- target->ApplyPercentModFloatValue(OBJECT_FIELD_SCALE_X, (float)GetAmount(), apply);
+ float scale = target->GetFloatValue(OBJECT_FIELD_SCALE_X);
+ ApplyPercentModFloatVar(scale, float(GetAmount()), apply);
+ target->SetObjectScale(scale);
}
void AuraEffect::HandleAuraCloneCaster(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -3017,7 +3019,12 @@ void AuraEffect::HandleAuraControlVehicle(AuraApplication const* aurApp, uint8 m
if (caster->GetTypeId() == TYPEID_UNIT)
caster->ToCreature()->RemoveCorpse();
}
- caster->_ExitVehicle();
+
+ if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT))
+ caster->_ExitVehicle();
+ else
+ target->GetVehicleKit()->RemovePassenger(caster); // Only remove passenger from vehicle without launching exit movement or despawning the vehicle
+
// some SPELL_AURA_CONTROL_VEHICLE auras have a dummy effect on the player - remove them
caster->RemoveAurasDueToSpell(GetId());
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 4cbb9a28603..4e0c0e0f831 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1397,7 +1397,26 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
float x, y, z, angle;
angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle);
- m_targets.SetDst(x, y, z, m_caster->GetOrientation());
+
+ float ground = z;
+ float liquidLevel = m_caster->GetMap()->GetWaterOrGroundLevel(x, y, z, &ground);
+ if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level
+ {
+ SendCastResult(SPELL_FAILED_NOT_HERE);
+ SendChannelUpdate(0);
+ finish(false);
+ return;
+ }
+
+ if (ground + 0.75 > liquidLevel)
+ {
+ SendCastResult(SPELL_FAILED_TOO_SHALLOW);
+ SendChannelUpdate(0);
+ finish(false);
+ return;
+ }
+
+ m_targets.SetDst(x, y, liquidLevel, m_caster->GetOrientation());
return;
}
default:
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 44b23d7b774..97a06415a9d 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -5013,25 +5013,9 @@ void Spell::EffectTransmitted(SpellEffIndex effIndex)
}
Map* cMap = m_caster->GetMap();
- if (goinfo->type == GAMEOBJECT_TYPE_FISHINGNODE || goinfo->type == GAMEOBJECT_TYPE_FISHINGHOLE)
- {
- LiquidData liqData;
- if (!cMap->IsInWater(fx, fy, fz + 1.f/* -0.5f */, &liqData)) // Hack to prevent fishing bobber from failing to land on fishing hole
- { // but this is not proper, we really need to ignore not materialized objects
- SendCastResult(SPELL_FAILED_NOT_HERE);
- SendChannelUpdate(0);
- return;
- }
-
- // replace by water level in this case
- //fz = cMap->GetWaterLevel(fx, fy);
- fz = liqData.level;
- }
// if gameobject is summoning object, it should be spawned right on caster's position
- else if (goinfo->type == GAMEOBJECT_TYPE_SUMMONING_RITUAL)
- {
+ if (goinfo->type == GAMEOBJECT_TYPE_SUMMONING_RITUAL)
m_caster->GetPosition(fx, fy, fz);
- }
GameObject* pGameObj = new GameObject;
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 700039983d3..bde496a9c5d 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1266,6 +1266,13 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_WINTERGRASP_NOBATTLETIME] = ConfigMgr::GetIntDefault("Wintergrasp.NoBattleTimer", 150);
m_int_configs[CONFIG_WINTERGRASP_RESTART_AFTER_CRASH] = ConfigMgr::GetIntDefault("Wintergrasp.CrashRestartTimer", 10);
+ // Stats limits
+ m_bool_configs[CONFIG_STATS_LIMITS_ENABLE] = ConfigMgr::GetBoolDefault("Stats.Limits.Enable", false);
+ m_float_configs[CONFIG_STATS_LIMITS_DODGE] = ConfigMgr::GetFloatDefault("Stats.Limits.Dodge", 95.0f);
+ m_float_configs[CONFIG_STATS_LIMITS_PARRY] = ConfigMgr::GetFloatDefault("Stats.Limits.Parry", 95.0f);
+ m_float_configs[CONFIG_STATS_LIMITS_BLOCK] = ConfigMgr::GetFloatDefault("Stats.Limits.Block", 95.0f);
+ m_float_configs[CONFIG_STATS_LIMITS_CRIT] = ConfigMgr::GetFloatDefault("Stats.Limits.Crit", 95.0f);
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index ca76bef435d..cf57a178a2c 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -167,6 +167,7 @@ enum WorldBoolConfigs
CONFIG_GUILD_LEVELING_ENABLED,
CONFIG_UI_QUESTLEVELS_IN_DIALOGS, // Should we add quest levels to the title in the NPC dialogs?
CONFIG_EVENT_ANNOUNCE,
+ CONFIG_STATS_LIMITS_ENABLE,
BOOL_CONFIG_VALUE_COUNT
};
@@ -183,6 +184,10 @@ enum WorldFloatConfigs
CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS,
CONFIG_THREAT_RADIUS,
CONFIG_CHANCE_OF_GM_SURVEY,
+ CONFIG_STATS_LIMITS_DODGE,
+ CONFIG_STATS_LIMITS_PARRY,
+ CONFIG_STATS_LIMITS_BLOCK,
+ CONFIG_STATS_LIMITS_CRIT,
FLOAT_CONFIG_VALUE_COUNT
};