diff options
9 files changed, 266 insertions, 225 deletions
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 6e771d2761b..1b59c273d52 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -29,13 +29,13 @@ #include <list> -class SpellInfo; - class CreatureAI; +class CreatureGroup; +class Group; class Quest; class Player; +class SpellInfo; class WorldSession; -class CreatureGroup; enum CreatureFlagsExtra { diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h index 3f16ea5f273..164735a56b5 100644 --- a/src/server/game/Entities/GameObject/GameObject.h +++ b/src/server/game/Entities/GameObject/GameObject.h @@ -27,6 +27,7 @@ #include "DatabaseEnv.h" class GameObjectAI; +class Group; #define MAX_GAMEOBJECT_QUEST_ITEMS 6 diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 5b6bf87057f..4ec0a93f71f 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -16,13 +16,13 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "Object.h" #include "Common.h" #include "SharedDefines.h" #include "WorldPacket.h" #include "Opcodes.h" #include "Log.h" #include "World.h" -#include "Object.h" #include "Creature.h" #include "Player.h" #include "Vehicle.h" @@ -204,7 +204,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c if (!target) return; - uint8 updatetype = UPDATETYPE_CREATE_OBJECT; + uint8 updateType = UPDATETYPE_CREATE_OBJECT; uint16 flags = m_updateFlag; /** lower flag1 **/ @@ -215,22 +215,22 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c { // UPDATETYPE_CREATE_OBJECT2 dynamic objects, corpses... if (isType(TYPEMASK_DYNAMICOBJECT) || isType(TYPEMASK_CORPSE) || isType(TYPEMASK_PLAYER)) - updatetype = UPDATETYPE_CREATE_OBJECT2; + updateType = UPDATETYPE_CREATE_OBJECT2; // UPDATETYPE_CREATE_OBJECT2 for pets... if (target->GetPetGUID() == GetGUID()) - updatetype = UPDATETYPE_CREATE_OBJECT2; + updateType = UPDATETYPE_CREATE_OBJECT2; // UPDATETYPE_CREATE_OBJECT2 for some gameobject types... if (isType(TYPEMASK_GAMEOBJECT)) { - switch (((GameObject*)this)->GetGoType()) + switch (ToGameObject()->GetGoType()) { case GAMEOBJECT_TYPE_TRAP: case GAMEOBJECT_TYPE_DUEL_ARBITER: case GAMEOBJECT_TYPE_FLAGSTAND: case GAMEOBJECT_TYPE_FLAGDROP: - updatetype = UPDATETYPE_CREATE_OBJECT2; + updateType = UPDATETYPE_CREATE_OBJECT2; break; case GAMEOBJECT_TYPE_TRANSPORT: flags |= UPDATEFLAG_TRANSPORT; @@ -242,24 +242,24 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c if (isType(TYPEMASK_UNIT)) { - if (((Unit*)this)->getVictim()) + if (ToUnit()->getVictim()) flags |= UPDATEFLAG_HAS_TARGET; } } - //sLog->outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updatetype, m_objectTypeId, flags, flags2); + //sLog->outDebug("BuildCreateUpdate: update-type: %u, object-type: %u got flags: %X, flags2: %X", updateType, m_objectTypeId, flags, flags2); ByteBuffer buf(500); - buf << (uint8)updatetype; + buf << uint8(updateType); buf.append(GetPackGUID()); - buf << (uint8)m_objectTypeId; + buf << uint8(m_objectTypeId); _BuildMovementUpdate(&buf, flags); UpdateMask updateMask; updateMask.SetCount(m_valuesCount); _SetCreateBits(&updateMask, target); - _BuildValuesUpdate(updatetype, &buf, &updateMask, target); + _BuildValuesUpdate(updateType, &buf, &updateMask, target); data->AddUpdateBlock(buf); } @@ -278,7 +278,7 @@ void Object::BuildValuesUpdateBlockForPlayer(UpdateData* data, Player* target) c { ByteBuffer buf(500); - buf << (uint8) UPDATETYPE_VALUES; + buf << uint8(UPDATETYPE_VALUES); buf.append(GetPackGUID()); UpdateMask updateMask; @@ -360,64 +360,73 @@ uint16 Object::GetUInt16Value(uint16 index, uint8 offset) const void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const { + Unit const* unit = NULL; + WorldObject const* object = NULL; + + if (isType(TYPEMASK_UNIT)) + unit = ToUnit(); + else + object = ((WorldObject*)this); + *data << uint16(flags); // update flags // 0x20 if (flags & UPDATEFLAG_LIVING) { - ((Unit*)this)->BuildMovementPacket(data); + unit->BuildMovementPacket(data); - *data << ((Unit*)this)->GetSpeed(MOVE_WALK); - *data << ((Unit*)this)->GetSpeed(MOVE_RUN); - *data << ((Unit*)this)->GetSpeed(MOVE_RUN_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_SWIM); - *data << ((Unit*)this)->GetSpeed(MOVE_SWIM_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT); - *data << ((Unit*)this)->GetSpeed(MOVE_FLIGHT_BACK); - *data << ((Unit*)this)->GetSpeed(MOVE_TURN_RATE); - *data << ((Unit*)this)->GetSpeed(MOVE_PITCH_RATE); + *data << unit->GetSpeed(MOVE_WALK) + << unit->GetSpeed(MOVE_RUN) + << unit->GetSpeed(MOVE_RUN_BACK) + << unit->GetSpeed(MOVE_SWIM) + << unit->GetSpeed(MOVE_SWIM_BACK) + << unit->GetSpeed(MOVE_FLIGHT) + << unit->GetSpeed(MOVE_FLIGHT_BACK) + << unit->GetSpeed(MOVE_TURN_RATE) + << unit->GetSpeed(MOVE_PITCH_RATE); // 0x08000000 - if (((Unit*)this)->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED) - Movement::PacketBuilder::WriteCreate(*((Unit*)this)->movespline, *data); + if (unit->m_movementInfo.GetMovementFlags() & MOVEMENTFLAG_SPLINE_ENABLED) + Movement::PacketBuilder::WriteCreate(*unit->movespline, *data); } else { if (flags & UPDATEFLAG_POSITION) { - Transport* transport = ((WorldObject*)this)->GetTransport(); + Transport* transport = object->GetTransport(); + if (transport) data->append(transport->GetPackGUID()); else *data << uint8(0); - *data << ((WorldObject*)this)->GetPositionX(); - *data << ((WorldObject*)this)->GetPositionY(); + *data << object->GetPositionX(); + *data << object->GetPositionY(); if (isType(TYPEMASK_UNIT)) - *data << ((Unit*)this)->GetPositionZMinusOffset(); + *data << unit->GetPositionZMinusOffset(); else - *data << ((WorldObject*)this)->GetPositionZ(); + *data << object->GetPositionZ(); if (transport) { - *data << ((WorldObject*)this)->GetTransOffsetX(); - *data << ((WorldObject*)this)->GetTransOffsetY(); - *data << ((WorldObject*)this)->GetTransOffsetZ(); + *data << object->GetTransOffsetX(); + *data << object->GetTransOffsetY(); + *data << object->GetTransOffsetZ(); } else { - *data << ((WorldObject*)this)->GetPositionX(); - *data << ((WorldObject*)this)->GetPositionY(); + *data << object->GetPositionX(); + *data << object->GetPositionY(); if (isType(TYPEMASK_UNIT)) - *data << ((Unit*)this)->GetPositionZMinusOffset(); + *data << unit->GetPositionZMinusOffset(); else - *data << ((WorldObject*)this)->GetPositionZ(); + *data << object->GetPositionZ(); } - *data << ((WorldObject*)this)->GetOrientation(); + *data << object->GetOrientation(); if (GetTypeId() == TYPEID_CORPSE) - *data << float(((WorldObject*)this)->GetOrientation()); + *data << float(object->GetOrientation()); else *data << float(0); } @@ -426,13 +435,13 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const // 0x40 if (flags & UPDATEFLAG_STATIONARY_POSITION) { - *data << ((WorldObject*)this)->GetPositionX(); - *data << ((WorldObject*)this)->GetPositionY(); + *data << object->GetPositionX(); + *data << object->GetPositionY(); if (isType(TYPEMASK_UNIT)) - *data << ((Unit*)this)->GetPositionZMinusOffset(); + *data << unit->GetPositionZMinusOffset(); else - *data << ((WorldObject*)this)->GetPositionZ(); - *data << ((WorldObject*)this)->GetOrientation(); + *data << object->GetPositionZ(); + *data << object->GetOrientation(); } } } @@ -476,7 +485,7 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const // 0x4 if (flags & UPDATEFLAG_HAS_TARGET) { - if (Unit* victim = ((Unit*)this)->getVictim()) + if (Unit* victim = unit->getVictim()) data->append(victim->GetPackGUID()); else *data << uint8(0); @@ -492,67 +501,71 @@ void Object::_BuildMovementUpdate(ByteBuffer* data, uint16 flags) const if (flags & UPDATEFLAG_VEHICLE) { /// @todo Allow players to aquire this updateflag. - *data << uint32(((Unit*)this)->GetVehicleKit()->GetVehicleInfo()->m_ID); - *data << float(((Creature*)this)->GetOrientation()); + *data << uint32(unit->GetVehicleKit()->GetVehicleInfo()->m_ID); + *data << float(unit->GetOrientation()); } // 0x200 if (flags & UPDATEFLAG_ROTATION) - { - *data << int64(((GameObject*)this)->GetRotation()); - } + *data << int64(ToGameObject()->GetRotation()); } -void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* updateMask, Player* target) const +void Object::_BuildValuesUpdate(uint8 updateType, ByteBuffer* data, UpdateMask* updateMask, Player* target) const { if (!target) return; bool IsActivateToQuest = false; - if (updatetype == UPDATETYPE_CREATE_OBJECT || updatetype == UPDATETYPE_CREATE_OBJECT2) - { - if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsDynTransport()) - { - if (((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster()) - IsActivateToQuest = true; - if (((GameObject*)this)->GetGoArtKit()) - updateMask->SetBit(GAMEOBJECT_BYTES_1); - } - else if (isType(TYPEMASK_UNIT)) - { - if (((Unit*)this)->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK)) - updateMask->SetBit(UNIT_FIELD_AURASTATE); - } + // Before trying to convert to each type there is a check, so safe + Unit const* unit = ToUnit(); + GameObject const* go = ToGameObject(); + + if (unit) + { + if (unit->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK)) + updateMask->SetBit(UNIT_FIELD_AURASTATE); } - else // case UPDATETYPE_VALUES + else if (go) { - if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport()) + if (updateType == UPDATETYPE_CREATE_OBJECT || updateType == UPDATETYPE_CREATE_OBJECT2) { - if (((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster()) - IsActivateToQuest = true; - - updateMask->SetBit(GAMEOBJECT_BYTES_1); + if (!go->IsDynTransport()) + { + if (go->ActivateToQuest(target) || target->isGameMaster()) + IsActivateToQuest = true; - if (ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_CHEST && ToGameObject()->GetGOInfo()->chest.groupLootRules && - ToGameObject()->HasLootRecipient()) - updateMask->SetBit(GAMEOBJECT_FLAGS); + if (go->GetGoArtKit()) + updateMask->SetBit(GAMEOBJECT_BYTES_1); + } } - else if (isType(TYPEMASK_UNIT)) + else { - if (((Unit*)this)->HasFlag(UNIT_FIELD_AURASTATE, PER_CASTER_AURA_STATE_MASK)) - updateMask->SetBit(UNIT_FIELD_AURASTATE); + if (!go->IsTransport()) + { + if (go->ActivateToQuest(target) || target->isGameMaster()) + IsActivateToQuest = true; + + updateMask->SetBit(GAMEOBJECT_BYTES_1); + + if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST && go->GetGOInfo()->chest.groupLootRules && + go->HasLootRecipient()) + { + updateMask->SetBit(GAMEOBJECT_FLAGS); + } + } } } - WPAssert(updateMask && updateMask->GetCount() == m_valuesCount); + ASSERT(updateMask && updateMask->GetCount() == m_valuesCount); - *data << (uint8)updateMask->GetBlockCount(); + *data << uint8(updateMask->GetBlockCount()); updateMask->AppendToPacket(data); // 2 specialized loops for speed optimization in non-unit case - if (isType(TYPEMASK_UNIT)) // unit (creature/player) case + if (unit) // unit (creature/player) case { + Creature const* creature = ToCreature(); for (uint16 index = 0; index < m_valuesCount; ++index) { if (updateMask->GetBit(index)) @@ -569,7 +582,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* if (appendValue & UNIT_NPC_FLAG_TRAINER) { - if (!this->ToCreature()->isCanTrainingOf(target, false)) + if (!creature->isCanTrainingOf(target, false)) appendValue &= ~(UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS | UNIT_NPC_FLAG_TRAINER_PROFESSION); } } @@ -578,8 +591,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* } else if (index == UNIT_FIELD_AURASTATE) { - // Check per caster aura states to not enable using a pell in client if specified aura is not by target - *data << ((Unit*)this)->BuildAuraStateUpdateForTarget(target); + // Check per caster aura states to not enable using a spell in client if specified aura is not by target + *data << unit->BuildAuraStateUpdateForTarget(target); } // FIXME: Some values at server stored in float format but must be sent to client in uint32 format else if (index >= UNIT_FIELD_BASEATTACKTIME && index <= UNIT_FIELD_RANGEDATTACKTIME) @@ -608,7 +621,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* { if (GetTypeId() == TYPEID_UNIT) { - CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate(); + CreatureTemplate const* cinfo = creature->GetCreatureTemplate(); // this also applies for transform auras if (SpellInfo const* transform = sSpellMgr->GetSpellInfo(ToUnit()->getTransForm())) @@ -648,7 +661,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* { uint32 dynamicFlags = m_uint32Values[index]; - if (Creature const* creature = ToCreature()) + if (creature) { if (creature->hasLootRecipient()) { @@ -673,16 +686,14 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* } // unit UNIT_DYNFLAG_TRACK_UNIT should only be sent to caster of SPELL_AURA_MOD_STALKED auras - if (Unit const* unit = ToUnit()) - if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT) - if (!unit->HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID())) - dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT; + if (dynamicFlags & UNIT_DYNFLAG_TRACK_UNIT) + if (!unit->HasAuraTypeWithCaster(SPELL_AURA_MOD_STALKED, target->GetGUID())) + dynamicFlags &= ~UNIT_DYNFLAG_TRACK_UNIT; *data << dynamicFlags; } // FG: pretend that OTHER players in own group are friendly ("blue") else if (index == UNIT_FIELD_BYTES_2 || index == UNIT_FIELD_FACTIONTEMPLATE) { - Unit const* unit = ToUnit(); if (unit->IsControlledByPlayer() && target != this && sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP) && unit->IsInRaidWith(target)) { FactionTemplateEntry const* ft1 = unit->getFactionTemplateEntry(); @@ -715,7 +726,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* } } } - else if (isType(TYPEMASK_GAMEOBJECT)) // gameobject case + else if (go) // gameobject case { for (uint16 index = 0; index < m_valuesCount; ++index) { @@ -726,7 +737,7 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* { if (IsActivateToQuest) { - switch (ToGameObject()->GetGoType()) + switch (go->GetGoType()) { case GAMEOBJECT_TYPE_CHEST: if (target->isGameMaster()) @@ -766,8 +777,8 @@ void Object::_BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask* else if (index == GAMEOBJECT_FLAGS) { uint32 flags = m_uint32Values[index]; - if (ToGameObject()->GetGoType() == GAMEOBJECT_TYPE_CHEST) - if (ToGameObject()->GetGOInfo()->chest.groupLootRules && !ToGameObject()->IsLootAllowedFor(target)) + if (go->GetGoType() == GAMEOBJECT_TYPE_CHEST) + if (go->GetGOInfo()->chest.groupLootRules && !go->IsLootAllowedFor(target)) flags |= GO_FLAG_LOCKED | GO_FLAG_NOT_SELECTABLE; *data << flags; @@ -1294,6 +1305,14 @@ bool Object::PrintIndexError(uint32 index, bool set) const return false; } +bool Position::operator==(Position const &a) +{ + return (G3D::fuzzyEq(a.m_positionX, m_positionX) && + G3D::fuzzyEq(a.m_positionY, m_positionY) && + G3D::fuzzyEq(a.m_positionZ, m_positionZ) && + G3D::fuzzyEq(a.m_orientation, m_orientation)); +} + bool Position::HasInLine(WorldObject const* target, float width) const { if (!HasInArc(M_PI, target)) @@ -1703,7 +1722,7 @@ void Position::RelocateOffset(const Position & offset) m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + M_PI)); m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation())); m_positionZ = GetPositionZ() + offset.GetPositionZ(); - m_orientation = GetOrientation() + offset.GetOrientation(); + SetOrientation(GetOrientation() + offset.GetOrientation()); } void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const @@ -1714,7 +1733,7 @@ void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation()); retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation()); retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ(); - retOffset.m_orientation = endPos.GetOrientation() - GetOrientation(); + retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation()); } float Position::GetAngle(const Position* obj) const @@ -1755,25 +1774,25 @@ void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) } } -bool Position::HasInArc(float arc, const Position* obj) const +bool Position::HasInArc(float arc, const Position* obj, float border) const { // always have self in arc if (obj == this) return true; // move arc to range 0.. 2*pi - arc = MapManager::NormalizeOrientation(arc); + arc = NormalizeOrientation(arc); float angle = GetAngle(obj); angle -= m_orientation; // move angle to range -pi ... +pi - angle = MapManager::NormalizeOrientation(angle); + angle = NormalizeOrientation(angle); if (angle > M_PI) angle -= 2.0f*M_PI; - float lborder = -1 * (arc/2.0f); // in range -pi..0 - float rborder = (arc/2.0f); // in range 0..pi + float lborder = -1 * (arc/border); // in range -pi..0 + float rborder = (arc/border); // in range 0..pi return ((angle >= lborder) && (angle <= rborder)); } @@ -2037,7 +2056,7 @@ bool WorldObject::CanDetect(WorldObject const* obj, bool ignoreStealth) const const WorldObject* seer = this; // Pets don't have detection, they use the detection of their masters - if (const Unit* thisUnit = ToUnit()) + if (Unit const* thisUnit = ToUnit()) if (Unit* controller = thisUnit->GetCharmerOrOwner()) seer = controller; @@ -2096,8 +2115,9 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const float distance = GetExactDist(obj); float combatReach = 0.0f; - if (isType(TYPEMASK_UNIT)) - combatReach = ((Unit*)this)->GetCombatReach(); + Unit const* unit = ToUnit(); + if (unit) + combatReach = unit->GetCombatReach(); if (distance < combatReach) return true; @@ -2105,14 +2125,14 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const if (!HasInArc(M_PI, obj)) return false; + GameObject const* go = ToGameObject(); for (uint32 i = 0; i < TOTAL_STEALTH_TYPES; ++i) { if (!(obj->m_stealth.GetFlags() & (1 << i))) continue; - if (isType(TYPEMASK_UNIT)) - if (((Unit*)this)->HasAuraTypeWithMiscvalue(SPELL_AURA_DETECT_STEALTH, i)) - return true; + if (unit && unit->HasAuraTypeWithMiscvalue(SPELL_AURA_DETECT_STEALTH, i)) + return true; // Starting points int32 detectionValue = 30; @@ -2124,8 +2144,8 @@ bool WorldObject::CanDetectStealthOf(WorldObject const* obj) const // Apply modifiers detectionValue += m_stealthDetect.GetValue(StealthType(i)); - if (obj->isType(TYPEMASK_GAMEOBJECT)) - if (Unit* owner = ((GameObject*)obj)->GetOwner()) + if (go) + if (Unit* owner = go->GetOwner()) detectionValue -= int32(owner->getLevelForTarget(this) - 1) * 5; detectionValue -= obj->m_stealth.GetValue(StealthType(i)); @@ -2955,7 +2975,7 @@ float WorldObject::GetObjectSize() const void WorldObject::MovePosition(Position &pos, float dist, float angle) { - angle += m_orientation; + angle += GetOrientation(); float destx, desty, destz, ground, floor; destx = pos.m_positionX + dist * std::cos(angle); desty = pos.m_positionY + dist * std::sin(angle); @@ -3000,7 +3020,7 @@ void WorldObject::MovePosition(Position &pos, float dist, float angle) void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float angle) { - angle += m_orientation; + angle += GetOrientation(); float destx, desty, destz, ground, floor; pos.m_positionZ += 2.0f; destx = pos.m_positionX + dist * std::cos(angle); @@ -3063,7 +3083,7 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float Trinity::NormalizeMapCoord(pos.m_positionX); Trinity::NormalizeMapCoord(pos.m_positionY); UpdateAllowedPositionZ(pos.m_positionX, pos.m_positionY, pos.m_positionZ); - pos.m_orientation = m_orientation; + pos.SetOrientation(GetOrientation()); } void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update) diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index 6c54ccfbdf7..70a7bcd7f39 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -21,10 +21,8 @@ #include "Common.h" #include "UpdateMask.h" -#include "UpdateData.h" #include "GridReference.h" #include "ObjectDefines.h" -#include "GridDefines.h" #include "Map.h" #include <set> @@ -101,20 +99,21 @@ enum NotifyFlags NOTIFY_ALL = 0xFF }; -class WorldPacket; -class UpdateData; -class ByteBuffer; -class WorldSession; +class Corpse; class Creature; -class Player; -class InstanceScript; +class CreatureAI; +class DynamicObject; class GameObject; +class Map; +class InstanceScript; +class Player; class TempSummon; -class Vehicle; -class CreatureAI; -class ZoneScript; -class Unit; class Transport; +class Unit; +class UpdateData; +class WorldObject; +class WorldPacket; +class ZoneScript; typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType; @@ -225,6 +224,9 @@ class Object Corpse* ToCorpse() { if (GetTypeId() == TYPEID_CORPSE) return reinterpret_cast<Corpse*>(this); else return NULL; } Corpse const* ToCorpse() const { if (GetTypeId() == TYPEID_CORPSE) return reinterpret_cast<Corpse const*>(this); else return NULL; } + DynamicObject* ToDynObject() { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject*>(this); else return NULL; } + DynamicObject const* ToDynObject() const { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject const*>(this); else return NULL; } + protected: Object(); @@ -288,21 +290,31 @@ struct Position float m_positionX; float m_positionY; float m_positionZ; +// Better to limit access to m_orientation field, but this will be hard to achieve with many scripts using array initialization for this structure +//private: float m_orientation; +//public: + + bool operator==(Position const &a); + + inline bool operator!=(Position const &a) + { + return !(operator==(a)); + } void Relocate(float x, float y) { m_positionX = x; m_positionY = y;} void Relocate(float x, float y, float z) { m_positionX = x; m_positionY = y; m_positionZ = z; } void Relocate(float x, float y, float z, float orientation) - { m_positionX = x; m_positionY = y; m_positionZ = z; m_orientation = orientation; } - void Relocate(const Position &pos) - { m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; m_orientation = pos.m_orientation; } - void Relocate(const Position* pos) - { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; m_orientation = pos->m_orientation; } - void RelocateOffset(const Position &offset); + { m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation); } + void Relocate(Position const &pos) + { m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos.m_orientation); } + void Relocate(Position const* pos) + { m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->m_orientation); } + void RelocateOffset(Position const &offset); void SetOrientation(float orientation) - { m_orientation = orientation; } + { m_orientation = NormalizeOrientation(orientation); } float GetPositionX() const { return m_positionX; } float GetPositionY() const { return m_positionY; } @@ -336,39 +348,54 @@ struct Position { float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy; } float GetExactDist2d(const float x, const float y) const { return sqrt(GetExactDist2dSq(x, y)); } - float GetExactDist2dSq(const Position* pos) const + float GetExactDist2dSq(Position const* pos) const { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy; } - float GetExactDist2d(const Position* pos) const + float GetExactDist2d(Position const* pos) const { return sqrt(GetExactDist2dSq(pos)); } float GetExactDistSq(float x, float y, float z) const { float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz; } float GetExactDist(float x, float y, float z) const { return sqrt(GetExactDistSq(x, y, z)); } - float GetExactDistSq(const Position* pos) const + float GetExactDistSq(Position const* pos) const { float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz; } - float GetExactDist(const Position* pos) const + float GetExactDist(Position const* pos) const { return sqrt(GetExactDistSq(pos)); } - void GetPositionOffsetTo(const Position & endPos, Position & retOffset) const; + void GetPositionOffsetTo(Position const & endPos, Position & retOffset) const; - float GetAngle(const Position* pos) const; + float GetAngle(Position const* pos) const; float GetAngle(float x, float y) const; - float GetRelativeAngle(const Position* pos) const + float GetRelativeAngle(Position const* pos) const { return GetAngle(pos) - m_orientation; } float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - m_orientation; } void GetSinCos(float x, float y, float &vsin, float &vcos) const; bool IsInDist2d(float x, float y, float dist) const { return GetExactDist2dSq(x, y) < dist * dist; } - bool IsInDist2d(const Position* pos, float dist) const + bool IsInDist2d(Position const* pos, float dist) const { return GetExactDist2dSq(pos) < dist * dist; } bool IsInDist(float x, float y, float z, float dist) const { return GetExactDistSq(x, y, z) < dist * dist; } - bool IsInDist(const Position* pos, float dist) const + bool IsInDist(Position const* pos, float dist) const { return GetExactDistSq(pos) < dist * dist; } - bool HasInArc(float arcangle, const Position* pos) const; + bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const; bool HasInLine(WorldObject const* target, float width) const; std::string ToString() const; + + // modulos a radian orientation to the range of 0..2PI + static float NormalizeOrientation(float o) + { + // fmod only supports positive numbers. Thus we have + // to emulate negative numbers + if (o < 0) + { + float mod = o *-1; + mod = fmod(mod, 2.0f * static_cast<float>(M_PI)); + mod = -mod + 2.0f * static_cast<float>(M_PI); + return mod; + } + return fmod(o, 2.0f * static_cast<float>(M_PI)); + } }; ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer); ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer); @@ -378,39 +405,31 @@ ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& st struct MovementInfo { // common - uint64 guid; - uint32 flags; - uint16 flags2; + uint64 guid; + uint32 flags; + uint16 flags2; Position pos; - uint32 time; + uint32 time; // transport - uint64 t_guid; + uint64 t_guid; Position t_pos; - uint32 t_time; - uint32 t_time2; - int8 t_seat; + int8 t_seat; + uint32 t_time; + uint32 t_time2; // swimming/flying - float pitch; + float pitch; // falling - uint32 fallTime; + uint32 fallTime; // jumping - float j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed; + float j_zspeed, j_sinAngle, j_cosAngle, j_xyspeed; // spline - float splineElevation; + float splineElevation; - MovementInfo() - { - pos.Relocate(0, 0, 0, 0); - guid = 0; - flags = 0; - flags2 = 0; - time = t_time = t_time2 = fallTime = 0; - splineElevation = 0; - pitch = j_zspeed = j_sinAngle = j_cosAngle = j_xyspeed = 0.0f; - t_guid = 0; - t_pos.Relocate(0, 0, 0, 0); - t_seat = -1; - } + MovementInfo() : + guid(), flags(), flags2(), pos(), time(), t_guid(), t_pos(), + t_seat(-1), t_time(), t_time2(), pitch(), fallTime(), + j_zspeed(), j_sinAngle(), j_cosAngle(), j_xyspeed() + { } uint32 GetMovementFlags() const { return flags; } void SetMovementFlags(uint32 flag) { flags = flag; } @@ -498,14 +517,14 @@ class WorldObject : public Object, public WorldLocation void MovePositionToFirstCollision(Position &pos, float dist, float angle); void GetFirstCollisionPosition(Position &pos, float dist, float angle); void GetRandomNearPosition(Position &pos, float radius); - void GetContactPoint(const WorldObject* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const; + void GetContactPoint(WorldObject const* obj, float &x, float &y, float &z, float distance2d = CONTACT_DISTANCE) const; float GetObjectSize() const; void UpdateGroundPositionZ(float x, float y, float &z) const; void UpdateAllowedPositionZ(float x, float y, float &z) const; - void GetRandomPoint(const Position &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const; - void GetRandomPoint(const Position &srcPos, float distance, Position &pos) const; + void GetRandomPoint(Position const &srcPos, float distance, float &rand_x, float &rand_y, float &rand_z) const; + void GetRandomPoint(Position const &srcPos, float distance, Position &pos) const; uint32 GetInstanceId() const { return m_InstanceId; } @@ -525,24 +544,24 @@ class WorldObject : public Object, public WorldLocation virtual std::string const& GetNameForLocaleIdx(LocaleConstant /*locale_idx*/) const { return m_name; } - float GetDistance(const WorldObject* obj) const; - float GetDistance(const Position &pos) const; + float GetDistance(WorldObject const* obj) const; + float GetDistance(Position const &pos) const; float GetDistance(float x, float y, float z) const; - float GetDistance2d(const WorldObject* obj) const; + float GetDistance2d(WorldObject const* obj) const; float GetDistance2d(float x, float y) const; - float GetDistanceZ(const WorldObject* obj) const; + float GetDistanceZ(WorldObject const* obj) const; - bool IsSelfOrInSameMap(const WorldObject* obj) const; - bool IsInMap(const WorldObject* obj) const; + bool IsSelfOrInSameMap(WorldObject const* obj) const; + bool IsInMap(WorldObject const* obj) const; bool IsWithinDist3d(float x, float y, float z, float dist) const; - bool IsWithinDist3d(const Position* pos, float dist) const; + bool IsWithinDist3d(Position const* pos, float dist) const; bool IsWithinDist2d(float x, float y, float dist) const; - bool IsWithinDist2d(const Position* pos, float dist) const; + bool IsWithinDist2d(Position const* pos, float dist) const; // use only if you will sure about placing both object at same map bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true) const; bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true) const; bool IsWithinLOS(float x, float y, float z) const; - bool IsWithinLOSInMap(const WorldObject* obj) const; + bool IsWithinLOSInMap(WorldObject const* obj) const; bool GetDistanceOrder(WorldObject const* obj1, WorldObject const* obj2, bool is3D = true) const; bool IsInRange(WorldObject const* obj, float minRange, float maxRange, bool is3D = true) const; bool IsInRange2d(float x, float y, float minRange, float maxRange) const; @@ -550,7 +569,7 @@ class WorldObject : public Object, public WorldLocation bool isInFront(WorldObject const* target, float arc = M_PI) const; bool isInBack(WorldObject const* target, float arc = M_PI) const; - bool IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size = 0) const; + bool IsInBetween(WorldObject const* obj1, WorldObject const* obj2, float size = 0) const; virtual void CleanupsBeforeDelete(bool finalCleanup = true); // used in destructor or explicitly before mass creature delete to remove cross-references to already deleted units @@ -581,7 +600,7 @@ class WorldObject : public Object, public WorldLocation float GetGridActivationRange() const; float GetVisibilityRange() const; - float GetSightRange(const WorldObject* target = NULL) const; + float GetSightRange(WorldObject const* target = NULL) const; bool canSeeOrDetect(WorldObject const* obj, bool ignoreStealth = false, bool distanceCheck = false) const; FlaggedValuesArray32<int32, uint32, StealthType, TOTAL_STEALTH_TYPES> m_stealth; @@ -608,7 +627,7 @@ class WorldObject : public Object, public WorldLocation void SetZoneScript(); ZoneScript* GetZoneScript() const { return m_zoneScript; } - TempSummon* SummonCreature(uint32 id, const Position &pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0) const; + TempSummon* SummonCreature(uint32 id, Position const &pos, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0, uint32 vehId = 0) const; TempSummon* SummonCreature(uint32 id, float x, float y, float z, float ang = 0, TempSummonType spwtype = TEMPSUMMON_MANUAL_DESPAWN, uint32 despwtime = 0) const; GameObject* SummonGameObject(uint32 entry, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 respawnTime); Creature* SummonTrigger(float x, float y, float z, float ang, uint32 dur, CreatureAI* (*GetAI)(Creature*) = NULL); @@ -710,13 +729,13 @@ namespace Trinity class ObjectDistanceOrderPred { public: - ObjectDistanceOrderPred(const WorldObject* pRefObj, bool ascending = true) : m_refObj(pRefObj), m_ascending(ascending) {} - bool operator()(const WorldObject* pLeft, const WorldObject* pRight) const + ObjectDistanceOrderPred(WorldObject const* pRefObj, bool ascending = true) : m_refObj(pRefObj), m_ascending(ascending) {} + bool operator()(WorldObject const* pLeft, WorldObject const* pRight) const { return m_ascending ? m_refObj->GetDistanceOrder(pLeft, pRight) : !m_refObj->GetDistanceOrder(pLeft, pRight); } private: - const WorldObject* m_refObj; + WorldObject const* m_refObj; const bool m_ascending; }; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 87ca7a6c62b..bf73feeae16 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9934,7 +9934,7 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin AddPct(DoneTotalMod, (*i)->GetAmount()); // done scripted mod (take it from owner) - Unit const * const owner = GetOwner() ? GetOwner() : this; + Unit const* owner = GetOwner() ? GetOwner() : this; AuraEffectList const& mOverrideClassScript= owner->GetAuraEffectsByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS); for (AuraEffectList::const_iterator i = mOverrideClassScript.begin(); i != mOverrideClassScript.end(); ++i) { diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 49df2659433..4896f29d205 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -19,6 +19,7 @@ #ifndef __UNIT_H #define __UNIT_H +#include "DBCStructure.h" #include "EventProcessor.h" #include "FollowerReference.h" #include "FollowerRefManager.h" diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp index 38f02622e5a..0a6c09093f1 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp @@ -672,7 +672,7 @@ public: if (Creature* Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), float(rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000)) { - Cyclone->ToCreature()->SetObjectScale(3.0f); + Cyclone->SetObjectScale(3.0f); Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); Cyclone->setFaction(me->getFaction()); Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp index 2cfe73ea719..a13d91e8bff 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -164,24 +164,24 @@ class boss_warchief_kargath_bladefist : public CreatureScript { for (std::vector<uint64>::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) { - Unit* temp = Unit::GetUnit(*me, *itr); - if (temp && temp->isAlive()) + Creature* creature = Unit::GetCreature(*me, *itr); + if (creature && creature->isAlive()) { - temp->GetMotionMaster()->Clear(true); - me->DealDamage(temp, temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - temp->ToCreature()->RemoveCorpse(); + creature->GetMotionMaster()->Clear(true); + me->DealDamage(creature, creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + creature->RemoveCorpse(); } } adds.clear(); for (std::vector<uint64>::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) { - Unit* temp = Unit::GetUnit(*me, *itr); - if (temp && temp->isAlive()) + Creature* creature = Unit::GetCreature(*me, *itr); + if (creature && creature->isAlive()) { - temp->GetMotionMaster()->Clear(true); - me->DealDamage(temp, temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - temp->ToCreature()->RemoveCorpse(); + creature->GetMotionMaster()->Clear(true); + me->DealDamage(creature, creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + creature->RemoveCorpse(); } } assassins.clear(); diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp index 95ba9476905..4af11191708 100644 --- a/src/server/scripts/Outland/zone_shattrath_city.cpp +++ b/src/server/scripts/Outland/zone_shattrath_city.cpp @@ -474,16 +474,16 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->setFaction(1194); - if (Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) + if (Creature* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) { - Creepjack->ToCreature()->AI()->EnterEvadeMode(); + Creepjack->AI()->EnterEvadeMode(); Creepjack->setFaction(1194); Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } - if (Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20)) + if (Creature* Malone = me->FindNearestCreature(NPC_MALONE, 20)) { - Malone->ToCreature()->AI()->EnterEvadeMode(); + Malone->AI()->EnterEvadeMode(); Malone->setFaction(1194); Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } @@ -521,31 +521,31 @@ public: { if (Event) SayTimer = NextStep(++Step); - } else SayTimer -= diff; + } + else + SayTimer -= diff; if (Attack) { - Player* player = Unit::GetPlayer(*me, PlayerGUID); me->setFaction(14); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (player) - { - Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20); - if (Creepjack) - { - Creepjack->Attack(player, true); - Creepjack->setFaction(14); - Creepjack->GetMotionMaster()->MoveChase(player); - Creepjack->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20); - if (Malone) + if (Player* player = Unit::GetPlayer(*me, PlayerGUID)) { - Malone->Attack(player, true); - Malone->setFaction(14); - Malone->GetMotionMaster()->MoveChase(player); - Malone->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } + if (Creature* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) + { + Creepjack->Attack(player, true); + Creepjack->setFaction(14); + Creepjack->GetMotionMaster()->MoveChase(player); + Creepjack->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + if (Creature* Malone = me->FindNearestCreature(NPC_MALONE, 20)) + { + Malone->Attack(player, true); + Malone->setFaction(14); + Malone->GetMotionMaster()->MoveChase(player); + Malone->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } DoStartMovement(player); AttackStart(player); } @@ -557,17 +557,17 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); me->RemoveAllAuras(); - if (Unit* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) + if (Creature* Creepjack = me->FindNearestCreature(NPC_CREEPJACK, 20)) { - Creepjack->ToCreature()->AI()->EnterEvadeMode(); + Creepjack->AI()->EnterEvadeMode(); Creepjack->setFaction(1194); Creepjack->GetMotionMaster()->MoveTargetedHome(); Creepjack->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); } - if (Unit* Malone = me->FindNearestCreature(NPC_MALONE, 20)) + if (Creature* Malone = me->FindNearestCreature(NPC_MALONE, 20)) { - Malone->ToCreature()->AI()->EnterEvadeMode(); + Malone->AI()->EnterEvadeMode(); Malone->setFaction(1194); Malone->GetMotionMaster()->MoveTargetedHome(); Malone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); |
