diff options
| author | DDuarte <dnpd.dd@gmail.com> | 2014-01-10 18:32:05 +0000 |
|---|---|---|
| committer | DDuarte <dnpd.dd@gmail.com> | 2014-01-10 18:32:05 +0000 |
| commit | 33c2bd5ce1f4f8d20981e9f7aea90e37de0abbda (patch) | |
| tree | 823ad5570f27e923c77203660ee7cc12e26182ec /src/server/game | |
| parent | 352a2682b1d531c83bd2b80704233677448e99de (diff) | |
| parent | a63780fd90701ed81a0a5f2030e82ab1f6927ab4 (diff) | |
Merge branch 'master' into 4.3.4
Conflicts:
src/server/game/Entities/Creature/Creature.cpp
src/server/game/Entities/Creature/Creature.h
src/server/game/Entities/Creature/GossipDef.cpp
src/server/game/Entities/Player/Player.cpp
src/server/game/Entities/Transport/Transport.cpp
src/server/game/Entities/Unit/Unit.cpp
src/server/game/Globals/ObjectMgr.cpp
src/server/game/Globals/ObjectMgr.h
src/server/game/Handlers/QuestHandler.cpp
src/server/game/Handlers/SpellHandler.cpp
src/server/game/Handlers/TradeHandler.cpp
src/server/game/Quests/QuestDef.h
src/server/game/Spells/Auras/SpellAuraEffects.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_halazzi.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_janalai.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp
src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp
src/server/scripts/EasternKingdoms/ZulAman/zulaman.cpp
src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp
src/server/scripts/EasternKingdoms/ZulGurub/boss_hakkar.cpp
src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp
src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp
src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp
src/server/scripts/EasternKingdoms/zone_arathi_highlands.cpp
src/server/scripts/EasternKingdoms/zone_burning_steppes.cpp
src/server/scripts/EasternKingdoms/zone_ghostlands.cpp
src/server/scripts/EasternKingdoms/zone_hinterlands.cpp
src/server/scripts/EasternKingdoms/zone_redridge_mountains.cpp
src/server/scripts/EasternKingdoms/zone_swamp_of_sorrows.cpp
src/server/scripts/Kalimdor/zone_azshara.cpp
src/server/scripts/Kalimdor/zone_darkshore.cpp
src/server/scripts/Kalimdor/zone_desolace.cpp
src/server/scripts/Northrend/zone_dalaran.cpp
src/tools/CMakeLists.txt
Diffstat (limited to 'src/server/game')
60 files changed, 596 insertions, 1076 deletions
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h index 0d5af4f8802..7c0e04aa957 100644 --- a/src/server/game/AI/CoreAI/GameObjectAI.h +++ b/src/server/game/AI/CoreAI/GameObjectAI.h @@ -22,6 +22,7 @@ #include "Define.h" #include <list> #include "Object.h" +#include "QuestDef.h" #include "GameObject.h" #include "CreatureAI.h" @@ -51,7 +52,7 @@ class GameObjectAI virtual bool GossipSelectCode(Player* /*player*/, uint32 /*sender*/, uint32 /*action*/, char const* /*code*/) { return false; } virtual bool QuestAccept(Player* /*player*/, Quest const* /*quest*/) { return false; } virtual bool QuestReward(Player* /*player*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; } - virtual uint32 GetDialogStatus(Player* /*player*/) { return 100; } + virtual uint32 GetDialogStatus(Player* /*player*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; } virtual void Destroyed(Player* /*player*/, uint32 /*eventId*/) { } virtual uint32 GetData(uint32 /*id*/) const { return 0; } virtual void SetData64(uint32 /*id*/, uint64 /*value*/) { } diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 18daf1ef8de..bc131724484 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -131,7 +131,7 @@ void PetAI::UpdateAI(uint32 diff) HandleReturnMovement(); } - // Autocast (casted only in combat or persistent spells in any state) + // Autocast (cast only in combat or persistent spells in any state) if (!me->HasUnitState(UNIT_STATE_CASTING)) { typedef std::vector<std::pair<Unit*, Spell*> > TargetSpellList; diff --git a/src/server/game/AI/CoreAI/TotemAI.cpp b/src/server/game/AI/CoreAI/TotemAI.cpp index 464021e1e53..9d751976f84 100644 --- a/src/server/game/AI/CoreAI/TotemAI.cpp +++ b/src/server/game/AI/CoreAI/TotemAI.cpp @@ -52,7 +52,7 @@ void TotemAI::UpdateAI(uint32 /*diff*/) if (me->ToTotem()->GetTotemType() != TOTEM_ACTIVE) return; - if (!me->IsAlive() || me->IsNonMeleeSpellCasted(false)) + if (!me->IsAlive() || me->IsNonMeleeSpellCast(false)) return; // Search spell diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index c70fc45be33..6d5ddfcae2b 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -156,7 +156,7 @@ void ScriptedAI::DoStopAttack() void ScriptedAI::DoCastSpell(Unit* target, SpellInfo const* spellInfo, bool triggered) { - if (!target || me->IsNonMeleeSpellCasted(false)) + if (!target || me->IsNonMeleeSpellCast(false)) return; me->StopMoving(); diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 1ced9e79672..8b914d7ca20 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -905,7 +905,10 @@ bool SmartGameObjectAI::QuestReward(Player* player, Quest const* quest, uint32 o } // Called when the dialog status between a player and the gameobject is requested. -uint32 SmartGameObjectAI::GetDialogStatus(Player* /*player*/) { return 100; } +uint32 SmartGameObjectAI::GetDialogStatus(Player* /*player*/) +{ + return DIALOG_STATUS_SCRIPTED_NO_STATUS; +} // Called when the gameobject is destroyed (destructible buildings only). void SmartGameObjectAI::Destroyed(Player* player, uint32 eventId) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index a45e45e58c2..b90ca2ed8cc 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -17,6 +17,7 @@ #include "Cell.h" #include "CellImpl.h" +#include "Chat.h" #include "CreatureTextMgr.h" #include "DatabaseEnv.h" #include "GossipDef.h" @@ -40,41 +41,22 @@ class TrinityStringTextBuilder { public: - TrinityStringTextBuilder(WorldObject* obj, ChatMsg msgtype, int32 id, uint32 language, uint64 targetGUID) - : _source(obj), _msgType(msgtype), _textId(id), _language(language), _targetGUID(targetGUID) + TrinityStringTextBuilder(WorldObject* obj, ChatMsg msgtype, int32 id, uint32 language, WorldObject* target) + : _source(obj), _msgType(msgtype), _textId(id), _language(language), _target(target) { } size_t operator()(WorldPacket* data, LocaleConstant locale) const { std::string text = sObjectMgr->GetTrinityString(_textId, locale); - std::string localizedName = _source->GetNameForLocaleIdx(locale); - - *data << uint8(_msgType); - *data << uint32(_language); - *data << uint64(_source->GetGUID()); - *data << uint32(1); // 2.1.0 - *data << uint32(localizedName.size() + 1); - *data << localizedName; - size_t whisperGUIDpos = data->wpos(); - *data << uint64(_targetGUID); // Unit Target - if (_targetGUID && !IS_PLAYER_GUID(_targetGUID)) - { - *data << uint32(1); // target name length - *data << uint8(0); // target name - } - *data << uint32(text.length() + 1); - *data << text; - *data << uint8(0); // ChatTag - - return whisperGUIDpos; + return ChatHandler::BuildChatPacket(*data, _msgType, Language(_language), _source, _target, text, 0, "", locale); } WorldObject* _source; ChatMsg _msgType; int32 _textId; uint32 _language; - uint64 _targetGUID; + WorldObject* _target; }; SmartScript::SmartScript() @@ -547,7 +529,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); } else - TC_LOG_DEBUG("scripts.ai", "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); + TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); } delete targets; @@ -578,7 +560,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u tempLastInvoker->GetGUIDLow(), e.action.cast.spell, (*itr)->GetGUIDLow(), e.action.cast.flags); } else - TC_LOG_DEBUG("scripts.ai", "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); + TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*itr)->GetGUID(), (*itr)->GetEntry(), uint32((*itr)->GetTypeId())); } delete targets; @@ -777,7 +759,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->DoFleeToGetAssistance(); if (e.action.flee.withEmote) { - TrinityStringTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, LANG_FLEE, LANG_UNIVERSAL, 0); + TrinityStringTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, LANG_FLEE, LANG_UNIVERSAL, NULL); sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); } TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow()); @@ -1020,7 +1002,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->CallForHelp((float)e.action.callHelp.range); if (e.action.callHelp.withEmote) { - TrinityStringTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, LANG_CALL_FOR_HELP, LANG_UNIVERSAL, 0); + TrinityStringTextBuilder builder(me, CHAT_MSG_MONSTER_EMOTE, LANG_CALL_FOR_HELP, LANG_UNIVERSAL, NULL); sCreatureTextMgr->SendChatPacket(me, builder, CHAT_MSG_MONSTER_EMOTE); } TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_CALL_FOR_HELP: Creature %u", me->GetGUIDLow()); @@ -1747,7 +1729,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u unit->CastSpell((*it)->ToUnit(), e.action.cast.spell, (e.action.cast.flags & SMARTCAST_TRIGGERED)); } else - TC_LOG_DEBUG("scripts.ai", "Spell %u not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*it)->GetGUID(), (*it)->GetEntry(), uint32((*it)->GetTypeId())); + TC_LOG_DEBUG("scripts.ai", "Spell %u not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: " UI64FMTD " Entry: %u Type: %u) already has the aura", e.action.cast.spell, (*it)->GetGUID(), (*it)->GetEntry(), uint32((*it)->GetTypeId())); } } @@ -2748,7 +2730,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui Unit* victim = me->GetVictim(); - if (!victim || !victim->IsNonMeleeSpellCasted(false, false, true)) + if (!victim || !victim->IsNonMeleeSpellCast(false, false, true)) return; if (e.event.targetCasting.spellId > 0) @@ -3174,12 +3156,12 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff) if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsInCombat())) return; - if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsInCombat()))//can be used with me=NULL (go script) + if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsInCombat())) //can be used with me=NULL (go script) return; if (e.timer < diff) { - // delay spell cast event if another spell is being casted + // delay spell cast event if another spell is being cast if (e.GetActionType() == SMART_ACTION_CAST) { if (!(e.action.cast.flags & SMARTCAST_INTERRUPT_PREVIOUS)) diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 03aabefcd88..e97fcfaa1ad 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -1149,7 +1149,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD: /* FIXME: for online player only currently */ case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED: - case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED: + case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST: case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED: SetCriteriaProgress(achievementCriteria, miscValue1, referencePlayer, PROGRESS_HIGHEST); break; diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index a5602a1b415..67288e0fadb 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -804,7 +804,7 @@ uint32 BattlefieldWG::GetData(uint32 data) const { switch (data) { - // Used to determine when the phasing spells must be casted + // Used to determine when the phasing spells must be cast // See: SpellArea::IsFitToRequirements case AREA_THE_SUNKEN_RING: case AREA_THE_BROKEN_TEMPLATE: diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h index cdfbbc480bb..74c5e70a633 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundDS.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundDS.h @@ -58,7 +58,7 @@ enum BattlegroundDSCreatures enum BattlegroundDSSpells { BG_DS_SPELL_FLUSH = 57405, // Visual and target selector for the starting knockback from the pipe - BG_DS_SPELL_FLUSH_KNOCKBACK = 61698, // Knockback effect for previous spell (triggered, not need to be casted) + BG_DS_SPELL_FLUSH_KNOCKBACK = 61698, // Knockback effect for previous spell (triggered, not needed to be cast) BG_DS_SPELL_WATER_SPOUT = 58873 // Knockback effect of the central waterfall }; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp index aa3568a62d5..5ebef030518 100644 --- a/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp @@ -397,10 +397,8 @@ bool BattlegroundIC::SetupBattleground() return false; } - //Send transport init packet to all player in map - for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(itr->first)) - GetBgMap()->SendInitTransports(player); + gunshipHorde->EnableMovement(false); + gunshipAlliance->EnableMovement(false); // setting correct factions for Keep Cannons for (uint8 i = BG_IC_NPC_KEEP_CANNON_1; i < BG_IC_NPC_KEEP_CANNON_12; ++i) diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp index c65d76cecd0..1faa168b3a8 100644 --- a/src/server/game/Chat/Channels/Channel.cpp +++ b/src/server/game/Chat/Channels/Channel.cpp @@ -600,14 +600,6 @@ void Channel::Say(uint64 guid, std::string const& what, uint32 lang) if (what.empty()) return; - uint8 chatTag = 0; - bool isGM = false; - if (Player* player = ObjectAccessor::FindPlayer(guid)) - { - chatTag = player->GetChatTag(); - isGM = player->GetSession()->HasPermission(rbac::RBAC_PERM_COMMAND_GM_CHAT); - } - // TODO: Add proper RBAC check if (sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL)) lang = LANG_UNIVERSAL; @@ -629,7 +621,11 @@ void Channel::Say(uint64 guid, std::string const& what, uint32 lang) } WorldPacket data; - ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), guid, guid, what, chatTag, "", "", 0, isGM, _name); + if (Player* player = ObjectAccessor::FindPlayer(guid)) + ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), player, player, what, 0, _name); + else + ChatHandler::BuildChatPacket(data, CHAT_MSG_CHANNEL, Language(lang), guid, guid, what, 0, "", "", 0, false, _name); + SendToAll(&data, !playersStore[guid].IsModerator() ? guid : false); } diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h index 0d7d520b4fa..215ce1c594a 100644 --- a/src/server/game/DataStores/DBCEnums.h +++ b/src/server/game/DataStores/DBCEnums.h @@ -258,7 +258,7 @@ enum AchievementCriteriaTypes ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT = 101, ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED = 102, ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED = 103, - ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED = 104, + ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST = 104, ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED = 105, ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED = 106, ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED = 107, diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index e416500f77f..949ca6324e9 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -1081,15 +1081,17 @@ void Creature::SelectLevel(const CreatureTemplate* cinfo) SetModifierValue(UNIT_MOD_MANA, BASE_VALUE, (float)mana); //damage - //float damagemod = _GetDamageMod(rank); // Set during loading templates into dmg_multiplier field - SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg); - SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg); + float basedamage = stats->GenerateBaseDamage(cinfo); - SetFloatValue(UNIT_FIELD_MINRANGEDDAMAGE, cinfo->minrangedmg); - SetFloatValue(UNIT_FIELD_MAXRANGEDDAMAGE, cinfo->maxrangedmg); + SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, ((basedamage + (stats->AttackPower / 14)) * cinfo->dmg_multiplier) * (cinfo->baseattacktime / 1000)); + SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (((basedamage * 1.5) + (stats->AttackPower / 14)) * cinfo->dmg_multiplier) * (cinfo->baseattacktime / 1000)); + SetBaseWeaponDamage(RANGED_ATTACK, MINDAMAGE, (basedamage + (stats->RangedAttackPower / 14)) * (cinfo->rangeattacktime / 1000)); + SetBaseWeaponDamage(RANGED_ATTACK, MAXDAMAGE, ((basedamage * 1.5) + (stats->RangedAttackPower / 14)) * (cinfo->rangeattacktime / 1000)); - SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, cinfo->attackpower); + float damagemod = 1.0f;//_GetDamageMod(rank); + + SetModifierValue(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower * damagemod); } @@ -1484,7 +1486,7 @@ void Creature::setDeathState(DeathState s) CreatureTemplate const* cinfo = GetCreatureTemplate(); SetUInt32Value(UNIT_NPC_FLAGS, cinfo->npcflag); - ClearUnitState(uint32(UNIT_STATE_ALL_STATE)); + ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_IGNORE_PATHFINDING)); SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); LoadCreaturesAddon(true); Motion_Initialize(); diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index d54a1a61258..6599bab80c7 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -175,6 +175,7 @@ struct CreatureTemplate // Benchmarked: Faster than std::map (insert/find) typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer; +#define MAX_CREATURE_BASE_DAMAGE 3 // GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push, N), also any gcc version not support it at some platform #if defined(__GNUC__) #pragma pack(1) @@ -182,12 +183,15 @@ typedef UNORDERED_MAP<uint32, CreatureTemplate> CreatureTemplateContainer; #pragma pack(push, 1) #endif -// Defines base stats for creatures (used to calculate HP/mana/armor). +// Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage). struct CreatureBaseStats { uint32 BaseHealth[MAX_CREATURE_BASE_HP]; uint32 BaseMana; uint32 BaseArmor; + uint32 AttackPower; + uint32 RangedAttackPower; + float BaseDamage[MAX_CREATURE_BASE_DAMAGE]; // Helpers @@ -210,6 +214,11 @@ struct CreatureBaseStats return uint32(ceil(BaseArmor * info->ModArmor)); } + float GenerateBaseDamage(CreatureTemplate const* info) const + { + return BaseDamage[info->expansion]; + } + static CreatureBaseStats const* GetBaseStats(uint8 level, uint8 unitClass); }; diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index 1af9b7fa73a..5b9f92103e3 100644 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -297,7 +297,7 @@ void QuestMenu::ClearMenu() _questMenuItems.clear(); } -void PlayerMenu::SendQuestGiverQuestList(QEmote eEmote, const std::string& Title, uint64 npcGUID) +void PlayerMenu::SendQuestGiverQuestList(QEmote const& eEmote, const std::string& Title, uint64 npcGUID) { WorldPacket data(SMSG_QUESTGIVER_QUEST_LIST, 100); // guess size data << uint64(npcGUID); @@ -480,8 +480,8 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const data << uint32(quest->GetRewOrReqMoney()); // reward money (below max lvl) data << uint32(quest->GetRewMoneyMaxLevel()); // used in XP calculation at client - data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (casted if RewSpellCast == 0) - data << int32(quest->GetRewSpellCast()); // casted spell + data << uint32(quest->GetRewSpell()); // reward spell, this spell will display (icon) (cast if RewSpellCast == 0) + data << int32(quest->GetRewSpellCast()); // cast spell // rewarded honor points data << uint32(quest->GetRewHonorAddition()); diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h index c76febc0165..8c720c5f550 100644 --- a/src/server/game/Entities/Creature/GossipDef.h +++ b/src/server/game/Entities/Creature/GossipDef.h @@ -273,7 +273,7 @@ class PlayerMenu /*********************************************************/ void SendQuestGiverStatus(uint32 questStatus, uint64 npcGUID) const; - void SendQuestGiverQuestList(QEmote eEmote, const std::string& Title, uint64 npcGUID); + void SendQuestGiverQuestList(QEmote const& eEmote, const std::string& Title, uint64 npcGUID); void SendQuestQueryResponse(Quest const* quest) const; void SendQuestGiverQuestDetails(Quest const* quest, uint64 npcGUID, bool activateAccept) const; diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 97287aabe3c..d36a1bad93e 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -652,7 +652,7 @@ void GameObject::Update(uint32 diff) void GameObject::Refresh() { - // not refresh despawned not casted GO (despawned casted GO destroyed in all cases anyway) + // Do not refresh despawned GO from spellcast (GO's from spellcast are destroyed after despawn) if (m_respawnTime > 0 && m_spawnedByDefault) return; @@ -1486,7 +1486,7 @@ void GameObject::Use(Unit* user) if (spellId == 62330) // GO store nonexistent spell, replace by expected { // spell have reagent and mana cost but it not expected use its - // it triggered spell in fact casted at currently channeled GO + // it triggered spell in fact cast at currently channeled GO spellId = 61993; triggered = true; } diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp index 01dfd92e34c..98eaec87817 100644 --- a/src/server/game/Entities/Item/Item.cpp +++ b/src/server/game/Entities/Item/Item.cpp @@ -103,7 +103,7 @@ void AddItemsSetItem(Player* player, Item* item) break; } - // spell casted only if fit form requirement, in other case will casted at form change + // spell cast only if fit form requirement, in other case will cast at form change player->ApplyEquipSpell(spellInfo, NULL, true); eff->spells[y] = spellInfo; break; diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 149560fd891..74d05ca58ea 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1738,6 +1738,10 @@ void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const { + // TODO: Allow transports to be part of dynamic vmap tree + if (GetTransport()) + return; + switch (GetTypeId()) { case TYPEID_UNIT: diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 45381864aac..f9d96225e3f 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2198,7 +2198,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati SetSemaphoreTeleportFar(false); //setup delayed teleport flag SetDelayedTeleportFlag(IsCanDelayTeleport()); - //if teleport spell is casted in Unit::Update() func + //if teleport spell is cast in Unit::Update() func //then we need to delay it until update process will be finished if (IsHasDelayedTeleport()) { @@ -2261,7 +2261,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati SetSemaphoreTeleportNear(false); //setup delayed teleport flag SetDelayedTeleportFlag(IsCanDelayTeleport()); - //if teleport spell is casted in Unit::Update() func + //if teleport spell is cast in Unit::Update() func //then we need to delay it until update process will be finished if (IsHasDelayedTeleport()) { @@ -2307,7 +2307,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati // stop spellcasting // not attempt interrupt teleportation spell at caster teleport if (!(options & TELE_TO_SPELL)) - if (IsNonMeleeSpellCasted(true)) + if (IsNonMeleeSpellCast(true)) InterruptNonMeleeSpells(true); //remove auras before removing from map... @@ -8713,7 +8713,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pEnchant->spellid[s]); if (!spellInfo) { - TC_LOG_ERROR("entities.player.items", "Player::CastItemCombatSpell(GUID: %u, name: %s, enchant: %i): unknown spell %i is casted, ignoring...", + TC_LOG_ERROR("entities.player.items", "Player::CastItemCombatSpell(GUID: %u, name: %s, enchant: %i): unknown spell %i is cast, ignoring...", GetGUIDLow(), GetName().c_str(), pEnchant->ID, pEnchant->spellid[s]); continue; } @@ -8774,7 +8774,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 // use triggered flag only for items with many spell casts and for not first cast uint8 count = 0; - // item spells casted at use + // item spells cast at use for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i) { _Spell const& spellData = proto->Spells[i]; @@ -8803,7 +8803,7 @@ void Player::CastItemUseSpell(Item* item, SpellCastTargets const& targets, uint8 ++count; } - // Item enchantments spells casted at use + // Item enchantments spells cast at use for (uint8 e_slot = 0; e_slot < MAX_ENCHANTMENT_SLOT; ++e_slot) { if (e_slot > PRISMATIC_ENCHANTMENT_SLOT && e_slot < PROP_ENCHANTMENT_SLOT_0) // not holding enchantment id @@ -11464,7 +11464,7 @@ InventoryResult Player::CanEquipItem(uint8 slot, uint16 &dest, Item* pItem, bool if (IsInCombat()&& (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer != 0) return EQUIP_ERR_CLIENT_LOCKED_OUT; // maybe exist better err - if (IsNonMeleeSpellCasted(false)) + if (IsNonMeleeSpellCast(false)) return EQUIP_ERR_CLIENT_LOCKED_OUT; } @@ -21395,7 +21395,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc } // not let cheating with start flight in time of logout process || if casting not finished || while in combat || if not use Spell's with EffectSendTaxi - if (IsNonMeleeSpellCasted(false)) + if (IsNonMeleeSpellCast(false)) { GetSession()->SendActivateTaxiReply(ERR_TAXIPLAYERBUSY); return false; @@ -24149,7 +24149,7 @@ void Player::RemoveItemDependentAurasAndCasts(Item* pItem) RemoveOwnedAura(itr); } - // currently casted spells can be dependent from item + // currently cast spells can be dependent from item for (uint32 i = 0; i < CURRENT_MAX_SPELL; ++i) if (Spell* spell = GetCurrentSpell(CurrentSpellTypes(i))) if (spell->getState() != SPELL_STATE_DELAYED && !HasItemFitToSpellRequirements(spell->m_spellInfo, pItem)) @@ -26514,7 +26514,7 @@ void Player::ActivateSpec(uint8 spec) if (spec > GetSpecsCount()) return; - if (IsNonMeleeSpellCasted(false)) + if (IsNonMeleeSpellCast(false)) InterruptNonMeleeSpells(false); SQLTransaction trans = CharacterDatabase.BeginTransaction(); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 17deabeba70..bec86f9ce90 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1120,7 +1120,7 @@ class TradeData uint64 m_money; // m_player place money to trade uint32 m_spell; // m_player apply spell to non-traded slot item - uint64 m_spellCastItem; // applied spell casted by item use + uint64 m_spellCastItem; // applied spell cast by item use uint64 m_items[TRADE_SLOT_COUNT]; // traded items from m_player side including non-traded slot }; diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp index 9026f4c0e46..b1d8c02f41d 100644 --- a/src/server/game/Entities/Transport/Transport.cpp +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -90,8 +90,7 @@ bool Transport::Create(uint32 guidlow, uint32 entry, uint32 mapid, float x, floa SetPeriod(tInfo->pathTime); SetEntry(goinfo->entry); SetDisplayId(goinfo->displayId); - SetGoState(GO_STATE_READY); - _pendingStop = goinfo->moTransport.canBeStopped != 0; + SetGoState(!goinfo->moTransport.canBeStopped ? GO_STATE_READY : GO_STATE_ACTIVE); SetGoType(GAMEOBJECT_TYPE_MO_TRANSPORT); SetGoAnimProgress(animprogress); SetName(goinfo->name); @@ -111,7 +110,8 @@ void Transport::Update(uint32 diff) if (GetKeyFrames().size() <= 1) return; - m_goValue.Transport.PathProgress += diff; + if (IsMoving() || !_pendingStop) + m_goValue.Transport.PathProgress += diff; uint32 timer = m_goValue.Transport.PathProgress % GetPeriod(); @@ -132,31 +132,23 @@ void Transport::Update(uint32 diff) if (timer < _currentFrame->DepartureTime) { SetMoving(false); - if (_pendingStop) + if (_pendingStop && GetGoState() != GO_STATE_READY) + { SetGoState(GO_STATE_READY); + m_goValue.Transport.PathProgress = (m_goValue.Transport.PathProgress / GetPeriod()); + m_goValue.Transport.PathProgress *= GetPeriod(); + m_goValue.Transport.PathProgress += _currentFrame->ArriveTime; + } break; // its a stop frame and we are waiting } } - if (_pendingStop && timer >= _currentFrame->DepartureTime && GetGoState() == GO_STATE_READY) - { - m_goValue.Transport.PathProgress = (m_goValue.Transport.PathProgress / GetPeriod()); - m_goValue.Transport.PathProgress *= GetPeriod(); - m_goValue.Transport.PathProgress += _currentFrame->ArriveTime; - break; - } - if (timer >= _currentFrame->DepartureTime && !_triggeredDepartureEvent) { DoEventIfAny(*_currentFrame, true); // departure event _triggeredDepartureEvent = true; } - if (timer >= _currentFrame->DepartureTime && timer < _currentFrame->NextArriveTime) - break; // found current waypoint - - MoveToNextWaypoint(); - // not waiting anymore SetMoving(true); @@ -164,13 +156,18 @@ void Transport::Update(uint32 diff) if (GetGOInfo()->moTransport.canBeStopped) SetGoState(GO_STATE_ACTIVE); + if (timer >= _currentFrame->DepartureTime && timer < _currentFrame->NextArriveTime) + break; // found current waypoint + + MoveToNextWaypoint(); + sScriptMgr->OnRelocate(this, _currentFrame->Node->index, _currentFrame->Node->mapid, _currentFrame->Node->x, _currentFrame->Node->y, _currentFrame->Node->z); TC_LOG_DEBUG("entities.transport", "Transport %u (%s) moved to node %u %u %f %f %f", GetEntry(), GetName().c_str(), _currentFrame->Node->index, _currentFrame->Node->mapid, _currentFrame->Node->x, _currentFrame->Node->y, _currentFrame->Node->z); // Departure event if (_currentFrame->IsTeleportFrame()) - if (TeleportTransport(_nextFrame->Node->mapid, _nextFrame->Node->x, _nextFrame->Node->y, _nextFrame->Node->z)) + if (TeleportTransport(_nextFrame->Node->mapid, _nextFrame->Node->x, _nextFrame->Node->y, _nextFrame->Node->z, _nextFrame->InitialOrientation)) return; // Update more in new map thread } @@ -185,7 +182,18 @@ void Transport::Update(uint32 diff) G3D::Vector3 pos, dir; _currentFrame->Spline->evaluate_percent(_currentFrame->Index, t, pos); _currentFrame->Spline->evaluate_derivative(_currentFrame->Index, t, dir); - UpdatePosition(pos.x, pos.y, pos.z, atan2(dir.x, dir.y)); + UpdatePosition(pos.x, pos.y, pos.z, atan2(dir.y, dir.x) + M_PI); + } + else + { + /* There are four possible scenarios that trigger loading/unloading passengers: + 1. transport moves from inactive to active grid + 2. the grid that transport is currently in becomes active + 3. transport moves from active to inactive grid + 4. the grid that transport is currently in unloads + */ + if (_staticPassengers.empty() && GetMap()->IsGridLoaded(GetPositionX(), GetPositionY())) // 2. + LoadStaticPassengers(); } } @@ -313,7 +321,7 @@ void Transport::UpdatePosition(float x, float y, float z, float o) 3. transport moves from active to inactive grid 4. the grid that transport is currently in unloads */ - if (_staticPassengers.empty() && newActive) // 1. and 2. + if (_staticPassengers.empty() && newActive) // 1. LoadStaticPassengers(); else if (!_staticPassengers.empty() && !newActive && Cell(x, y).DiffGrid(Cell(GetPositionX(), GetPositionY()))) // 3. UnloadStaticPassengers(); @@ -403,52 +411,24 @@ float Transport::CalculateSegmentPos(float now) return segmentPos / frame.NextDistFromPrev; } -bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) +bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, float o) { Map const* oldMap = GetMap(); if (oldMap->GetId() != newMapid) { Map* newMap = sMapMgr->CreateBaseMap(newMapid); - Map::PlayerList const& oldPlayers = GetMap()->GetPlayers(); - if (!oldPlayers.isEmpty()) - { - UpdateData data(GetMapId()); - BuildOutOfRangeUpdateBlock(&data); - WorldPacket packet; - data.BuildPacket(&packet); - for (Map::PlayerList::const_iterator itr = oldPlayers.begin(); itr != oldPlayers.end(); ++itr) - if (itr->GetSource()->GetTransport() != this) - itr->GetSource()->SendDirectMessage(&packet); - } - UnloadStaticPassengers(); GetMap()->RemoveFromMap<Transport>(this, false); SetMap(newMap); - Map::PlayerList const& newPlayers = GetMap()->GetPlayers(); - if (!newPlayers.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = newPlayers.begin(); itr != newPlayers.end(); ++itr) - { - if (itr->GetSource()->GetTransport() != this) - { - UpdateData data(newMapid); - BuildCreateUpdateBlockForPlayer(&data, itr->GetSource()); - WorldPacket packet; - data.BuildPacket(&packet); - itr->GetSource()->SendDirectMessage(&packet); - } - } - } - for (std::set<WorldObject*>::iterator itr = _passengers.begin(); itr != _passengers.end();) { WorldObject* obj = (*itr++); float destX, destY, destZ, destO; obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); - TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, GetOrientation()); + TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o); switch (obj->GetTypeId()) { @@ -474,7 +454,7 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) } } - Relocate(x, y, z, GetOrientation()); + Relocate(x, y, z, o); GetMap()->AddToMap<Transport>(this); return true; } @@ -487,13 +467,13 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) { float destX, destY, destZ, destO; (*itr)->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO); - TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, GetOrientation()); + TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o); (*itr)->ToUnit()->NearTeleportTo(destX, destY, destZ, destO); } } - UpdatePosition(x, y, z, GetOrientation()); + UpdatePosition(x, y, z, o); return false; } } diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h index e290a5d5e00..b0e80ea27b3 100644 --- a/src/server/game/Entities/Transport/Transport.h +++ b/src/server/game/Entities/Transport/Transport.h @@ -78,7 +78,7 @@ class Transport : public GameObject, public TransportBase private: void MoveToNextWaypoint(); float CalculateSegmentPos(float perc); - bool TeleportTransport(uint32 newMapid, float x, float y, float z); + bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o); void UpdatePassengerPositions(std::set<WorldObject*>& passengers); void DoEventIfAny(KeyFrame const& node, bool departure); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 02bdc5f3a8c..0f2104bd8c2 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1834,7 +1834,7 @@ void Unit::AttackerStateUpdate (Unit* victim, WeaponAttackType attType, bool ext if (attType != BASE_ATTACK && attType != OFF_ATTACK) return; // ignore ranged case - // melee attack spell casted at main hand attack only - no normal melee dmg dealt + // melee attack spell cast at main hand attack only - no normal melee dmg dealt if (attType == BASE_ATTACK && m_currentSpells[CURRENT_MELEE_SPELL] && !extra) m_currentSpells[CURRENT_MELEE_SPELL]->cast(); else @@ -2496,7 +2496,7 @@ uint32 Unit::GetUnitMeleeSkill(Unit const* target) const float Unit::GetUnitDodgeChance() const { - if (IsNonMeleeSpellCasted(false) || HasUnitState(UNIT_STATE_CONTROLLED)) + if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED)) return 0.0f; if (GetTypeId() == TYPEID_PLAYER) @@ -2516,7 +2516,7 @@ float Unit::GetUnitDodgeChance() const float Unit::GetUnitParryChance() const { - if (IsNonMeleeSpellCasted(false) || HasUnitState(UNIT_STATE_CONTROLLED)) + if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED)) return 0.0f; float chance = 0.0f; @@ -2559,7 +2559,7 @@ float Unit::GetUnitMissChance(WeaponAttackType attType) const float Unit::GetUnitBlockChance() const { - if (IsNonMeleeSpellCasted(false) || HasUnitState(UNIT_STATE_CONTROLLED)) + if (IsNonMeleeSpellCast(false) || HasUnitState(UNIT_STATE_CONTROLLED)) return 0.0f; if (Player const* player = ToPlayer()) @@ -2698,7 +2698,7 @@ void Unit::_UpdateAutoRepeatSpell() { // check "realtime" interrupts // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect - if (((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCasted(false, false, true, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == 75)) && + if (((GetTypeId() == TYPEID_PLAYER && ToPlayer()->isMoving()) || IsNonMeleeSpellCast(false, false, true, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo->Id == 75)) && !HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_currentSpells[CURRENT_AUTOREPEAT_SPELL]->m_spellInfo)) { // cancel wand shoot @@ -2732,7 +2732,7 @@ void Unit::_UpdateAutoRepeatSpell() } } -void Unit::SetCurrentCastedSpell(Spell* pSpell) +void Unit::SetCurrentCastSpell(Spell* pSpell) { ASSERT(pSpell); // NULL may be never passed here, use InterruptSpell or InterruptNonMeleeSpells @@ -2845,16 +2845,16 @@ void Unit::FinishSpell(CurrentSpellTypes spellType, bool ok /*= true*/) spell->finish(ok); } -bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skipAutorepeat, bool isAutoshoot, bool skipInstant) const +bool Unit::IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled, bool skipAutorepeat, bool isAutoshoot, bool skipInstant) const { // We don't do loop here to explicitly show that melee spell is excluded. // Maybe later some special spells will be excluded too. - // if skipInstant then instant spells shouldn't count as being casted + // if skipInstant then instant spells shouldn't count as being cast if (skipInstant && m_currentSpells[CURRENT_GENERIC_SPELL] && !m_currentSpells[CURRENT_GENERIC_SPELL]->GetCastTime()) return false; - // generic spells are casted when they are not finished and not delayed + // generic spells are cast when they are not finished and not delayed if (m_currentSpells[CURRENT_GENERIC_SPELL] && (m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_FINISHED) && (withDelayed || m_currentSpells[CURRENT_GENERIC_SPELL]->getState() != SPELL_STATE_DELAYED)) @@ -2862,14 +2862,14 @@ bool Unit::IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled, bool skip if (!isAutoshoot || !(m_currentSpells[CURRENT_GENERIC_SPELL]->m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS)) return true; } - // channeled spells may be delayed, but they are still considered casted + // channeled spells may be delayed, but they are still considered cast else if (!skipChanneled && m_currentSpells[CURRENT_CHANNELED_SPELL] && (m_currentSpells[CURRENT_CHANNELED_SPELL]->getState() != SPELL_STATE_FINISHED)) { if (!isAutoshoot || !(m_currentSpells[CURRENT_CHANNELED_SPELL]->m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS)) return true; } - // autorepeat spells may be finished or delayed, but they are still considered casted + // autorepeat spells may be finished or delayed, but they are still considered cast else if (!skipAutorepeat && m_currentSpells[CURRENT_AUTOREPEAT_SPELL]) return true; @@ -6334,7 +6334,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere // Runic Power Back on Snare/Root if (dummySpell->Id == 61257) { - // only for spells and hit/crit (trigger start always) and not start from self casted spells + // only for spells and hit/crit (trigger start always) and not start from self cast spells if (procSpell == 0 || !(procEx & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) || this == victim) return false; // Need snare or root mechanic @@ -7585,7 +7585,7 @@ bool Unit::AttackStop() void Unit::CombatStop(bool includingCast) { - if (includingCast && IsNonMeleeSpellCasted(false)) + if (includingCast && IsNonMeleeSpellCast(false)) InterruptNonMeleeSpells(false); AttackStop(); @@ -8134,7 +8134,7 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth) if (gain) player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE, gain, 0, 0, victim); - player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED, addhealth); + player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CAST, addhealth); } if (Player* player = victim->ToPlayer()) @@ -10651,7 +10651,7 @@ void Unit::setDeathState(DeathState s) getHostileRefManager().deleteReferences(); ClearComboPointHolders(); // any combo points pointed to unit lost at it death - if (IsNonMeleeSpellCasted(false)) + if (IsNonMeleeSpellCast(false)) InterruptNonMeleeSpells(false); ExitVehicle(); // Exit vehicle before calling RemoveAllControlled @@ -11070,7 +11070,7 @@ int32 Unit::ModSpellDuration(SpellInfo const* spellProto, Unit const* target, in } } - // Glyphs which increase duration of selfcasted buffs + // Glyphs which increase duration of selfcast buffs if (target == this) { switch (spellProto->SpellFamilyName) @@ -11117,7 +11117,7 @@ DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) if (!i->hitTime) return DIMINISHING_LEVEL_1; - // If last spell was casted more than 15 seconds ago - reset the count. + // If last spell was cast more than 15 seconds ago - reset the count. if (i->stack == 0 && getMSTimeDiff(i->hitTime, getMSTime()) > 15000) { i->hitCount = DIMINISHING_LEVEL_1; @@ -11775,7 +11775,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup) if (finalCleanup) m_cleanupDone = true; - m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList + m_Events.KillAllEvents(false); // non-delatable (currently cast spells) will not deleted now but it will deleted at call in Map::RemoveAllObjectsInRemoveList CombatStop(); ClearComboPointHolders(); DeleteThreatList(); @@ -12947,7 +12947,7 @@ void Unit::ApplyCastTimePercentMod(float val, bool apply) uint32 Unit::GetCastingTimeForBonus(SpellInfo const* spellProto, DamageEffectType damagetype, uint32 CastingTime) const { - // Not apply this to creature casted spells with casttime == 0 + // Not apply this to creature cast spells with casttime == 0 if (CastingTime == 0 && GetTypeId() == TYPEID_UNIT && !ToCreature()->IsPet()) return 3500; @@ -15804,7 +15804,7 @@ void Unit::StopAttackFaction(uint32 faction_id) if (victim->GetFactionTemplateEntry()->faction == faction_id) { AttackStop(); - if (IsNonMeleeSpellCasted(false)) + if (IsNonMeleeSpellCast(false)) InterruptNonMeleeSpells(false); // melee and ranged forced attack cancel @@ -15835,7 +15835,7 @@ void Unit::OutDebugInfo() const { TC_LOG_ERROR("entities.unit", "Unit::OutDebugInfo"); TC_LOG_INFO("entities.unit", "GUID " UI64FMTD ", entry %u, type %u, name %s", GetGUID(), GetEntry(), (uint32)GetTypeId(), GetName().c_str()); - TC_LOG_INFO("entities.unit", "OwnerGUID " UI64FMTD ", MinionGUID " UI64FMTD ", CharmerGUID " UI64FMTD ", CharmedGUID "UI64FMTD, GetOwnerGUID(), GetMinionGUID(), GetCharmerGUID(), GetCharmGUID()); + TC_LOG_INFO("entities.unit", "OwnerGUID " UI64FMTD ", MinionGUID " UI64FMTD ", CharmerGUID " UI64FMTD ", CharmedGUID " UI64FMTD, GetOwnerGUID(), GetMinionGUID(), GetCharmerGUID(), GetCharmGUID()); TC_LOG_INFO("entities.unit", "In world %u, unit type mask %u", (uint32)(IsInWorld() ? 1 : 0), m_unitTypeMask); if (IsInWorld()) TC_LOG_INFO("entities.unit", "Mapid %u", GetMapId()); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 8411b282402..22a48d791e1 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1828,15 +1828,15 @@ class Unit : public WorldObject float GetNegStat(Stats stat) const { return GetFloatValue(UNIT_FIELD_NEGSTAT0+stat); } float GetCreateStat(Stats stat) const { return m_createStats[stat]; } - void SetCurrentCastedSpell(Spell* pSpell); + void SetCurrentCastSpell(Spell* pSpell); virtual void ProhibitSpellSchool(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/) { } void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed = true, bool withInstant = true); void FinishSpell(CurrentSpellTypes spellType, bool ok = true); - // set withDelayed to true to account delayed spells as casted - // delayed+channeled spells are always accounted as casted + // set withDelayed to true to account delayed spells as cast + // delayed+channeled spells are always accounted as cast // we can skip channeled or delayed checks using flags - bool IsNonMeleeSpellCasted(bool withDelayed, bool skipChanneled = false, bool skipAutorepeat = false, bool isAutoshoot = false, bool skipInstant = true) const; + bool IsNonMeleeSpellCast(bool withDelayed, bool skipChanneled = false, bool skipAutorepeat = false, bool isAutoshoot = false, bool skipInstant = true) const; // set withDelayed to true to interrupt delayed spells too // delayed+channeled spells are always interrupted @@ -2180,8 +2180,8 @@ class Unit : public WorldObject uint32 m_removedAurasCount; AuraEffectList m_modAuras[TOTAL_AURAS]; - AuraList m_scAuras; // casted singlecast auras - AuraApplicationList m_interruptableAuras; // auras which have interrupt mask applied on unit + AuraList m_scAuras; // cast singlecast auras + AuraApplicationList m_interruptableAuras; // auras which have interrupt mask applied on unit AuraStateAurasMap m_auraStateAuras; // Used for improve performance of aura state checks on aura apply/remove uint32 m_interruptMask; diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 4877d904f72..c4963f6372c 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -1627,7 +1627,8 @@ void ObjectMgr::LoadCreatures() continue; } - if (data.spawnMask & ~spawnMasks[data.mapid]) + // Skip spawnMask check for transport maps + if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `creature` have creature (GUID: %u) that have wrong spawn mask %u including not supported difficulty modes for map (Id: %u) spawnMasks[data.mapid]: %u.", guid, data.spawnMask, data.mapid, spawnMasks[data.mapid]); bool ok = true; @@ -1962,7 +1963,7 @@ void ObjectMgr::LoadGameobjects() data.spawnMask = fields[14].GetUInt8(); - if (data.spawnMask & ~spawnMasks[data.mapid]) + if (!_transportMaps.count(data.mapid) && data.spawnMask & ~spawnMasks[data.mapid]) TC_LOG_ERROR("sql.sql", "Table `gameobject` has gameobject (GUID: %u Entry: %u) that has wrong spawn mask %u including not supported difficulty modes for map (Id: %u), skip", guid, data.id, data.spawnMask, data.mapid); data.phaseMask = fields[15].GetUInt32(); @@ -4071,21 +4072,21 @@ void ObjectMgr::LoadQuests() { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u does not exist, quest will not have a spell reward.", qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); - qinfo->RewardSpellCast = 0; // no spell will be casted on player + qinfo->RewardSpellCast = 0; // no spell will be cast on player } else if (!SpellMgr::IsSpellValid(spellInfo)) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpellCast` = %u but spell %u is broken, quest will not have a spell reward.", qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); - qinfo->RewardSpellCast = 0; // no spell will be casted on player + qinfo->RewardSpellCast = 0; // no spell will be cast on player } else if (GetTalentSpellCost(qinfo->RewardSpellCast)) { TC_LOG_ERROR("sql.sql", "Quest %u has `RewardSpell` = %u but spell %u is talent, quest will not have a spell reward.", qinfo->GetQuestId(), qinfo->RewardSpellCast, qinfo->RewardSpellCast); - qinfo->RewardSpellCast = 0; // no spell will be casted on player + qinfo->RewardSpellCast = 0; // no spell will be cast on player } } @@ -6471,6 +6472,8 @@ void ObjectMgr::LoadGameObjectTemplate() TC_LOG_ERROR("sql.sql", "GameObject (Entry: %u GoType: %u) have data0=%u but TaxiPath (Id: %u) not exist.", entry, got.type, got.moTransport.taxiPathId, got.moTransport.taxiPathId); } + if (uint32 transportMap = got.moTransport.mapID) + _transportMaps.insert(transportMap); break; } case GAMEOBJECT_TYPE_SUMMONING_RITUAL: //18 @@ -8545,8 +8548,8 @@ CreatureBaseStats const* ObjectMgr::GetCreatureBaseStats(uint8 level, uint8 unit void ObjectMgr::LoadCreatureClassLevelStats() { uint32 oldMSTime = getMSTime(); - // 0 1 2 3 4 5 6 7 - QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basehp3, basemana, basearmor FROM creature_classlevelstats"); + // 0 1 2 3 4 5 6 7 8 9 10 11 12 + QueryResult result = WorldDatabase.Query("SELECT level, class, basehp0, basehp1, basehp2, basehp3, basemana, basearmor, attackpower, rangedattackpower, damage_base, damage_exp1, damage_exp2 FROM creature_classlevelstats"); if (!result) { @@ -8570,6 +8573,12 @@ void ObjectMgr::LoadCreatureClassLevelStats() stats.BaseMana = fields[6].GetUInt32(); stats.BaseArmor = fields[7].GetUInt32(); + stats.AttackPower = fields[8].GetInt16(); + stats.RangedAttackPower = fields[9].GetInt16(); + + for (uint8 i = 0; i < MAX_CREATURE_BASE_DAMAGE; ++i) + stats.BaseDamage[i] = fields[i + 10].GetFloat(); + if (!Class || ((1 << (Class - 1)) & CLASSMASK_ALL_CREATURES) == 0) TC_LOG_ERROR("sql.sql", "Creature base stats for level %u has invalid class %u", Level, Class); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index fb106884bba..dfd0192dfed 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -1408,7 +1408,9 @@ class ObjectMgr GO_TO_GO, GO_TO_CREATURE // GO is dependant on creature }; + HotfixData _hotfixData; + std::set<uint32> _transportMaps; // Helper container storing map ids that are for transports only, loaded from gameobject_template }; #define sObjectMgr ACE_Singleton<ObjectMgr, ACE_Null_Mutex>::instance() diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp index e33e8f73cd6..73c46cc0372 100644 --- a/src/server/game/Handlers/ChatHandler.cpp +++ b/src/server/game/Handlers/ChatHandler.cpp @@ -415,7 +415,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::BuildChatPacket(data, uint8(type), Language(lang), _player, NULL, msg); + ChatHandler::BuildChatPacket(data, type, Language(lang), _player, NULL, msg); group->BroadcastPacket(&data, false); } break; case CHAT_MSG_RAID_WARNING: @@ -445,7 +445,7 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData) sScriptMgr->OnPlayerChat(GetPlayer(), type, lang, msg, group); WorldPacket data; - ChatHandler::BuildChatPacket(data, uint8(type), Language(lang), _player, NULL, msg);; + ChatHandler::BuildChatPacket(data, type, Language(lang), _player, NULL, msg);; group->BroadcastPacket(&data, false); } break; case CHAT_MSG_CHANNEL: @@ -614,7 +614,7 @@ void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recvData) return; WorldPacket data; - ChatHandler::BuildChatPacket(data, type, uint32(LANG_ADDON), this, this, message, 0, "", DEFAULT_LOCALE, prefix.c_str()); + ChatHandler::BuildChatPacket(data, type, LANG_ADDON, this, this, message, 0, "", DEFAULT_LOCALE, prefix.c_str()); group->BroadcastAddonMessagePacket(&data, prefix, false); break; } @@ -647,7 +647,7 @@ void WorldSession::HandleAddonMessagechatOpcode(WorldPacket& recvData) break; WorldPacket data; - ChatHandler::BuildChatPacket(data, type, uint32(LANG_ADDON), this, this, message, 0, "", DEFAULT_LOCALE, prefix.c_str()); + ChatHandler::BuildChatPacket(data, type, LANG_ADDON, this, this, message, 0, "", DEFAULT_LOCALE, prefix.c_str()); group->BroadcastAddonMessagePacket(&data, prefix, true, -1, group->GetMemberGroup(sender->GetGUID())); break; } diff --git a/src/server/game/Handlers/LootHandler.cpp b/src/server/game/Handlers/LootHandler.cpp index 9a32df7d4af..7b1e2474c8d 100644 --- a/src/server/game/Handlers/LootHandler.cpp +++ b/src/server/game/Handlers/LootHandler.cpp @@ -238,7 +238,7 @@ void WorldSession::HandleLootOpcode(WorldPacket& recvData) GetPlayer()->SendLoot(guid, LOOT_CORPSE); // interrupt cast - if (GetPlayer()->IsNonMeleeSpellCasted(false)) + if (GetPlayer()->IsNonMeleeSpellCast(false)) GetPlayer()->InterruptNonMeleeSpells(false); } diff --git a/src/server/game/Handlers/QuestHandler.cpp b/src/server/game/Handlers/QuestHandler.cpp index a1ece86de09..0cb1a51329f 100644 --- a/src/server/game/Handlers/QuestHandler.cpp +++ b/src/server/game/Handlers/QuestHandler.cpp @@ -37,7 +37,6 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData) uint64 guid; recvData >> guid; uint32 questStatus = DIALOG_STATUS_NONE; - uint32 defstatus = DIALOG_STATUS_NONE; Object* questgiver = ObjectAccessor::GetObjectByTypeMask(*_player, guid, TYPEMASK_UNIT|TYPEMASK_GAMEOBJECT); if (!questgiver) @@ -50,23 +49,23 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData) { case TYPEID_UNIT: { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", uint32(GUID_LOPART(guid))); - Creature* cr_questgiver=questgiver->ToCreature(); + TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for npc, guid = %u", questgiver->GetGUIDLow()); + Creature* cr_questgiver = questgiver->ToCreature(); if (!cr_questgiver->IsHostileTo(_player)) // do not show quest status to enemies { questStatus = sScriptMgr->GetDialogStatus(_player, cr_questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, cr_questgiver, defstatus); + if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) + questStatus = getDialogStatus(_player, cr_questgiver); } break; } case TYPEID_GAMEOBJECT: { - TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", uint32(GUID_LOPART(guid))); - GameObject* go_questgiver=(GameObject*)questgiver; + TC_LOG_DEBUG("network", "WORLD: Received CMSG_QUESTGIVER_STATUS_QUERY for GameObject guid = %u", questgiver->GetGUIDLow()); + GameObject* go_questgiver = questgiver->ToGameObject(); questStatus = sScriptMgr->GetDialogStatus(_player, go_questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, go_questgiver, defstatus); + if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) + questStatus = getDialogStatus(_player, go_questgiver); break; } default: @@ -75,7 +74,7 @@ void WorldSession::HandleQuestgiverStatusQueryOpcode(WorldPacket& recvData) } //inform client about status of quest - _player->PlayerTalkClass->SendQuestGiverStatus(questStatus, guid); + _player->PlayerTalkClass->SendQuestGiverStatus(uint8(questStatus), guid); } void WorldSession::HandleQuestgiverHelloOpcode(WorldPacket& recvData) @@ -665,9 +664,9 @@ void WorldSession::HandleQuestPushResult(WorldPacket& recvPacket) } } -uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver, uint32 defstatus) +uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver) { - uint32 result = defstatus; + uint32 result = DIALOG_STATUS_NONE; QuestRelationBounds qr; QuestRelationBounds qir; @@ -708,7 +707,7 @@ uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver, uint32 if ((status == QUEST_STATUS_COMPLETE && !player->GetQuestRewardStatus(quest_id)) || (quest->IsAutoComplete() && player->CanTakeQuest(quest, false))) { - if (quest->IsAutoComplete() && quest->IsRepeatable()) + if (quest->IsAutoComplete() && quest->IsRepeatable() && !quest->IsDailyOrWeekly()) result2 = DIALOG_STATUS_REWARD_REP; else result2 = DIALOG_STATUS_REWARD; @@ -739,11 +738,11 @@ uint32 WorldSession::getDialogStatus(Player* player, Object* questgiver, uint32 { if (player->SatisfyQuestLevel(quest, false)) { - if (quest->IsAutoComplete() || (quest->IsRepeatable() && player->IsQuestRewarded(quest_id))) + if (quest->IsAutoComplete()) result2 = DIALOG_STATUS_REWARD_REP; else if (player->getLevel() <= ((player->GetQuestLevel(quest) == -1) ? player->getLevel() : player->GetQuestLevel(quest) + sWorld->getIntConfig(CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF))) { - if (quest->HasFlag(QUEST_FLAGS_DAILY) || quest->HasFlag(QUEST_FLAGS_WEEKLY)) + if (quest->IsDaily()) result2 = DIALOG_STATUS_AVAILABLE_REP; else result2 = DIALOG_STATUS_AVAILABLE; @@ -775,7 +774,6 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket for (Player::ClientGUIDs::const_iterator itr = _player->m_clientGUIDs.begin(); itr != _player->m_clientGUIDs.end(); ++itr) { uint32 questStatus = DIALOG_STATUS_NONE; - uint32 defstatus = DIALOG_STATUS_NONE; if (IS_CRE_OR_VEH_OR_PET_GUID(*itr)) { @@ -785,9 +783,10 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket continue; if (!questgiver->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER)) continue; + questStatus = sScriptMgr->GetDialogStatus(_player, questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, questgiver, defstatus); + if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) + questStatus = getDialogStatus(_player, questgiver); data << uint64(questgiver->GetGUID()); data << uint32(questStatus); @@ -796,13 +795,12 @@ void WorldSession::HandleQuestgiverStatusMultipleQuery(WorldPacket& /*recvPacket else if (IS_GAMEOBJECT_GUID(*itr)) { GameObject* questgiver = GetPlayer()->GetMap()->GetGameObject(*itr); - if (!questgiver) - continue; - if (questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) + if (!questgiver || questgiver->GetGoType() != GAMEOBJECT_TYPE_QUESTGIVER) continue; + questStatus = sScriptMgr->GetDialogStatus(_player, questgiver); - if (questStatus > 6) - questStatus = getDialogStatus(_player, questgiver, defstatus); + if (questStatus == DIALOG_STATUS_SCRIPTED_NO_STATUS) + questStatus = getDialogStatus(_player, questgiver); data << uint64(questgiver->GetGUID()); data << uint32(questStatus); diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp index 9324f52be3e..5da2512b873 100644 --- a/src/server/game/Handlers/SpellHandler.cpp +++ b/src/server/game/Handlers/SpellHandler.cpp @@ -86,10 +86,10 @@ void WorldSession::HandleUseItemOpcode(WorldPacket& recvPacket) return; uint8 bagIndex, slot, castFlags; - uint8 castCount; // next cast if exists (single or not) + uint8 castCount; // next cast if exists (single or not) uint64 itemGUID; uint32 glyphIndex; // something to do with glyphs? - uint32 spellId; // casted spell id + uint32 spellId; // cast spell id recvPacket >> bagIndex >> slot >> castCount >> spellId >> itemGUID >> glyphIndex >> castFlags; @@ -401,7 +401,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) } } - // Client is resending autoshot cast opcode when other spell is casted during shoot rotation + // Client is resending autoshot cast opcode when other spell is cast during shoot rotation // Skip it to prevent "interrupt" message if (spellInfo->IsAutoRepeatRangedSpell() && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && caster->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_spellInfo == spellInfo) @@ -427,7 +427,7 @@ void WorldSession::HandleCastSpellOpcode(WorldPacket& recvPacket) { SpellInfo const* actualSpellInfo = spellInfo->GetAuraRankForLevel(targets.GetUnitTarget()->getLevel()); - // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message + // if rank not found then function return NULL but in explicit cast case original spell can be cast and later failed with appropriate error message if (actualSpellInfo) spellInfo = actualSpellInfo; } @@ -445,7 +445,7 @@ void WorldSession::HandleCancelCastOpcode(WorldPacket& recvPacket) recvPacket.read_skip<uint8>(); // counter, increments with every CANCEL packet, don't use for now recvPacket >> spellId; - if (_player->IsNonMeleeSpellCasted(false)) + if (_player->IsNonMeleeSpellCast(false)) _player->InterruptNonMeleeSpells(false, spellId, false); } @@ -462,7 +462,7 @@ void WorldSession::HandleCancelAuraOpcode(WorldPacket& recvPacket) if (spellInfo->Attributes & SPELL_ATTR0_CANT_CANCEL) return; - // channeled spell case (it currently casted then) + // channeled spell case (it currently cast then) if (spellInfo->IsChanneled()) { if (Spell* curSpell = _player->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) diff --git a/src/server/game/Handlers/TradeHandler.cpp b/src/server/game/Handlers/TradeHandler.cpp index 44e590cb795..650301575c2 100644 --- a/src/server/game/Handlers/TradeHandler.cpp +++ b/src/server/game/Handlers/TradeHandler.cpp @@ -412,7 +412,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) Spell* his_spell = NULL; SpellCastTargets his_targets; - // not accept if spell can't be casted now (cheating) + // not accept if spell can't be cast now (cheating) if (uint32 my_spell_id = my_trade->GetSpell()) { SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(my_spell_id); @@ -447,7 +447,7 @@ void WorldSession::HandleAcceptTradeOpcode(WorldPacket& /*recvPacket*/) } } - // not accept if spell can't be casted now (cheating) + // not accept if spell can't be cast now (cheating) if (uint32 his_spell_id = his_trade->GetSpell()) { SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(his_spell_id); diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h index 2d7dbad2541..9ccc3a839be 100644 --- a/src/server/game/Instances/InstanceScript.h +++ b/src/server/game/Instances/InstanceScript.h @@ -249,6 +249,16 @@ AI* GetInstanceAI(T* obj, char const* scriptName) return new AI(obj); return NULL; -} +}; + +template<class AI, class T> +AI* GetInstanceAI(T* obj) +{ + if (InstanceMap* instance = obj->GetMap()->ToInstanceMap()) + if (instance->GetInstanceScript()) + return new AI(obj); + + return NULL; +}; #endif // TRINITY_INSTANCE_DATA_H diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 4f3640fe73b..bc478f260ca 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -63,19 +63,12 @@ Map::~Map() obj->ResetMap(); } - for (TransportsContainer::iterator itr = _transports.begin(); itr != _transports.end();) - { - Transport* transport = *itr; - ++itr; - - transport->RemoveFromWorld(); - delete transport; - } - if (!m_scriptSchedule.empty()) sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size()); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId); + MMAP::MMapManager* manager = MMAP::MMapFactory::CreateOrGetMMapManager(); + manager->UnloadMapInstance(GetId(), i_InstanceId); // Delete the dtNavMeshQuery + manager->UnloadMap(GetId()); // Unload the loaded tiles and delete the dtNavMesh } bool Map::ExistMap(uint32 mapid, int gx, int gy) @@ -128,12 +121,16 @@ bool Map::ExistVMap(uint32 mapid, int gx, int gy) void Map::LoadMMap(int gx, int gy) { - bool mmapLoadResult = MMAP::MMapFactory::createOrGetMMapManager()->loadMap((sWorld->GetDataPath() + "mmaps").c_str(), GetId(), gx, gy); + bool mmapLoadResult = false; + if (GetEntry()->Instanceable()) + mmapLoadResult = MMAP::MMapFactory::CreateOrGetMMapManager()->LoadMapTile(GetId(), 0, 0); // Ignore the tile entry for instances, as they only have 1 tile. + else + mmapLoadResult = MMAP::MMapFactory::CreateOrGetMMapManager()->LoadMapTile(GetId(), gx, gy); if (mmapLoadResult) - TC_LOG_INFO("maps", "MMAP loaded name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + TC_LOG_INFO("maps", "MMAP loaded name: %s, id: %d, x: %d, y: %d", GetMapName(), GetId(), gx, gy); else - TC_LOG_INFO("maps", "Could not load MMAP name:%s, id:%d, x:%d, y:%d (mmap rep.: x:%d, y:%d)", GetMapName(), GetId(), gx, gy, gx, gy); + TC_LOG_INFO("maps", "Could not load MMAP name: %s, id: %d, x: %d, y: %d", GetMapName(), GetId(), gx, gy); } void Map::LoadVMap(int gx, int gy) @@ -235,9 +232,9 @@ i_gridExpiry(expiry), i_scriptLock(false) { m_parentMap = (_parent ? _parent : this); - for (unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) + for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx) { - for (unsigned int j=0; j < MAX_NUMBER_OF_GRIDS; ++j) + for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j) { //z code GridMaps[idx][j] =NULL; @@ -562,6 +559,22 @@ bool Map::AddToMap(Transport* obj) obj->AddToWorld(); _transports.insert(obj); + // Broadcast creation to players + if (!GetPlayers().isEmpty()) + { + for (Map::PlayerList::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr) + { + if (itr->GetSource()->GetTransport() != obj) + { + UpdateData data; + obj->BuildCreateUpdateBlockForPlayer(&data, itr->GetSource()); + WorldPacket packet; + data.BuildPacket(&packet); + itr->GetSource()->SendDirectMessage(&packet); + } + } + } + return true; } @@ -810,6 +823,18 @@ void Map::RemoveFromMap(Transport* obj, bool remove) { obj->RemoveFromWorld(); + Map::PlayerList const& players = GetPlayers(); + if (!players.isEmpty()) + { + UpdateData data; + obj->BuildOutOfRangeUpdateBlock(&data); + WorldPacket packet; + data.BuildPacket(&packet); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + if (itr->GetSource()->GetTransport() != obj) + itr->GetSource()->SendDirectMessage(&packet); + } + if (_transportsUpdateIter != _transports.end()) { TransportsContainer::iterator itr = _transports.find(obj); @@ -1317,7 +1342,7 @@ bool Map::UnloadGrid(NGridType& ngrid, bool unloadAll) delete GridMaps[gx][gy]; } VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gx, gy); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(GetId(), gx, gy); + MMAP::MMapFactory::CreateOrGetMMapManager()->UnloadMapTile(GetId(), gx, gy); } else ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridCoord(gx, gy)); @@ -1357,6 +1382,17 @@ void Map::UnloadAll() ++i; UnloadGrid(grid, true); // deletes the grid and removes it from the GridRefManager } + + for (TransportsContainer::iterator itr = _transports.begin(); itr != _transports.end();) + { + Transport* transport = *itr; + ++itr; + + transport->RemoveFromWorld(); + delete transport; + } + + _transports.clear(); } // ***************************** diff --git a/src/server/game/Maps/MapInstanced.cpp b/src/server/game/Maps/MapInstanced.cpp index 667f94fb53a..d191293ecaf 100644 --- a/src/server/game/Maps/MapInstanced.cpp +++ b/src/server/game/Maps/MapInstanced.cpp @@ -260,7 +260,7 @@ bool MapInstanced::DestroyInstance(InstancedMaps::iterator &itr) if (m_InstancedMaps.size() <= 1 && sWorld->getBoolConfig(CONFIG_GRID_UNLOAD)) { VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(itr->second->GetId()); - MMAP::MMapFactory::createOrGetMMapManager()->unloadMap(itr->second->GetId()); + MMAP::MMapFactory::CreateOrGetMMapManager()->UnloadMap(itr->second->GetId()); // in that case, unload grids of the base map, too // so in the next map creation, (EnsureGridCreated actually) VMaps will be reloaded Map::UnloadAll(); diff --git a/src/server/game/Maps/TransportMgr.cpp b/src/server/game/Maps/TransportMgr.cpp index 11798201397..328342ab303 100644 --- a/src/server/game/Maps/TransportMgr.cpp +++ b/src/server/game/Maps/TransportMgr.cpp @@ -87,28 +87,60 @@ void TransportMgr::LoadTransportTemplates() TC_LOG_INFO("server.loading", ">> Loaded %u transport templates in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } +class SplineRawInitializer +{ +public: + SplineRawInitializer(Movement::PointsArray& points) : _points(points) { } + + void operator()(uint8& mode, bool& cyclic, Movement::PointsArray& points, int& lo, int& hi) const + { + mode = Movement::SplineBase::ModeCatmullrom; + cyclic = false; + points.assign(_points.begin(), _points.end()); + lo = 1; + hi = points.size() - 2; + } + + Movement::PointsArray& _points; +}; + void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTemplate* transport) { uint32 pathId = goInfo->moTransport.taxiPathId; TaxiPathNodeList const& path = sTaxiPathNodesByPath[pathId]; std::vector<KeyFrame>& keyFrames = transport->keyFrames; - Movement::PointsArray splinePath; + Movement::PointsArray splinePath, allPoints; bool mapChange = false; - bool cyclic = true; + for (size_t i = 0; i < path.size(); ++i) + allPoints.push_back(G3D::Vector3(path[i].x, path[i].y, path[i].z)); + + // Add extra points to allow derivative calculations for all path nodes + allPoints.insert(allPoints.begin(), allPoints.front().lerp(allPoints[1], -0.2f)); + allPoints.push_back(allPoints.back().lerp(allPoints[allPoints.size() - 2], -0.2f)); + allPoints.push_back(allPoints.back().lerp(allPoints[allPoints.size() - 2], -1.0f)); + + SplineRawInitializer initer(allPoints); + TransportSpline orientationSpline; + orientationSpline.init_spline_custom(initer); + orientationSpline.initLengths(); + for (size_t i = 0; i < path.size(); ++i) { if (!mapChange) { TaxiPathNodeEntry const& node_i = path[i]; - if (i != path.size() - 1 && (node_i.actionFlag == 1 || node_i.mapid != path[i + 1].mapid)) + if (i != path.size() - 1 && (node_i.actionFlag & 1 || node_i.mapid != path[i + 1].mapid)) { - cyclic = false; keyFrames.back().Teleport = true; mapChange = true; } else { KeyFrame k(node_i); + G3D::Vector3 h; + orientationSpline.evaluate_derivative(i + 1, 0.0f, h); + k.InitialOrientation = Position::NormalizeOrientation(atan2(h.y, h.x) + M_PI); + keyFrames.push_back(k); splinePath.push_back(G3D::Vector3(node_i.x, node_i.y, node_i.z)); transport->mapsUsed.insert(k.Node->mapid); @@ -118,16 +150,15 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl mapChange = false; } - // Not sure if data8 means the transport can be stopped or that its path in dbc does not contain extra spline points - if (!goInfo->moTransport.canBeStopped && splinePath.size() >= 2) + if (splinePath.size() >= 2) { // Remove special catmull-rom spline points - splinePath.erase(splinePath.begin()); - keyFrames.erase(keyFrames.begin()); - splinePath.pop_back(); - keyFrames.pop_back(); - // Cyclic spline has one more extra point - if (cyclic && !splinePath.empty()) + if (!keyFrames.front().IsStopFrame() && !keyFrames.front().Node->arrivalEventID && !keyFrames.front().Node->departureEventID) + { + splinePath.erase(splinePath.begin()); + keyFrames.erase(keyFrames.begin()); + } + if (!keyFrames.back().IsStopFrame() && !keyFrames.back().Node->arrivalEventID && !keyFrames.back().Node->departureEventID) { splinePath.pop_back(); keyFrames.pop_back(); @@ -170,67 +201,41 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl // find the rest of the distances between key points // Every path segment has its own spline - if (cyclic) - { - TransportSpline* spline = new TransportSpline(); - spline->init_cyclic_spline(&splinePath[0], splinePath.size(), Movement::SplineBase::ModeCatmullrom, 0); - spline->initLengths(); - keyFrames[0].DistFromPrev = spline->length(spline->last() - 2, spline->last() - 1); - keyFrames[0].Spline = spline; - for (size_t i = 0; i < keyFrames.size(); ++i) - { - keyFrames[i].Index = i + 1; - keyFrames[i].DistFromPrev = spline->length(i, i + 1); - if (i > 0) - keyFrames[i - 1].NextDistFromPrev = keyFrames[i].DistFromPrev; - keyFrames[i].Spline = spline; - if (keyFrames[i].IsStopFrame()) - { - // remember first stop frame - if (firstStop == -1) - firstStop = i; - lastStop = i; - } - } - } - else + size_t start = 0; + for (size_t i = 1; i < keyFrames.size(); ++i) { - size_t start = 0; - for (size_t i = 1; i < keyFrames.size(); ++i) + if (keyFrames[i - 1].Teleport || i + 1 == keyFrames.size()) { - if (keyFrames[i - 1].Teleport || i + 1 == keyFrames.size()) + size_t extra = !keyFrames[i - 1].Teleport ? 1 : 0; + TransportSpline* spline = new TransportSpline(); + spline->init_spline(&splinePath[start], i - start + extra, Movement::SplineBase::ModeCatmullrom); + spline->initLengths(); + for (size_t j = start; j < i + extra; ++j) { - size_t extra = !keyFrames[i - 1].Teleport ? 1 : 0; - TransportSpline* spline = new TransportSpline(); - spline->init_spline(&splinePath[start], i - start + extra, Movement::SplineBase::ModeCatmullrom); - spline->initLengths(); - for (size_t j = start; j < i + extra; ++j) - { - keyFrames[j].Index = j - start + 1; - keyFrames[j].DistFromPrev = spline->length(j - start, j + 1 - start); - if (j > 0) - keyFrames[j - 1].NextDistFromPrev = keyFrames[j].DistFromPrev; - keyFrames[j].Spline = spline; - } - - if (keyFrames[i - 1].Teleport) - { - keyFrames[i].Index = i - start + 1; - keyFrames[i].DistFromPrev = 0.0f; - keyFrames[i - 1].NextDistFromPrev = 0.0f; - keyFrames[i].Spline = spline; - } - - start = i; + keyFrames[j].Index = j - start + 1; + keyFrames[j].DistFromPrev = spline->length(j - start, j + 1 - start); + if (j > 0) + keyFrames[j - 1].NextDistFromPrev = keyFrames[j].DistFromPrev; + keyFrames[j].Spline = spline; } - if (keyFrames[i].IsStopFrame()) + if (keyFrames[i - 1].Teleport) { - // remember first stop frame - if (firstStop == -1) - firstStop = i; - lastStop = i; + keyFrames[i].Index = i - start + 1; + keyFrames[i].DistFromPrev = 0.0f; + keyFrames[i - 1].NextDistFromPrev = 0.0f; + keyFrames[i].Spline = spline; } + + start = i; + } + + if (keyFrames[i].IsStopFrame()) + { + // remember first stop frame + if (firstStop == -1) + firstStop = i; + lastStop = i; } } @@ -373,7 +378,7 @@ Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map* float x = startNode->x; float y = startNode->y; float z = startNode->z; - float o = 0.0f; + float o = tInfo->keyFrames.begin()->InitialOrientation; // initialize the gameobject base uint32 guidLow = guid ? guid : sObjectMgr->GenerateLowGuid(HIGHGUID_MO_TRANSPORT); diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h index 205a614eabb..c2f82069b30 100644 --- a/src/server/game/Maps/TransportMgr.h +++ b/src/server/game/Maps/TransportMgr.h @@ -38,7 +38,7 @@ typedef UNORDERED_MAP<uint32, std::set<uint32> > TransportInstanceMap; struct KeyFrame { - explicit KeyFrame(TaxiPathNodeEntry const& _node) : Index(0), Node(&_node), + explicit KeyFrame(TaxiPathNodeEntry const& _node) : Index(0), Node(&_node), InitialOrientation(0.0f), DistSinceStop(-1.0f), DistUntilStop(-1.0f), DistFromPrev(-1.0f), TimeFrom(0.0f), TimeTo(0.0f), Teleport(false), ArriveTime(0), DepartureTime(0), Spline(NULL), NextDistFromPrev(0.0f), NextArriveTime(0) { @@ -46,6 +46,7 @@ struct KeyFrame uint32 Index; TaxiPathNodeEntry const* Node; + float InitialOrientation; float DistSinceStop; float DistUntilStop; float DistFromPrev; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index ddca3a92fd8..03c44cc3a75 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -396,7 +396,7 @@ enum SpellAttr3 SPELL_ATTR3_ONLY_TARGET_PLAYERS = 0x00000100, // 8 can only target players SPELL_ATTR3_TRIGGERED_CAN_TRIGGER_PROC_2 = 0x00000200, // 9 triggered from effect? SPELL_ATTR3_MAIN_HAND = 0x00000400, // 10 Main hand weapon required - SPELL_ATTR3_BATTLEGROUND = 0x00000800, // 11 Can casted only on battleground + SPELL_ATTR3_BATTLEGROUND = 0x00000800, // 11 Can only be cast in battleground SPELL_ATTR3_ONLY_TARGET_GHOSTS = 0x00001000, // 12 SPELL_ATTR3_UNK13 = 0x00002000, // 13 SPELL_ATTR3_IS_HONORLESS_TARGET = 0x00004000, // 14 "Honorless Target" only this spells have this flag @@ -4049,7 +4049,7 @@ enum PartyResult }; const uint32 MMAP_MAGIC = 0x4d4d4150; // 'MMAP' -#define MMAP_VERSION 4 +#define MMAP_VERSION 5 struct MmapTileHeader { diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp index ef24b112253..63b1cf283a4 100755 --- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp @@ -86,7 +86,6 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* unit, uint32 diff) unit->MovePositionToFirstCollision(pos, dest, 0.0f); PathGenerator path(unit); - path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ); if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp index f78411fc547..1c65499fe50 100644 --- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp @@ -44,7 +44,6 @@ void FleeingMovementGenerator<T>::_setTargetLocation(T* owner) _getPoint(owner, x, y, z); PathGenerator path(owner); - path.SetPathLengthLimit(30.0f); bool result = path.CalculatePath(x, y, z); if (!result || (path.GetPathType() & PATHFIND_NOPATH)) { diff --git a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp index 2d9fe4dd27f..ecf9e0c9ede 100644 --- a/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp @@ -60,7 +60,7 @@ void HomeMovementGenerator<Creature>::_setTargetLocation(Creature* owner) arrived = false; - owner->ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~UNIT_STATE_EVADE)); + owner->ClearUnitState(uint32(UNIT_STATE_ALL_STATE & ~(UNIT_STATE_EVADE | UNIT_STATE_IGNORE_PATHFINDING))); } bool HomeMovementGenerator<Creature>::DoUpdate(Creature* owner, const uint32 /*time_diff*/) diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp index 91ad6d2b676..19295f63712 100644 --- a/src/server/game/Movement/PathGenerator.cpp +++ b/src/server/game/Movement/PathGenerator.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/> * Copyright (C) 2005-2011 MaNGOS <http://getmangos.com/> * * This program is free software; you can redistribute it and/or modify @@ -26,21 +27,19 @@ #include "DetourCommon.h" #include "DetourNavMeshQuery.h" +float PathGenerator::MinWallDistance = 2.5f; + ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(const Unit* owner) : - _polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false), - _forceDestination(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), - _endPosition(G3D::Vector3::zero()), _sourceUnit(owner), _navMesh(NULL), - _navMeshQuery(NULL) + _type(PATHFIND_BLANK), _endPosition(G3D::Vector3::zero()), + _sourceUnit(owner), _navMesh(NULL), _navMeshQuery(NULL) { - memset(_pathPolyRefs, 0, sizeof(_pathPolyRefs)); - - TC_LOG_DEBUG("maps", "++ PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); + TC_LOG_DEBUG("maps", "PathGenerator::PathGenerator for %u \n", _sourceUnit->GetGUIDLow()); uint32 mapId = _sourceUnit->GetMapId(); if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) { - MMAP::MMapManager* mmap = MMAP::MMapFactory::createOrGetMMapManager(); + MMAP::MMapManager* mmap = MMAP::MMapFactory::CreateOrGetMMapManager(); _navMesh = mmap->GetNavMesh(mapId); _navMeshQuery = mmap->GetNavMeshQuery(mapId, _sourceUnit->GetInstanceId()); } @@ -50,16 +49,23 @@ PathGenerator::PathGenerator(const Unit* owner) : PathGenerator::~PathGenerator() { - TC_LOG_DEBUG("maps", "++ PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow()); + TC_LOG_DEBUG("maps", "PathGenerator::~PathGenerator() for %u \n", _sourceUnit->GetGUIDLow()); } bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool forceDest) { + // Clear the previous path, just in case that the same PathGenerator instance is being used + _pathPoints.clear(); + float x, y, z; _sourceUnit->GetPosition(x, y, z); if (!Trinity::IsValidMapCoord(destX, destY, destZ) || !Trinity::IsValidMapCoord(x, y, z)) + { + TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() called with invalid map coords, destX: %f destY: %f destZ: %f x: %f y: %f z: %f for creature %u", destX, destY, destZ, x, y, z, _sourceUnit->GetGUIDLow()); + _type = PATHFIND_NOPATH; return false; + } G3D::Vector3 dest(destX, destY, destZ); SetEndPosition(dest); @@ -67,463 +73,103 @@ bool PathGenerator::CalculatePath(float destX, float destY, float destZ, bool fo G3D::Vector3 start(x, y, z); SetStartPosition(start); - _forceDestination = forceDest; - - TC_LOG_DEBUG("maps", "++ PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow()); + TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u \n", _sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap // check if the start and end point have a .mmtile loaded (can we pass via not loaded tile on the way?) - if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING) || - !HaveTile(start) || !HaveTile(dest)) + if (!_navMesh || !_navMeshQuery || _sourceUnit->HasUnitState(UNIT_STATE_IGNORE_PATHFINDING)) { - BuildShortcut(); + TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() navmesh is not initialized for %u \n", _sourceUnit->GetGUIDLow()); _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _pathPoints.push_back(start); + _pathPoints.push_back(dest); return true; } UpdateFilter(); - BuildPolyPath(start, dest); - return true; -} - -dtPolyRef PathGenerator::GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* point, float* distance) const -{ - if (!polyPath || !polyPathSize) - return INVALID_POLYREF; - - dtPolyRef nearestPoly = INVALID_POLYREF; - float minDist2d = FLT_MAX; - float minDist3d = 0.0f; - - for (uint32 i = 0; i < polyPathSize; ++i) - { - float closestPoint[VERTEX_SIZE]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(polyPath[i], point, closestPoint))) - continue; - - float d = dtVdist2DSqr(point, closestPoint); - if (d < minDist2d) - { - minDist2d = d; - nearestPoly = polyPath[i]; - minDist3d = dtVdistSqr(point, closestPoint); - } - - if (minDist2d < 1.0f) // shortcut out - close enough for us - break; - } - - if (distance) - *distance = dtSqrt(minDist3d); - - return (minDist2d < 3.0f) ? nearestPoly : INVALID_POLYREF; -} - -dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) const -{ - // first we check the current path - // if the current path doesn't contain the current poly, - // we need to use the expensive navMesh.findNearestPoly - dtPolyRef polyRef = GetPathPolyByPosition(_pathPolyRefs, _polyLength, point, distance); - if (polyRef != INVALID_POLYREF) - return polyRef; - - // we don't have it in our old path - // try to get it by findNearestPoly() - // first try with low search box - float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area - float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; - if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) - { - *distance = dtVdist(closestPoint, point); - return polyRef; - } - - // still nothing .. - // try with bigger search box - // Note that the extent should not overlap more than 128 polygons in the navmesh (see dtNavMeshQuery::findNearestPoly) - extents[1] = 50.0f; + float startPos[3]; + startPos[0] = -y; + startPos[1] = z; + startPos[2] = -x; - if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) - { - *distance = dtVdist(closestPoint, point); - return polyRef; - } + float endPos[3]; + endPos[0] = -destY; + endPos[1] = destZ; + endPos[2] = -destX; - return INVALID_POLYREF; -} + float polyPickExt[3]; + polyPickExt[0] = 2.5f; + polyPickExt[1] = 2.5f; + polyPickExt[2] = 2.5f; -void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos) -{ - // *** getting start/end poly logic *** + // + dtPolyRef startRef; + dtPolyRef endRef; - float distToStartPoly, distToEndPoly; - float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; - float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; + float nearestPt[3]; - dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly); - dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly); + _navMeshQuery->findNearestPoly(startPos, polyPickExt, &_filter, &startRef, nearestPt); + _navMeshQuery->findNearestPoly(endPos, polyPickExt, &_filter, &endRef, nearestPt); - // we have a hole in our mesh - // make shortcut path and mark it as NOPATH ( with flying and swimming exception ) - // its up to caller how he will use this info - if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) + if (!startRef || !endRef) { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); - BuildShortcut(); - bool path = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanFly(); - - bool waterPath = _sourceUnit->GetTypeId() == TYPEID_UNIT && _sourceUnit->ToCreature()->CanSwim(); - if (waterPath) - { - // Check both start and end points, if they're both in water, then we can *safely* let the creature move - for (uint32 i = 0; i < _pathPoints.size(); ++i) - { - ZLiquidStatus status = _sourceUnit->GetBaseMap()->getLiquidStatus(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z, MAP_ALL_LIQUIDS, NULL); - // One of the points is not in the water, cancel movement. - if (status == LIQUID_MAP_NO_WATER) - { - waterPath = false; - break; - } - } - } - - _type = (path || waterPath) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; - return; - } - - // we may need a better number here - bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); - if (farFromPoly) - { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); - - bool buildShotrcut = false; - if (_sourceUnit->GetTypeId() == TYPEID_UNIT) - { - Creature* owner = (Creature*)_sourceUnit; - - G3D::Vector3 const& p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (_sourceUnit->GetBaseMap()->IsUnderWater(p.x, p.y, p.z)) - { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: underWater case\n"); - if (owner->CanSwim()) - buildShotrcut = true; - } - else - { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: flying case\n"); - if (owner->CanFly()) - buildShotrcut = true; - } - } - - if (buildShotrcut) - { - BuildShortcut(); - _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - return; - } - else - { - float closestPoint[VERTEX_SIZE]; - // we may want to use closestPointOnPolyBoundary instead - if (dtStatusSucceed(_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint))) - { - dtVcopy(endPoint, closestPoint); - SetActualEndPosition(G3D::Vector3(endPoint[2], endPoint[0], endPoint[1])); - } - - _type = PATHFIND_INCOMPLETE; - } - } - - // *** poly path generating logic *** - - // start and end are on same polygon - // just need to move in straight line - if (startPoly == endPoly) - { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPoly == endPoly)\n"); - - BuildShortcut(); - - _pathPolyRefs[0] = startPoly; - _polyLength = 1; - - _type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: path type %d\n", _type); - return; - } - - // look for startPoly/endPoly in current path - /// @todo we can merge it with getPathPolyByPosition() loop - bool startPolyFound = false; - bool endPolyFound = false; - uint32 pathStartIndex = 0; - uint32 pathEndIndex = 0; - - if (_polyLength) - { - for (; pathStartIndex < _polyLength; ++pathStartIndex) - { - // here to carch few bugs - ASSERT(_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); - - if (_pathPolyRefs[pathStartIndex] == startPoly) - { - startPolyFound = true; - break; - } - } - - for (pathEndIndex = _polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) - if (_pathPolyRefs[pathEndIndex] == endPoly) - { - endPolyFound = true; - break; - } - } - - if (startPolyFound && endPolyFound) - { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); - - // we moved along the path and the target did not move out of our old poly-path - // our path is a simple subpath case, we have all the data we need - // just "cut" it out - - _polyLength = pathEndIndex - pathStartIndex + 1; - memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, _polyLength * sizeof(dtPolyRef)); + TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u no polygons found for start and end locations\n", _sourceUnit->GetGUIDLow()); + _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _pathPoints.push_back(start); + _pathPoints.push_back(dest); + return false; } - else if (startPolyFound && !endPolyFound) - { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); - - // we are moving on the old path but target moved out - // so we have atleast part of poly-path ready - - _polyLength -= pathStartIndex; - - // try to adjust the suffix of the path instead of recalculating entire length - // at given interval the target cannot get too far from its last location - // thus we have less poly to cover - // sub-path of optimal path is optimal - - // take ~80% of the original length - /// @todo play with the values here - uint32 prefixPolyLength = uint32(_polyLength * 0.8f + 0.5f); - memmove(_pathPolyRefs, _pathPolyRefs+pathStartIndex, prefixPolyLength * sizeof(dtPolyRef)); - - dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; - - // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data - float suffixEndPoint[VERTEX_SIZE]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))) - { - // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that - // try to recover by using prev polyref - --prefixPolyLength; - suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint))) - { - // suffixStartPoly is still invalid, error state - BuildShortcut(); - _type = PATHFIND_NOPATH; - return; - } - } - - // generate suffix - uint32 suffixPolyLength = 0; - dtStatus dtResult = _navMeshQuery->findPath( - suffixStartPoly, // start polygon - endPoly, // end polygon - suffixEndPoint, // start position - endPoint, // end position - &_filter, // polygon search filter - _pathPolyRefs + prefixPolyLength - 1, // [out] path - (int*)&suffixPolyLength, - MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path - - if (!suffixPolyLength || dtStatusFailed(dtResult)) - { - // this is probably an error state, but we'll leave it - // and hopefully recover on the next Update - // we still need to copy our preffix - TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow()); - } - TC_LOG_DEBUG("maps", "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n", _polyLength, prefixPolyLength, suffixPolyLength); + int hops; + dtPolyRef* hopBuffer = new dtPolyRef[8192]; + dtStatus status = _navMeshQuery->findPath(startRef, endRef, startPos, endPos, &_filter, hopBuffer, &hops, 8192); - // new path = prefix + suffix - overlap - _polyLength = prefixPolyLength + suffixPolyLength - 1; - } - else + if (!dtStatusSucceed(status)) { - TC_LOG_DEBUG("maps", "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); - - // either we have no path at all -> first run - // or something went really wrong -> we aren't moving along the path to the target - // just generate new path - - // free and invalidate old path data - Clear(); - - dtStatus dtResult = _navMeshQuery->findPath( - startPoly, // start polygon - endPoly, // end polygon - startPoint, // start position - endPoint, // end position - &_filter, // polygon search filter - _pathPolyRefs, // [out] path - (int*)&_polyLength, - MAX_PATH_LENGTH); // max number of polygons in output path - - if (!_polyLength || dtStatusFailed(dtResult)) - { - // only happens if we passed bad data to findPath(), or navmesh is messed up - TC_LOG_ERROR("maps", "%u's Path Build failed: 0 length path", _sourceUnit->GetGUIDLow()); - BuildShortcut(); - _type = PATHFIND_NOPATH; - return; - } + TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u no path found for start and end locations\n", _sourceUnit->GetGUIDLow()); + _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _pathPoints.push_back(start); + _pathPoints.push_back(dest); + return false; } - // by now we know what type of path we can get - if (_pathPolyRefs[_polyLength - 1] == endPoly && !(_type & PATHFIND_INCOMPLETE)) - _type = PATHFIND_NORMAL; - else - _type = PATHFIND_INCOMPLETE; - - // generate the point-path out of our up-to-date poly-path - BuildPointPath(startPoint, endPoint); -} - -void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoint) -{ - float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; - uint32 pointCount = 0; - dtStatus dtResult = DT_FAILURE; - if (_useStraightPath) - { - dtResult = _navMeshQuery->findStraightPath( - startPoint, // start position - endPoint, // end position - _pathPolyRefs, // current path - _polyLength, // lenth of current path - pathPoints, // [out] path corner points - NULL, // [out] flags - NULL, // [out] shortened path - (int*)&pointCount, - _pointPathLimit); // maximum number of points/polygons to use - } - else - { - dtResult = FindSmoothPath( - startPoint, // start position - endPoint, // end position - _pathPolyRefs, // current path - _polyLength, // length of current path - pathPoints, // [out] path corner points - (int*)&pointCount, - _pointPathLimit); // maximum number of points - } + int resultHopCount; + float* straightPath = new float[2048 * 3]; + unsigned char* pathFlags = new unsigned char[2048]; + dtPolyRef* pathRefs = new dtPolyRef[2048]; - if (pointCount < 2 || dtStatusFailed(dtResult)) + status = _navMeshQuery->findStraightPath(startPos, endPos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048); + if (!dtStatusSucceed(status)) { - // only happens if pass bad data to findStraightPath or navmesh is broken - // single point paths can be generated here - /// @todo check the exact cases - TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount); - BuildShortcut(); - _type = PATHFIND_NOPATH; - return; - } - else if (pointCount == _pointPathLimit) - { - TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d\n", pointCount, _pointPathLimit); - BuildShortcut(); - _type = PATHFIND_SHORT; - return; + TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u no straight path found for start and end locations\n", _sourceUnit->GetGUIDLow()); + _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _pathPoints.push_back(start); + _pathPoints.push_back(dest); + return false; } - _pathPoints.resize(pointCount); - for (uint32 i = 0; i < pointCount; ++i) - _pathPoints[i] = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); - - NormalizePath(); + SmoothPath(polyPickExt, resultHopCount, straightPath); // Separate the path from the walls - // first point is always our current location - we need the next one - SetActualEndPosition(_pathPoints[pointCount-1]); - - // force the given destination, if needed - if (_forceDestination && - (!(_type & PATHFIND_NORMAL) || !InRange(GetEndPosition(), GetActualEndPosition(), 1.0f, 1.0f))) + for (uint32 i = 0; i < resultHopCount; ++i) { - // we may want to keep partial subpath - if (Dist3DSqr(GetActualEndPosition(), GetEndPosition()) < 0.3f * Dist3DSqr(GetStartPosition(), GetEndPosition())) - { - SetActualEndPosition(GetEndPosition()); - _pathPoints[_pathPoints.size()-1] = GetEndPosition(); - } - else - { - SetActualEndPosition(GetEndPosition()); - BuildShortcut(); - } - - _type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); + _pathPoints.push_back(G3D::Vector3(-straightPath[i * 3 + 2], -straightPath[i * 3 + 0], straightPath[i * 3 + 1])); + TC_LOG_DEBUG("maps", "PathGenerator::CalculatePath() for %u path point %u: (%f, %f, %f)", _sourceUnit->GetGUIDLow(), i, _pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z); } - TC_LOG_DEBUG("maps", "++ PathGenerator::BuildPointPath path type %d size %d poly-size %d\n", _type, pointCount, _polyLength); -} - -void PathGenerator::NormalizePath() -{ - for (uint32 i = 0; i < _pathPoints.size(); ++i) - _sourceUnit->UpdateAllowedPositionZ(_pathPoints[i].x, _pathPoints[i].y, _pathPoints[i].z); -} - -void PathGenerator::BuildShortcut() -{ - TC_LOG_DEBUG("maps", "++ BuildShortcut :: making shortcut\n"); - - Clear(); - - // make two point path, our curr pos is the start, and dest is the end - _pathPoints.resize(2); - - // set start and a default next position - _pathPoints[0] = GetStartPosition(); - _pathPoints[1] = GetActualEndPosition(); - - NormalizePath(); - - _type = PATHFIND_SHORTCUT; + _type = PATHFIND_NORMAL; + return true; } void PathGenerator::CreateFilter() { - uint16 includeFlags = 0; + uint16 includeFlags = POLY_FLAG_WALK | POLY_FLAG_SWIM; uint16 excludeFlags = 0; - if (_sourceUnit->GetTypeId() == TYPEID_UNIT) + if (_sourceUnit->GetTypeId() == TYPEID_UNIT && !_sourceUnit->ToCreature()->CanSwim()) { - Creature* creature = (Creature*)_sourceUnit; - if (creature->CanWalk()) - includeFlags |= NAV_GROUND; // walk - - // creatures don't take environmental damage - if (creature->CanSwim()) - includeFlags |= (NAV_WATER | NAV_MAGMA | NAV_SLIME); // swim - } - else // assume Player - { - // perfect support not possible, just stay 'safe' - includeFlags |= (NAV_GROUND | NAV_WATER | NAV_MAGMA | NAV_SLIME); + includeFlags = POLY_FLAG_WALK; + excludeFlags = POLY_FLAG_SWIM; } _filter.setIncludeFlags(includeFlags); @@ -534,275 +180,130 @@ void PathGenerator::CreateFilter() void PathGenerator::UpdateFilter() { - // allow creatures to cheat and use different movement types if they are moved - // forcefully into terrain they can't normally move in - if (_sourceUnit->IsInWater() || _sourceUnit->IsUnderWater()) - { - uint16 includedFlags = _filter.getIncludeFlags(); - includedFlags |= GetNavTerrain(_sourceUnit->GetPositionX(), - _sourceUnit->GetPositionY(), - _sourceUnit->GetPositionZ()); - _filter.setIncludeFlags(includedFlags); - } } -NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) +float PathGenerator::GetTriangleArea(float* verts, int nv) { - LiquidData data; - ZLiquidStatus liquidStatus = _sourceUnit->GetBaseMap()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data); - if (liquidStatus == LIQUID_MAP_NO_WATER) - return NAV_GROUND; - - switch (data.type_flags) - { - case MAP_LIQUID_TYPE_WATER: - case MAP_LIQUID_TYPE_OCEAN: - return NAV_WATER; - case MAP_LIQUID_TYPE_MAGMA: - return NAV_MAGMA; - case MAP_LIQUID_TYPE_SLIME: - return NAV_SLIME; - default: - return NAV_GROUND; - } + float area = 0; + for (int i = 0; i < nv - 1; i++) + area += verts[i * 3] * verts[i * 3 + 5] - verts[i * 3 + 3] * verts[i * 3 + 2]; + area += verts[(nv - 1) * 3] * verts[2] - verts[0] * verts[(nv - 1) * 3 + 2]; + return area * 0.5f; } -bool PathGenerator::HaveTile(const G3D::Vector3& p) const +bool PathGenerator::PointInPoly(float* pos, float* verts, int nv, float err) { - int tx = -1, ty = -1; - float point[VERTEX_SIZE] = {p.y, p.z, p.x}; - - _navMesh->calcTileLoc(point, &tx, &ty); - - /// Workaround - /// For some reason, often the tx and ty variables wont get a valid value - /// Use this check to prevent getting negative tile coords and crashing on getTileAt - if (tx < 0 || ty < 0) - return false; - - return (_navMesh->getTileAt(tx, ty, 0) != NULL); -} - -uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited) -{ - int32 furthestPath = -1; - int32 furthestVisited = -1; - - // Find furthest common polygon. - for (int32 i = npath-1; i >= 0; --i) + // Poly area + float area = abs(PathGenerator::GetTriangleArea(verts, nv)); + + // Calculate each area of the triangles + float testTri[9]; + memcpy(testTri, pos, sizeof(float) * 3); + float area1 = 0; + for(int i = 0; i < nv - 1; ++i) { - bool found = false; - for (int32 j = nvisited-1; j >= 0; --j) - { - if (path[i] == visited[j]) - { - furthestPath = i; - furthestVisited = j; - found = true; - } - } - if (found) - break; + memcpy(&testTri[3], &verts[i * 3], sizeof(float) * 3); + memcpy(&testTri[6], &verts[i * 3 + 3], sizeof(float) * 3); + area1 += abs(PathGenerator::GetTriangleArea(testTri, 3)); + if (area1 - err > area) + return false; } - // If no intersection found just return current path. - if (furthestPath == -1 || furthestVisited == -1) - return npath; + // Last one + memcpy(&testTri[3], verts, sizeof(float) * 3); + memcpy(&testTri[6], &verts[nv * 3 - 3] , sizeof(float) * 3); + area1 += abs(PathGenerator::GetTriangleArea(testTri, 3)); - // Concatenate paths. + return abs(area1 - area) < err; +} - // Adjust beginning of the buffer to include the visited. - uint32 req = nvisited - furthestVisited; - uint32 orig = uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath; - uint32 size = npath > orig ? npath - orig : 0; - if (req + size > maxPath) - size = maxPath-req; +float PathGenerator::DistanceToWall(float* polyPickExt, float* pos, float* hitPos, float* hitNormal) +{ + float distanceToWall = 0; + dtPolyRef ref; - if (size) - memmove(path + req, path + orig, size * sizeof(dtPolyRef)); + dtStatus status = _navMeshQuery->findNearestPoly(pos, polyPickExt, &_filter, &ref, 0); - // Store visited - for (uint32 i = 0; i < req; ++i) - path[i] = visited[(nvisited - 1) - i]; + if (!dtStatusSucceed(status) || ref == 0) + return -1; - return req+size; -} + const dtMeshTile* tile = 0; + const dtPoly* poly = 0; + if (dtStatusFailed(_navMesh->getTileAndPolyByRef(ref, &tile, &poly))) + return -1; -bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, - float minTargetDist, dtPolyRef const* path, uint32 pathSize, - float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) -{ - // Find steer target. - static const uint32 MAX_STEER_POINTS = 3; - float steerPath[MAX_STEER_POINTS*VERTEX_SIZE]; - unsigned char steerPathFlags[MAX_STEER_POINTS]; - dtPolyRef steerPathPolys[MAX_STEER_POINTS]; - uint32 nsteerPath = 0; - dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, - steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); - if (!nsteerPath || dtStatusFailed(dtResult)) - return false; - - // Find vertex far enough to steer to. - uint32 ns = 0; - while (ns < nsteerPath) + // Collect vertices. + float verts[DT_VERTS_PER_POLYGON * 3]; + int nv = 0; + for (unsigned char i = 0; i < poly->vertCount; ++i) { - // Stop at Off-Mesh link or when point is further than slop away. - if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !InRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) - break; - ns++; + dtVcopy(&verts[nv * 3], &tile->verts[poly->verts[i] * 3]); + nv++; } - // Failed to find good point to steer to. - if (ns >= nsteerPath) - return false; - dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]); - steerPos[1] = startPos[1]; // keep Z value - steerPosFlag = steerPathFlags[ns]; - steerPosRef = steerPathPolys[ns]; + bool inside = PathGenerator::PointInPoly(pos, verts, nv, 0.05f); + if (!inside) + return -1; - return true; + if (!dtStatusSucceed(_navMeshQuery->findDistanceToWall(ref, pos, 100.0f, &_filter, &distanceToWall, hitPos, hitNormal))) + return -1; + + return distanceToWall; } -dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPos, - dtPolyRef const* polyPath, uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) +void PathGenerator::SmoothPath(float* polyPickExt, int pathLength, float*& straightPath) { - *smoothPathSize = 0; - uint32 nsmoothPath = 0; - - dtPolyRef polys[MAX_PATH_LENGTH]; - memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize); - uint32 npolys = polyPathSize; - - float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; - if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[0], startPos, iterPos))) - return DT_FAILURE; - - if (dtStatusFailed(_navMeshQuery->closestPointOnPolyBoundary(polys[npolys-1], endPos, targetPos))) - return DT_FAILURE; - - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - - // Move towards target a small advancement at a time until target reached or - // when ran out of memory to store the path. - while (npolys && nsmoothPath < maxSmoothPathSize) + float hitPos[3]; + float hitNormal[3]; + float testPos[3]; + float distanceToWall = 0; + float up[]= { 0, 1, 0 }; + float origDis = 0; + + for (int i = 1; i < pathLength - 1; ++i) { - // Find location to steer towards. - float steerPos[VERTEX_SIZE]; - unsigned char steerPosFlag; - dtPolyRef steerPosRef = INVALID_POLYREF; - - if (!GetSteerTarget(iterPos, targetPos, SMOOTH_PATH_SLOP, polys, npolys, steerPos, steerPosFlag, steerPosRef)) - break; - - bool endOfPath = (steerPosFlag & DT_STRAIGHTPATH_END); - bool offMeshConnection = (steerPosFlag & DT_STRAIGHTPATH_OFFMESH_CONNECTION); - - // Find movement delta. - float delta[VERTEX_SIZE]; - dtVsub(delta, steerPos, iterPos); - float len = dtSqrt(dtVdot(delta, delta)); - // If the steer target is end of path or off-mesh link, do not move past the location. - if ((endOfPath || offMeshConnection) && len < SMOOTH_PATH_STEP_SIZE) - len = 1.0f; - else - len = SMOOTH_PATH_STEP_SIZE / len; - - float moveTgt[VERTEX_SIZE]; - dtVmad(moveTgt, iterPos, delta, len); - - // Move - float result[VERTEX_SIZE]; - const static uint32 MAX_VISIT_POLY = 16; - dtPolyRef visited[MAX_VISIT_POLY]; - - uint32 nvisited = 0; - _navMeshQuery->moveAlongSurface(polys[0], iterPos, moveTgt, &_filter, result, visited, (int*)&nvisited, MAX_VISIT_POLY); - npolys = FixupCorridor(polys, npolys, MAX_PATH_LENGTH, visited, nvisited); - - _navMeshQuery->getPolyHeight(polys[0], result, &result[1]); - result[1] += 0.5f; - dtVcopy(iterPos, result); - - // Handle end of path and off-mesh links when close enough. - if (endOfPath && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) - { - // Reached end of path. - dtVcopy(iterPos, targetPos); - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; - } - break; - } - else if (offMeshConnection && InRangeYZX(iterPos, steerPos, SMOOTH_PATH_SLOP, 1.0f)) - { - // Advance the path up to and over the off-mesh connection. - dtPolyRef prevRef = INVALID_POLYREF; - dtPolyRef polyRef = polys[0]; - uint32 npos = 0; - while (npos < npolys && polyRef != steerPosRef) - { - prevRef = polyRef; - polyRef = polys[npos]; - npos++; - } - - for (uint32 i = npos; i < npolys; ++i) - polys[i-npos] = polys[i]; - - npolys -= npos; + dtPolyRef pt; + float* curPoi = &straightPath[i * 3]; + distanceToWall = DistanceToWall(polyPickExt, curPoi, hitPos, hitNormal); - // Handle the connection. - float startPos[VERTEX_SIZE], endPos[VERTEX_SIZE]; - if (dtStatusSucceed(_navMesh->getOffMeshConnectionPolyEndPoints(prevRef, polyRef, startPos, endPos))) + if (distanceToWall < PathGenerator::MinWallDistance && distanceToWall >= 0) + { + float vec[3]; + dtVsub(vec, &straightPath[i * 3 - 3], &straightPath[i * 3]); + // If distanceToWall is 0 means the point is in the edge, so we can't get the hitpos. + if (distanceToWall == 0) { - if (nsmoothPath < maxSmoothPathSize) + // Test the left side + dtVcross(testPos, vec, up); + dtVadd(testPos, testPos, curPoi); + float ft = PathGenerator::MinWallDistance / dtVdist(testPos, curPoi); + dtVlerp(testPos, curPoi, testPos, ft); + distanceToWall = DistanceToWall(polyPickExt, testPos, hitPos, hitNormal); + if (abs(PathGenerator::MinWallDistance - distanceToWall) > 0.1f) { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], startPos); - nsmoothPath++; + // Test the right side + dtVcross(testPos, up, vec); + dtVadd(testPos, testPos, curPoi); + ft = PathGenerator::MinWallDistance / dtVdist(testPos, curPoi); + dtVlerp(testPos, curPoi, testPos, ft); + distanceToWall = DistanceToWall(polyPickExt, testPos, hitPos, hitNormal); } - // Move position at the other side of the off-mesh link. - dtVcopy(iterPos, endPos); - _navMeshQuery->getPolyHeight(polys[0], iterPos, &iterPos[1]); - iterPos[1] += 0.5f; + + // If the test point is better than the orig point, replace it. + if (abs(distanceToWall - PathGenerator::MinWallDistance) < 0.1f) + dtVcopy(curPoi, testPos); } - } + else + { + // We get the hitpos with a ray + float ft = PathGenerator::MinWallDistance / distanceToWall; + dtVlerp(testPos, hitPos, curPoi, ft); + distanceToWall = DistanceToWall(polyPickExt, testPos, hitPos, hitNormal); - // Store results. - if (nsmoothPath < maxSmoothPathSize) - { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); - nsmoothPath++; + if (abs(distanceToWall - PathGenerator::MinWallDistance) < 0.1f) + dtVcopy(curPoi, testPos); + } } } - - *smoothPathSize = nsmoothPath; - - // this is most likely a loop - return nsmoothPath < MAX_POINT_PATH_LENGTH ? DT_SUCCESS : DT_FAILURE; -} - -bool PathGenerator::InRangeYZX(const float* v1, const float* v2, float r, float h) const -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; // elevation - const float dz = v2[2] - v1[2]; - return (dx * dx + dz * dz) < r * r && fabsf(dy) < h; -} - -bool PathGenerator::InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const -{ - G3D::Vector3 d = p1 - p2; - return (d.x * d.x + d.y * d.y) < r * r && fabsf(d.z) < h; -} - -float PathGenerator::Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const -{ - return (p1 - p2).squaredLength(); } diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h index ac66b7cec57..075d6dabc9f 100644 --- a/src/server/game/Movement/PathGenerator.h +++ b/src/server/game/Movement/PathGenerator.h @@ -26,18 +26,6 @@ class Unit; -// 74*4.0f=296y number_of_points*interval = max_path_len -// this is way more than actual evade range -// I think we can safely cut those down even more -#define MAX_PATH_LENGTH 74 -#define MAX_POINT_PATH_LENGTH 74 - -#define SMOOTH_PATH_STEP_SIZE 4.0f -#define SMOOTH_PATH_SLOP 0.3f - -#define VERTEX_SIZE 3 -#define INVALID_POLYREF 0 - enum PathType { PATHFIND_BLANK = 0x00, // path not built yet @@ -49,6 +37,12 @@ enum PathType PATHFIND_SHORT = 0x20, // path is longer or equal to its limited path length }; +enum PolyFlag +{ + POLY_FLAG_WALK = 1, + POLY_FLAG_SWIM = 2 +}; + class PathGenerator { public: @@ -59,10 +53,6 @@ class PathGenerator // return: true if new path was calculated, false otherwise (no change needed) bool CalculatePath(float destX, float destY, float destZ, bool forceDest = false); - // option setters - use optional - void SetUseStraightPath(bool useStraightPath) { _useStraightPath = useStraightPath; } - void SetPathLengthLimit(float distance) { _pointPathLimit = std::min<uint32>(uint32(distance/SMOOTH_PATH_STEP_SIZE), MAX_POINT_PATH_LENGTH); } - // result getters G3D::Vector3 const& GetStartPosition() const { return _startPosition; } G3D::Vector3 const& GetEndPosition() const { return _endPosition; } @@ -71,19 +61,13 @@ class PathGenerator Movement::PointsArray const& GetPath() const { return _pathPoints; } PathType GetPathType() const { return _type; } + + static float MinWallDistance; private: - - dtPolyRef _pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references - uint32 _polyLength; // number of polygons in the path - Movement::PointsArray _pathPoints; // our actual (x,y,z) path to the target PathType _type; // tells what kind of path this is - bool _useStraightPath; // type of path will be generated - bool _forceDestination; // when set, we will always arrive at given point - uint32 _pointPathLimit; // limit point path size; min(this, MAX_POINT_PATH_LENGTH) - G3D::Vector3 _startPosition; // {x, y, z} of current location G3D::Vector3 _endPosition; // {x, y, z} of the destination G3D::Vector3 _actualEndPosition; // {x, y, z} of the closest possible point to given destination @@ -97,37 +81,16 @@ class PathGenerator void SetStartPosition(G3D::Vector3 const& point) { _startPosition = point; } void SetEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; _endPosition = point; } void SetActualEndPosition(G3D::Vector3 const& point) { _actualEndPosition = point; } - void NormalizePath(); - - void Clear() - { - _polyLength = 0; - _pathPoints.clear(); - } - bool InRange(G3D::Vector3 const& p1, G3D::Vector3 const& p2, float r, float h) const; - float Dist3DSqr(G3D::Vector3 const& p1, G3D::Vector3 const& p2) const; - bool InRangeYZX(float const* v1, float const* v2, float r, float h) const; + // Path smoothing + void SmoothPath(float* polyPickExt, int pathLength, float*& straightPath); + float DistanceToWall(float* polyPickExt, float* pos, float* hitPos, float* hitNormal); + // dtPointInPolygon will return false when the point is too close to the edge, so we rewrite the test function. + static bool PointInPoly(float* pos, float* verts, int nv, float err); + static float GetTriangleArea(float* verts, int nv); - dtPolyRef GetPathPolyByPosition(dtPolyRef const* polyPath, uint32 polyPathSize, float const* Point, float* Distance = NULL) const; - dtPolyRef GetPolyByLocation(float const* Point, float* Distance) const; - bool HaveTile(G3D::Vector3 const& p) const; - - void BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 const& endPos); - void BuildPointPath(float const* startPoint, float const* endPoint); - void BuildShortcut(); - - NavTerrain GetNavTerrain(float x, float y, float z); void CreateFilter(); void UpdateFilter(); - - // smooth path aux functions - uint32 FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, dtPolyRef const* visited, uint32 nvisited); - bool GetSteerTarget(float const* startPos, float const* endPos, float minTargetDist, dtPolyRef const* path, uint32 pathSize, float* steerPos, - unsigned char& steerPosFlag, dtPolyRef& steerPosRef); - dtStatus FindSmoothPath(float const* startPos, float const* endPos, - dtPolyRef const* polyPath, uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, uint32 smoothPathMaxSize); }; #endif diff --git a/src/server/game/Movement/Spline/Spline.cpp b/src/server/game/Movement/Spline/Spline.cpp index 887541e2289..6424afc5d6e 100644 --- a/src/server/game/Movement/Spline/Spline.cpp +++ b/src/server/game/Movement/Spline/Spline.cpp @@ -156,7 +156,7 @@ float SplineBase::SegLengthLinear(index_type index) const return (points[index] - points[index+1]).length(); } -float SplineBase::SegLengthCatmullRom( index_type index ) const +float SplineBase::SegLengthCatmullRom(index_type index) const { ASSERT(index >= index_lo && index < index_hi); diff --git a/src/server/game/Movement/Spline/Spline.h b/src/server/game/Movement/Spline/Spline.h index dab31e957f1..1444b2872d1 100644 --- a/src/server/game/Movement/Spline/Spline.h +++ b/src/server/game/Movement/Spline/Spline.h @@ -118,7 +118,7 @@ public: /** As i can see there are a lot of ways how spline can be initialized would be no harm to have some custom initializers. */ - template<class Init> inline void init_spline(Init& initializer) + template<class Init> inline void init_spline_custom(Init& initializer) { initializer(m_mode, cyclic, points, index_lo, index_hi); } diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h index 599780d5cbe..2464b99c0ab 100644 --- a/src/server/game/Quests/QuestDef.h +++ b/src/server/game/Quests/QuestDef.h @@ -123,6 +123,9 @@ enum QuestGiverStatus DIALOG_STATUS_AVAILABLE = 0x100, DIALOG_STATUS_REWARD2 = 0x200, // no yellow dot on minimap DIALOG_STATUS_REWARD = 0x400 // yellow dot on minimap + + // Custom value meaning that script call did not return any valid quest status + DIALOG_STATUS_SCRIPTED_NO_STATUS = 0x1000, }; enum QuestFlags diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Scripting/MapScripts.cpp index 7f2e1f095e4..b9765bbbdc2 100644 --- a/src/server/game/Scripting/MapScripts.cpp +++ b/src/server/game/Scripting/MapScripts.cpp @@ -166,7 +166,7 @@ inline Unit* Map::_GetScriptUnit(Object* obj, bool isSource, const ScriptInfo* s { unit = obj->ToUnit(); if (!unit) - TC_LOG_ERROR("scripts", "%s %s object could not be casted to unit.", + TC_LOG_ERROR("scripts", "%s %s object could not be cast to unit.", scriptInfo->GetDebugInfo().c_str(), isSource ? "source" : "target"); } return unit; @@ -242,7 +242,7 @@ inline void Map::_ScriptProcessDoor(Object* source, Object* target, const Script { WorldObject* wSource = dynamic_cast <WorldObject*> (source); if (!wSource) - TC_LOG_ERROR("scripts", "%s source object could not be casted to world object (TypeId: %u, Entry: %u, GUID: %u), skipping.", + TC_LOG_ERROR("scripts", "%s source object could not be cast to world object (TypeId: %u, Entry: %u, GUID: %u), skipping.", scriptInfo->GetDebugInfo().c_str(), source->GetTypeId(), source->GetEntry(), source->GetGUIDLow()); else { diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index ddf6fe3a093..20b40051c19 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -778,8 +778,7 @@ uint32 ScriptMgr::GetDialogStatus(Player* player, Creature* creature) ASSERT(player); ASSERT(creature); - /// @todo 100 is a funny magic number to have hanging around here... - GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, 100); + GET_SCRIPT_RET(CreatureScript, creature->GetScriptId(), tmpscript, DIALOG_STATUS_SCRIPTED_NO_STATUS); player->PlayerTalkClass->ClearMenus(); return tmpscript->GetDialogStatus(player, creature); } @@ -864,8 +863,7 @@ uint32 ScriptMgr::GetDialogStatus(Player* player, GameObject* go) ASSERT(player); ASSERT(go); - /// @todo 100 is a funny magic number to have hanging around here... - GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, 100); + GET_SCRIPT_RET(GameObjectScript, go->GetScriptId(), tmpscript, DIALOG_STATUS_SCRIPTED_NO_STATUS); player->PlayerTalkClass->ClearMenus(); return tmpscript->GetDialogStatus(player, go); } diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 86ddc377bc2..a10707924e4 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -24,6 +24,7 @@ #include <ace/Atomic_Op.h> #include "DBCStores.h" +#include "QuestDef.h" #include "SharedDefines.h" #include "World.h" #include "Weather.h" @@ -446,7 +447,7 @@ class CreatureScript : public UnitScript, public UpdatableScript<Creature> virtual bool OnQuestReward(Player* /*player*/, Creature* /*creature*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; } // Called when the dialog status between a player and the creature is requested. - virtual uint32 GetDialogStatus(Player* /*player*/, Creature* /*creature*/) { return 100; } + virtual uint32 GetDialogStatus(Player* /*player*/, Creature* /*creature*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; } // Called when a CreatureAI object is needed for the creature. virtual CreatureAI* GetAI(Creature* /*creature*/) const { return NULL; } @@ -481,7 +482,7 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject> virtual bool OnQuestReward(Player* /*player*/, GameObject* /*go*/, Quest const* /*quest*/, uint32 /*opt*/) { return false; } // Called when the dialog status between a player and the gameobject is requested. - virtual uint32 GetDialogStatus(Player* /*player*/, GameObject* /*go*/) { return 100; } + virtual uint32 GetDialogStatus(Player* /*player*/, GameObject* /*go*/) { return DIALOG_STATUS_SCRIPTED_NO_STATUS; } // Called when the game object is destroyed (destructible buildings only). virtual void OnDestroyed(GameObject* /*go*/, Player* /*player*/) { } diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 4954d099dab..7227254b9f7 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -363,7 +363,7 @@ class WorldSession uint32 GetLatency() const { return m_latency; } void SetLatency(uint32 latency) { m_latency = latency; } void ResetClientTimeDelay() { m_clientTimeDelay = 0; } - uint32 getDialogStatus(Player* player, Object* questgiver, uint32 defstatus); + uint32 getDialogStatus(Player* player, Object* questgiver); ACE_Atomic_Op<ACE_Thread_Mutex, time_t> m_timeOutTime; void UpdateTimeOutTime(uint32 diff) diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 4a9854333a5..53350f8328a 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -804,7 +804,7 @@ void AuraEffect::ApplySpellMod(Unit* target, bool apply) { Aura* aura = iter->second->GetBase(); // only passive and permament auras-active auras should have amount set on spellcast and not be affected - // if aura is casted by others, it will not be affected + // if aura is cast by others, it will not be affected if ((aura->IsPassive() || aura->IsPermanent()) && aura->GetCasterGUID() == guid && aura->GetSpellInfo()->IsAffectedBySpellMod(m_spellmod)) { if (GetMiscValue() == SPELLMOD_ALL_EFFECTS) @@ -4704,7 +4704,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool case 42783: // Wrath of the Astromancer target->CastSpell(target, GetAmount(), true, NULL, this); break; - case 46308: // Burning Winds casted only at creatures at spawn + case 46308: // Burning Winds cast only at creatures at spawn target->CastSpell(target, 47287, true, NULL, this); break; case 52172: // Coyote Spirit Despawn Aura diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index a984ee7b035..4a1eeed46b1 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -114,12 +114,12 @@ void AuraApplication::_Remove() void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) { - // mark as selfcasted if needed + // mark as selfcast if needed _flags |= (GetBase()->GetCasterGUID() == GetTarget()->GetGUID()) ? AFLAG_CASTER : AFLAG_NONE; - // aura is casted by self or an enemy + // aura is cast by self or an enemy // one negative effect and we know aura is negative - if (IsSelfcasted() || !caster || !caster->IsFriendlyTo(GetTarget())) + if (IsSelfcast() || !caster || !caster->IsFriendlyTo(GetTarget())) { bool negativeFound = false; for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) @@ -132,7 +132,7 @@ void AuraApplication::_InitFlags(Unit* caster, uint8 effMask) } _flags |= negativeFound ? AFLAG_NEGATIVE : AFLAG_POSITIVE; } - // aura is casted by friend + // aura is cast by friend // one positive effect and we know aura is positive else { @@ -315,7 +315,7 @@ Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owne // check if aura can be owned by owner if (owner->isType(TYPEMASK_UNIT)) if (!owner->IsInWorld() || ((Unit*)owner)->IsDuringRemoveFromWorld()) - // owner not in world so don't allow to own not self casted single target auras + // owner not in world so don't allow to own not self cast single target auras if (casterGUID != owner->GetGUID() && spellproto->IsSingleTarget()) return NULL; @@ -1284,7 +1284,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b } break; case SPELLFAMILY_ROGUE: - // Sprint (skip non player casted spells by category) + // Sprint (skip non player cast spells by category) if (GetSpellInfo()->SpellFamilyFlags[0] & 0x40 && GetSpellInfo()->GetCategory() == 44) // in official maybe there is only one icon? if (target->HasAura(58039)) // Glyph of Blurred Speed @@ -1500,7 +1500,7 @@ bool Aura::CanBeAppliedOn(Unit* target) // area auras mustn't be applied if (GetOwner() != target) return false; - // not selfcasted single target auras mustn't be applied + // do not apply non-selfcast single target auras if (GetCasterGUID() != GetOwner()->GetGUID() && GetSpellInfo()->IsSingleTarget()) return false; return true; diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 9e7d0cce82c..123ad9d5a8a 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -69,7 +69,7 @@ class AuraApplication uint8 GetEffectMask() const { return _flags & (AFLAG_EFF_INDEX_0 | AFLAG_EFF_INDEX_1 | AFLAG_EFF_INDEX_2); } bool HasEffect(uint8 effect) const { ASSERT(effect < MAX_SPELL_EFFECTS); return _flags & (1<<effect); } bool IsPositive() const { return _flags & AFLAG_POSITIVE; } - bool IsSelfcasted() const { return _flags & AFLAG_CASTER; } + bool IsSelfcast() const { return _flags & AFLAG_CASTER; } uint8 GetEffectsToApply() const { return _effectsToApply; } void SetRemoveMode(AuraRemoveMode mode) { _removeMode = mode; } diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 08d500ec666..a46f5cdaa9a 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2409,7 +2409,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied - //Spells with this flag cannot trigger if effect is casted on self + //Spells with this flag cannot trigger if effect is cast on self bool canEffectTrigger = !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && CanExecuteTriggersOnHit(mask); Unit* spellHitTarget = NULL; @@ -3000,7 +3000,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1)); //Prevent casting at cast another spell (ServerSide check) - if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS) && m_caster->IsNonMeleeSpellCasted(false, true, true) && m_cast_count) + if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS) && m_caster->IsNonMeleeSpellCast(false, true, true) && m_cast_count) { SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS); finish(false); @@ -3067,7 +3067,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered else m_casttime = m_spellInfo->CalcCastTime(m_caster->getLevel(), this); - // don't allow channeled spells / spells with cast time to be casted while moving + // don't allow channeled spells / spells with cast time to be cast while moving // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in) // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect if (((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->isMoving() && @@ -3084,7 +3084,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered TC_LOG_DEBUG("spells", "Spell::prepare: spell id %u source %u caster %d customCastFlags %u mask %u", m_spellInfo->Id, m_caster->GetEntry(), m_originalCaster ? m_originalCaster->GetEntry() : -1, _triggeredCastFlags, m_targets.GetTargetMask()); //Containers for channeled spells have to be set - /// @todoApply this to all casted spells if needed + /// @todoApply this to all cast spells if needed // Why check duration? 29350: channelled triggers channelled if ((_triggeredCastFlags & TRIGGERED_CAST_DIRECTLY) && (!m_spellInfo->IsChanneled() || !m_spellInfo->GetMaxDuration())) cast(true); @@ -3103,7 +3103,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered } } - m_caster->SetCurrentCastedSpell(this); + m_caster->SetCurrentCastSpell(this); SendSpellStart(); // set target for proper facing @@ -3213,7 +3213,7 @@ void Spell::cast(bool skipCheck) if (m_caster->GetTypeId() == TYPEID_PLAYER) { // Set spell which will drop charges for triggered cast spells - // if not successfully casted, will be remove in finish(false) + // if not successfully cast, will be remove in finish(false) m_caster->ToPlayer()->SetSpellModTakingSpell(this, true); } @@ -3250,7 +3250,7 @@ void Spell::cast(bool skipCheck) { if (!my_trade->IsInAcceptProcess()) { - // Spell will be casted at completing the trade. Silently ignore at this place + // Spell will be cast after completing the trade. Silently ignore at this place my_trade->SetSpell(m_spellInfo->Id, m_CastItem); SendCastResult(SPELL_FAILED_DONT_REPORT); SendInterrupted(0); @@ -3340,7 +3340,7 @@ void Spell::cast(bool skipCheck) m_spellState = SPELL_STATE_DELAYED; SetDelayStart(0); - if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true)) + if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCast(false, false, true)) m_caster->ClearUnitState(UNIT_STATE_CASTING); } else @@ -3667,7 +3667,7 @@ void Spell::finish(bool ok) if (m_spellInfo->IsChanneled()) m_caster->UpdateInterruptMask(); - if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true)) + if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCast(false, false, true)) m_caster->ClearUnitState(UNIT_STATE_CASTING); // Unsummon summon as possessed creatures on spell cancel @@ -4029,7 +4029,7 @@ void Spell::SendSpellGo() if (castFlags & CAST_FLAG_RUNE_LIST) // rune cooldowns list { - /// @todo There is a crash caused by a spell with CAST_FLAG_RUNE_LIST casted by a creature + /// @todo There is a crash caused by a spell with CAST_FLAG_RUNE_LIST cast by a creature //The creature is the mover of a player, so HandleCastSpellOpcode uses it as the caster if (Player* player = m_caster->ToPlayer()) { @@ -4975,7 +4975,7 @@ SpellCastResult Spell::CheckCast(bool strict) if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER) && !target->HasInArc(static_cast<float>(M_PI), m_caster)) return SPELL_FAILED_NOT_INFRONT; - if (m_caster->GetEntry() != WORLD_TRIGGER) // Ignore LOS for gameobjects casts (wrongly casted by a trigger) + if (m_caster->GetEntry() != WORLD_TRIGGER) // Ignore LOS for gameobjects casts (wrongly cast by a trigger) if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOSInMap(target)) return SPELL_FAILED_LINE_OF_SIGHT; } @@ -5007,7 +5007,7 @@ SpellCastResult Spell::CheckCast(bool strict) } } - // Spell casted only on battleground + // Spell cast only in battleground if ((m_spellInfo->AttributesEx3 & SPELL_ATTR3_BATTLEGROUND) && m_caster->GetTypeId() == TYPEID_PLAYER) if (!m_caster->ToPlayer()->InBattleground()) return SPELL_FAILED_ONLY_BATTLEGROUNDS; @@ -5230,7 +5230,6 @@ SpellCastResult Spell::CheckCast(bool strict) target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ); target->GetFirstCollisionPosition(pos, CONTACT_DISTANCE, target->GetRelativeAngle(m_caster)); - m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f); bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize()); if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT) return SPELL_FAILED_OUT_OF_RANGE; @@ -5554,7 +5553,7 @@ SpellCastResult Spell::CheckCast(bool strict) if (!m_targets.GetUnitTarget()) return SPELL_FAILED_BAD_IMPLICIT_TARGETS; - // can be casted at non-friendly unit or own pet/charm + // can be cast at non-friendly unit or own pet/charm if (m_caster->IsFriendlyTo(m_targets.GetUnitTarget())) return SPELL_FAILED_TARGET_FRIENDLY; @@ -5783,7 +5782,7 @@ SpellCastResult Spell::CheckCasterAuras() const } } } - // You are prevented from casting and the spell casted does not grant immunity. Return a failed error. + // You are prevented from casting and the spell cast does not grant immunity. Return a failed error. else return prevented_reason; } @@ -6190,19 +6189,39 @@ SpellCastResult Spell::CheckItems() } } - SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(m_spellInfo->Effects[i].MiscValue); + SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(m_spellInfo->Effects[i].MiscValue); // do not allow adding usable enchantments to items that have use effect already - if (pEnchant && isItemUsable) + if (enchantEntry) + { for (uint8 s = 0; s < MAX_ITEM_ENCHANTMENT_EFFECTS; ++s) - if (pEnchant->type[s] == ITEM_ENCHANTMENT_TYPE_USE_SPELL) - return SPELL_FAILED_ON_USE_ENCHANT; + { + switch (enchantEntry->type[s]) + { + case ITEM_ENCHANTMENT_TYPE_USE_SPELL: + if (isItemUsable) + return SPELL_FAILED_ON_USE_ENCHANT; + break; + case ITEM_ENCHANTMENT_TYPE_PRISMATIC_SOCKET: + { + uint32 numSockets = 0; + for (uint32 socket = 0; socket < MAX_ITEM_PROTO_SOCKETS; ++socket) + if (targetItem->GetTemplate()->Socket[socket].Color) + ++numSockets; + + if (numSockets == MAX_ITEM_PROTO_SOCKETS || targetItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT)) + return SPELL_FAILED_MAX_SOCKETS; + break; + } + } + } + } // Not allow enchant in trade slot for some enchant type if (targetItem->GetOwner() != m_caster) { - if (!pEnchant) + if (!enchantEntry) return SPELL_FAILED_ERROR; - if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND) + if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND) return SPELL_FAILED_NOT_TRADEABLE; } break; @@ -6671,11 +6690,11 @@ bool SpellEvent::Execute(uint64 e_time, uint32 p_time) /* if (m_Spell->m_spellInfo->IsChanneled()) { - // evented channeled spell is processed separately, casted once after delay, and not destroyed till finish + // evented channeled spell is processed separately, cast once after delay, and not destroyed till finish // check, if we have casting anything else except this channeled spell and autorepeat - if (m_Spell->GetCaster()->IsNonMeleeSpellCasted(false, true, true)) + if (m_Spell->GetCaster()->IsNonMeleeSpellCast(false, true, true)) { - // another non-melee non-delayed spell is casted now, abort + // another non-melee non-delayed spell is cast now, abort m_Spell->cancel(); } else @@ -6898,7 +6917,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk 0 : m_caster->ToPlayer()->GetSkillValue(skillId); // skill bonus provided by casting spell (mostly item spells) - // add the effect base points modifier from the spell casted (cheat lock / skeleton key etc.) + // add the effect base points modifier from the spell cast (cheat lock / skeleton key etc.) if (m_spellInfo->Effects[effIndex].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET || m_spellInfo->Effects[effIndex].TargetB.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET) skillValue += m_spellInfo->Effects[effIndex].CalcValue(); @@ -7199,7 +7218,7 @@ bool Spell::CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToC bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const { bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER)); - // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a casted spell with TARGET_UNIT_CASTER + // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a cast spell with TARGET_UNIT_CASTER for (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i) { if ((effMask & (1 << i)) && (!only_on_caster || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER))) @@ -7289,7 +7308,7 @@ void Spell::TriggerGlobalCooldown() return; // Global cooldown can't leave range 1..1.5 secs - // There are some spells (mostly not casted directly by player) that have < 1 sec and > 1.5 sec global cooldowns + // There are some spells (mostly not cast directly by player) that have < 1 sec and > 1.5 sec global cooldowns // but as tests show are not affected by any spell mods. if (m_spellInfo->StartRecoveryTime >= MIN_GCD && m_spellInfo->StartRecoveryTime <= MAX_GCD) { diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 37316e1d6bb..b6cf0a1f9b7 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -209,7 +209,7 @@ enum SpellEffectHandleMode class Spell { - friend void Unit::SetCurrentCastedSpell(Spell* pSpell); + friend void Unit::SetCurrentCastSpell(Spell* pSpell); friend class SpellScript; public: diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index a22e32abf82..922074970b2 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -4614,8 +4614,8 @@ void Spell::EffectKnockBack(SpellEffIndex effIndex) if (unitTarget->HasUnitState(UNIT_STATE_ROOT | UNIT_STATE_STUNNED)) return; - // Instantly interrupt non melee spells being casted - if (unitTarget->IsNonMeleeSpellCasted(true)) + // Instantly interrupt non melee spells being cast + if (unitTarget->IsNonMeleeSpellCast(true)) unitTarget->InterruptNonMeleeSpells(true); float ratio = 0.1f; @@ -4716,8 +4716,6 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) if (!unitTarget) return; - float speedZ = (float)(m_spellInfo->Effects[effIndex].CalcValue() / 10); - float speedXY = (float)(m_spellInfo->Effects[effIndex].MiscValue/10); Position pos; if (m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_PULL_TOWARDS_DEST) { @@ -4731,6 +4729,9 @@ void Spell::EffectPullTowards(SpellEffIndex effIndex) pos.Relocate(m_caster); } + float speedXY = float(m_spellInfo->Effects[effIndex].MiscValue) * 0.1f; + float speedZ = unitTarget->GetDistance(pos) / speedXY * 0.5f * Movement::gravity; + unitTarget->GetMotionMaster()->MoveJump(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), speedXY, speedZ); } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 79a8c54cdbb..9bf2059b618 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1478,10 +1478,10 @@ SpellCastResult SpellInfo::CheckShapeshift(uint32 form) const uint32 stanceMask = (form ? 1 << (form - 1) : 0); - if (stanceMask & StancesNot) // can explicitly not be casted in this stance + if (stanceMask & StancesNot) // can explicitly not be cast in this stance return SPELL_FAILED_NOT_SHAPESHIFT; - if (stanceMask & Stances) // can explicitly be casted in this stance + if (stanceMask & Stances) // can explicitly be cast in this stance return SPELL_CAST_OK; bool actAsShifted = false; @@ -2711,12 +2711,12 @@ bool SpellInfo::_IsPositiveEffect(uint8 effIndex, bool deep) const case SPELL_AURA_PREVENT_RESURRECTION: return false; case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also. - // part of negative spell if casted at self (prevent cancel) + // part of negative spell if cast at self (prevent cancel) if (Effects[effIndex].TargetA.GetTarget() == TARGET_UNIT_CASTER) return false; break; case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also - // part of positive spell if casted at self + // part of positive spell if cast at self if (Effects[effIndex].TargetA.GetTarget() != TARGET_UNIT_CASTER) return false; // but not this if this first effect (didn't find better check) diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 6d58da9095b..945f907f548 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -1528,8 +1528,8 @@ void SpellMgr::LoadSpellLearnSpells() if (!GetSpellInfo(dbc_node.spell)) continue; - // talent or passive spells or skill-step spells auto-casted and not need dependent learning, - // pet teaching spells must not be dependent learning (casted) + // talent or passive spells or skill-step spells auto-cast and not need dependent learning, + // pet teaching spells must not be dependent learning (cast) // other required explicit dependent learning dbc_node.autoLearned = entry->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET || GetTalentSpellCost(spell) > 0 || entry->IsPassive() || entry->HasEffect(SPELL_EFFECT_SKILL_STEP); @@ -3725,7 +3725,7 @@ void SpellMgr::LoadSpellInfoCorrections() break; // This would never crit on retail and it has attribute for SPELL_ATTR3_NO_DONE_BONUS because is handled from player, // until someone figures how to make scions not critting without hack and without making them main casters this should stay here. - case 63934: // Arcane Barrage (casted by players and NONMELEEDAMAGELOG with caster Scion of Eternity (original caster)). + case 63934: // Arcane Barrage (cast by players and NONMELEEDAMAGELOG with caster Scion of Eternity (original caster)). spellInfo->AttributesEx2 |= SPELL_ATTR2_CANT_CRIT; break; // ENDOF EYE OF ETERNITY SPELLS diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 0d5643bc50c..4c25adb0476 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -775,11 +775,11 @@ class AuraScript : public _SpellScript // returns spellid of the spell uint32 GetId() const; - // returns guid of object which casted the aura (m_originalCaster of the Spell class) + // returns guid of object which cast the aura (m_originalCaster of the Spell class) uint64 GetCasterGUID() const; - // returns unit which casted the aura or NULL if not avalible (caster logged out for example) + // returns unit which cast the aura or NULL if not avalible (caster logged out for example) Unit* GetCaster() const; - // returns object on which aura was casted, target for non-area auras, area aura source for area auras + // returns object on which aura was cast, target for non-area auras, area aura source for area auras WorldObject* GetOwner() const; // returns owner if it's unit or unit derived object, NULL otherwise (only for persistent area auras NULL is returned) Unit* GetUnitOwner() const; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 8c3d92dcbfe..91606b7214a 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -152,7 +152,7 @@ World::~World() delete command; VMAP::VMapFactory::clear(); - MMAP::MMapFactory::clear(); + MMAP::MMapFactory::Clear(); /// @todo free addSessQueue } |
