From 8aa80eef181af4babea7dd65b938b5d88de9cd03 Mon Sep 17 00:00:00 2001 From: P-Kito Date: Thu, 16 Apr 2020 11:39:45 +0200 Subject: [PATCH] feat(Core/SAI): new Actions + Polar Coords System Offset Relocating (#2880) --- .../game/AI/SmartScripts/SmartScript.cpp | 183 ++++++++++++- .../game/AI/SmartScripts/SmartScriptMgr.cpp | 8 + .../game/AI/SmartScripts/SmartScriptMgr.h | 45 +++- src/server/game/Entities/Object/Object.cpp | 247 +++++++++--------- src/server/game/Entities/Object/Object.h | 1 + 5 files changed, 361 insertions(+), 123 deletions(-) diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 5ba608593..83dfb39a5 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -1822,6 +1822,15 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!me) break; + if (e.action.orientation.random > 0) + { + float randomOri = frand(0.0f, 2 * M_PI); + me->SetFacingTo(randomOri); + if (e.action.orientation.quickChange) + me->SetOrientation(randomOri); + break; + } + if (e.GetTargetType() == SMART_TARGET_SELF) { me->SetFacingTo((me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && me->GetTransGUID() ? me->GetTransportHomePosition() : me->GetHomePosition()).GetOrientation()); @@ -3031,6 +3040,178 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u me->FindMap()->LoadGrid(e.target.x, e.target.y); break; } + case SMART_ACTION_PLAYER_TALK: + { + ObjectList* targets = GetTargets(e, unit); + char const* text = sObjectMgr->GetAcoreString(e.action.playerTalk.textId, DEFAULT_LOCALE); + + if (targets) + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + if (IsPlayer(*itr)) + !e.action.playerTalk.flag ? (*itr)->ToPlayer()->Say(text, LANG_UNIVERSAL) : (*itr)->ToPlayer()->Yell(text, LANG_UNIVERSAL); + + delete targets; + break; + } + case SMART_ACTION_CUSTOM_CAST: + { + if (!me) + break; + + ObjectList* targets = GetTargets(e, unit); + if (!targets) + break; + + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + { + if (IsUnit(*itr)) + { + if (e.action.castCustom.flags & SMARTCAST_INTERRUPT_PREVIOUS) + me->InterruptNonMeleeSpells(false); + + if (e.action.castCustom.flags & SMARTCAST_COMBAT_MOVE) + { + // If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed + // unless target is outside spell range, out of mana, or LOS. + + bool _allowMove = false; + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.castCustom.spell); + int32 mana = me->GetPower(POWER_MANA); + + if (me->GetDistance((*itr)->ToUnit()) > spellInfo->GetMaxRange(true) || + me->GetDistance((*itr)->ToUnit()) < spellInfo->GetMinRange(true) || + !me->IsWithinLOSInMap((*itr)->ToUnit()) || + mana < spellInfo->CalcPowerCost(me, spellInfo->GetSchoolMask())) + _allowMove = true; + + CAST_AI(SmartAI, me->AI())->SetCombatMove(_allowMove); + } + + if (!(e.action.castCustom.flags & SMARTCAST_AURA_NOT_PRESENT) || !(*itr)->ToUnit()->HasAura(e.action.castCustom.spell)) + { + CustomSpellValues values; + if (e.action.castCustom.bp1) + values.AddSpellMod(SPELLVALUE_BASE_POINT0, e.action.castCustom.bp1); + if (e.action.castCustom.bp2) + values.AddSpellMod(SPELLVALUE_BASE_POINT1, e.action.castCustom.bp2); + if (e.action.castCustom.bp3) + values.AddSpellMod(SPELLVALUE_BASE_POINT2, e.action.castCustom.bp3); + me->CastCustomSpell(e.action.castCustom.spell, values, (*itr)->ToUnit(), (e.action.castCustom.flags & SMARTCAST_TRIGGERED) ? TRIGGERED_FULL_MASK : TRIGGERED_NONE); + } + } + } + delete targets; + break; + } + case SMART_ACTION_VORTEX_SUMMON: + { + if (!me) + break; + + ObjectList* targets = GetTargets(e, unit); + if (!targets) + break; + + TempSummonType summon_type = (e.action.summonVortex.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN; + + float a = static_cast(e.action.summonVortex.a); + float k = static_cast(e.action.summonVortex.k) / 1000.0f; + float r_max = static_cast(e.action.summonVortex.r_max); + float delta_phi = M_PI * static_cast(e.action.summonVortex.phi_delta) / 180.0f; + + // r(phi) = a * e ^ (k * phi) + // r(phi + delta_phi) = a * e ^ (k * (phi + delta_phi)) + // r(phi + delta_phi) = a * e ^ (k * phi) * e ^ (k * delta_phi) + // r(phi + delta_phi) = r(phi) * e ^ (k * delta_phi) + float factor = std::exp(k * delta_phi); + + // r(0) = a * e ^ (k * 0) = a * e ^ 0 = a * 1 = a + float summonRadius = a; + + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + { + // Offset by orientation, should not count into radius calculation, + // but is needed for vortex direction (polar coordinates) + float phi = (*itr)->GetOrientation(); + + do + { + Position summonPosition(**itr); + summonPosition.RelocatePolarOffset(phi, summonRadius); + + me->SummonCreature(e.action.summonVortex.summonEntry, summonPosition, summon_type, e.action.summonVortex.summonDuration); + + phi += delta_phi; + summonRadius *= factor; + } while (summonRadius <= r_max); + } + + delete targets; + break; + } + case SMART_ACTION_CONE_SUMMON: + { + if (!me) + break; + + TempSummonType spawnType = (e.action.coneSummon.summonDuration > 0) ? TEMPSUMMON_TIMED_DESPAWN : TEMPSUMMON_CORPSE_DESPAWN; + + float distInARow = static_cast(e.action.coneSummon.distanceBetweenSummons); + float coneAngle = static_cast(e.action.coneSummon.coneAngle) * M_PI / 180.0f; + + for (uint32 radius = 0; radius <= e.action.coneSummon.coneLength; radius += e.action.coneSummon.distanceBetweenRings) + { + float deltaAngle = 0.0f; + if (radius > 0) + deltaAngle = distInARow / radius; + + uint32 count = 1; + if (deltaAngle > 0) + count += coneAngle / deltaAngle; + + float currentAngle = -static_cast(count) * deltaAngle / 2.0f; + + if (e.GetTargetType() == SMART_TARGET_SELF || e.GetTargetType() == SMART_TARGET_NONE) + currentAngle += G3D::fuzzyGt(e.target.o, 0.0f) ? (e.target.o - me->GetOrientation()) : 0.0f; + else if (ObjectList* targets = GetTargets(e, unit)) + { + currentAngle += (me->GetAngle(targets->front()) - me->GetOrientation()); + delete targets; + } + + for (uint32 index = 0; index < count; ++index) + { + Position spawnPosition(*me); + spawnPosition.RelocatePolarOffset(currentAngle, radius); + currentAngle += deltaAngle; + + me->SummonCreature(e.action.coneSummon.summonEntry, spawnPosition, spawnType, e.action.coneSummon.summonDuration); + } + } + + break; + } + case SMART_ACTION_CU_ENCOUNTER_START: + { + ObjectList* targets = GetTargets(e, unit); + if (!targets) + break; + + for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) + { + if (Player* playerTarget = (*itr)->ToPlayer()) + { + playerTarget->RemoveArenaSpellCooldowns(); + playerTarget->RemoveAurasDueToSpell(57724); // Spell Shaman Debuff - Sated (Heroism) + playerTarget->RemoveAurasDueToSpell(57723); // Spell Shaman Debuff - Exhaustion (Bloodlust) + playerTarget->RemoveAurasDueToSpell(2825); // Bloodlust + playerTarget->RemoveAurasDueToSpell(32182); // Heroism + } + } + + delete targets; + break; + } default: sLog->outErrorDb("SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Unhandled Action type %u", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType()); break; @@ -4310,7 +4491,7 @@ void SmartScript::OnUpdate(uint32 const diff) void SmartScript::FillScript(SmartAIEventList e, WorldObject* obj, AreaTrigger const* at) { (void)at; // ensure that the variable is referenced even if extra logs are disabled in order to pass compiler checks - + if (e.empty()) { #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 14e41341a..7cb5a4310 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -870,6 +870,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) if (!IsSpellValid(e, e.action.crossCast.spell)) return false; break; + case SMART_ACTION_CUSTOM_CAST: + if (!IsSpellValid(e, e.action.castCustom.spell)) + return false; + break; case SMART_ACTION_CALL_AREAEXPLOREDOREVENTHAPPENS: case SMART_ACTION_CALL_GROUPEVENTHAPPENS: if (Quest const* qid = sObjectMgr->GetQuestTemplate(e.action.quest.quest)) @@ -1208,6 +1212,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_STOP_MOTION: case SMART_ACTION_NO_ENVIRONMENT_UPDATE: case SMART_ACTION_ZONE_UNDER_ATTACK: + case SMART_ACTION_CONE_SUMMON: + case SMART_ACTION_VORTEX_SUMMON: + case SMART_ACTION_PLAYER_TALK: + case SMART_ACTION_CU_ENCOUNTER_START: break; default: sLog->outErrorDb("SmartAIMgr: Not handled action_type(%u), event_type(%u), Entry %d SourceType %u Event %u, skipped.", e.GetActionType(), e.GetEventType(), e.entryOrGuid, e.GetScriptType(), e.event_id); diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 058ab75d8..7dd060775 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -457,7 +457,7 @@ enum SMART_ACTION SMART_ACTION_EVADE = 24, // No Params SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID - SMART_ACTION_COMBAT_STOP = 27, // + SMART_ACTION_COMBAT_STOP = 27, // SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid (0 removes all auras), charges (0 removes aura) SMART_ACTION_FOLLOW = 29, // Distance (0 = default), Angle (0 = default), EndCreatureEntry, credit, creditType (0monsterkill, 1event) SMART_ACTION_RANDOM_PHASE = 30, // PhaseId1, PhaseId2, PhaseId3... @@ -496,7 +496,7 @@ enum SMART_ACTION SMART_ACTION_SET_COUNTER = 63, // id, value, reset (0/1) SMART_ACTION_STORE_TARGET_LIST = 64, // varID, SMART_ACTION_WP_RESUME = 65, // none - SMART_ACTION_SET_ORIENTATION = 66, // + SMART_ACTION_SET_ORIENTATION = 66, // quick change, random orientation? (0/1) SMART_ACTION_CREATE_TIMED_EVENT = 67, // id, InitialMin, InitialMax, RepeatMin(only if it repeats), RepeatMax(only if it repeats), chance SMART_ACTION_PLAYMOVIE = 68, // entry SMART_ACTION_MOVE_TO_POS = 69, // PointId (optional x,y,z offset), transport, controlled, ContactDistance @@ -590,7 +590,13 @@ enum SMART_ACTION SMART_ACTION_MUSIC = 216, // SoundId, onlySelf, type SMART_ACTION_RANDOM_MUSIC = 217, // SoundId1, SoundId2, SoundId3, SoundId4, onlySelf, type - SMART_ACTION_AC_END = 218, // placeholder + SMART_ACTION_CUSTOM_CAST = 218, // spellId, castflag, bp0, bp1, bp2 + SMART_ACTION_CONE_SUMMON = 219, // entry, duration (0 = perm), dist between rings, dist between earch summon in a row, length of cone, width of cone (angle) + SMART_ACTION_PLAYER_TALK = 220, // acore_string.entry, yell? (0/1) + SMART_ACTION_VORTEX_SUMMON = 221, // entry, duration (0 = perm), spiral scaling, spiral appearance, range max, phi_delta <-- yes confusing math, try it ingame and see, my lovely AC boys! + SMART_ACTION_CU_ENCOUNTER_START = 222, // Resets cooldowns on all targets and removes Heroism debuff(s) + + SMART_ACTION_AC_END = 223, // placeholder }; struct SmartAction @@ -1173,6 +1179,7 @@ struct SmartAction struct { uint32 quickChange; + uint32 random; } orientation; struct @@ -1181,6 +1188,38 @@ struct SmartAction uint32 movementExpired; } stopMotion; + struct + { + uint32 summonEntry; + uint32 summonDuration; + uint32 distanceBetweenRings; + uint32 distanceBetweenSummons; + uint32 coneLength; + uint32 coneAngle; + } coneSummon; + + struct { + uint32 textId; + uint32 flag; + } playerTalk; + + struct { + uint32 spell; + uint32 flags; + uint32 bp1; + uint32 bp2; + uint32 bp3; + } castCustom; + + struct { + uint32 summonEntry; + uint32 summonDuration; + uint32 a; + uint32 k; + uint32 r_max; + uint32 phi_delta; + } summonVortex; + //! Note for any new future actions //! All parameters must have type uint32 diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index ed4e8c236..8155ae362 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -122,7 +122,7 @@ Object::~Object() } void Object::_InitValues() -{ +{ m_uint32Values = new uint32[m_valuesCount]; memset(m_uint32Values, 0, m_valuesCount*sizeof(uint32)); @@ -132,7 +132,7 @@ void Object::_InitValues() } void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh) -{ +{ if (!m_uint32Values) _InitValues(); uint64 guid = MAKE_NEW_GUID(guidlow, entry, guidhigh); @@ -143,7 +143,7 @@ void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh) } std::string Object::_ConcatFields(uint16 startIndex, uint16 size) const -{ +{ std::ostringstream ss; for (uint16 index = 0; index < size; ++index) ss << GetUInt32Value(index + startIndex) << ' '; @@ -151,7 +151,7 @@ std::string Object::_ConcatFields(uint16 startIndex, uint16 size) const } void Object::AddToWorld() -{ +{ if (m_inWorld) return; @@ -164,7 +164,7 @@ void Object::AddToWorld() } void Object::RemoveFromWorld() -{ +{ if (!m_inWorld) return; @@ -175,7 +175,7 @@ void Object::RemoveFromWorld() } void Object::BuildMovementUpdateBlock(UpdateData* data, uint32 flags) const -{ +{ ByteBuffer buf(500); buf << uint8(UPDATETYPE_MOVEMENT); @@ -187,7 +187,7 @@ void Object::BuildMovementUpdateBlock(UpdateData* data, uint32 flags) const } void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const -{ +{ if (!target) return; @@ -246,7 +246,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c } void Object::SendUpdateToPlayer(Player* player) -{ +{ // send create update to player UpdateData upd; WorldPacket packet; @@ -257,7 +257,7 @@ void Object::SendUpdateToPlayer(Player* player) } void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) const -{ +{ ByteBuffer buf(500); buf << (uint8) UPDATETYPE_VALUES; @@ -269,12 +269,12 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) c } void Object::BuildOutOfRangeUpdateBlock(UpdateData* data) const -{ +{ data->AddOutOfRangeGUID(GetGUID()); } void Object::DestroyForPlayer(Player* target, bool onDeath) const -{ +{ ASSERT(target); if (isType(TYPEMASK_UNIT) || isType(TYPEMASK_PLAYER)) @@ -299,7 +299,7 @@ void Object::DestroyForPlayer(Player* target, bool onDeath) const } void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const -{ +{ Unit const* unit = NULL; WorldObject const* object = NULL; @@ -455,7 +455,7 @@ void Object::BuildMovementUpdate(ByteBuffer* data, uint16 flags) const } void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target) const -{ +{ if (!target) return; @@ -482,7 +482,7 @@ void Object::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* targe } void Object::ClearUpdateMask(bool remove) -{ +{ _changesMask.Clear(); if (m_objectUpdated) @@ -494,7 +494,7 @@ void Object::ClearUpdateMask(bool remove) } void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) const -{ +{ UpdateDataMapType::iterator iter = data_map.find(player); if (iter == data_map.end()) @@ -508,7 +508,7 @@ void Object::BuildFieldsUpdate(Player* player, UpdateDataMapType& data_map) cons } uint32 Object::GetUpdateFieldData(Player const* target, uint32*& flags) const -{ +{ uint32 visibleFlag = UF_FLAG_PUBLIC; if (target == this) @@ -561,7 +561,7 @@ uint32 Object::GetUpdateFieldData(Player const* target, uint32*& flags) const } void Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uint32 count) -{ +{ if (data.empty()) return; @@ -578,7 +578,7 @@ void Object::_LoadIntoDataField(std::string const& data, uint32 startOffset, uin } void Object::SetInt32Value(uint16 index, int32 value) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); if (m_int32Values[index] != value) @@ -595,7 +595,7 @@ void Object::SetInt32Value(uint16 index, int32 value) } void Object::SetUInt32Value(uint16 index, uint32 value) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); if (m_uint32Values[index] != value) @@ -612,7 +612,7 @@ void Object::SetUInt32Value(uint16 index, uint32 value) } void Object::UpdateUInt32Value(uint16 index, uint32 value) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); m_uint32Values[index] = value; @@ -620,7 +620,7 @@ void Object::UpdateUInt32Value(uint16 index, uint32 value) } void Object::SetUInt64Value(uint16 index, uint64 value) -{ +{ ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true)); if (*((uint64*)&(m_uint32Values[index])) != value) { @@ -638,7 +638,7 @@ void Object::SetUInt64Value(uint16 index, uint64 value) } bool Object::AddUInt64Value(uint16 index, uint64 value) -{ +{ ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true)); if (value && !*((uint64*)&(m_uint32Values[index]))) { @@ -660,7 +660,7 @@ bool Object::AddUInt64Value(uint16 index, uint64 value) } bool Object::RemoveUInt64Value(uint16 index, uint64 value) -{ +{ ASSERT(index + 1 < m_valuesCount || PrintIndexError(index, true)); if (value && *((uint64*)&(m_uint32Values[index])) == value) { @@ -682,7 +682,7 @@ bool Object::RemoveUInt64Value(uint16 index, uint64 value) } void Object::SetFloatValue(uint16 index, float value) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); if (m_floatValues[index] != value) @@ -699,7 +699,7 @@ void Object::SetFloatValue(uint16 index, float value) } void Object::SetByteValue(uint16 index, uint8 offset, uint8 value) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); if (offset > 3) @@ -723,7 +723,7 @@ void Object::SetByteValue(uint16 index, uint8 offset, uint8 value) } void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); if (offset > 1) @@ -747,7 +747,7 @@ void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value) } void Object::SetStatFloatValue(uint16 index, float value) -{ +{ if (value < 0) value = 0.0f; @@ -755,7 +755,7 @@ void Object::SetStatFloatValue(uint16 index, float value) } void Object::SetStatInt32Value(uint16 index, int32 value) -{ +{ if (value < 0) value = 0; @@ -763,7 +763,7 @@ void Object::SetStatInt32Value(uint16 index, int32 value) } void Object::ApplyModUInt32Value(uint16 index, int32 val, bool apply) -{ +{ int32 cur = GetUInt32Value(index); cur += (apply ? val : -val); if (cur < 0) @@ -772,21 +772,21 @@ void Object::ApplyModUInt32Value(uint16 index, int32 val, bool apply) } void Object::ApplyModInt32Value(uint16 index, int32 val, bool apply) -{ +{ int32 cur = GetInt32Value(index); cur += (apply ? val : -val); SetInt32Value(index, cur); } void Object::ApplyModSignedFloatValue(uint16 index, float val, bool apply) -{ +{ float cur = GetFloatValue(index); cur += (apply ? val : -val); SetFloatValue(index, cur); } void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply) -{ +{ float cur = GetFloatValue(index); cur += (apply ? val : -val); if (cur < 0) @@ -795,7 +795,7 @@ void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply) } void Object::SetFlag(uint16 index, uint32 newFlag) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); uint32 oldval = m_uint32Values[index]; uint32 newval = oldval | newFlag; @@ -814,7 +814,7 @@ void Object::SetFlag(uint16 index, uint32 newFlag) } void Object::RemoveFlag(uint16 index, uint32 oldFlag) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); ASSERT(m_uint32Values); @@ -835,7 +835,7 @@ void Object::RemoveFlag(uint16 index, uint32 oldFlag) } void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); if (offset > 3) @@ -858,7 +858,7 @@ void Object::SetByteFlag(uint16 index, uint8 offset, uint8 newFlag) } void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag) -{ +{ ASSERT(index < m_valuesCount || PrintIndexError(index, true)); if (offset > 3) @@ -881,13 +881,22 @@ void Object::RemoveByteFlag(uint16 index, uint8 offset, uint8 oldFlag) } bool Object::PrintIndexError(uint32 index, bool set) const -{ +{ sLog->outString("Attempt %s non-existed value field: %u (count: %u) for object typeid: %u type mask: %u", (set ? "set value to" : "get value from"), index, m_valuesCount, GetTypeId(), m_objectType); // ASSERT must fail after function call return false; } +void Position::RelocatePolarOffset(float angle, float dist, float z /*= 0.0f*/) +{ + SetOrientation(GetOrientation() + angle); + + m_positionX = GetPositionX() + dist * std::cos(GetOrientation()); + m_positionY = GetPositionY() + dist * std::sin(GetOrientation()); + m_positionZ = GetPositionZ() + z; +} + bool Position::HasInLine(WorldObject const* target, float width) const { if (!HasInArc(M_PI, target)) @@ -985,7 +994,7 @@ void WorldObject::Update(uint32 time_diff) #endif void WorldObject::SetWorldObject(bool on) -{ +{ if (!IsInWorld()) return; @@ -993,7 +1002,7 @@ void WorldObject::SetWorldObject(bool on) } bool WorldObject::IsWorldObject() const -{ +{ if (m_isWorldObject) return true; @@ -1004,7 +1013,7 @@ bool WorldObject::IsWorldObject() const } void WorldObject::setActive(bool on) -{ +{ if (m_isActive == on) return; @@ -1049,13 +1058,13 @@ void WorldObject::SetVisibilityDistanceOverride(bool isVisibilityDistanceOverrid } void WorldObject::CleanupsBeforeDelete(bool /*finalCleanup*/) -{ +{ if (IsInWorld()) RemoveFromWorld(); } void WorldObject::_Create(uint32 guidlow, HighGuid guidhigh, uint32 phaseMask) -{ +{ Object::_Create(guidlow, 0, guidhigh); SetPhaseMask(phaseMask, false); } @@ -1076,13 +1085,13 @@ void WorldObject::GetZoneAndAreaId(uint32& zoneid, uint32& areaid, bool /*forceR } InstanceScript* WorldObject::GetInstanceScript() -{ +{ Map* map = GetMap(); return map->IsDungeon() ? map->ToInstanceMap()->GetInstanceScript() : NULL; } float WorldObject::GetDistanceZ(const WorldObject* obj) const -{ +{ float dz = fabs(GetPositionZ() - obj->GetPositionZ()); float sizefactor = GetObjectSize() + obj->GetObjectSize(); float dist = dz - sizefactor; @@ -1090,7 +1099,7 @@ float WorldObject::GetDistanceZ(const WorldObject* obj) const } bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D) const -{ +{ float sizefactor = GetObjectSize() + obj->GetObjectSize(); float maxdist = dist2compare + sizefactor; @@ -1129,7 +1138,7 @@ Position WorldObject::GetHitSpherePointFor(Position const& dest) const } bool WorldObject::IsWithinLOS(float ox, float oy, float oz, LineOfSightChecks checks) const -{ +{ if (IsInWorld()) { float x, y, z; @@ -1166,7 +1175,7 @@ void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, } bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D /* = true */) const -{ +{ float dx1 = GetPositionX() - obj1->GetPositionX(); float dy1 = GetPositionY() - obj1->GetPositionY(); float distsq1 = dx1*dx1 + dy1*dy1; @@ -1189,7 +1198,7 @@ bool WorldObject::GetDistanceOrder(WorldObject const* obj1, WorldObject const* o } bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D /* = true */) const -{ +{ float dx = GetPositionX() - obj->GetPositionX(); float dy = GetPositionY() - obj->GetPositionY(); float distsq = dx*dx + dy*dy; @@ -1214,7 +1223,7 @@ bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRan } bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) const -{ +{ float dx = GetPositionX() - x; float dy = GetPositionY() - y; float distsq = dx*dx + dy*dy; @@ -1234,7 +1243,7 @@ bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange) } bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float maxRange) const -{ +{ float dx = GetPositionX() - x; float dy = GetPositionY() - y; float dz = GetPositionZ() - z; @@ -1359,23 +1368,23 @@ bool Position::HasInArc(float arc, const Position* obj, float targetRadius) cons float lborder = -1 * (arc/2.0f); // in range -pi..0 float rborder = (arc/2.0f); // in range 0..pi - // pussywizard: take into consideration target size - if (targetRadius > 0.0f) - { - float distSq = GetExactDist2dSq(obj); - // pussywizard: at least a part of target's model is in every direction - if (distSq < targetRadius*targetRadius) - return true; - float angularRadius = 2.0f * atan(targetRadius / (2.0f * sqrt(distSq))); - lborder -= angularRadius; - rborder += angularRadius; + // pussywizard: take into consideration target size + if (targetRadius > 0.0f) + { + float distSq = GetExactDist2dSq(obj); + // pussywizard: at least a part of target's model is in every direction + if (distSq < targetRadius*targetRadius) + return true; + float angularRadius = 2.0f * atan(targetRadius / (2.0f * sqrt(distSq))); + lborder -= angularRadius; + rborder += angularRadius; } return ((angle >= lborder) && (angle <= rborder)); } bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size) const -{ +{ if (!obj1 || !obj2) return false; @@ -1397,17 +1406,17 @@ bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2, } bool WorldObject::isInFront(WorldObject const* target, float arc) const -{ +{ return HasInArc(arc, target); } bool WorldObject::isInBack(WorldObject const* target, float arc) const -{ +{ return !HasInArc(2 * M_PI - arc, target); } void WorldObject::GetRandomPoint(const Position &pos, float distance, float &rand_x, float &rand_y, float &rand_z) const -{ +{ if (!distance) { pos.GetPosition(rand_x, rand_y, rand_z); @@ -1428,14 +1437,14 @@ void WorldObject::GetRandomPoint(const Position &pos, float distance, float &ran } void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const -{ +{ float new_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z /*+ 2.0f*/, true); // pussywizard: +2.0f is added in all inner functions if (new_z > INVALID_HEIGHT) z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface } void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const -{ +{ // TODO: Allow transports to be part of dynamic vmap tree //if (GetTransport()) // return; @@ -1508,7 +1517,7 @@ bool Position::IsPositionValid() const } float WorldObject::GetGridActivationRange() const -{ +{ if (ToPlayer()) return IsInWintergrasp() ? VISIBILITY_DIST_WINTERGRASP : GetMap()->GetVisibilityRange(); else if (ToCreature()) @@ -1520,7 +1529,7 @@ float WorldObject::GetGridActivationRange() const } float WorldObject::GetVisibilityRange() const -{ +{ if (IsVisibilityOverridden() && GetTypeId() == TYPEID_UNIT) return MAX_VISIBILITY_DISTANCE; else if (GetTypeId() == TYPEID_GAMEOBJECT) @@ -1537,7 +1546,7 @@ float WorldObject::GetVisibilityRange() const } float WorldObject::GetSightRange(const WorldObject* target) const -{ +{ if (ToUnit()) { if (ToPlayer()) @@ -1684,7 +1693,7 @@ bool WorldObject::CanNeverSee(WorldObject const* obj) const } bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth, bool checkClient, bool checkAlert) const -{ +{ const WorldObject* seer = this; // Pets don't have detection, they use the detection of their masters @@ -1717,7 +1726,7 @@ bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth, bool che } bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const -{ +{ uint32 mask = obj->m_invisibility.GetFlags() & m_invisibilityDetect.GetFlags(); // xinef: include invisible flags of caster in the mask, 2 invisible objects should be able to detect eachother mask |= obj->m_invisibility.GetFlags() & m_invisibility.GetFlags(); @@ -1759,7 +1768,7 @@ bool WorldObject::CanDetectInvisibilityOf(WorldObject const* obj) const } bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) const -{ +{ // Combat reach is the minimal distance (both in front and behind), // and it is also used in the range calculation. // One stealth point increases the visibility range by 0.3 yard. @@ -1839,7 +1848,7 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj, bool checkAlert) co } void WorldObject::SendPlaySound(uint32 Sound, bool OnlySelf) -{ +{ WorldPacket data(SMSG_PLAY_SOUND, 4); data << Sound; if (OnlySelf && GetTypeId() == TYPEID_PLAYER) @@ -1859,7 +1868,7 @@ void WorldObject::SendPlayMusic(uint32 Music, bool OnlySelf) } void Object::ForceValuesUpdateAtIndex(uint32 i) -{ +{ _changesMask.SetBit(i); if (m_inWorld && !m_objectUpdated) { @@ -1919,7 +1928,7 @@ namespace acore } // namespace acore void WorldObject::MonsterSay(const char* text, uint32 language, WorldObject const* target) -{ +{ CellCoord p = acore::ComputeCellCoord(GetPositionX(), GetPositionY()); Cell cell(p); @@ -1933,7 +1942,7 @@ void WorldObject::MonsterSay(const char* text, uint32 language, WorldObject cons } void WorldObject::MonsterSay(int32 textId, uint32 language, WorldObject const* target) -{ +{ CellCoord p = acore::ComputeCellCoord(GetPositionX(), GetPositionY()); Cell cell(p); @@ -1947,7 +1956,7 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, WorldObject const* t } void WorldObject::MonsterYell(const char* text, uint32 language, WorldObject const* target) -{ +{ CellCoord p = acore::ComputeCellCoord(GetPositionX(), GetPositionY()); Cell cell(p); @@ -1961,7 +1970,7 @@ void WorldObject::MonsterYell(const char* text, uint32 language, WorldObject con } void WorldObject::MonsterYell(int32 textId, uint32 language, WorldObject const* target) -{ +{ CellCoord p = acore::ComputeCellCoord(GetPositionX(), GetPositionY()); Cell cell(p); @@ -1975,7 +1984,7 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, WorldObject const* } void WorldObject::MonsterTextEmote(const char* text, WorldObject const* target, bool IsBossEmote) -{ +{ WorldPacket data; ChatHandler::BuildChatPacket(data, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, LANG_UNIVERSAL, this, target, text); @@ -1983,7 +1992,7 @@ void WorldObject::MonsterTextEmote(const char* text, WorldObject const* target, } void WorldObject::MonsterTextEmote(int32 textId, WorldObject const* target, bool IsBossEmote) -{ +{ CellCoord p = acore::ComputeCellCoord(GetPositionX(), GetPositionY()); Cell cell(p); @@ -1997,7 +2006,7 @@ void WorldObject::MonsterTextEmote(int32 textId, WorldObject const* target, bool } void WorldObject::MonsterWhisper(const char* text, Player const* target, bool IsBossWhisper) -{ +{ if (!target) return; @@ -2008,7 +2017,7 @@ void WorldObject::MonsterWhisper(const char* text, Player const* target, bool Is } void WorldObject::MonsterWhisper(int32 textId, Player const* target, bool IsBossWhisper) -{ +{ if (!target) return; @@ -2028,7 +2037,7 @@ void WorldObject::MonsterWhisper(int32 textId, Player const* target, bool IsBoss } void Unit::BuildHeartBeatMsg(WorldPacket* data) const -{ +{ data->Initialize(MSG_MOVE_HEARTBEAT, 32); data->append(GetPackGUID()); BuildMovementPacket(data); @@ -2036,7 +2045,7 @@ void Unit::BuildHeartBeatMsg(WorldPacket* data) const // pussywizard! void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /*self*/, bool includeMargin, Player const* skipped_rcvr) -{ +{ dist += GetObjectSize(); if (includeMargin) dist += VISIBILITY_COMPENSATION; // pussywizard: to ensure everyone receives all important packets @@ -2045,14 +2054,14 @@ void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /* } void WorldObject::SendObjectDeSpawnAnim(uint64 guid) -{ +{ WorldPacket data(SMSG_GAMEOBJECT_DESPAWN_ANIM, 8); data << uint64(guid); SendMessageToSet(&data, true); } void WorldObject::SetMap(Map* map) -{ +{ ASSERT(map); ASSERT(!IsInWorld() || GetTypeId() == TYPEID_CORPSE); if (m_currMap == map) // command add npc: first create, than loadfromdb @@ -2077,7 +2086,7 @@ void WorldObject::SetMap(Map* map) } void WorldObject::ResetMap() -{ +{ ASSERT(m_currMap); ASSERT(!IsInWorld()); if (IsWorldObject()) @@ -2095,13 +2104,13 @@ void WorldObject::ResetMap() } Map const* WorldObject::GetBaseMap() const -{ +{ ASSERT(m_currMap); return m_currMap->GetParent(); } void WorldObject::AddObjectToRemoveList() -{ +{ ASSERT(m_uint32Values); Map* map = FindMap(); @@ -2115,7 +2124,7 @@ void WorldObject::AddObjectToRemoveList() } TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropertiesEntry const* properties /*= NULL*/, uint32 duration /*= 0*/, Unit* summoner /*= NULL*/, uint32 spellId /*= 0*/, uint32 vehId /*= 0*/) -{ +{ uint32 mask = UNIT_MASK_SUMMON; if (properties) { @@ -2219,7 +2228,7 @@ TempSummon* Map::SummonCreature(uint32 entry, Position const& pos, SummonPropert */ void Map::SummonCreatureGroup(uint8 group, std::list* list /*= NULL*/) -{ +{ std::vector const* data = sObjectMgr->GetSummonGroup(GetId(), SUMMONER_TYPE_MAP, group); if (!data) return; @@ -2231,7 +2240,7 @@ void Map::SummonCreatureGroup(uint8 group, std::list* list /*= NULL } GameObject* Map::SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime, bool checkTransport) -{ +{ GameObjectTemplate const* goinfo = sObjectMgr->GetGameObjectTemplate(entry); if (!goinfo) { @@ -2257,7 +2266,7 @@ GameObject* Map::SummonGameObject(uint32 entry, float x, float y, float z, float } void WorldObject::SetZoneScript() -{ +{ if (Map* map = FindMap()) { if (map->IsDungeon()) @@ -2274,7 +2283,7 @@ void WorldObject::SetZoneScript() } TempSummon* WorldObject::SummonCreature(uint32 entry, const Position &pos, TempSummonType spwtype, uint32 duration, uint32 /*vehId*/, SummonPropertiesEntry const *properties) const -{ +{ if (Map* map = FindMap()) { if (TempSummon* summon = map->SummonCreature(entry, pos, properties, duration, isType(TYPEMASK_UNIT) ? (Unit*)this : NULL)) @@ -2288,7 +2297,7 @@ TempSummon* WorldObject::SummonCreature(uint32 entry, const Position &pos, TempS } GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime, bool checkTransport) -{ +{ if (!IsInWorld()) return NULL; @@ -2323,7 +2332,7 @@ GameObject* WorldObject::SummonGameObject(uint32 entry, float x, float y, float } Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint32 duration, bool setLevel, CreatureAI* (*GetAI)(Creature*)) -{ +{ TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN; Creature* summon = SummonCreature(WORLD_TRIGGER, x, y, z, ang, summonType, duration); if (!summon) @@ -2351,7 +2360,7 @@ Creature* WorldObject::SummonTrigger(float x, float y, float z, float ang, uint3 * @param list List to store pointers to summoned creatures. */ void WorldObject::SummonCreatureGroup(uint8 group, std::list* list /*= NULL*/) -{ +{ ASSERT((GetTypeId() == TYPEID_GAMEOBJECT || GetTypeId() == TYPEID_UNIT) && "Only GOs and creatures can summon npc groups!"); std::vector const* data = sObjectMgr->GetSummonGroup(GetEntry(), GetTypeId() == TYPEID_GAMEOBJECT ? SUMMONER_TYPE_GAMEOBJECT : SUMMONER_TYPE_CREATURE, group); @@ -2365,7 +2374,7 @@ void WorldObject::SummonCreatureGroup(uint8 group, std::list* list } Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive) const -{ +{ Creature* creature = NULL; acore::NearestCreatureEntryWithLiveStateInObjectRangeCheck checker(*this, entry, alive, range); acore::CreatureLastSearcher searcher(this, creature, checker); @@ -2374,7 +2383,7 @@ Creature* WorldObject::FindNearestCreature(uint32 entry, float range, bool alive } GameObject* WorldObject::FindNearestGameObject(uint32 entry, float range) const -{ +{ GameObject* go = NULL; acore::NearestGameObjectEntryInObjectRangeCheck checker(*this, entry, range); acore::GameObjectLastSearcher searcher(this, go, checker); @@ -2383,7 +2392,7 @@ GameObject* WorldObject::FindNearestGameObject(uint32 entry, float range) const } GameObject* WorldObject::FindNearestGameObjectOfType(GameobjectTypes type, float range) const -{ +{ GameObject* go = NULL; acore::NearestGameObjectTypeInObjectRangeCheck checker(*this, type, range); acore::GameObjectLastSearcher searcher(this, go, checker); @@ -2392,7 +2401,7 @@ GameObject* WorldObject::FindNearestGameObjectOfType(GameobjectTypes type, float } Player* WorldObject::SelectNearestPlayer(float distance) const -{ +{ Player* target = NULL; acore::NearestPlayerInObjectRangeCheck checker(this, distance); @@ -2403,7 +2412,7 @@ Player* WorldObject::SelectNearestPlayer(float distance) const } void WorldObject::GetGameObjectListWithEntryInGrid(std::list& gameobjectList, uint32 entry, float maxSearchRange) const -{ +{ CellCoord pair(acore::ComputeCellCoord(this->GetPositionX(), this->GetPositionY())); Cell cell(pair); cell.SetNoCreate(); @@ -2416,7 +2425,7 @@ void WorldObject::GetGameObjectListWithEntryInGrid(std::list& gameo } void WorldObject::GetCreatureListWithEntryInGrid(std::list& creatureList, uint32 entry, float maxSearchRange) const -{ +{ CellCoord pair(acore::ComputeCellCoord(this->GetPositionX(), this->GetPositionY())); Cell cell(pair); cell.SetNoCreate(); @@ -2504,7 +2513,7 @@ namespace acore //=================================================================================================== void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float absAngle) const -{ +{ x = GetPositionX() + (GetObjectSize() + distance2d) * cos(absAngle); y = GetPositionY() + (GetObjectSize() + distance2d) * sin(absAngle); @@ -2513,7 +2522,7 @@ void WorldObject::GetNearPoint2D(float &x, float &y, float distance2d, float abs } void WorldObject::GetNearPoint(WorldObject const* searcher, float &x, float &y, float &z, float searcher_size, float distance2d, float absAngle, float controlZ) const -{ +{ GetNearPoint2D(x, y, distance2d+searcher_size, absAngle); z = GetPositionZ(); if (searcher) @@ -2560,7 +2569,7 @@ void WorldObject::GetVoidClosePoint(float& x, float& y, float& z, float size, fl } bool WorldObject::GetClosePoint(float &x, float &y, float &z, float size, float distance2d, float angle, const WorldObject* forWho, bool force) const -{ +{ // angle calculated from current orientation GetNearPoint(forWho, x, y, z, size, distance2d, GetOrientation() + angle); @@ -2589,7 +2598,7 @@ bool WorldObject::GetClosePoint(float &x, float &y, float &z, float size, float } void WorldObject::GetContactPoint(const WorldObject* obj, float &x, float &y, float &z, float distance2d) const -{ +{ // angle to face `obj` to `this` using distance includes size of `obj` GetNearPoint(obj, x, y, z, obj->GetObjectSize(), distance2d, GetAngle(obj)); @@ -2604,7 +2613,7 @@ void WorldObject::GetContactPoint(const WorldObject* obj, float &x, float &y, fl void WorldObject::GetChargeContactPoint(const WorldObject* obj, float &x, float &y, float &z, float distance2d) const -{ +{ // angle to face `obj` to `this` using distance includes size of `obj` GetNearPoint(obj, x, y, z, obj->GetObjectSize(), distance2d, GetAngle(obj)); @@ -2618,7 +2627,7 @@ void WorldObject::GetChargeContactPoint(const WorldObject* obj, float &x, float } void WorldObject::MovePosition(Position &pos, float dist, float angle) -{ +{ angle += m_orientation; float destx, desty, destz, ground, floor; destx = pos.m_positionX + dist * cos(angle); @@ -2662,7 +2671,7 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle) } void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float angle) -{ +{ angle += m_orientation; float destx, desty, destz; destx = pos.m_positionX + dist * cos(angle); @@ -2763,7 +2772,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float } void WorldObject::MovePositionToFirstCollisionForTotem(Position &pos, float dist, float angle, bool forGameObject) -{ +{ angle += m_orientation; float destx, desty, destz, ground, floor; pos.m_positionZ += 2.0f; @@ -2865,7 +2874,7 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update) } void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/) -{ +{ WorldPacket data(SMSG_PLAY_OBJECT_SOUND, 4+8); data << uint32(sound_id); data << uint64(GetGUID()); @@ -2876,7 +2885,7 @@ void WorldObject::PlayDistanceSound(uint32 sound_id, Player* target /*= NULL*/) } void WorldObject::PlayDirectSound(uint32 sound_id, Player* target /*= NULL*/) -{ +{ WorldPacket data(SMSG_PLAY_SOUND, 4); data << uint32(sound_id); if (target) @@ -2886,7 +2895,7 @@ void WorldObject::PlayDirectSound(uint32 sound_id, Player* target /*= NULL*/) } void WorldObject::DestroyForNearbyPlayers() -{ +{ if (!IsInWorld()) return; @@ -2913,14 +2922,14 @@ void WorldObject::DestroyForNearbyPlayers() } void WorldObject::UpdateObjectVisibility(bool /*forced*/, bool /*fromUpdate*/) -{ +{ //updates object's visibility for nearby players acore::VisibleChangesNotifier notifier(*this); VisitNearbyWorldObject(GetVisibilityRange()+VISIBILITY_COMPENSATION, notifier); } void WorldObject::AddToNotify(uint16 f) -{ +{ if (!(m_notifyflags & f)) if (Unit* u = ToUnit()) { @@ -3019,7 +3028,7 @@ struct WorldObjectChangeAccumulator }; void WorldObject::BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& player_set) -{ +{ CellCoord p = acore::ComputeCellCoord(GetPositionX(), GetPositionY()); Cell cell(p); cell.SetNoCreate(); @@ -3033,7 +3042,7 @@ void WorldObject::BuildUpdate(UpdateDataMapType& data_map, UpdatePlayerSet& play } void WorldObject::GetCreaturesWithEntryInRange(std::list &creatureList, float radius, uint32 entry) -{ +{ CellCoord pair(acore::ComputeCellCoord(this->GetPositionX(), this->GetPositionY())); Cell cell(pair); cell.SetNoCreate(); @@ -3049,7 +3058,7 @@ void WorldObject::GetCreaturesWithEntryInRange(std::list &creatureLis } uint64 WorldObject::GetTransGUID() const -{ +{ if (GetTransport()) return GetTransport()->GetGUID(); return 0; diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index b53f35388..e5167c03c 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -427,6 +427,7 @@ struct Position { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; m_orientation = pos->m_orientation; } + void RelocatePolarOffset(float angle, float dist, float z = 0.0f); void RelocateOffset(const Position &offset); void SetOrientation(float orientation) {