aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/collision/Management/VMapManager2.cpp3
-rwxr-xr-xsrc/server/collision/Management/VMapManager2.h2
-rw-r--r--src/server/collision/Maps/MapTree.cpp4
-rw-r--r--src/server/collision/Models/WorldModel.cpp3
-rwxr-xr-xsrc/server/collision/Models/WorldModel.h1
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp20
-rwxr-xr-xsrc/server/game/Grids/Notifiers/GridNotifiers.h28
-rwxr-xr-xsrc/server/game/Spells/Spell.cpp55
8 files changed, 85 insertions, 31 deletions
diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp
index 62abc31831a..81b97f5f352 100644
--- a/src/server/collision/Management/VMapManager2.cpp
+++ b/src/server/collision/Management/VMapManager2.cpp
@@ -245,7 +245,7 @@ namespace VMAP
return false;
}
- WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename)
+ WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags/* Only used when creating the model */)
{
//! Critical section, thread safe access to iLoadedModelFiles
TRINITY_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);
@@ -261,6 +261,7 @@ namespace VMAP
return NULL;
}
sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());
+ worldmodel->Flags = flags;
model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
model->second.setModel(worldmodel);
}
diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h
index 1fba108388a..4b66a2e9fc7 100755
--- a/src/server/collision/Management/VMapManager2.h
+++ b/src/server/collision/Management/VMapManager2.h
@@ -103,7 +103,7 @@ namespace VMAP
bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const;
- WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);
+ WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename, uint32 flags = 0);
void releaseModelInstance(const std::string& filename);
// what's the use of this? o.O
diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp
index fda0535e8a7..c839f3f4ffa 100644
--- a/src/server/collision/Maps/MapTree.cpp
+++ b/src/server/collision/Maps/MapTree.cpp
@@ -309,7 +309,7 @@ namespace VMAP
#endif
if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))
{
- WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
+ WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : loading %s", spawn.name.c_str());
if (model)
{
@@ -380,7 +380,7 @@ namespace VMAP
if (result)
{
// acquire model instance
- WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
+ WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name, spawn.flags);
if (!model)
sLog->outError("StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);
diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp
index a7de37d41e6..b49538a485d 100644
--- a/src/server/collision/Models/WorldModel.cpp
+++ b/src/server/collision/Models/WorldModel.cpp
@@ -420,6 +420,9 @@ namespace VMAP
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
{
+ // M2 models are not taken into account for LoS calculation
+ if (Flags & MOD_M2)
+ return false;
// small M2 workaround, maybe better make separate class with virtual intersection funcs
// in any case, there's no need to use a bound tree if we only have one submodel
if (groupModels.size() == 1)
diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h
index ebf828e4935..dbaccb58573 100755
--- a/src/server/collision/Models/WorldModel.h
+++ b/src/server/collision/Models/WorldModel.h
@@ -113,6 +113,7 @@ namespace VMAP
bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const;
bool writeFile(const std::string &filename);
bool readFile(const std::string &filename);
+ uint32 Flags;
protected:
uint32 RootWMOID;
std::vector<GroupModel> groupModels;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 29484f2695a..04eab0b7d56 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -12148,6 +12148,26 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell) co
|| target->GetReactionTo(this) > REP_NEUTRAL)
return false;
+ // Not all neutral creatures can be attacked
+ if (GetReactionTo(target) == REP_NEUTRAL &&
+ target->GetReactionTo(this) == REP_NEUTRAL)
+ {
+ if (
+ !(target->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER) &&
+ !(target->GetTypeId() == TYPEID_UNIT && GetTypeId() == TYPEID_UNIT)
+ )
+ {
+ Player const* player = target->GetTypeId() == TYPEID_PLAYER ? target->ToPlayer() : ToPlayer();
+ Unit const* creature = target->GetTypeId() == TYPEID_UNIT ? target : this;
+
+ if (FactionTemplateEntry const* factionTemplate = creature->getFactionTemplateEntry())
+ if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction))
+ if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry))
+ if (repState->Flags & FACTION_FLAG_PEACE_FORCED)
+ return false;
+ }
+ }
+
Creature const* creatureAttacker = ToCreature();
if (creatureAttacker && creatureAttacker->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_UNK26)
return false;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index e3029a1be65..4112711ad3c 100755
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -530,20 +530,38 @@ namespace Trinity
class RaiseDeadObjectCheck
{
public:
- RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {}
+ RaiseDeadObjectCheck(Unit* source, float range) : _source(source), i_range(range) {}
bool operator()(Creature* u)
{
- if (i_funit->GetTypeId() != TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) ||
- u->getDeathState() != CORPSE || u->isInFlight() ||
+ if (_source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) ||
+ u->getDeathState() != CORPSE ||
(u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0 ||
(u->GetDisplayId() != u->GetNativeDisplayId()))
return false;
- return i_funit->IsWithinDistInMap(u, i_range);
+ return _source->IsWithinDistInMap(u, i_range);
+ }
+
+ bool operator()(Player* u)
+ {
+ if (_source == u || _source->GetTypeId() != TYPEID_PLAYER || !((Player*)_source)->isHonorOrXPTarget(u) ||
+ u->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) || u->isInFlight() || !u->isDead() ||
+ (u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0)
+ return false;
+
+ return _source->IsWithinDistInMap(u, i_range);
+ }
+
+ bool operator()(Corpse* u)
+ {
+ if (_source->GetTypeId() != TYPEID_PLAYER || u->GetType() == CORPSE_BONES)
+ return false;
+
+ return _source->IsWithinDistInMap(u, i_range);
}
template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
private:
- Unit* const i_funit;
+ Unit* const _source;
float i_range;
};
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 670b743d725..6cacf5e7e5a 100755
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -598,24 +598,10 @@ WorldObject* Spell::FindCorpseUsing()
// non-standard target selection
float max_range = m_spellInfo->GetMaxRange(false);
- CellCoord p(Trinity::ComputeCellCoord(m_caster->GetPositionX(), m_caster->GetPositionY()));
- Cell cell(p);
- cell.SetNoCreate();
-
WorldObject* result = NULL;
-
T u_check(m_caster, max_range);
Trinity::WorldObjectSearcher<T> searcher(m_caster, result, u_check);
-
- TypeContainerVisitor<Trinity::WorldObjectSearcher<T>, GridTypeMapContainer > grid_searcher(searcher);
- cell.Visit(p, grid_searcher, *m_caster->GetMap(), *m_caster, max_range);
-
- if (!result)
- {
- TypeContainerVisitor<Trinity::WorldObjectSearcher<T>, WorldTypeMapContainer > world_searcher(searcher);
- cell.Visit(p, world_searcher, *m_caster->GetMap(), *m_caster, max_range);
- }
-
+ m_caster->GetMap()->VisitFirstFound(m_caster->GetPositionX(), m_caster->GetPositionY(), max_range, searcher);
return result;
}
@@ -2554,11 +2540,15 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
{
case 46584: // Raise Dead
{
- if (WorldObject* result = FindCorpseUsing<Trinity::RaiseDeadObjectCheck> ())
+ if (WorldObject* result = FindCorpseUsing<Trinity::RaiseDeadObjectCheck>())
{
switch (result->GetTypeId())
{
case TYPEID_UNIT:
+ case TYPEID_PLAYER:
+ unitList.push_back(result->ToUnit());
+ // no break;
+ case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
m_targets.SetDst(*result);
break;
default:
@@ -2582,7 +2572,7 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
{
CleanupTargetList();
- WorldObject* result = FindCorpseUsing <Trinity::ExplodeCorpseObjectCheck> ();
+ WorldObject* result = FindCorpseUsing<Trinity::ExplodeCorpseObjectCheck>();
if (result)
{
@@ -2824,12 +2814,12 @@ uint32 Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur)
unitList.remove(m_targets.GetUnitTarget());
Trinity::RandomResizeList(unitList, maxTargets);
}
+ }
- CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i));
+ CallScriptAfterUnitTargetSelectHandlers(unitList, SpellEffIndex(i));
- for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
- AddUnitTarget(*itr, effectMask, false);
- }
+ for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
+ AddUnitTarget(*itr, effectMask, false);
if (!gobjectList.empty())
{
@@ -3725,6 +3715,27 @@ void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cas
case SPELL_FAILED_CUSTOM_ERROR:
data << uint32(customError);
break;
+ case SPELL_FAILED_REAGENTS:
+ {
+ uint32 missingItem = 0;
+ for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++)
+ {
+ if (spellInfo->Reagent[i] <= 0)
+ continue;
+
+ uint32 itemid = spellInfo->Reagent[i];
+ uint32 itemcount = spellInfo->ReagentCount[i];
+
+ if (!caster->HasItemCount(itemid, itemcount))
+ {
+ missingItem = itemid;
+ break;
+ }
+ }
+
+ data << uint32(missingItem); // first missing item
+ break;
+ }
default:
break;
}
@@ -5926,7 +5937,7 @@ SpellCastResult Spell::CheckItems()
}
}
if (!p_caster->HasItemCount(itemid, itemcount))
- return SPELL_FAILED_ITEM_NOT_READY; //0x54
+ return SPELL_FAILED_REAGENTS;
}
}