aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Server/AuthSocket.cpp13
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp24
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h6
-rw-r--r--src/server/game/Chat/Chat.cpp22
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp43
-rw-r--r--src/server/game/Entities/Creature/Creature.h9
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp2
-rw-r--r--src/server/game/Entities/Object/Object.cpp6
-rw-r--r--src/server/game/Entities/Player/Player.cpp15
-rw-r--r--src/server/game/Entities/Player/Player.h6
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp62
-rw-r--r--src/server/game/Entities/Unit/Unit.h8
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h11
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp2
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp2
-rw-r--r--src/server/game/Handlers/QueryHandler.cpp1
-rw-r--r--src/server/game/Handlers/VehicleHandler.cpp2
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.cpp4
-rw-r--r--src/server/game/Maps/Map.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp2
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp10
-rw-r--r--src/server/game/Scripting/ScriptMgr.h8
-rw-r--r--src/server/game/Spells/Spell.cpp20
-rw-r--r--src/server/scripts/Commands/cs_account.cpp12
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp2
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp8
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp9
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp2
-rw-r--r--src/server/shared/Database/MySQLThreading.h4
-rw-r--r--src/tools/mesh_extractor/ContinentBuilder.cpp154
-rw-r--r--src/tools/mesh_extractor/Geometry.cpp6
-rw-r--r--src/tools/mesh_extractor/MPQ.h3
-rw-r--r--src/tools/mesh_extractor/MPQManager.cpp4
-rw-r--r--src/tools/mesh_extractor/MeshExtractor.cpp64
-rw-r--r--src/tools/mesh_extractor/TileBuilder.cpp310
-rw-r--r--src/tools/mesh_extractor/TileBuilder.h6
-rw-r--r--src/tools/mesh_extractor/Utils.cpp42
-rw-r--r--src/tools/mesh_extractor/Utils.h6
-rw-r--r--src/tools/mesh_extractor/WorldModelHandler.cpp35
-rw-r--r--src/tools/mesh_extractor/WorldModelHandler.h2
42 files changed, 480 insertions, 473 deletions
diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp
index 1ab9ae6eb62..4a9d3ce7faf 100644
--- a/src/server/authserver/Server/AuthSocket.cpp
+++ b/src/server/authserver/Server/AuthSocket.cpp
@@ -222,12 +222,25 @@ void AuthSocket::OnClose(void)
// Read the packet from the client
void AuthSocket::OnRead()
{
+ #define MAX_AUTH_LOGON_CHALLENGES_IN_A_ROW 3
+ uint32 challengesInARow = 0;
uint8 _cmd;
while (1)
{
if (!socket().recv_soft((char *)&_cmd, 1))
return;
+ if (_cmd == AUTH_LOGON_CHALLENGE)
+ {
+ ++challengesInARow;
+ if (challengesInARow == MAX_AUTH_LOGON_CHALLENGES_IN_A_ROW)
+ {
+ TC_LOG_WARN(LOG_FILTER_AUTHSERVER, "Got %u AUTH_LOGON_CHALLENGE in a row from '%s', possible ongoing DoS", challengesInARow, socket().getRemoteAddress().c_str());
+ socket().shutdown();
+ return;
+ }
+ }
+
size_t i;
// Circle through known commands and call the correct command handler
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index a56d0f94f2d..57fd7ea2d73 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -206,7 +206,7 @@ void SmartAI::EndPath(bool fail)
mLastWP = NULL;
if (mCanRepeatPath)
- StartPath(mRun, GetScript()->GetPathId(), mCanRepeatPath);
+ StartPath(mRun, GetScript()->GetPathId(), true);
else
GetScript()->SetPathId(0);
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index ba1e59e0cc9..3823f7ba287 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -942,7 +942,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
instance->SetData64(e.action.setInstanceData64.field, targets->front()->GetGUID());
- TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: %u, data: "UI64FMTD,
+ TC_LOG_DEBUG(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction: SMART_ACTION_SET_INST_DATA64: Field: %u, data: " UI64FMTD,
e.action.setInstanceData64.field, targets->front()->GetGUID());
delete targets;
@@ -1585,8 +1585,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
break;
}
- ObjectList* targets = GetTargets(e, unit);
- if (targets)
+ if (ObjectList* targets = GetTargets(e, unit))
{
for (ObjectList::iterator itr = targets->begin(); itr != targets->end(); ++itr)
{
@@ -2551,7 +2550,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
case SMART_TARGET_CLOSEST_ENEMY:
{
if (me)
- if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist))
+ if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly))
l->push_back(target);
break;
@@ -2559,7 +2558,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /*
case SMART_TARGET_CLOSEST_FRIENDLY:
{
if (me)
- if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist))
+ if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly))
l->push_back(target);
break;
@@ -3443,13 +3442,13 @@ void SmartScript::DoFindFriendlyMissingBuff(std::list<Creature*>& list, float ra
cell.Visit(p, grid_creature_searcher, *me->GetMap(), *me, range);
}
-Unit* SmartScript::DoFindClosestFriendlyInRange(float range)
+Unit* SmartScript::DoFindClosestFriendlyInRange(float range, bool playerOnly)
{
if (!me)
return NULL;
Unit* unit = NULL;
- Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(me, me, range);
+ Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(me, me, range, playerOnly);
Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(me, unit, u_check);
me->VisitNearbyObject(range, searcher);
return unit;
@@ -3463,16 +3462,15 @@ void SmartScript::SetScript9(SmartScriptHolder& e, uint32 entry)
return;
for (SmartAIEventList::iterator i = mTimedActionList.begin(); i != mTimedActionList.end(); ++i)
{
- if (i == mTimedActionList.begin())
- {
- i->enableTimed = true;//enable processing only for the first action
- }
- else i->enableTimed = false;
+ i->enableTimed = i == mTimedActionList.begin();//enable processing only for the first action
- if (e.action.timedActionList.timerType == 1)
+ if (e.action.timedActionList.timerType == 0)
+ i->event.type = SMART_EVENT_UPDATE_OOC;
+ else if (e.action.timedActionList.timerType == 1)
i->event.type = SMART_EVENT_UPDATE_IC;
else if (e.action.timedActionList.timerType > 1)
i->event.type = SMART_EVENT_UPDATE;
+
InitTimer((*i));
}
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index b22f2d81b26..b1b9f4d6725 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -89,7 +89,7 @@ class SmartScript
Unit* DoSelectLowestHpFriendly(float range, uint32 MinHPDiff);
void DoFindFriendlyCC(std::list<Creature*>& _list, float range);
void DoFindFriendlyMissingBuff(std::list<Creature*>& list, float range, uint32 spellid);
- Unit* DoFindClosestFriendlyInRange(float range);
+ Unit* DoFindClosestFriendlyInRange(float range, bool playerOnly);
void StoreTargetList(ObjectList* targets, uint32 id)
{
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 90819e7a2c3..56fa7ed1275 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1021,8 +1021,8 @@ enum SMARTAI_TARGETS
SMART_TARGET_ACTION_INVOKER_VEHICLE = 22, // Unit's vehicle who caused this Event to occur
SMART_TARGET_OWNER_OR_SUMMONER = 23, // Unit's owner or summoner
SMART_TARGET_THREAT_LIST = 24, // All units on creature's threat list
- SMART_TARGET_CLOSEST_ENEMY = 25, // maxDist
- SMART_TARGET_CLOSEST_FRIENDLY = 26, // maxDist
+ SMART_TARGET_CLOSEST_ENEMY = 25, // maxDist, playerOnly
+ SMART_TARGET_CLOSEST_FRIENDLY = 26, // maxDist, playerOnly
SMART_TARGET_END = 27
};
@@ -1109,11 +1109,13 @@ struct SmartTarget
struct
{
uint32 maxDist;
+ uint32 playerOnly;
} closestAttackable;
struct
{
uint32 maxDist;
+ uint32 playerOnly;
} closestFriendly;
struct
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index aaa630ce4b8..a5c059b30df 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -344,7 +344,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st
Player* player = m_session->GetPlayer();
if (!AccountMgr::IsPlayerAccount(m_session->GetSecurity()))
{
- uint64 guid = player->GetSelection();
+ uint64 guid = player->GetTarget();
uint32 areaId = player->GetAreaId();
std::string areaName = "Unknown";
std::string zoneName = "Unknown";
@@ -713,12 +713,10 @@ Player* ChatHandler::getSelectedPlayer()
if (!m_session)
return NULL;
- uint64 guid = m_session->GetPlayer()->GetSelection();
+ if (Player* selected = m_session->GetPlayer()->GetSelectedPlayer())
+ return selected;
- if (guid == 0)
- return m_session->GetPlayer();
-
- return ObjectAccessor::FindPlayer(guid);
+ return m_session->GetPlayer();
}
Unit* ChatHandler::getSelectedUnit()
@@ -726,12 +724,10 @@ Unit* ChatHandler::getSelectedUnit()
if (!m_session)
return NULL;
- uint64 guid = m_session->GetPlayer()->GetSelection();
+ if (Unit* selected = m_session->GetPlayer()->GetSelectedUnit())
+ return selected;
- if (guid == 0)
- return m_session->GetPlayer();
-
- return ObjectAccessor::GetUnit(*m_session->GetPlayer(), guid);
+ return m_session->GetPlayer();
}
WorldObject* ChatHandler::getSelectedObject()
@@ -739,7 +735,7 @@ WorldObject* ChatHandler::getSelectedObject()
if (!m_session)
return NULL;
- uint64 guid = m_session->GetPlayer()->GetSelection();
+ uint64 guid = m_session->GetPlayer()->GetTarget();
if (guid == 0)
return GetNearbyGameObject();
@@ -752,7 +748,7 @@ Creature* ChatHandler::getSelectedCreature()
if (!m_session)
return NULL;
- return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(), m_session->GetPlayer()->GetSelection());
+ return ObjectAccessor::GetCreatureOrPetOrVehicle(*m_session->GetPlayer(), m_session->GetPlayer()->GetTarget());
}
char* ChatHandler::extractKeyFromLink(char* text, char const* linkType, char** something1)
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 169d5feae03..4efd78d5932 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -165,6 +165,7 @@ m_creatureInfo(NULL), m_creatureData(NULL), m_path_id(0), m_formation(NULL)
ResetLootMode(); // restore default loot mode
TriggerJustRespawned = false;
m_isTempWorldObject = false;
+ _focusSpell = NULL;
}
Creature::~Creature()
@@ -1709,7 +1710,7 @@ SpellInfo const* Creature::reachWithSpellCure(Unit* victim)
}
// select nearest hostile unit within the given distance (regardless of threat list).
-Unit* Creature::SelectNearestTarget(float dist) const
+Unit* Creature::SelectNearestTarget(float dist, bool playerOnly /* = false */) const
{
CellCoord p(Trinity::ComputeCellCoord(GetPositionX(), GetPositionY()));
Cell cell(p);
@@ -1721,7 +1722,7 @@ Unit* Creature::SelectNearestTarget(float dist) const
if (dist == 0.0f)
dist = MAX_VISIBILITY_DISTANCE;
- Trinity::NearestHostileUnitCheck u_check(this, dist);
+ Trinity::NearestHostileUnitCheck u_check(this, dist, playerOnly);
Trinity::UnitLastSearcher<Trinity::NearestHostileUnitCheck> searcher(this, target, u_check);
TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::NearestHostileUnitCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
@@ -2640,3 +2641,41 @@ void Creature::SetDisplayId(uint32 modelId)
SetFloatValue(UNIT_FIELD_COMBATREACH, minfo->combat_reach * GetObjectScale());
}
}
+
+void Creature::SetTarget(uint64 guid)
+{
+ if (!_focusSpell)
+ SetUInt64Value(UNIT_FIELD_TARGET, guid);
+}
+
+void Creature::FocusTarget(Spell const* focusSpell, WorldObject const* target)
+{
+ // already focused
+ if (_focusSpell)
+ return;
+
+ _focusSpell = focusSpell;
+ SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID());
+ if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST)
+ AddUnitState(UNIT_STATE_ROTATING);
+
+ // Set serverside orientation if needed (needs to be after attribute check)
+ SetInFront(target);
+}
+
+void Creature::ReleaseFocus(Spell const* focusSpell)
+{
+ // focused to something else
+ if (focusSpell != _focusSpell)
+ return;
+
+ _focusSpell = NULL;
+ if (Unit* victim = GetVictim())
+ SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID());
+ else
+ SetUInt64Value(UNIT_FIELD_TARGET, 0);
+
+ if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST)
+ ClearUnitState(UNIT_STATE_ROTATING);
+}
+
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index b720a063f2d..3a07d9c101b 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -609,7 +609,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
void SendAIReaction(AiReaction reactionType);
- Unit* SelectNearestTarget(float dist = 0) const;
+ Unit* SelectNearestTarget(float dist = 0, bool playerOnly = false) const;
Unit* SelectNearestTargetInAttackDistance(float dist = 0) const;
Player* SelectNearestPlayer(float distance = 0) const;
Unit* SelectNearestHostileUnitInAggroRange(bool useLOS = false) const;
@@ -703,6 +703,11 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
bool m_isTempWorldObject; //true when possessed
+ // Handling caster facing during spellcast
+ void SetTarget(uint64 guid);
+ void FocusTarget(Spell const* focusSpell, WorldObject const* target);
+ void ReleaseFocus(Spell const* focusSpell);
+
protected:
bool CreateFromProto(uint32 guidlow, uint32 Entry, uint32 vehId, uint32 team, const CreatureData* data = NULL);
bool InitEntry(uint32 entry, uint32 team=ALLIANCE, const CreatureData* data=NULL);
@@ -762,6 +767,8 @@ class Creature : public Unit, public GridObject<Creature>, public MapCreature
//Formation var
CreatureGroup* m_formation;
bool TriggerJustRespawned;
+
+ Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing
};
class AssistDelayEvent : public BasicEvent
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 15e7eb436e1..eef416b339d 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -1508,7 +1508,7 @@ void GameObject::Use(Unit* user)
Player* player = user->ToPlayer();
- Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetSelection());
+ Player* targetPlayer = ObjectAccessor::FindPlayer(player->GetTarget());
// accept only use by player from same raid as caster, except caster itself
if (!targetPlayer || targetPlayer == player || !targetPlayer->IsInSameRaidWith(player))
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 5a787f910b8..9d77e144c0b 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -91,7 +91,7 @@ WorldObject::~WorldObject()
{
if (GetTypeId() == TYPEID_CORPSE)
{
- TC_LOG_FATAL(LOG_FILTER_GENERAL, "Object::~Object Corpse guid="UI64FMTD", type=%d, entry=%u deleted but still in map!!",
+ TC_LOG_FATAL(LOG_FILTER_GENERAL, "Object::~Object Corpse guid=" UI64FMTD ", type=%d, entry=%u deleted but still in map!!",
GetGUID(), ((Corpse*)this)->GetType(), GetEntry());
ASSERT(false);
}
@@ -103,7 +103,7 @@ Object::~Object()
{
if (IsInWorld())
{
- TC_LOG_FATAL(LOG_FILTER_GENERAL, "Object::~Object - guid="UI64FMTD", typeid=%d, entry=%u deleted but still in world!!", GetGUID(), GetTypeId(), GetEntry());
+ TC_LOG_FATAL(LOG_FILTER_GENERAL, "Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in world!!", GetGUID(), GetTypeId(), GetEntry());
if (isType(TYPEMASK_ITEM))
TC_LOG_FATAL(LOG_FILTER_GENERAL, "Item slot %u", ((Item*)this)->GetSlot());
ASSERT(false);
@@ -112,7 +112,7 @@ Object::~Object()
if (m_objectUpdated)
{
- TC_LOG_FATAL(LOG_FILTER_GENERAL, "Object::~Object - guid="UI64FMTD", typeid=%d, entry=%u deleted but still in update list!!", GetGUID(), GetTypeId(), GetEntry());
+ TC_LOG_FATAL(LOG_FILTER_GENERAL, "Object::~Object - guid=" UI64FMTD ", typeid=%d, entry=%u deleted but still in update list!!", GetGUID(), GetTypeId(), GetEntry());
ASSERT(false);
sObjectAccessor->RemoveUpdateObject(this);
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8217682f103..9ada25b1c81 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -673,7 +673,6 @@ Player::Player(WorldSession* session): Unit(true)
if (!GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS))
SetAcceptWhispers(true);
- m_curSelection = 0;
m_lootGuid = 0;
m_comboTarget = 0;
@@ -20455,7 +20454,7 @@ void Player::PossessSpellInitialize()
if (!charmInfo)
{
- TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::PossessSpellInitialize(): charm ("UI64FMTD") has no charminfo!", charm->GetGUID());
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::PossessSpellInitialize(): charm (" UI64FMTD ") has no charminfo!", charm->GetGUID());
return;
}
@@ -20567,7 +20566,7 @@ void Player::CharmSpellInitialize()
CharmInfo* charmInfo = charm->GetCharmInfo();
if (!charmInfo)
{
- TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::CharmSpellInitialize(): the player's charm ("UI64FMTD") has no charminfo!", charm->GetGUID());
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player::CharmSpellInitialize(): the player's charm (" UI64FMTD ") has no charminfo!", charm->GetGUID());
return;
}
@@ -22397,15 +22396,15 @@ bool Player::IsQuestRewarded(uint32 quest_id) const
Unit* Player::GetSelectedUnit() const
{
- if (m_curSelection)
- return ObjectAccessor::GetUnit(*this, m_curSelection);
+ if (uint64 selectionGUID = GetUInt64Value(UNIT_FIELD_TARGET))
+ return ObjectAccessor::GetUnit(*this, selectionGUID);
return NULL;
}
Player* Player::GetSelectedPlayer() const
{
- if (m_curSelection)
- return ObjectAccessor::GetPlayer(*this, m_curSelection);
+ if (uint64 selectionGUID = GetUInt64Value(UNIT_FIELD_TARGET))
+ return ObjectAccessor::GetPlayer(*this, selectionGUID);
return NULL;
}
@@ -25416,7 +25415,7 @@ void Player::SetEquipmentSet(uint32 index, EquipmentSet eqset)
if (!found) // something wrong...
{
- TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player %s tried to save equipment set "UI64FMTD" (index %u), but that equipment set not found!", GetName().c_str(), eqset.Guid, index);
+ TC_LOG_ERROR(LOG_FILTER_PLAYER, "Player %s tried to save equipment set " UI64FMTD " (index %u), but that equipment set not found!", GetName().c_str(), eqset.Guid, index);
return;
}
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index bac794422be..fee542a752e 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1506,10 +1506,11 @@ class Player : public Unit, public GridObject<Player>
size_t GetRewardedQuestCount() const { return m_RewardedQuests.size(); }
bool IsQuestRewarded(uint32 quest_id) const;
- uint64 GetSelection() const { return m_curSelection; }
Unit* GetSelectedUnit() const;
Player* GetSelectedPlayer() const;
- void SetSelection(uint64 guid) { m_curSelection = guid; SetUInt64Value(UNIT_FIELD_TARGET, guid); }
+
+ void SetTarget(uint64 /*guid*/) OVERRIDE { } /// Used for serverside target changes, does not apply to players
+ void SetSelection(uint64 guid) { SetUInt64Value(UNIT_FIELD_TARGET, guid); }
uint8 GetComboPoints() const { return m_comboPoints; }
uint64 GetComboTarget() const { return m_comboTarget; }
@@ -2424,7 +2425,6 @@ class Player : public Unit, public GridObject<Player>
bool m_itemUpdateQueueBlocked;
uint32 m_ExtraFlags;
- uint64 m_curSelection;
uint64 m_comboTarget;
int8 m_comboPoints;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 2a2a18eb609..0617dec179d 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -259,7 +259,6 @@ Unit::Unit(bool isWorldObject) :
m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE);
- _focusSpell = NULL;
_lastLiquid = NULL;
_isWalkingBeforeCharm = false;
}
@@ -568,6 +567,9 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam
if (IsAIEnabled)
GetAI()->DamageDealt(victim, damage, damagetype);
+ // Hook for OnDamage Event
+ sScriptMgr->OnDamage(this, victim, damage);
+
if (victim->GetTypeId() == TYPEID_PLAYER && this != victim)
{
// Signal to pets that their owner was attacked
@@ -5249,18 +5251,19 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// cast 45429 Arcane Bolt if Exalted by Scryers
case 45481:
{
- if (GetTypeId() != TYPEID_PLAYER)
+ Player* player = ToPlayer();
+ if (!player)
return false;
// Get Aldor reputation rank
- if (ToPlayer()->GetReputationRank(932) == REP_EXALTED)
+ if (player->GetReputationRank(932) == REP_EXALTED)
{
target = this;
triggered_spell_id = 45479;
break;
}
// Get Scryers reputation rank
- if (ToPlayer()->GetReputationRank(934) == REP_EXALTED)
+ if (player->GetReputationRank(934) == REP_EXALTED)
{
// triggered at positive/self casts also, current attack target used then
if (target && IsFriendlyTo(target))
@@ -5268,8 +5271,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
target = GetVictim();
if (!target)
{
- uint64 selected_guid = ToPlayer()->GetSelection();
- target = ObjectAccessor::GetUnit(*this, selected_guid);
+ target = player->GetSelectedUnit();
if (!target)
return false;
}
@@ -9579,6 +9581,9 @@ int32 Unit::DealHeal(Unit* victim, uint32 addhealth)
if (addhealth)
gain = victim->ModifyHealth(int32(addhealth));
+ // Hook for OnHeal Event
+ sScriptMgr->OnHeal(this, victim, gain);
+
Unit* unit = this;
if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsTotem())
@@ -15872,7 +15877,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
if (GetCharmInfo())
GetCharmInfo()->SetPetNumber(0, true);
else
- TC_LOG_ERROR(LOG_FILTER_UNITS, "Aura::HandleModCharm: target="UI64FMTD" with typeid=%d has a charm aura but no charm info!", GetGUID(), GetTypeId());
+ TC_LOG_ERROR(LOG_FILTER_UNITS, "Aura::HandleModCharm: target=" UI64FMTD " with typeid=%d has a charm aura but no charm info!", GetGUID(), GetTypeId());
}
}
break;
@@ -16895,7 +16900,7 @@ void Unit::_ExitVehicle(Position const* exitPosition)
if (vehicle->GetBase()->HasUnitTypeMask(UNIT_MASK_MINION) && vehicle->GetBase()->GetTypeId() == TYPEID_UNIT)
if (((Minion*)vehicle->GetBase())->GetOwner() == this)
- vehicle->GetBase()->ToCreature()->DespawnOrUnsummon();
+ vehicle->GetBase()->ToCreature()->DespawnOrUnsummon(1);
if (HasUnitTypeMask(UNIT_MASK_ACCESSORY))
{
@@ -17176,8 +17181,8 @@ void Unit::StopAttackFaction(uint32 faction_id)
void Unit::OutDebugInfo() const
{
TC_LOG_ERROR(LOG_FILTER_UNITS, "Unit::OutDebugInfo");
- TC_LOG_INFO(LOG_FILTER_UNITS, "GUID "UI64FMTD", entry %u, type %u, name %s", GetGUID(), GetEntry(), (uint32)GetTypeId(), GetName().c_str());
- TC_LOG_INFO(LOG_FILTER_UNITS, "OwnerGUID "UI64FMTD", MinionGUID "UI64FMTD", CharmerGUID "UI64FMTD", CharmedGUID "UI64FMTD, GetOwnerGUID(), GetMinionGUID(), GetCharmerGUID(), GetCharmGUID());
+ TC_LOG_INFO(LOG_FILTER_UNITS, "GUID " UI64FMTD ", entry %u, type %u, name %s", GetGUID(), GetEntry(), (uint32)GetTypeId(), GetName().c_str());
+ TC_LOG_INFO(LOG_FILTER_UNITS, "OwnerGUID " UI64FMTD ", MinionGUID " UI64FMTD ", CharmerGUID " UI64FMTD ", CharmedGUID "UI64FMTD, GetOwnerGUID(), GetMinionGUID(), GetCharmerGUID(), GetCharmGUID());
TC_LOG_INFO(LOG_FILTER_UNITS, "In world %u, unit type mask %u", (uint32)(IsInWorld() ? 1 : 0), m_unitTypeMask);
if (IsInWorld())
TC_LOG_INFO(LOG_FILTER_UNITS, "Mapid %u", GetMapId());
@@ -17462,43 +17467,6 @@ bool Unit::SetHover(bool enable, bool /*packetOnly = false*/)
return true;
}
-void Unit::SetTarget(uint64 guid)
-{
- if (!_focusSpell)
- SetUInt64Value(UNIT_FIELD_TARGET, guid);
-}
-
-void Unit::FocusTarget(Spell const* focusSpell, WorldObject const* target)
-{
- // already focused
- if (_focusSpell)
- return;
-
- _focusSpell = focusSpell;
- SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID());
- if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST)
- AddUnitState(UNIT_STATE_ROTATING);
-
- // Set serverside orientation if needed (needs to be after attribute check)
- SetInFront(target);
-}
-
-void Unit::ReleaseFocus(Spell const* focusSpell)
-{
- // focused to something else
- if (focusSpell != _focusSpell)
- return;
-
- _focusSpell = NULL;
- if (Unit* victim = GetVictim())
- SetUInt64Value(UNIT_FIELD_TARGET, victim->GetGUID());
- else
- SetUInt64Value(UNIT_FIELD_TARGET, 0);
-
- if (focusSpell->GetSpellInfo()->AttributesEx5 & SPELL_ATTR5_DONT_TURN_DURING_CAST)
- ClearUnitState(UNIT_STATE_ROTATING);
-}
-
void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const
{
if (!target)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 119a1dd1966..13f8c8e781f 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -2124,11 +2124,8 @@ class Unit : public WorldObject
TempSummon* ToTempSummon() { if (IsSummon()) return reinterpret_cast<TempSummon*>(this); else return NULL; }
TempSummon const* ToTempSummon() const { if (IsSummon()) return reinterpret_cast<TempSummon const*>(this); else return NULL; }
- void SetTarget(uint64 guid);
-
- // Handling caster facing during spellcast
- void FocusTarget(Spell const* focusSpell, WorldObject const* target);
- void ReleaseFocus(Spell const* focusSpell);
+ uint64 GetTarget() const { return GetUInt64Value(UNIT_FIELD_TARGET); }
+ virtual void SetTarget(uint64 /*guid*/) = 0;
// Movement info
Movement::MoveSpline * movespline;
@@ -2253,7 +2250,6 @@ class Unit : public WorldObject
bool m_cleanupDone; // lock made to not add stuff after cleanup before delete
bool m_duringRemoveFromWorld; // lock made to not add stuff after begining removing from world
- Spell const* _focusSpell; ///> Locks the target during spell cast for proper facing
bool _isWalkingBeforeCharm; // Are we walking before we were charmed?
time_t _lastDamagedTime; // Part of Evade mechanics
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 637e0792a74..d0df63155b2 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -871,10 +871,10 @@ namespace Trinity
class AnyFriendlyUnitInObjectRangeCheck
{
public:
- AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {}
+ AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool playerOnly = false) : i_obj(obj), i_funit(funit), i_range(range), i_playerOnly(playerOnly) {}
bool operator()(Unit* u)
{
- if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u))
+ if (u->IsAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u) && (!i_playerOnly || u->GetTypeId() == TYPEID_PLAYER))
return true;
else
return false;
@@ -883,6 +883,7 @@ namespace Trinity
WorldObject const* i_obj;
Unit const* i_funit;
float i_range;
+ bool i_playerOnly;
};
class AnyGroupedUnitInObjectRangeCheck
@@ -1035,7 +1036,7 @@ namespace Trinity
class NearestHostileUnitCheck
{
public:
- explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0) : me(creature)
+ explicit NearestHostileUnitCheck(Creature const* creature, float dist = 0, bool playerOnly = false) : me(creature), i_playerOnly(playerOnly)
{
m_range = (dist == 0 ? 9999 : dist);
}
@@ -1047,6 +1048,9 @@ namespace Trinity
if (!me->IsValidAttackTarget(u))
return false;
+ if (i_playerOnly && u->GetTypeId() != TYPEID_PLAYER)
+ return false;
+
m_range = me->GetDistance(u); // use found unit range as new range limit for next check
return true;
}
@@ -1054,6 +1058,7 @@ namespace Trinity
private:
Creature const* me;
float m_range;
+ bool i_playerOnly;
NearestHostileUnitCheck(NearestHostileUnitCheck const&);
};
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index b47e085ab6c..c1756311bc1 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -485,7 +485,7 @@ void WorldSession::HandleCalendarEventRsvp(WorldPacket& recvData)
uint32 status;
recvData >> eventId >> inviteId >> status;
- TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_CALENDAR_EVENT_RSVP [" UI64FMTD"] EventId ["
+ TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "CMSG_CALENDAR_EVENT_RSVP [" UI64FMTD "] EventId ["
UI64FMTD "], InviteId [" UI64FMTD "], status %u", guid, eventId,
inviteId, status);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index f65641eaa76..71453581ed0 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1167,8 +1167,6 @@ void WorldSession::HandleInspectOpcode(WorldPacket& recvData)
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_INSPECT");
- _player->SetSelection(guid);
-
Player* player = ObjectAccessor::FindPlayer(guid);
if (!player)
{
diff --git a/src/server/game/Handlers/QueryHandler.cpp b/src/server/game/Handlers/QueryHandler.cpp
index 5a94d5b391b..4638e05ee3d 100644
--- a/src/server/game/Handlers/QueryHandler.cpp
+++ b/src/server/game/Handlers/QueryHandler.cpp
@@ -267,7 +267,6 @@ void WorldSession::HandleNpcTextQueryOpcode(WorldPacket& recvData)
TC_LOG_DEBUG(LOG_FILTER_NETWORKIO, "WORLD: CMSG_NPC_TEXT_QUERY ID '%u'", textID);
recvData >> guid;
- GetPlayer()->SetSelection(guid);
GossipText const* pGossip = sObjectMgr->GetGossipText(textID);
diff --git a/src/server/game/Handlers/VehicleHandler.cpp b/src/server/game/Handlers/VehicleHandler.cpp
index c44d8a2d38e..b099ba96060 100644
--- a/src/server/game/Handlers/VehicleHandler.cpp
+++ b/src/server/game/Handlers/VehicleHandler.cpp
@@ -206,7 +206,7 @@ void WorldSession::HandleEjectPassenger(WorldPacket &data)
TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "Player %u attempted to eject creature GUID %u from non-ejectable seat.", GetPlayer()->GetGUIDLow(), GUID_LOPART(guid));
}
else
- TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleEjectPassenger: Player %u tried to eject invalid GUID "UI64FMTD, GetPlayer()->GetGUIDLow(), guid);
+ TC_LOG_ERROR(LOG_FILTER_NETWORKIO, "HandleEjectPassenger: Player %u tried to eject invalid GUID " UI64FMTD, GetPlayer()->GetGUIDLow(), guid);
}
void WorldSession::HandleRequestVehicleExit(WorldPacket& /*recvData*/)
diff --git a/src/server/game/Instances/InstanceSaveMgr.cpp b/src/server/game/Instances/InstanceSaveMgr.cpp
index 6370eda6568..d7ffb70ccfa 100644
--- a/src/server/game/Instances/InstanceSaveMgr.cpp
+++ b/src/server/game/Instances/InstanceSaveMgr.cpp
@@ -336,7 +336,7 @@ void InstanceSaveManager::LoadResetTimes()
InstResetTimeMapDiffType::iterator itr = instResetTime.find(instance);
if (itr != instResetTime.end() && itr->second.second != resettime)
{
- CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '"UI64FMTD"' WHERE id = '%u'", uint64(resettime), instance);
+ CharacterDatabase.DirectPExecute("UPDATE instance SET resettime = '" UI64FMTD "' WHERE id = '%u'", uint64(resettime), instance);
itr->second.second = resettime;
}
}
@@ -408,7 +408,7 @@ void InstanceSaveManager::LoadResetTimes()
// calculate the next reset time
t = (t / DAY) * DAY;
t += ((today - t) / period + 1) * period + diff;
- CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '"UI64FMTD"' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty);
+ CharacterDatabase.DirectPExecute("UPDATE instance_reset SET resettime = '" UI64FMTD "' WHERE mapid = '%u' AND difficulty= '%u'", (uint64)t, mapid, difficulty);
}
SetResetTimeFor(mapid, difficulty, t);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 04c2c22c595..4660489004d 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -360,7 +360,7 @@ void Map::EnsureGridLoadedForActiveObject(const Cell &cell, WorldObject* object)
// refresh grid state & timer
if (grid->GetGridState() != GRID_STATE_ACTIVE)
{
- TC_LOG_DEBUG(LOG_FILTER_MAPS, "Active object "UI64FMTD" triggers loading of grid [%u, %u] on map %u", object->GetGUID(), cell.GridX(), cell.GridY(), GetId());
+ TC_LOG_DEBUG(LOG_FILTER_MAPS, "Active object " UI64FMTD " triggers loading of grid [%u, %u] on map %u", object->GetGUID(), cell.GridX(), cell.GridY(), GetId());
ResetGridExpiry(*grid, 0.1f);
grid->SetGridState(GRID_STATE_ACTIVE);
}
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 8056d6263c0..6311e629641 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -78,7 +78,7 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature* creature)
if (i_path->at(i_currentNode)->event_id && urand(0, 99) < i_path->at(i_currentNode)->event_chance)
{
- TC_LOG_DEBUG(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for "UI64FMTD".", i_path->at(i_currentNode)->event_id, i_currentNode, creature->GetGUID());
+ TC_LOG_DEBUG(LOG_FILTER_MAPSCRIPTS, "Creature movement start script %u at point %u for " UI64FMTD ".", i_path->at(i_currentNode)->event_id, i_currentNode, creature->GetGUID());
creature->GetMap()->ScriptsStart(sWaypointScripts, i_path->at(i_currentNode)->event_id, creature, NULL);
}
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 966b3edfcb9..fb96c327b05 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1363,6 +1363,16 @@ void ScriptMgr::OnGroupDisband(Group* group)
}
// Unit
+void ScriptMgr::OnHeal(Unit* healer, Unit* reciever, uint32 gain)
+{
+ FOREACH_SCRIPT(UnitScript)->OnHeal(healer, reciever, gain);
+}
+
+void ScriptMgr::OnDamage(Unit* attacker, Unit* victim, uint32 damage)
+{
+ FOREACH_SCRIPT(UnitScript)->OnDamage(attacker, victim, damage);
+}
+
void ScriptMgr::ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage)
{
FOREACH_SCRIPT(UnitScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage);
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index e7946501616..a3eff880bb9 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -396,6 +396,12 @@ class UnitScript : public ScriptObject
UnitScript(const char* name, bool addToScripts = true);
public:
+ // Called when a unit deals damage to another unit
+ virtual void OnHeal(Unit* /*healer*/, Unit* /*reciever*/, uint32 /*gain*/) { }
+
+ // Called when a unit deals damage to another unit
+ virtual void OnDamage(Unit* /*attacker*/, Unit* /*victim*/, uint32 /*damage*/) { }
+
// Called when DoT's Tick Damage is being Dealt
virtual void ModifyPeriodicDamageAurasTick(Unit* /*target*/, Unit* /*attacker*/, uint32& /*damage*/) { }
@@ -1054,6 +1060,8 @@ class ScriptMgr
public: /* UnitScript */
+ void OnHeal(Unit* healer, Unit* reciever, uint32 gain);
+ void OnDamage(Unit* attacker, Unit* victim, uint32 damage);
void ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage);
void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage);
void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 866cd888c3e..2eee80924a4 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -643,7 +643,7 @@ void Spell::InitExplicitTargets(SpellCastTargets const& targets)
if (Player* playerCaster = m_caster->ToPlayer())
{
// selection has to be found and to be valid target for the spell
- if (Unit* selectedUnit = ObjectAccessor::GetUnit(*m_caster, playerCaster->GetSelection()))
+ if (Unit* selectedUnit = ObjectAccessor::GetUnit(*m_caster, playerCaster->GetTarget()))
if (m_spellInfo->CheckExplicitTarget(m_caster, selectedUnit) == SPELL_CAST_OK)
unit = selectedUnit;
}
@@ -1777,9 +1777,9 @@ void Spell::SelectEffectTypeImplicitTargets(uint8 effIndex)
{
case SPELL_EFFECT_SUMMON_RAF_FRIEND:
case SPELL_EFFECT_SUMMON_PLAYER:
- if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->ToPlayer()->GetSelection())
+ if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->GetTarget())
{
- WorldObject* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection());
+ WorldObject* target = ObjectAccessor::FindPlayer(m_caster->GetTarget());
CallScriptObjectTargetSelectHandlers(target, SpellEffIndex(effIndex));
@@ -3095,7 +3095,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
// set target for proper facing
if ((m_casttime || m_spellInfo->IsChanneled()) && !(_triggeredCastFlags & TRIGGERED_IGNORE_SET_FACING))
if (m_caster->GetTypeId() == TYPEID_UNIT && m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
- m_caster->FocusTarget(this, m_targets.GetObjectTarget());
+ m_caster->ToCreature()->FocusTarget(this, m_targets.GetObjectTarget());
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_GCD))
TriggerGlobalCooldown();
@@ -3661,8 +3661,8 @@ void Spell::finish(bool ok)
((Puppet*)charm)->UnSummon();
}
- if (m_caster->GetTypeId() == TYPEID_UNIT)
- m_caster->ReleaseFocus(this);
+ if (Creature* creatureCaster = m_caster->ToCreature())
+ creatureCaster->ReleaseFocus(this);
if (!ok)
return;
@@ -5323,10 +5323,10 @@ SpellCastResult Spell::CheckCast(bool strict)
{
if (m_caster->GetTypeId() != TYPEID_PLAYER)
return SPELL_FAILED_BAD_TARGETS;
- if (!m_caster->ToPlayer()->GetSelection())
+ if (!m_caster->GetTarget())
return SPELL_FAILED_BAD_TARGETS;
- Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetSelection());
+ Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetTarget());
if (!target || m_caster->ToPlayer() == target || (!target->IsInSameRaidWith(m_caster->ToPlayer()) && m_spellInfo->Id != 48955)) // refer-a-friend spell
return SPELL_FAILED_BAD_TARGETS;
@@ -5358,10 +5358,10 @@ SpellCastResult Spell::CheckCast(bool strict)
Player* playerCaster = m_caster->ToPlayer();
//
- if (!(playerCaster->GetSelection()))
+ if (!(playerCaster->GetTarget()))
return SPELL_FAILED_BAD_TARGETS;
- Player* target = ObjectAccessor::FindPlayer(playerCaster->GetSelection());
+ Player* target = playerCaster->GetSelectedPlayer();
if (!target ||
!(target->GetSession()->GetRecruiterId() == playerCaster->GetSession()->GetAccountId() || target->GetSession()->GetAccountId() == playerCaster->GetSession()->GetRecruiterId()))
diff --git a/src/server/scripts/Commands/cs_account.cpp b/src/server/scripts/Commands/cs_account.cpp
index 332169ebd00..45ab88e9688 100644
--- a/src/server/scripts/Commands/cs_account.cpp
+++ b/src/server/scripts/Commands/cs_account.cpp
@@ -450,12 +450,12 @@ public:
uint32 pwConfig = sWorld->getIntConfig(CONFIG_ACC_PASSCHANGESEC); // 0 - PW_NONE, 1 - PW_EMAIL, 2 - PW_RBAC
// Command is supposed to be: .account password [$oldpassword] [$newpassword] [$newpasswordconfirmation] [$emailconfirmation]
- char* oldPassword = strtok((char*)args, " "); // This extracts [$oldpassword]
- char* newPassword = strtok(NULL, " "); // This extracts [$newpassword]
- char* passwordConfirmation = strtok(NULL, " "); // This extracts [$newpasswordconfirmation]
- const char* emailConfirmation; // This defines the emailConfirmation variable, which is optional depending on sec type.
- if (!(emailConfirmation = strtok(NULL, " "))) // This extracts [$emailconfirmation]. If it doesn't exist, however...
- emailConfirmation = ""; // ... it's simply "" for emailConfirmation.
+ char* oldPassword = strtok((char*)args, " "); // This extracts [$oldpassword]
+ char* newPassword = strtok(NULL, " "); // This extracts [$newpassword]
+ char* passwordConfirmation = strtok(NULL, " "); // This extracts [$newpasswordconfirmation]
+ char const* emailConfirmation = strtok(NULL, " "); // This defines the emailConfirmation variable, which is optional depending on sec type.
+ if (!emailConfirmation) // This extracts [$emailconfirmation]. If it doesn't exist, however...
+ emailConfirmation = ""; // ... it's simply "" for emailConfirmation.
//Is any of those variables missing for any reason ? We return false.
if (!oldPassword || !newPassword || !passwordConfirmation)
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 6c831520d59..199b1e43f6c 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -179,7 +179,7 @@ public:
return false;
}
- if (handler->GetSession()->GetPlayer()->GetSelection())
+ if (handler->GetSession()->GetPlayer()->GetTarget())
unit->PlayDistanceSound(soundId, handler->GetSession()->GetPlayer());
else
unit->PlayDirectSound(soundId, handler->GetSession()->GetPlayer());
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 513d378287b..3d531cee1f5 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -529,7 +529,7 @@ public:
{
Unit* target = handler->getSelectedUnit();
- if (!target || !handler->GetSession()->GetPlayer()->GetSelection())
+ if (!target || !handler->GetSession()->GetPlayer()->GetTarget())
{
handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE);
handler->SetSentErrorMessage(true);
@@ -597,7 +597,7 @@ public:
static bool HandleGUIDCommand(ChatHandler* handler, char const* /*args*/)
{
- uint64 guid = handler->GetSession()->GetPlayer()->GetSelection();
+ uint64 guid = handler->GetSession()->GetPlayer()->GetTarget();
if (guid == 0)
{
@@ -1762,7 +1762,7 @@ public:
// accept only explicitly selected target (not implicitly self targeting case)
Unit* target = handler->getSelectedUnit();
- if (player->GetSelection() && target)
+ if (player->GetTarget() && target)
{
if (target->GetTypeId() != TYPEID_UNIT || target->IsPet())
{
@@ -2107,7 +2107,7 @@ public:
}
Unit* target = handler->getSelectedUnit();
- if (!target || !handler->GetSession()->GetPlayer()->GetSelection())
+ if (!target || !handler->GetSession()->GetPlayer()->GetTarget())
{
handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE);
handler->SetSentErrorMessage(true);
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index f10a929c675..1cedeb79c22 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -1297,22 +1297,17 @@ public:
char* receiver_str = strtok((char*)args, " ");
char* text = strtok(NULL, "");
- uint64 guid = handler->GetSession()->GetPlayer()->GetSelection();
- Creature* creature = handler->GetSession()->GetPlayer()->GetMap()->GetCreature(guid);
-
+ Creature* creature = handler->getSelectedCreature();
if (!creature || !receiver_str || !text)
- {
return false;
- }
- uint64 receiver_guid= atol(receiver_str);
+ uint64 receiver_guid = atol(receiver_str);
// check online security
if (handler->HasLowerSecurity(ObjectAccessor::FindPlayer(receiver_guid), 0))
return false;
creature->MonsterWhisper(text, receiver_guid);
-
return true;
}
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 987807c2080..9a9dfa60521 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -1069,7 +1069,7 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript
{
me->AI()->DoCast(me, SPELL_SYLVANAS_DESTROY_ICE_WALL, false);
if (_isattackingwall)
- _events.ScheduleEvent(EVENT_ESCAPE_22, 1000);
+ _events.ScheduleEvent(EVENT_ESCAPE_23, 1000);
}
break;
diff --git a/src/server/shared/Database/MySQLThreading.h b/src/server/shared/Database/MySQLThreading.h
index 3dc2add8132..4fe928dcc22 100644
--- a/src/server/shared/Database/MySQLThreading.h
+++ b/src/server/shared/Database/MySQLThreading.h
@@ -33,7 +33,7 @@ class MySQL
static void Thread_Init()
{
mysql_thread_init();
- TC_LOG_WARN(LOG_FILTER_SQL, "Core thread with ID ["UI64FMTD"] initializing MySQL thread.",
+ TC_LOG_WARN(LOG_FILTER_SQL, "Core thread with ID [" UI64FMTD "] initializing MySQL thread.",
(uint64)ACE_Based::Thread::currentId());
}
@@ -44,7 +44,7 @@ class MySQL
static void Thread_End()
{
mysql_thread_end();
- TC_LOG_WARN(LOG_FILTER_SQL, "Core thread with ID ["UI64FMTD"] shutting down MySQL thread.",
+ TC_LOG_WARN(LOG_FILTER_SQL, "Core thread with ID [" UI64FMTD "] shutting down MySQL thread.",
(uint64)ACE_Based::Thread::currentId());
}
diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp
index 7708aa36617..c90a6e527f7 100644
--- a/src/tools/mesh_extractor/ContinentBuilder.cpp
+++ b/src/tools/mesh_extractor/ContinentBuilder.cpp
@@ -6,104 +6,59 @@
#include "Cache.h"
#include "ace/Task.h"
#include "Recast.h"
+#include "DetourCommon.h"
class BuilderThread : public ACE_Task_Base
{
private:
int X, Y, MapId;
- bool Instance;
std::string Continent;
dtNavMeshParams Params;
ContinentBuilder* cBuilder;
- WorldModelRoot* Model;
- const WorldModelDefinition* Definition;
public:
BuilderThread(ContinentBuilder* _cBuilder, dtNavMeshParams& params) : Params(params), cBuilder(_cBuilder), Free(true) {}
- void SetData(int x, int y, int map, const std::string& cont, bool instance, WorldModelRoot* model, const WorldModelDefinition* def)
+
+ void SetData(int x, int y, int map, const std::string& cont)
{
X = x;
Y = y;
MapId = map;
Continent = cont;
- Instance = instance;
- if (Instance)
- {
- Model = model;
- Definition = def;
- }
- else
- Model = NULL;
}
int svc()
{
- if (Instance)
+ Free = false;
+ printf("[%02i,%02i] Building tile\n", X, Y);
+ TileBuilder builder(cBuilder, Continent, X, Y, MapId);
+ char buff[100];
+ sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X);
+ FILE* f = fopen(buff, "r");
+ if (f) // Check if file already exists.
{
- // Build a WMO
- printf("Building WMO %s ( %u )", Continent.c_str(), MapId);
- TileBuilder builder(cBuilder, Continent, X, Y, MapId);
- char buff[100];
- sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X);
- FILE* f = fopen(buff, "r");
- if (f) // Check if file already exists.
- {
- printf("Instance %s ( %u ) skipped, file already exists\n", Continent.c_str(), MapId);
- fclose(f);
- return 0;
- }
-
- uint8* nav = builder.BuildInstance(Params, Model, *Definition);
- if (nav)
- {
- f = fopen(buff, "wb");
- if (!f)
- {
- printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
- return 0;
- }
- MmapTileHeader header;
- header.size = builder.DataSize;
- fwrite(&header, sizeof(MmapTileHeader), 1, f);
- fwrite(nav, sizeof(unsigned char), builder.DataSize, f);
- fclose(f);
- }
- dtFree(nav);
+ printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y);
+ fclose(f);
+ Free = true;
return 0;
}
- else
+ uint8* nav = builder.BuildTiled(Params);
+ if (nav)
{
- Free = false;
- printf("[%02i,%02i] Building tile\n", X, Y);
- TileBuilder builder(cBuilder, Continent, X, Y, MapId);
- char buff[100];
- sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X);
- FILE* f = fopen(buff, "r");
- if (f) // Check if file already exists.
+ f = fopen(buff, "wb");
+ if (!f)
{
- printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y);
- fclose(f);
- Free = true;
+ printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
return 0;
}
- uint8* nav = builder.Build(Params);
- if (nav)
- {
- f = fopen(buff, "wb");
- if (!f)
- {
- printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
- return 0;
- }
- MmapTileHeader header;
- header.size = builder.DataSize;
- fwrite(&header, sizeof(MmapTileHeader), 1, f);
- fwrite(nav, sizeof(unsigned char), builder.DataSize, f);
- fclose(f);
- }
- dtFree(nav);
- printf("[%02i,%02i] Tile Built!\n", X, Y);
- Free = true;
+ MmapTileHeader header;
+ header.size = builder.DataSize;
+ fwrite(&header, sizeof(MmapTileHeader), 1, f);
+ fwrite(nav, sizeof(unsigned char), builder.DataSize, f);
+ fclose(f);
}
+ dtFree(nav);
+ printf("[%02i,%02i] Tile Built!\n", X, Y);
+ Free = true;
return 0;
}
@@ -155,26 +110,57 @@ void ContinentBuilder::Build()
CalculateTileBounds();
dtNavMeshParams params;
- params.maxPolys = 1 << STATIC_POLY_BITS;
- params.maxTiles = TileMap->TileTable.size();
- rcVcopy(params.orig, bmin);
- params.tileHeight = Constants::TileSize;
- params.tileWidth = Constants::TileSize;
- fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
- fclose(mmap);
+
std::vector<BuilderThread*> Threads;
if (TileMap->IsGlobalModel)
{
printf("Map %s ( %u ) is a WMO. Building with 1 thread.\n", Continent.c_str(), MapId);
- BuilderThread* thread = new BuilderThread(this, params);
- Threads.push_back(thread);
- thread->SetData(65, 65, MapId, Continent, true, TileMap->Model, &TileMap->ModelDefinition);
- thread->activate();
- thread->wait();
+
+ TileBuilder* builder = new TileBuilder(this, Continent, 0, 0, MapId);
+ builder->AddGeometry(TileMap->Model, TileMap->ModelDefinition);
+ uint8* nav = builder->BuildInstance(params);
+ if (nav)
+ {
+ // Set some params for the navmesh
+ dtMeshHeader* header = (dtMeshHeader*)nav;
+ dtVcopy(params.orig, header->bmin);
+ params.tileWidth = header->bmax[0] - header->bmin[0];
+ params.tileHeight = header->bmax[2] - header->bmin[2];
+ params.maxTiles = 1;
+ params.maxPolys = header->polyCount;
+ fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
+ fclose(mmap);
+
+ char buff[100];
+ sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, 0, 0);
+ FILE* f = fopen(buff, "wb");
+ if (!f)
+ {
+ printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
+ return;
+ }
+
+ MmapTileHeader mheader;
+ mheader.size = builder->DataSize;
+ fwrite(&mheader, sizeof(MmapTileHeader), 1, f);
+ fwrite(nav, sizeof(unsigned char), builder->DataSize, f);
+ fclose(f);
+ }
+
+ dtFree(nav);
+ delete builder;
}
else
{
+ params.maxPolys = 32768;
+ params.maxTiles = 4096;
+ rcVcopy(params.orig, Constants::Origin);
+ params.tileHeight = Constants::TileSize;
+ params.tileWidth = Constants::TileSize;
+ fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
+ fclose(mmap);
+
for (uint32 i = 0; i < NumberOfThreads; ++i)
Threads.push_back(new BuilderThread(this, params));
printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads);
@@ -187,7 +173,7 @@ void ContinentBuilder::Build()
{
if ((*_th)->Free)
{
- (*_th)->SetData(itr->X, itr->Y, MapId, Continent, false, NULL, NULL);
+ (*_th)->SetData(itr->X, itr->Y, MapId, Continent);
(*_th)->activate();
next = true;
break;
diff --git a/src/tools/mesh_extractor/Geometry.cpp b/src/tools/mesh_extractor/Geometry.cpp
index 37f5c68bb6d..df828dcd573 100644
--- a/src/tools/mesh_extractor/Geometry.cpp
+++ b/src/tools/mesh_extractor/Geometry.cpp
@@ -17,7 +17,7 @@ void Geometry::CalculateBoundingBox( float*& min, float*& max )
max = new float[3];
for (int i = 0; i < 3; ++i)
{
- max[i] = std::numeric_limits<float>::min();
+ max[i] = std::numeric_limits<float>::lowest();
min[i] = std::numeric_limits<float>::max();
}
@@ -42,8 +42,8 @@ void Geometry::CalculateBoundingBox( float*& min, float*& max )
void Geometry::CalculateMinMaxHeight( float& min, float& max )
{
- min = 0.0f;
- max = 0.0f;
+ min = std::numeric_limits<float>::max();
+ max = std::numeric_limits<float>::lowest();
for (std::vector<Vector3>::iterator itr = Vertices.begin(); itr != Vertices.end(); ++itr)
{
diff --git a/src/tools/mesh_extractor/MPQ.h b/src/tools/mesh_extractor/MPQ.h
index 2f8b082f526..30e11741550 100644
--- a/src/tools/mesh_extractor/MPQ.h
+++ b/src/tools/mesh_extractor/MPQ.h
@@ -26,7 +26,8 @@ public:
libmpq__off_t size, transferred;
libmpq__file_unpacked_size(mpq_a, filenum, &size);
- char *buffer = new char[size];
+ char* buffer = new char[size + 1];
+ buffer[size] = '\0';
libmpq__file_read(mpq_a, filenum, (unsigned char*)buffer, size, &transferred);
diff --git a/src/tools/mesh_extractor/MPQManager.cpp b/src/tools/mesh_extractor/MPQManager.cpp
index 3c63aed97d0..4d3ab808a2e 100644
--- a/src/tools/mesh_extractor/MPQManager.cpp
+++ b/src/tools/mesh_extractor/MPQManager.cpp
@@ -23,7 +23,7 @@ void MPQManager::Initialize()
for (uint32 i = 0; i < size; ++i)
{
MPQArchive* arc = new MPQArchive(std::string("Data/" + std::string(Files[i])).c_str());
- Archives.push_front(arc);
+ Archives.push_front(arc); // MPQ files have to be transversed in reverse order to properly account for patched files
printf("Opened %s\n", Files[i]);
}
}
@@ -109,5 +109,7 @@ FILE* MPQManager::GetFileFrom(const std::string& path, MPQArchive* file )
exit(1);
}
fwrite(buffer, sizeof(uint8), size, ret);
+ fseek(ret, 0, SEEK_SET);
+ delete[] buffer;
return ret;
}
diff --git a/src/tools/mesh_extractor/MeshExtractor.cpp b/src/tools/mesh_extractor/MeshExtractor.cpp
index 4a312640395..0d9160a610b 100644
--- a/src/tools/mesh_extractor/MeshExtractor.cpp
+++ b/src/tools/mesh_extractor/MeshExtractor.cpp
@@ -76,7 +76,7 @@ void ExtractDBCs()
std::string component = "component.wow-" + std::string(MPQManager::Languages[*itr]) + ".txt";
// Extract the component file
- Utils::SaveToDisk(MPQHandler->GetFile(component), path + component);
+ Utils::SaveToDisk(MPQHandler->GetFileFrom(component, MPQHandler->LocaleFiles[*itr]), path + component);
// Extract the DBC files for the given locale
for (std::set<std::string>::iterator itr2 = DBCFiles.begin(); itr2 != DBCFiles.end(); ++itr2)
Utils::SaveToDisk(MPQHandler->GetFileFrom(*itr2, MPQHandler->LocaleFiles[*itr]), path + (itr2->c_str() + folderLen));
@@ -328,6 +328,8 @@ void PrintUsage()
void LoadTile(dtNavMesh*& navMesh, const char* tile)
{
FILE* f = fopen(tile, "rb");
+ if (!f)
+ return;
MmapTileHeader header;
if (fread(&header, sizeof(MmapTileHeader), 1, f) != 1)
@@ -376,37 +378,37 @@ int main(int argc, char* argv[])
if (extractFlags & Constants::EXTRACT_FLAG_TEST)
{
- float start[] = { 0.0f, 0.0f, 0.0f };
- float end[] = { 0.0f, 0.0f, 0.0f };
+ float start[] = { 16226.200195f, 16257.000000f, 13.202200f };
+ float end[] = { 16245.725586f, 16382.465820f, 47.384956f };
//
float m_spos[3];
- m_spos[0] = -1.0f * start[1];
+ m_spos[0] = -start[1];
m_spos[1] = start[2];
- m_spos[2] = -1.0f * start[0];
+ m_spos[2] = -start[0];
//
float m_epos[3];
- m_epos[0] = -1.0f * end[1];
+ m_epos[0] = -end[1];
m_epos[1] = end[2];
- m_epos[2] = -1.0f * end[0];
+ m_epos[2] = -end[0];
//
dtQueryFilter m_filter;
- m_filter.setIncludeFlags(0xffff);
- m_filter.setExcludeFlags(0);
+ m_filter.setIncludeFlags(Constants::POLY_AREA_ROAD | Constants::POLY_AREA_TERRAIN);
+ m_filter.setExcludeFlags(Constants::POLY_AREA_WATER);
//
float m_polyPickExt[3];
- m_polyPickExt[0] = 2;
- m_polyPickExt[1] = 4;
- m_polyPickExt[2] = 2;
+ m_polyPickExt[0] = 2.5f;
+ m_polyPickExt[1] = 2.5f;
+ m_polyPickExt[2] = 2.5f;
//
dtPolyRef m_startRef;
dtPolyRef m_endRef;
- FILE* mmap = fopen(".mmap", "rb");
+ FILE* mmap = fopen("mmaps/001.mmap", "rb");
dtNavMeshParams params;
int count = fread(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
@@ -420,13 +422,16 @@ int main(int argc, char* argv[])
dtNavMeshQuery* navMeshQuery = new dtNavMeshQuery();
navMesh->init(&params);
- LoadTile(navMesh, ".mmtile");
- LoadTile(navMesh, ".mmtile");
- LoadTile(navMesh, ".mmtile");
- LoadTile(navMesh, ".mmtile");
- LoadTile(navMesh, ".mmtile");
- LoadTile(navMesh, ".mmtile");
-
+ for (int i = 0; i <= 32; ++i)
+ {
+ for (int j = 0; j <= 32; ++j)
+ {
+ char buff[100];
+ sprintf(buff, "mmaps/001%02i%02i.mmtile", i, j);
+ LoadTile(navMesh, buff);
+ }
+ }
+
navMeshQuery->init(navMesh, 2048);
float nearestPt[3];
@@ -440,7 +445,24 @@ int main(int argc, char* argv[])
return 0;
}
- printf("Found!");
+ int hops;
+ dtPolyRef* hopBuffer = new dtPolyRef[8192];
+ dtStatus status = navMeshQuery->findPath(m_startRef, m_endRef, m_spos, m_epos, &m_filter, hopBuffer, &hops, 8192);
+
+ int resultHopCount;
+ float* straightPath = new float[2048*3];
+ unsigned char* pathFlags = new unsigned char[2048];
+ dtPolyRef* pathRefs = new dtPolyRef[2048];
+
+ status = navMeshQuery->findStraightPath(m_spos, m_epos, hopBuffer, hops, straightPath, pathFlags, pathRefs, &resultHopCount, 2048);
+ std::vector<Vector3> FinalPath;
+ FinalPath.reserve(resultHopCount);
+ for (uint32 i = 0; i < resultHopCount; ++i)
+ {
+ Vector3 finalV = Utils::ToWoWCoords(Vector3(straightPath[i * 3 + 0], straightPath[i * 3 + 1], straightPath[i * 3 + 2]));
+ FinalPath.push_back(finalV);
+ printf("Point %f %f %f\n", finalV.x, finalV.y, finalV.z);
+ }
}
return 0;
diff --git a/src/tools/mesh_extractor/TileBuilder.cpp b/src/tools/mesh_extractor/TileBuilder.cpp
index 857cf7f16d8..51df91d2652 100644
--- a/src/tools/mesh_extractor/TileBuilder.cpp
+++ b/src/tools/mesh_extractor/TileBuilder.cpp
@@ -16,51 +16,25 @@
TileBuilder::TileBuilder(ContinentBuilder* _cBuilder, std::string world, int x, int y, uint32 mapId) :
World(world), X(x), Y(y), MapId(mapId), _Geometry(NULL), DataSize(0), cBuilder(_cBuilder)
{
- /*
- Test, non-working values
- // Cell Size = TileSize / TileVoxelSize
- // 1800 = TileVoxelSize
- Config.cs = Constants::TileSize / 1800;
- // Cell Height
- Config.ch = 0.4f;
- // Min Region Area = 20^2
- Config.minRegionArea = 20*20;
- // Merge Region Area = 40^2
- Config.mergeRegionArea = 40*40;
- Config.tileSize = Constants::TileSize / 4;
+ // Config for normal maps
+ memset(&Config, 0, sizeof(rcConfig));
+ Config.cs = Constants::TileSize / 1800.0f; // TileSize / voxelSize
+ Config.ch = 0.3f;
+ Config.minRegionArea = 36;
+ Config.mergeRegionArea = 144;
Config.walkableSlopeAngle = 50.0f;
Config.detailSampleDist = 3.0f;
Config.detailSampleMaxError = 1.25f;
- Config.walkableClimb = floorf(1.0f / Config.ch);
- Config.walkableHeight = ceilf(1.652778f / Config.ch);
- Config.walkableRadius = ceilf(0.2951389f / Config.cs);
+ Config.walkableClimb = 1.0f / Config.ch;
+ Config.walkableHeight = 2.1 / Config.ch;
+ Config.walkableRadius = 0.6f / Config.cs;
Config.maxEdgeLen = Config.walkableRadius * 8;
- Config.borderSize = Config.walkableRadius + 4;
- Config.width = 1800 + Config.borderSize * 2;
- Config.height = 1800 + Config.borderSize * 2;
- Config.maxVertsPerPoly = 6;
+ Config.borderSize = Config.walkableRadius + 8;
+ Config.tileSize = 1800;
Config.maxSimplificationError = 1.3f;
- */
-
- // All are in UNIT metrics!
- memset(&Config, 0, sizeof(rcConfig));
-
- Config.maxVertsPerPoly = DT_VERTS_PER_POLYGON;
- Config.cs = Constants::BaseUnitDim;
- Config.ch = Constants::BaseUnitDim;
- Config.walkableSlopeAngle = 60.0f;
- Config.tileSize = Constants::VertexPerTile;
- Config.walkableRadius = 1;
- Config.borderSize = Config.walkableRadius + 3;
- Config.maxEdgeLen = Constants::VertexPerTile + 1; //anything bigger than tileSize
- Config.walkableHeight = 3;
- Config.walkableClimb = 2; // keep less than walkableHeight
- Config.minRegionArea = rcSqr(60);
- Config.mergeRegionArea = rcSqr(50);
- Config.maxSimplificationError = 2.0f; // eliminates most jagged edges (tinny polygons)
- Config.detailSampleDist = Config.cs * 64;
- Config.detailSampleMaxError = Config.ch * 2;
+ Config.maxVertsPerPoly = 6;
+ // Config for instances
memset(&InstanceConfig, 0, sizeof(rcConfig));
InstanceConfig.cs = 0.2f;
InstanceConfig.ch = 0.3f;
@@ -90,33 +64,22 @@ void TileBuilder::CalculateTileBounds( float*& bmin, float*& bmax, dtNavMeshPara
bmax[2] = Constants::Origin[2] /*navMeshParams.orig[2]*/ + (Constants::TileSize * (Y + 1));
}
-uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoot* root, const WorldModelDefinition& def )
+void TileBuilder::AddGeometry(WorldModelRoot* root, const WorldModelDefinition& def)
{
_Geometry = new Geometry();
_Geometry->Transform = true;
- WorldModelHandler::InsertModelGeometry(_Geometry->Vertices, _Geometry->Triangles, def, root);
+ WorldModelHandler::InsertModelGeometry(_Geometry->Vertices, _Geometry->Triangles, def, root, false);
- if (Constants::Debug)
- {
- char buff[100];
- sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X);
- FILE* debug = fopen(buff, "wb");
- for (uint32 i = 0; i < _Geometry->Vertices.size(); ++i)
- {
- const Vector3& vector = _Geometry->Vertices[i];
- fprintf(debug, "v %f %f %f\n", vector.x, vector.y, vector.z);
- }
- for (uint32 i = 0; i < _Geometry->Triangles.size(); ++i)
- {
- const Triangle<uint32>& triangle = _Geometry->Triangles[i];
- fprintf(debug, "f %u %u %u\n", triangle.V0 + 1, triangle.V1 + 1, triangle.V2 + 1);
- }
- fclose(debug);
- }
+ OutputDebugVertices();
+}
+
+uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams )
+{
+ float* bmin = NULL, *bmax = NULL;
- float* bmin, *bmax;
_Geometry->CalculateBoundingBox(bmin, bmax);
+
rcVcopy(InstanceConfig.bmax, bmax);
rcVcopy(InstanceConfig.bmin, bmin);
@@ -126,14 +89,13 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
int* triangles;
uint8* areas;
_Geometry->GetRawData(vertices, triangles, areas);
- _Geometry->Vertices.clear();
- _Geometry->Triangles.clear();
- // this sets the dimensions of the heightfield - should maybe happen before border padding
+ // this sets the dimensions of the heightfield
rcCalcGridSize(InstanceConfig.bmin, InstanceConfig.bmax, InstanceConfig.cs, &InstanceConfig.width, &InstanceConfig.height);
+
rcHeightfield* hf = rcAllocHeightfield();
rcCreateHeightfield(Context, *hf, InstanceConfig.width, InstanceConfig.height, InstanceConfig.bmin, InstanceConfig.bmax, InstanceConfig.cs, InstanceConfig.ch);
-
+
rcClearUnwalkableTriangles(Context, InstanceConfig.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas);
rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, InstanceConfig.walkableClimb);
@@ -190,9 +152,10 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
params.walkableClimb = InstanceConfig.walkableClimb * InstanceConfig.ch;
params.walkableHeight = InstanceConfig.walkableHeight * InstanceConfig.ch;
params.walkableRadius = InstanceConfig.walkableRadius * InstanceConfig.cs;
- params.tileX = 0;
- params.tileY = 0;
+ params.tileX = X;
+ params.tileY = Y;
params.tileLayer = 0;
+ params.buildBvTree = true;
rcVcopy(params.bmax, bmax);
rcVcopy(params.bmin, bmin);
@@ -200,7 +163,14 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
// Offmesh-connection settings
params.offMeshConCount = 0; // none for now
- //params.tileSize = Constants::VertexPerMap;
+ rcFreeHeightField(hf);
+ rcFreeCompactHeightfield(chf);
+ rcFreeContourSet(contours);
+ delete vertices;
+ delete triangles;
+ delete areas;
+ delete bmin;
+ delete bmax;
if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount)
{
@@ -208,20 +178,18 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
// keep in mind that we do output those into debug info
// drop tiles with only exact count - some tiles may have geometry while having less tiles
printf("No polygons to build on tile, skipping.\n");
- delete areas;
- delete triangles;
- delete vertices;
+ rcFreePolyMesh(pmesh);
+ rcFreePolyMeshDetail(dmesh);
return NULL;
}
int navDataSize;
uint8* navData;
- printf("Creating the navmesh with %i vertices, %i polys, %i triangles!\n", pmesh->nverts, pmesh->npolys, dmesh->ntris);
+ printf("Creating the navmesh with %i vertices, %i polys, %i triangles!\n", params.vertCount, params.polyCount, params.detailTriCount);
bool result = dtCreateNavMeshData(&params, &navData, &navDataSize);
- delete areas;
- delete triangles;
- delete vertices;
+ rcFreePolyMesh(pmesh);
+ rcFreePolyMeshDetail(dmesh);
if (result)
{
@@ -233,7 +201,7 @@ uint8* TileBuilder::BuildInstance( dtNavMeshParams& navMeshParams, WorldModelRoo
return NULL;
}
-uint8* TileBuilder::Build(dtNavMeshParams& navMeshParams)
+uint8* TileBuilder::BuildTiled(dtNavMeshParams& navMeshParams)
{
_Geometry = new Geometry();
_Geometry->Transform = true;
@@ -245,10 +213,14 @@ uint8* TileBuilder::Build(dtNavMeshParams& navMeshParams)
if (_Geometry->Vertices.empty() && _Geometry->Triangles.empty())
return NULL;
+ float* bmin = NULL, *bmax = NULL;
+ CalculateTileBounds(bmin, bmax, navMeshParams);
+ _Geometry->CalculateMinMaxHeight(bmin[1], bmax[1]);
+
// again, we load everything - wasteful but who cares
- for (int ty = Y - 2; ty <= Y + 2; ty++)
+ for (int ty = Y - 1; ty <= Y + 1; ty++)
{
- for (int tx = X - 2; tx <= X + 2; tx++)
+ for (int tx = X - 1; tx <= X + 1; tx++)
{
// don't load main tile again
if (tx == X && ty == Y)
@@ -267,23 +239,7 @@ uint8* TileBuilder::Build(dtNavMeshParams& navMeshParams)
}
}
- if (Constants::Debug)
- {
- char buff[100];
- sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X);
- FILE* debug = fopen(buff, "wb");
- for (uint32 i = 0; i < _Geometry->Vertices.size(); ++i)
- {
- const Vector3& vector = _Geometry->Vertices[i];
- fprintf(debug, "v %f %f %f\n", vector.x, vector.y, vector.z);
- }
- for (uint32 i = 0; i < _Geometry->Triangles.size(); ++i)
- {
- const Triangle<uint32>& triangle = _Geometry->Triangles[i];
- fprintf(debug, "f %u %u %u\n", triangle.V0 + 1, triangle.V1 + 1, triangle.V2 + 1);
- }
- fclose(debug);
- }
+ OutputDebugVertices();
uint32 numVerts = _Geometry->Vertices.size();
uint32 numTris = _Geometry->Triangles.size();
@@ -294,93 +250,38 @@ uint8* TileBuilder::Build(dtNavMeshParams& navMeshParams)
_Geometry->Vertices.clear();
_Geometry->Triangles.clear();
+ // add border
+ bmin[0] -= Config.borderSize * Config.cs;
+ bmin[2] -= Config.borderSize * Config.cs;
+ bmax[0] += Config.borderSize * Config.cs;
+ bmax[2] += Config.borderSize * Config.cs;
- rcVcopy(Config.bmin, cBuilder->bmin);
- rcVcopy(Config.bmax, cBuilder->bmax);
+ rcHeightfield* hf = rcAllocHeightfield();
+ int width = Config.tileSize + (Config.borderSize * 2);
+ rcCreateHeightfield(Context, *hf, width, width, bmin, bmax, Config.cs, Config.ch);
- // this sets the dimensions of the heightfield - should maybe happen before border padding
- rcCalcGridSize(Config.bmin, Config.bmax, Config.cs, &Config.width, &Config.height);
+ rcClearUnwalkableTriangles(Context, Config.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas);
+ rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb);
- // Initialize per tile config.
- rcConfig tileCfg = Config;
- tileCfg.width = Config.tileSize + Config.borderSize * 2;
- tileCfg.height = Config.tileSize + Config.borderSize * 2;
+ rcFilterLowHangingWalkableObstacles(Context, Config.walkableClimb, *hf);
+ rcFilterLedgeSpans(Context, Config.walkableHeight, Config.walkableClimb, *hf);
+ rcFilterWalkableLowHeightSpans(Context, Config.walkableHeight, *hf);
- // merge per tile poly and detail meshes
- rcPolyMesh** pmmerge = new rcPolyMesh*[Constants::TilesPerMap * Constants::TilesPerMap];
- rcPolyMeshDetail** dmmerge = new rcPolyMeshDetail*[Constants::TilesPerMap * Constants::TilesPerMap];
+ rcCompactHeightfield* chf = rcAllocCompactHeightfield();
+ rcBuildCompactHeightfield(Context, Config.walkableHeight, Config.walkableClimb, *hf, *chf);
- int nmerge = 0;
- for (int y = 0; y < Constants::TilesPerMap; ++y)
- {
- for (int x = 0; x < Constants::TilesPerMap; ++x)
- {
- // Calculate the per tile bounding box.
- tileCfg.bmin[0] = Config.bmin[0] + float(x * Config.tileSize - Config.borderSize) * Config.cs;
- tileCfg.bmin[2] = Config.bmin[2] + float(y * Config.tileSize - Config.borderSize) * Config.cs;
- tileCfg.bmax[0] = Config.bmin[0] + float((x + 1) * Config.tileSize + Config.borderSize) * Config.cs;
- tileCfg.bmax[2] = Config.bmin[2] + float((y + 1) * Config.tileSize + Config.borderSize) * Config.cs;
-
-
- rcHeightfield* hf = rcAllocHeightfield();
- rcCreateHeightfield(Context, *hf, tileCfg.width, tileCfg.height, tileCfg.bmin, tileCfg.bmax, tileCfg.cs, tileCfg.ch);
- rcClearUnwalkableTriangles(Context, tileCfg.walkableSlopeAngle, vertices, numVerts, triangles, numTris, areas);
- rcRasterizeTriangles(Context, vertices, numVerts, triangles, areas, numTris, *hf, Config.walkableClimb);
-
- // Once all geometry is rasterized, we do initial pass of filtering to
- // remove unwanted overhangs caused by the conservative rasterization
- // as well as filter spans where the character cannot possibly stand.
- rcFilterLowHangingWalkableObstacles(Context, Config.walkableClimb, *hf);
- rcFilterLedgeSpans(Context, tileCfg.walkableHeight, tileCfg.walkableClimb, *hf);
- rcFilterWalkableLowHeightSpans(Context, tileCfg.walkableHeight, *hf);
-
- // Compact the heightfield so that it is faster to handle from now on.
- // This will result in more cache coherent data as well as the neighbours
- // between walkable cells will be calculated.
- rcCompactHeightfield* chf = rcAllocCompactHeightfield();
- rcBuildCompactHeightfield(Context, tileCfg.walkableHeight, tileCfg.walkableClimb, *hf, *chf);
-
- rcFreeHeightField(hf);
-
- // Erode the walkable area by agent radius.
- rcErodeWalkableArea(Context, Config.walkableRadius, *chf);
- // Prepare for region partitioning, by calculating distance field along the walkable surface.
- rcBuildDistanceField(Context, *chf);
- // Partition the walkable surface into simple regions without holes.
- rcBuildRegions(Context, *chf, tileCfg.borderSize, tileCfg.minRegionArea, tileCfg.mergeRegionArea);
-
- // Create contours.
- rcContourSet* cset = rcAllocContourSet();
- rcBuildContours(Context, *chf, tileCfg.maxSimplificationError, tileCfg.maxEdgeLen, *cset);
-
- // Build polygon navmesh from the contours.
- rcPolyMesh* pmesh = rcAllocPolyMesh();
- rcBuildPolyMesh(Context, *cset, tileCfg.maxVertsPerPoly, *pmesh);
-
- // Build detail mesh.
- rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail();
- rcBuildPolyMeshDetail(Context, *pmesh, *chf, tileCfg.detailSampleDist, tileCfg.detailSampleMaxError, *dmesh);
-
- // Free memory
- rcFreeCompactHeightfield(chf);
- rcFreeContourSet(cset);
-
- pmmerge[nmerge] = pmesh;
- dmmerge[nmerge] = dmesh;
- ++nmerge;
- }
- }
+ rcErodeWalkableArea(Context, Config.walkableRadius, *chf);
+ rcBuildDistanceField(Context, *chf);
+ rcBuildRegions(Context, *chf, Config.borderSize, Config.minRegionArea, Config.mergeRegionArea);
+
+ rcContourSet* contours = rcAllocContourSet();
+ rcBuildContours(Context, *chf, Config.maxSimplificationError, Config.maxEdgeLen, *contours);
rcPolyMesh* pmesh = rcAllocPolyMesh();
- rcMergePolyMeshes(Context, pmmerge, nmerge, *pmesh);
+ rcBuildPolyMesh(Context, *contours, Config.maxVertsPerPoly, *pmesh);
rcPolyMeshDetail* dmesh = rcAllocPolyMeshDetail();
- rcMergePolyMeshDetails(Context, dmmerge, nmerge, *dmesh);
-
- delete[] pmmerge;
- delete[] dmmerge;
-
- printf("[%02i,%02i] Meshes merged!\n", X, Y);
+ rcBuildPolyMeshDetail(Context, *pmesh, *chf, Config.detailSampleDist, Config.detailSampleMaxError, *dmesh);
// Set flags according to area types (e.g. Swim for Water)
for (int i = 0; i < pmesh->npolys; i++)
@@ -407,54 +308,60 @@ uint8* TileBuilder::Build(dtNavMeshParams& navMeshParams)
params.detailVertsCount = dmesh->nverts;
params.detailTris = dmesh->tris;
params.detailTriCount = dmesh->ntris;
- rcVcopy(params.bmin, pmesh->bmin);
- rcVcopy(params.bmax, pmesh->bmax);
// General settings
params.ch = Config.ch;
params.cs = Config.cs;
- params.walkableClimb = Constants::BaseUnitDim * Config.walkableClimb;
- params.walkableHeight = Constants::BaseUnitDim * Config.walkableHeight;
- params.walkableRadius = Constants::BaseUnitDim * Config.walkableRadius;
- params.tileX = (((cBuilder->bmin[0] + cBuilder->bmax[0]) / 2) - navMeshParams.orig[0]) / Constants::TileSize;
- params.tileY = (((cBuilder->bmin[2] + cBuilder->bmax[2]) / 2) - navMeshParams.orig[2]) / Constants::TileSize;
+ params.walkableClimb = Config.walkableClimb * Config.ch;
+ params.walkableHeight = Config.walkableHeight * Config.ch;
+ params.walkableRadius = Config.walkableRadius * Config.cs;
+ params.tileX = X;
+ params.tileY = Y;
+ params.tileLayer = 0;
+ params.buildBvTree = true;
+
+ // Recalculate the bounds with the added geometry
+ float* bmin2 = NULL, *bmax2 = NULL;
+ CalculateTileBounds(bmin2, bmax2, navMeshParams);
+ bmin2[1] = bmin[1];
+ bmax2[1] = bmax[1];
- rcVcopy(params.bmin, cBuilder->bmin);
- rcVcopy(params.bmax, cBuilder->bmax);
+ rcVcopy(params.bmax, bmax2);
+ rcVcopy(params.bmin, bmin2);
// Offmesh-connection settings
params.offMeshConCount = 0; // none for now
- //params.tileSize = Constants::VertexPerMap;
+ rcFreeHeightField(hf);
+ rcFreeCompactHeightfield(chf);
+ rcFreeContourSet(contours);
+ delete vertices;
+ delete triangles;
+ delete areas;
+ delete bmin;
+ delete bmax;
if (!params.polyCount || !params.polys || Constants::TilesPerMap * Constants::TilesPerMap == params.polyCount)
{
// we have flat tiles with no actual geometry - don't build those, its useless
// keep in mind that we do output those into debug info
// drop tiles with only exact count - some tiles may have geometry while having less tiles
- printf("[%02i,%02i] No polygons to build on tile, skipping.\n", X, Y);
+ printf("[%02i, %02i] No polygons to build on tile, skipping.\n", X, Y);
rcFreePolyMesh(pmesh);
rcFreePolyMeshDetail(dmesh);
- delete areas;
- delete triangles;
- delete vertices;
return NULL;
}
int navDataSize;
uint8* navData;
- printf("[%02i,%02i] Creating the navmesh with %i vertices, %i polys, %i triangles!\n", X, Y, pmesh->nverts, pmesh->npolys, dmesh->ntris);
+ printf("[%02i, %02i] Creating the navmesh with %i vertices, %i polys, %i triangles!\n", X, Y, params.vertCount, params.polyCount, params.detailTriCount);
bool result = dtCreateNavMeshData(&params, &navData, &navDataSize);
- // Free some memory
rcFreePolyMesh(pmesh);
rcFreePolyMeshDetail(dmesh);
- delete areas;
- delete triangles;
- delete vertices;
if (result)
{
- printf("[%02i,%02i] NavMesh created, size %i!\n", X, Y, navDataSize);
+ printf("[%02i, %02i] NavMesh created, size %i!\n", X, Y, navDataSize);
DataSize = navDataSize;
return navData;
}
@@ -462,6 +369,27 @@ uint8* TileBuilder::Build(dtNavMeshParams& navMeshParams)
return NULL;
}
+void TileBuilder::OutputDebugVertices()
+{
+ if (Constants::Debug)
+ {
+ char buff[100];
+ sprintf(buff, "mmaps/%s_%02u%02u.obj", World.c_str(), Y, X);
+ FILE* debug = fopen(buff, "wb");
+ for (uint32 i = 0; i < _Geometry->Vertices.size(); ++i)
+ {
+ const Vector3& vector = _Geometry->Vertices[i];
+ fprintf(debug, "v %f %f %f\n", vector.x, vector.y, vector.z);
+ }
+ for (uint32 i = 0; i < _Geometry->Triangles.size(); ++i)
+ {
+ const Triangle<uint32>& triangle = _Geometry->Triangles[i];
+ fprintf(debug, "f %u %u %u\n", triangle.V0 + 1, triangle.V1 + 1, triangle.V2 + 1);
+ }
+ fclose(debug);
+ }
+}
+
TileBuilder::~TileBuilder()
{
delete Context;
diff --git a/src/tools/mesh_extractor/TileBuilder.h b/src/tools/mesh_extractor/TileBuilder.h
index 814f989486e..165b3594ed6 100644
--- a/src/tools/mesh_extractor/TileBuilder.h
+++ b/src/tools/mesh_extractor/TileBuilder.h
@@ -16,8 +16,10 @@ public:
~TileBuilder();
void CalculateTileBounds(float*& bmin, float*& bmax, dtNavMeshParams& navMeshParams);
- uint8* Build(dtNavMeshParams& navMeshParams);
- uint8* BuildInstance(dtNavMeshParams& navMeshParams, WorldModelRoot* root, const WorldModelDefinition& def);
+ uint8* BuildTiled(dtNavMeshParams& navMeshParams);
+ uint8* BuildInstance(dtNavMeshParams& navMeshParams);
+ void AddGeometry(WorldModelRoot* root, const WorldModelDefinition& def);
+ void OutputDebugVertices();
std::string World;
int X;
int Y;
diff --git a/src/tools/mesh_extractor/Utils.cpp b/src/tools/mesh_extractor/Utils.cpp
index 10e0bdc0d04..24cfb5cd1db 100644
--- a/src/tools/mesh_extractor/Utils.cpp
+++ b/src/tools/mesh_extractor/Utils.cpp
@@ -87,7 +87,7 @@ std::string Utils::FixModelPath(const std::string& path )
return Utils::GetPathBase(path) + ".M2";
}
-Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec)
+Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec, bool translate)
{
// Sources of information:
/// http://www.pxr.dk/wowdev/wiki/index.php?title=ADT/v18&oldid=3715
@@ -99,15 +99,21 @@ Vector3 Utils::TransformDoodadVertex(const IDefinition& def, Vector3& vec)
Vector3 ret = Utils::VectorTransform(vec, rot);
// And finally scale and translate it to our origin
- return (ret * def.Scale()) + Vector3(Constants::MaxXY - def.Position.z, Constants::MaxXY - def.Position.x, def.Position.y);
+ ret = ret * def.Scale();
+ if (translate)
+ ret = ret + Vector3(Constants::MaxXY - def.Position.z, Constants::MaxXY - def.Position.x, def.Position.y);
+ return ret;
}
-Vector3 Utils::TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec )
+Vector3 Utils::TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec, bool translate )
{
G3D::Quat quat = G3D::Quat(-inst.QuatY, inst.QuatZ, -inst.QuatX, inst.QuatW);
Vector3 ret = Utils::VectorTransform(vec, G3D::Matrix4(quat.toRotationMatrix()));
- return (ret * (inst.Scale / 1024.0f)) + Vector3(Constants::MaxXY - inst.Position.z, Constants::MaxXY - inst.Position.x, inst.Position.y);
+ ret = ret * (inst.Scale / 1024.0f);
+ if (translate)
+ ret = ret + Vector3(Constants::MaxXY - inst.Position.z, Constants::MaxXY - inst.Position.x, inst.Position.y);
+ return ret;
}
float Utils::ToRadians( float degrees )
@@ -138,11 +144,11 @@ Vector3 Vector3::Read( FILE* file )
return ret;
}
-Vector3 Utils::GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int /*x*/, int /*y*/)
+Vector3 Utils::GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int x, int y, bool translate)
{
if (Utils::Distance(height, 0.0f) > 0.5f)
basePosition.z = 0.0f;
- return Utils::TransformDoodadVertex(def, basePosition + Vector3(basePosition.x * Constants::UnitSize, basePosition.y * Constants::UnitSize, height));
+ return Utils::TransformDoodadVertex(def, basePosition + Vector3(x * Constants::UnitSize, y * Constants::UnitSize, height), translate);
}
float Utils::Distance( float x, float y )
@@ -167,29 +173,43 @@ void Utils::SaveToDisk( FILE* stream, const std::string& path )
if (!disk)
{
printf("SaveToDisk: Could not save file %s to disk, please verify that you have write permissions on that directory\n", path.c_str());
+ fclose(stream);
return;
}
uint32 size = Utils::Size(stream);
uint8* data = new uint8[size];
// Read the data to an array
- if (fread(data, 1, size, stream) != 1)
+ size_t read = fread(data, size, 1, stream);
+ if (read != 1)
{
- printf("SaveToDisk: Error reading from Stream while trying to save file %s to disck.\n", path.c_str());
+ printf("SaveToDisk: Error reading from Stream while trying to save file %s to disk.\n", path.c_str());
+ fclose(disk);
+ fclose(stream);
return;
}
+
// And write it in the file
- fwrite(data, 1, size, disk);
+ size_t wrote = fwrite(data, size, 1, disk);
+ if (wrote != 1)
+ {
+ printf("SaveToDisk: Error writing to the file while trying to save %s to disk.\n", path.c_str());
+ fclose(stream);
+ fclose(disk);
+ return;
+ }
// Close the filestream
fclose(disk);
+ fclose(stream);
+
// Free the used memory
- delete [] data;
+ delete[] data;
}
Vector3 Utils::ToWoWCoords(const Vector3& vec )
{
- return Vector3(-vec.z, vec.x, vec.y);
+ return Vector3(-vec.z, -vec.x, vec.y);
}
std::string Utils::GetExtension( std::string path )
diff --git a/src/tools/mesh_extractor/Utils.h b/src/tools/mesh_extractor/Utils.h
index a307dd4f695..d6bb421a633 100644
--- a/src/tools/mesh_extractor/Utils.h
+++ b/src/tools/mesh_extractor/Utils.h
@@ -367,7 +367,7 @@ public:
}
static float ToRadians(float degrees);
static std::string GetPathBase(const std::string& path);
- static Vector3 GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int /*x*/, int /*y*/);
+ static Vector3 GetLiquidVert(const IDefinition& def, Vector3 basePosition, float height, int /*x*/, int /*y*/, bool translate = true);
static float Distance(float x, float y);
template<typename T>
static bool IsAllZero(T* arr, uint32 size)
@@ -383,8 +383,8 @@ public:
static Vector3 ToWoWCoords(const Vector3& vec );
static std::string GetExtension( std::string path );
static char* GetPlainName(const char* FileName);
- static Vector3 TransformDoodadVertex(const IDefinition& def, Vector3& vec);
+ static Vector3 TransformDoodadVertex(const IDefinition& def, Vector3& vec, bool translate = true);
static Vector3 VectorTransform(const Vector3& vec, const G3D::Matrix4& matrix, bool normal = false );
- static Vector3 TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec );
+ static Vector3 TransformWmoDoodad(const DoodadInstance& inst, const WorldModelDefinition& root, Vector3& vec, bool translate = true );
};
#endif
diff --git a/src/tools/mesh_extractor/WorldModelHandler.cpp b/src/tools/mesh_extractor/WorldModelHandler.cpp
index 24f63dc1e33..3565a1d6af0 100644
--- a/src/tools/mesh_extractor/WorldModelHandler.cpp
+++ b/src/tools/mesh_extractor/WorldModelHandler.cpp
@@ -79,13 +79,17 @@ void WorldModelHandler::ProcessInternal( MapChunk* mcnk )
fseek(stream, mcnk->Source->Offset, SEEK_SET);
}
-void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root )
+void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root, bool translate )
{
for (std::vector<WorldModelGroup>::iterator group = root->Groups.begin(); group != root->Groups.end(); ++group)
{
uint32 vertOffset = verts.size();
for (std::vector<Vector3>::iterator itr2 = group->Vertices.begin(); itr2 != group->Vertices.end(); ++itr2)
- verts.push_back(Utils::TransformDoodadVertex(def, *itr2)); // Transform the vertex to world space
+ {
+ Vector3 v = Utils::TransformDoodadVertex(def, *itr2, translate);
+ // If translate is false, then we were called directly from the TileBuilder to add data to it's _Geometry member, hence, we have to manually convert the vertices to Recast format.
+ verts.push_back(translate ? v : Utils::ToRecast(v)); // Transform the vertex to world space
+ }
for (uint32 i = 0; i < group->Triangles.size(); ++i)
{
@@ -122,7 +126,10 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
continue;
int vertOffset = verts.size();
for (std::vector<Vector3>::iterator itr2 = model->Vertices.begin(); itr2 != model->Vertices.end(); ++itr2)
- verts.push_back(Utils::TransformDoodadVertex(def, Utils::TransformWmoDoodad(*instance, def, *itr2)));
+ {
+ Vector3 v = Utils::TransformDoodadVertex(def, Utils::TransformWmoDoodad(*instance, def, *itr2, false), translate);
+ verts.push_back(translate ? v : Utils::ToRecast(v));
+ }
for (std::vector<Triangle<uint16> >::iterator itr2 = model->Triangles.begin(); itr2 != model->Triangles.end(); ++itr2)
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WMO, itr2->V0 + vertOffset, itr2->V1 + vertOffset, itr2->V2 + vertOffset));
}
@@ -144,14 +151,20 @@ void WorldModelHandler::InsertModelGeometry( std::vector<Vector3>& verts, std::v
continue;
uint32 vertOffset = verts.size();
- verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
- liquidDataGeometry.HeightMap[x][y], x, y));
- verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
- liquidDataGeometry.HeightMap[x + 1][y], x + 1, y));
- verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
- liquidDataGeometry.HeightMap[x][y + 1], x, y + 1));
- verts.push_back(Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
- liquidDataGeometry.HeightMap[x + 1][y + 1], x + 1, y + 1));
+
+ Vector3 v1 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
+ liquidDataGeometry.HeightMap[x][y], x, y, translate);
+ Vector3 v2 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
+ liquidDataGeometry.HeightMap[x + 1][y], x + 1, y, translate);
+ Vector3 v3 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
+ liquidDataGeometry.HeightMap[x][y + 1], x, y + 1, translate);
+ Vector3 v4 = Utils::GetLiquidVert(def, liquidHeader.BaseLocation,
+ liquidDataGeometry.HeightMap[x + 1][y + 1], x + 1, y + 1, translate);
+
+ verts.push_back(translate ? v1 : Utils::ToRecast(v1));
+ verts.push_back(translate ? v2 : Utils::ToRecast(v2));
+ verts.push_back(translate ? v3 : Utils::ToRecast(v3));
+ verts.push_back(translate ? v4 : Utils::ToRecast(v4));
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset, vertOffset + 2, vertOffset + 1));
tris.push_back(Triangle<uint32>(Constants::TRIANGLE_TYPE_WATER, vertOffset + 2, vertOffset + 3, vertOffset + 1));
diff --git a/src/tools/mesh_extractor/WorldModelHandler.h b/src/tools/mesh_extractor/WorldModelHandler.h
index 0611a02f764..87a5ad62938 100644
--- a/src/tools/mesh_extractor/WorldModelHandler.h
+++ b/src/tools/mesh_extractor/WorldModelHandler.h
@@ -34,7 +34,7 @@ public:
std::vector<Vector3> Vertices;
std::vector<Triangle<uint32> > Triangles;
bool IsSane() { return _definitions && _paths; }
- static void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root);
+ static void InsertModelGeometry(std::vector<Vector3>& verts, std::vector<Triangle<uint32> >& tris, const WorldModelDefinition& def, WorldModelRoot* root, bool translate = true);
protected:
void ProcessInternal(MapChunk* data);
private: