diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/collision/Management/VMapManager2.cpp | 3 | ||||
-rwxr-xr-x | src/server/collision/Management/VMapManager2.h | 2 | ||||
-rw-r--r-- | src/server/collision/Maps/MapTree.cpp | 4 | ||||
-rw-r--r-- | src/server/collision/Models/WorldModel.cpp | 3 | ||||
-rwxr-xr-x | src/server/collision/Models/WorldModel.h | 1 | ||||
-rwxr-xr-x | src/server/game/Entities/Unit/Unit.cpp | 20 | ||||
-rwxr-xr-x | src/server/game/Grids/Notifiers/GridNotifiers.h | 28 | ||||
-rwxr-xr-x | src/server/game/Spells/Spell.cpp | 55 |
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; } } |