diff options
| author | Shauren <shauren.trinity@gmail.com> | 2018-12-09 14:45:03 +0100 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2018-12-09 14:45:03 +0100 |
| commit | f94deace764f0b8d99249760d2bc2e85c891c387 (patch) | |
| tree | 4c7c56f34768fc7aef05268061a12845c5bf67ce /src/server/game/Entities/Creature | |
| parent | 8725eec9c1c15f3e76bd9d524d4a5d8d0b3f0a44 (diff) | |
| parent | a70030ff252b266d12023ffada2a309409c1ccdb (diff) | |
Merge branch 'bfa'
Diffstat (limited to 'src/server/game/Entities/Creature')
| -rw-r--r-- | src/server/game/Entities/Creature/Creature.cpp | 148 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/Creature.h | 4 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/CreatureData.h | 31 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/GossipDef.cpp | 8 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/Trainer.cpp | 31 | ||||
| -rw-r--r-- | src/server/game/Entities/Creature/Trainer.h | 3 |
6 files changed, 139 insertions, 86 deletions
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index e0f03a7717e..fde7d49a943 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -77,68 +77,67 @@ VendorItem const* VendorItemData::FindItemCostPair(uint32 item_id, uint32 extend return nullptr; } -uint32 CreatureTemplate::GetRandomValidModelId() const -{ - uint8 c = 0; - uint32 modelIDs[4]; - - if (Modelid1) modelIDs[c++] = Modelid1; - if (Modelid2) modelIDs[c++] = Modelid2; - if (Modelid3) modelIDs[c++] = Modelid3; - if (Modelid4) modelIDs[c++] = Modelid4; - - return ((c>0) ? modelIDs[urand(0, c-1)] : 0); -} +CreatureModel const CreatureModel::DefaultInvisibleModel(11686, 1.0f, 1.0f); +CreatureModel const CreatureModel::DefaultVisibleModel(17519, 1.0f, 1.0f); -uint32 CreatureTemplate::GetFirstValidModelId() const +CreatureModel const* CreatureTemplate::GetModelByIdx(uint32 idx) const { - if (Modelid1) return Modelid1; - if (Modelid2) return Modelid2; - if (Modelid3) return Modelid3; - if (Modelid4) return Modelid4; - return 0; + return idx < Models.size() ? &Models[idx] : nullptr; } -uint32 CreatureTemplate::GetFirstInvisibleModel() const +CreatureModel const* CreatureTemplate::GetRandomValidModel() const { - CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid1); - if (modelInfo && modelInfo->is_trigger) - return Modelid1; + if (!Models.size()) + return nullptr; - modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid2); - if (modelInfo && modelInfo->is_trigger) - return Modelid2; + // If only one element, ignore the Probability (even if 0) + if (Models.size() == 1) + return &Models[0]; - modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid3); - if (modelInfo && modelInfo->is_trigger) - return Modelid3; + auto selectedItr = Trinity::Containers::SelectRandomWeightedContainerElement(Models, [](CreatureModel const& model) + { + return model.Probability; + }); - modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid4); - if (modelInfo && modelInfo->is_trigger) - return Modelid4; + return &(*selectedItr); +} - return 11686; +CreatureModel const* CreatureTemplate::GetFirstValidModel() const +{ + for (CreatureModel const& model : Models) + if (model.CreatureDisplayID) + return &model; + + return nullptr; } -uint32 CreatureTemplate::GetFirstVisibleModel() const +CreatureModel const* CreatureTemplate::GetModelWithDisplayId(uint32 displayId) const { - CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid1); - if (modelInfo && !modelInfo->is_trigger) - return Modelid1; + for (CreatureModel const& model : Models) + if (displayId == model.CreatureDisplayID) + return &model; - modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid2); - if (modelInfo && !modelInfo->is_trigger) - return Modelid2; + return nullptr; +} - modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid3); - if (modelInfo && !modelInfo->is_trigger) - return Modelid3; +CreatureModel const* CreatureTemplate::GetFirstInvisibleModel() const +{ + for (CreatureModel const& model : Models) + if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID)) + if (modelInfo && modelInfo->is_trigger) + return &model; + + return &CreatureModel::DefaultInvisibleModel; +} - modelInfo = sObjectMgr->GetCreatureModelInfo(Modelid4); - if (modelInfo && !modelInfo->is_trigger) - return Modelid4; +CreatureModel const* CreatureTemplate::GetFirstVisibleModel() const +{ + for (CreatureModel const& model : Models) + if (CreatureModelInfo const* modelInfo = sObjectMgr->GetCreatureModelInfo(model.CreatureDisplayID)) + if (modelInfo && !modelInfo->is_trigger) + return &model; - return 17519; + return &CreatureModel::DefaultVisibleModel; } bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) @@ -347,22 +346,22 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(cinfo->unit_class)); // Cancel load if no model defined - if (!(cinfo->GetFirstValidModelId())) + if (!(cinfo->GetFirstValidModel())) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has no model defined in table `creature_template`, can't load. ", entry); return false; } - uint32 displayID = ObjectMgr::ChooseDisplayId(GetCreatureTemplate(), data); - CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID); + CreatureModel model = *ObjectMgr::ChooseDisplayId(cinfo, data); + CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&model, cinfo); if (!minfo) // Cancel load if no model defined { - TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid model %u defined in table `creature_template`, can't load.", entry, displayID); + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has invalid model %u defined in table `creature_template`, can't load.", entry, model.CreatureDisplayID); return false; } - SetDisplayId(displayID); - SetNativeDisplayId(displayID); + SetDisplayId(model.CreatureDisplayID, model.DisplayScale); + SetNativeDisplayId(model.CreatureDisplayID, model.DisplayScale); SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); // Load creature equipment @@ -388,7 +387,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/) SetSpeedRate(MOVE_SWIM, 1.0f); // using 1.0 rate SetSpeedRate(MOVE_FLIGHT, 1.0f); // using 1.0 rate - // Will set UNIT_FIELD_BOUNDINGRADIUS and UNIT_FIELD_COMBATREACH + // Will set UNIT_FIELD_BOUNDINGRADIUS, UNIT_FIELD_COMBATREACH and UNIT_FIELD_DISPLAYSCALE SetObjectScale(cinfo->scale); SetFloatValue(UNIT_FIELD_HOVERHEIGHT, cinfo->HoverHeight); @@ -434,6 +433,8 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/, SetUInt32Value(OBJECT_DYNAMIC_FLAGS, dynamicFlags); + SetUInt32Value(UNIT_FIELD_STATE_ANIM_ID, sAnimationDataStore.GetNumRows()); + RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); SetBaseAttackTime(BASE_ATTACK, cInfo->BaseAttackTime); @@ -894,7 +895,8 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float if (!CreateFromProto(guidlow, entry, data, vehId)) return false; - switch (GetCreatureTemplate()->rank) + cinfo = GetCreatureTemplate(); // might be different than initially requested + switch (cinfo->rank) { case CREATURE_ELITE_RARE: m_corpseDelay = sWorld->getIntConfig(CONFIG_CORPSE_DECAY_RARE); @@ -924,12 +926,12 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float Relocate(x, y, z, ang); } - uint32 displayID = GetNativeDisplayId(); - CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID); + CreatureModel display(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f); + CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, cinfo); if (minfo && !IsTotem()) // Cancel load if no model defined or if totem { - SetDisplayId(displayID); - SetNativeDisplayId(displayID); + SetDisplayId(display.CreatureDisplayID, display.DisplayScale); + SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale); SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); } @@ -942,10 +944,10 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 entry, float m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_GHOST); } - if (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING) + if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING) AddUnitState(UNIT_STATE_IGNORE_PATHFINDING); - if (GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK) + if (cinfo->flags_extra & CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK) { ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK, true); ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK_DEST, true); @@ -1129,9 +1131,9 @@ void Creature::SaveToDB(uint32 mapid, std::vector<Difficulty> const& spawnDiffic CreatureTemplate const* cinfo = GetCreatureTemplate(); if (cinfo) { - if (displayId == cinfo->Modelid1 || displayId == cinfo->Modelid2 || - displayId == cinfo->Modelid3 || displayId == cinfo->Modelid4) - displayId = 0; + for (CreatureModel model : cinfo->Models) + if (displayId && displayId == model.CreatureDisplayID) + displayId = 0; if (npcflag == cinfo->npcflag) npcflag = 0; @@ -1844,12 +1846,12 @@ void Creature::Respawn(bool force) setDeathState(JUST_RESPAWNED); - uint32 displayID = GetNativeDisplayId(); - CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&displayID); + CreatureModel display(GetNativeDisplayId(), GetNativeDisplayScale(), 1.0f); + CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelRandomGender(&display, GetCreatureTemplate()); if (minfo) // Cancel load if no model defined { - SetDisplayId(displayID); - SetNativeDisplayId(displayID); + SetDisplayId(display.CreatureDisplayID, display.DisplayScale); + SetNativeDisplayId(display.CreatureDisplayID, display.DisplayScale); SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender); } @@ -2575,7 +2577,7 @@ uint8 Creature::GetLevelForTarget(WorldObject const* target) const uint8 targetLevelWithDelta = unitTarget->getLevel() + GetInt32Value(UNIT_FIELD_SCALING_LEVEL_DELTA); if (target->IsPlayer()) - targetLevelWithDelta += target->GetUInt32Value(PLAYER_FIELD_SCALING_PLAYER_LEVEL_DELTA); + targetLevelWithDelta += target->GetUInt32Value(ACTIVE_PLAYER_FIELD_SCALING_PLAYER_LEVEL_DELTA); return RoundToInterval<uint8>(targetLevelWithDelta, GetUInt32Value(UNIT_FIELD_SCALING_LEVEL_MIN), GetUInt32Value(UNIT_FIELD_SCALING_LEVEL_MAX)); } @@ -2853,9 +2855,9 @@ void Creature::SetObjectScale(float scale) } } -void Creature::SetDisplayId(uint32 modelId) +void Creature::SetDisplayId(uint32 modelId, float displayScale /*= 1.f*/) { - Unit::SetDisplayId(modelId); + Unit::SetDisplayId(modelId, displayScale); if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId)) { @@ -2864,6 +2866,12 @@ void Creature::SetDisplayId(uint32 modelId) } } +void Creature::SetDisplayFromModel(uint32 modelIdx) +{ + if (CreatureModel const* model = GetCreatureTemplate()->GetModelByIdx(modelIdx)) + SetDisplayId(model->CreatureDisplayID, model->DisplayScale); +} + void Creature::SetTarget(ObjectGuid const& guid) { if (IsFocusing(nullptr, true)) diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index d87db9be2ca..b56fe8c9137 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -69,7 +69,8 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma void RemoveFromWorld() override; void SetObjectScale(float scale) override; - void SetDisplayId(uint32 modelId) override; + void SetDisplayId(uint32 displayId, float displayScale = 1.f) override; + void SetDisplayFromModel(uint32 modelIdx); void DisappearAndDie(); @@ -149,7 +150,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma bool UpdateStats(Stats stat) override; bool UpdateAllStats() override; - void UpdateResistances(uint32 school) override; void UpdateArmor() override; void UpdateMaxHealth() override; void UpdateMaxPower(Powers power) override; diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h index d0d29d842e7..02fdcfbff16 100644 --- a/src/server/game/Entities/Creature/CreatureData.h +++ b/src/server/game/Entities/Creature/CreatureData.h @@ -301,16 +301,29 @@ struct CreatureLevelScaling int16 DeltaLevelMax; }; +struct CreatureModel +{ + static CreatureModel const DefaultInvisibleModel; + static CreatureModel const DefaultVisibleModel; + + CreatureModel() : + CreatureDisplayID(0), DisplayScale(0.0f), Probability(0.0f) { } + + CreatureModel(uint32 creatureDisplayID, float displayScale, float probability) : + CreatureDisplayID(creatureDisplayID), DisplayScale(displayScale), Probability(probability) { } + + uint32 CreatureDisplayID; + float DisplayScale; + float Probability; +}; + // from `creature_template` table struct TC_GAME_API CreatureTemplate { uint32 Entry; uint32 DifficultyEntry[MAX_CREATURE_DIFFICULTIES]; uint32 KillCredit[MAX_KILL_CREDIT]; - uint32 Modelid1; - uint32 Modelid2; - uint32 Modelid3; - uint32 Modelid4; + std::vector<CreatureModel> Models; std::string Name; std::string FemaleName; std::string SubName; @@ -369,10 +382,12 @@ struct TC_GAME_API CreatureTemplate uint32 MechanicImmuneMask; uint32 flags_extra; uint32 ScriptID; - uint32 GetRandomValidModelId() const; - uint32 GetFirstValidModelId() const; - uint32 GetFirstInvisibleModel() const; - uint32 GetFirstVisibleModel() const; + CreatureModel const* GetModelByIdx(uint32 idx) const; + CreatureModel const* GetRandomValidModel() const; + CreatureModel const* GetFirstValidModel() const; + CreatureModel const* GetModelWithDisplayId(uint32 displayId) const; + CreatureModel const* GetFirstInvisibleModel() const; + CreatureModel const* GetFirstVisibleModel() const; // helpers SkillType GetRequiredLootSkill() const diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 98a253fe870..9f5b461ef8d 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -286,6 +286,7 @@ void PlayerMenu::SendPointOfInterest(uint32 id) const } WorldPackets::NPC::GossipPOI packet; + packet.ID = pointOfInterest->ID; packet.Name = pointOfInterest->Name; LocaleConstant localeConstant = _session->GetSessionDbLocaleIndex(); @@ -438,6 +439,7 @@ void PlayerMenu::SendQuestGiverQuestDetails(Quest const* quest, ObjectGuid npcGU packet.InformUnit = _session->GetPlayer()->GetDivider(); packet.QuestID = quest->GetQuestId(); packet.PortraitGiver = quest->GetQuestGiverPortrait(); + packet.PortraitGiverMount = quest->GetQuestGiverPortraitMount(); packet.PortraitTurnIn = quest->GetQuestTurnInPortrait(); packet.AutoLaunched = autoLaunched; packet.DisplayPopup = displayPopup; @@ -512,6 +514,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const packet.Info.QuestID = quest->GetQuestId(); packet.Info.QuestType = quest->GetQuestType(); packet.Info.QuestLevel = quest->GetQuestLevel(); + packet.Info.QuestScalingFactionGroup = quest->GetQuestScalingFactionGroup(); packet.Info.QuestMaxScalingLevel = quest->GetQuestMaxScalingLevel(); packet.Info.QuestPackageID = quest->GetQuestPackageID(); packet.Info.QuestMinLevel = quest->GetMinLevel(); @@ -543,12 +546,14 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const packet.Info.StartItem = quest->GetSrcItemId(); packet.Info.Flags = quest->GetFlags(); packet.Info.FlagsEx = quest->GetFlagsEx(); + packet.Info.FlagsEx2 = quest->GetFlagsEx2(); packet.Info.RewardTitle = quest->GetRewTitle(); packet.Info.RewardArenaPoints = quest->GetRewArenaPoints(); packet.Info.RewardSkillLineID = quest->GetRewardSkillId(); packet.Info.RewardNumSkillUps = quest->GetRewardSkillPoints(); packet.Info.RewardFactionFlags = quest->GetRewardReputationMask(); packet.Info.PortraitGiver = quest->GetQuestGiverPortrait(); + packet.Info.PortraitGiverMount = quest->GetQuestGiverPortraitMount(); packet.Info.PortraitTurnIn = quest->GetQuestTurnInPortrait(); for (uint8 i = 0; i < QUEST_ITEM_DROP_COUNT; ++i) @@ -585,7 +590,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const packet.Info.POIPriority = quest->GetPOIPriority(); packet.Info.AllowableRaces = quest->GetAllowableRaces(); - packet.Info.QuestRewardID = quest->GetRewardId(); + packet.Info.TreasurePickerID = quest->GetTreasurePickerId(); packet.Info.Expansion = quest->GetExpansion(); for (QuestObjective const& questObjective : quest->GetObjectives()) @@ -666,6 +671,7 @@ void PlayerMenu::SendQuestGiverOfferReward(Quest const* quest, ObjectGuid npcGUI packet.PortraitTurnIn = quest->GetQuestTurnInPortrait(); packet.PortraitGiver = quest->GetQuestGiverPortrait(); + packet.PortraitGiverMount = quest->GetQuestGiverPortraitMount(); packet.QuestPackageID = quest->GetQuestPackageID(); _session->SendPacket(packet.Write()); diff --git a/src/server/game/Entities/Creature/Trainer.cpp b/src/server/game/Entities/Creature/Trainer.cpp index fb9f0af7f19..af59acb7496 100644 --- a/src/server/game/Entities/Creature/Trainer.cpp +++ b/src/server/game/Entities/Creature/Trainer.cpp @@ -24,6 +24,10 @@ namespace Trainer { + bool Spell::IsCastable() const + { + return sSpellMgr->AssertSpellInfo(SpellId)->HasEffect(SPELL_EFFECT_LEARN_SPELL); + } Trainer::Trainer(uint32 id, Type type, std::string greeting, std::vector<Spell> spells) : _id(id), _type(type), _spells(std::move(spells)) { @@ -136,9 +140,30 @@ namespace Trainer return SpellState::Unavailable; // check ranks - if (uint32 previousRankSpellId = sSpellMgr->GetPrevSpellInChain(trainerSpell->LearnedSpellId)) - if (!player->HasSpell(previousRankSpellId)) - return SpellState::Unavailable; + bool hasLearnSpellEffect = false; + bool knowsAllLearnedSpells = true; + for (SpellEffectInfo const* spellEffect : sSpellMgr->AssertSpellInfo(trainerSpell->SpellId)->GetEffectsForDifficulty(DIFFICULTY_NONE)) + { + if (!spellEffect || !spellEffect->IsEffect(SPELL_EFFECT_LEARN_SPELL)) + continue; + + hasLearnSpellEffect = true; + if (!player->HasSpell(spellEffect->TriggerSpell)) + knowsAllLearnedSpells = false; + + if (uint32 previousRankSpellId = sSpellMgr->GetPrevSpellInChain(spellEffect->TriggerSpell)) + if (!player->HasSpell(previousRankSpellId)) + return SpellState::Unavailable; + } + + if (!hasLearnSpellEffect) + { + if (uint32 previousRankSpellId = sSpellMgr->GetPrevSpellInChain(trainerSpell->SpellId)) + if (!player->HasSpell(previousRankSpellId)) + return SpellState::Unavailable; + } + else if (knowsAllLearnedSpells) + return SpellState::Known; // check additional spell requirement for (auto const& requirePair : sSpellMgr->GetSpellsRequiredForSpellBounds(trainerSpell->SpellId)) diff --git a/src/server/game/Entities/Creature/Trainer.h b/src/server/game/Entities/Creature/Trainer.h index f7e9c51dba1..20ee7deb3f5 100644 --- a/src/server/game/Entities/Creature/Trainer.h +++ b/src/server/game/Entities/Creature/Trainer.h @@ -59,8 +59,7 @@ namespace Trainer std::array<uint32, 3> ReqAbility = { }; uint8 ReqLevel = 0; - uint32 LearnedSpellId = 0; - bool IsCastable() const { return LearnedSpellId != SpellId; } + bool IsCastable() const; }; class Trainer |
