aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorDDuarte <dnpd.dd@gmail.com>2014-01-10 18:32:05 +0000
committerDDuarte <dnpd.dd@gmail.com>2014-01-10 18:32:05 +0000
commit33c2bd5ce1f4f8d20981e9f7aea90e37de0abbda (patch)
tree823ad5570f27e923c77203660ee7cc12e26182ec /src/server/game
parent352a2682b1d531c83bd2b80704233677448e99de (diff)
parenta63780fd90701ed81a0a5f2030e82ab1f6927ab4 (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')
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h3
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp2
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.cpp2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp5
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp44
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp2
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.cpp2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundDS.h2
-rw-r--r--src/server/game/Battlegrounds/Zones/BattlegroundIC.cpp6
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp14
-rw-r--r--src/server/game/DataStores/DBCEnums.h2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp16
-rw-r--r--src/server/game/Entities/Creature/Creature.h11
-rw-r--r--src/server/game/Entities/Creature/GossipDef.cpp6
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp4
-rw-r--r--src/server/game/Entities/Item/Item.cpp2
-rw-r--r--src/server/game/Entities/Object/Object.cpp4
-rw-r--r--src/server/game/Entities/Player/Player.cpp20
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Transport/Transport.cpp86
-rw-r--r--src/server/game/Entities/Transport/Transport.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp42
-rw-r--r--src/server/game/Entities/Unit/Unit.h12
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp23
-rw-r--r--src/server/game/Globals/ObjectMgr.h2
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp8
-rw-r--r--src/server/game/Handlers/LootHandler.cpp2
-rw-r--r--src/server/game/Handlers/QuestHandler.cpp44
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp12
-rw-r--r--src/server/game/Handlers/TradeHandler.cpp4
-rw-r--r--src/server/game/Instances/InstanceScript.h12
-rw-r--r--src/server/game/Maps/Map.cpp68
-rw-r--r--src/server/game/Maps/MapInstanced.cpp2
-rw-r--r--src/server/game/Maps/TransportMgr.cpp139
-rw-r--r--src/server/game/Maps/TransportMgr.h3
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h4
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp1
-rw-r--r--src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp1
-rw-r--r--src/server/game/Movement/MovementGenerators/HomeMovementGenerator.cpp2
-rw-r--r--src/server/game/Movement/PathGenerator.cpp835
-rw-r--r--src/server/game/Movement/PathGenerator.h65
-rw-r--r--src/server/game/Movement/Spline/Spline.cpp2
-rw-r--r--src/server/game/Movement/Spline/Spline.h2
-rw-r--r--src/server/game/Quests/QuestDef.h3
-rw-r--r--src/server/game/Scripting/MapScripts.cpp4
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp6
-rw-r--r--src/server/game/Scripting/ScriptMgr.h5
-rw-r--r--src/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp4
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp14
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h2
-rw-r--r--src/server/game/Spells/Spell.cpp73
-rw-r--r--src/server/game/Spells/Spell.h2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp9
-rw-r--r--src/server/game/Spells/SpellInfo.cpp8
-rw-r--r--src/server/game/Spells/SpellMgr.cpp6
-rw-r--r--src/server/game/Spells/SpellScript.h6
-rw-r--r--src/server/game/World/World.cpp2
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
}