diff options
| author | Vincent-Michael <Vincent_Michael@gmx.de> | 2013-06-11 22:07:11 +0200 |
|---|---|---|
| committer | Vincent-Michael <Vincent_Michael@gmx.de> | 2013-06-11 22:07:11 +0200 |
| commit | 0bebf40fe7fc6ffdf3e86452f14e3bf647380b15 (patch) | |
| tree | 42afd9e6643b3bd3400c9f4f80fd3991748fbcd7 /src/server/game | |
| parent | 93c86b0c52a99d69fd14f4904a000b6c86759c69 (diff) | |
| parent | 9ec22fffa00135cd776afebe2899bf54fb52f15f (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')
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 }; |
