Skip to content

Commit

Permalink
StaticFlags: Implement CreatureTypeFlags from StaticFlags
Browse files Browse the repository at this point in the history
Closes #546
  • Loading branch information
insunaa authored and killerwife committed Jan 5, 2025
1 parent aa6d157 commit b6ff3cf
Show file tree
Hide file tree
Showing 13 changed files with 146 additions and 67 deletions.
2 changes: 1 addition & 1 deletion src/game/AI/BaseAI/CreatureAI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ CreatureAI::CreatureAI(Creature* creature, uint32 combatActions) :
m_creature(creature),
m_deathPrevented(false), m_followAngle(0.f), m_followDist(0.f)
{
m_dismountOnAggro = !(m_creature->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT);
m_dismountOnAggro = !(m_creature->GetCreatureInfo()->HasFlag(CreatureTypeFlags::ALLOW_MOUNTED_COMBAT));
SetMeleeEnabled(!(m_creature->GetSettings().HasFlag(CreatureStaticFlags::NO_MELEE_FLEE)
|| m_creature->GetSettings().HasFlag(CreatureStaticFlags4::NO_MELEE_APPROACH)));
if (m_creature->GetSettings().HasFlag(CreatureStaticFlags::SESSILE))
Expand Down
2 changes: 1 addition & 1 deletion src/game/AI/ScriptDevAI/base/escort_ai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ bool npc_escortAI::AssistPlayerInCombat(Unit* who)
return false;

// experimental (unknown) flag not present
if (!(m_creature->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_CAN_ASSIST))
if (!(m_creature->GetCreatureInfo()->HasFlag(CreatureTypeFlags::CAN_ASSIST)))
return false;

// unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
Expand Down
2 changes: 1 addition & 1 deletion src/game/AI/ScriptDevAI/base/follower_ai.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ bool FollowerAI::AssistPlayerInCombat(Unit* who)
return false;

// experimental (unknown) flag not present
if (!(m_creature->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_CAN_ASSIST))
if (!(m_creature->GetCreatureInfo()->HasFlag(CreatureTypeFlags::CAN_ASSIST)))
return false;

// unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
Expand Down
2 changes: 1 addition & 1 deletion src/game/Entities/Creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2186,7 +2186,7 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
}

// Dead player can see ghosts
if (GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_GHOST_VISIBLE)
if (GetCreatureInfo()->HasFlag(CreatureTypeFlags::VISIBLE_TO_GHOSTS))
return true;

// and not see any other
Expand Down
20 changes: 13 additions & 7 deletions src/game/Entities/Creature.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "Common.h"
#include "Entities/Unit.h"
#include "Globals/SharedDefines.h"
#include "Entities/CreatureDefines.h"
#include "Server/DBCEnums.h"
#include "Util/Util.h"
#include "Entities/CreatureSpellList.h"
Expand Down Expand Up @@ -107,7 +108,7 @@ struct CreatureInfo
uint32 UnitFlags2; // enum UnitFlags2
uint32 DynamicFlags;
uint32 ExtraFlags;
uint32 CreatureTypeFlags; // enum CreatureTypeFlags mask values
uint32 TypeFlags; // enum TypeFlags mask values
uint32 StaticFlags;
uint32 StaticFlags2;
uint32 StaticFlags3;
Expand Down Expand Up @@ -194,29 +195,34 @@ struct CreatureInfo

SkillType GetRequiredLootSkill() const
{
if (CreatureTypeFlags & CREATURE_TYPEFLAGS_HERBLOOT)
if (HasFlag(CreatureTypeFlags::SKIN_WITH_HERBALISM))
return SKILL_HERBALISM;
if (CreatureTypeFlags & CREATURE_TYPEFLAGS_MININGLOOT)
if (HasFlag(CreatureTypeFlags::SKIN_WITH_MINING))
return SKILL_MINING;
if (CreatureTypeFlags & CREATURE_TYPEFLAGS_ENGINEERLOOT)
if (HasFlag(CreatureTypeFlags::SKIN_WITH_ENGINEERING))
return SKILL_ENGINEERING;
return SKILL_SKINNING;
// normal case
}

bool IsExotic() const
{
return (CreatureTypeFlags & CREATURE_TYPEFLAGS_EXOTIC) != 0;
return bool(CreatureTypeFlags(TypeFlags) & CreatureTypeFlags::TAMEABLE_EXOTIC) != 0;
}

bool isTameable(bool exotic) const
{
if (CreatureType != CREATURE_TYPE_BEAST || Family == 0 || (CreatureTypeFlags & CREATURE_TYPEFLAGS_TAMEABLE) == 0)
if (CreatureType != CREATURE_TYPE_BEAST || Family == 0 || !HasFlag(CreatureTypeFlags::TAMEABLE))
return false;

// if can tame exotic then can tame any tameable
return exotic || !IsExotic();
}

bool HasFlag(CreatureTypeFlags flags) const
{
return bool(CreatureTypeFlags(TypeFlags) & flags);
}
};

struct CreatureCooldowns
Expand Down Expand Up @@ -783,7 +789,7 @@ class Creature : public Unit
uint32 GetInteractionPauseTimer() const { return m_interactionPauseTimer; }

GridReference<Creature>& GetGridRef() { return m_gridRef; }
bool IsRegeneratingHealth() const { return (GetCreatureInfo()->RegenerateStats & REGEN_FLAG_HEALTH) != 0 && !(GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_SIEGE_WEAPON); }
bool IsRegeneratingHealth() const { return (GetCreatureInfo()->RegenerateStats & REGEN_FLAG_HEALTH) != 0 && !(GetCreatureInfo()->HasFlag(CreatureTypeFlags::ALLOW_INTERACTION_WHILE_IN_COMBAT)); }
bool IsRegeneratingPower() const;
virtual uint8 GetPetAutoSpellSize() const { return CREATURE_MAX_SPELLS; }
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
Expand Down
38 changes: 38 additions & 0 deletions src/game/Entities/CreatureDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,42 @@ enum class CreatureStaticFlags8 : uint32

DEFINE_ENUM_FLAG(CreatureStaticFlags8);

enum class CreatureTypeFlags : uint32
{
TAMEABLE = 0x00000001, // Tameable by any hunter
VISIBLE_TO_GHOSTS = 0x00000002, // Creatures which can _also_ be seen when player is a ghost, used in CanInteract function by client, can't be attacked
BOSS_MOB = 0x00000004, // "BOSS" flag for tooltips
DO_NOT_PLAY_WOUND_ANIM = 0x00000008,
NO_FACTION_TOOLTIP = 0x00000010, // controls something in client tooltip related to creature faction
MORE_AUDIBLE = 0x00000020, // may be sound related
SPELL_ATTACKABLE = 0x00000040, // may be related to attackable / not attackable creatures with spells, used together with lua_IsHelpfulSpell/lua_IsHarmfulSpell
INTERACT_WHILE_DEAD = 0x00000080, // Creature can be interacted with even if it's dead
SKIN_WITH_HERBALISM = 0x00000100, // Can be looted by herbalist
SKIN_WITH_MINING = 0x00000200, // Can be looted by miner
NO_DEATH_MESSAGE = 0x00000400, // no idea, but it used by client
ALLOW_MOUNTED_COMBAT = 0x00000800, // possibility to attack and cast spells while mounted
CAN_ASSIST = 0x00001000, // Can aid any player (and group) in combat. Typically seen for escorting NPC's
NO_PET_BAR = 0x00002000, // checked from calls in Lua_PetHasActionBar
MASK_UID = 0x00004000, // Lua_UnitGUID, client does guid_low &= 0xFF000000 if this flag is set
SKIN_WITH_ENGINEERING = 0x00008000, // Can be looted by engineer
TAMEABLE_EXOTIC = 0x00010000, // Can be tamed by hunter as exotic pet
USE_MODEL_COLLISION_SIZE = 0x00020000, // related to CreatureDisplayInfo and scaling in some way
ALLOW_INTERACTION_WHILE_IN_COMBAT = 0x00040000, // Related to vehicle/siege weapons
COLLIDE_WITH_MISSILES = 0x00080000, // may be has something to do with missiles
NO_NAME_PLATE = 0x00100000, // no idea, but it used by client, may be related to rendering
DO_NOT_PLAY_MOUNTED_ANIMATIONS = 0x00200000, // may be has something to do with animation (disable animation?)
LINK_ALL = 0x00400000, // this one probably controls some creature visual
INTERACT_ONLY_WITH_CREATOR = 0x00800000, // First seen in 3.2.2. Related to banner/backpack of creature/companion, used in CanInteract function by client
DO_NOT_PLAY_UNIT_EVENT_SOUNDS = 0x01000000, // pet sounds related?
HAS_NO_SHADOW_BLOB = 0x02000000, // this one probably controls some creature visual
TREAT_AS_RAID_UNIT_FOR_HELPFUL_SPELLS = 0x04000000, // creature has no type, or forces creature to be considered as in party, may be related to creature assistance
FORCE_GOSSIP = 0x08000000, // used in Lua_ForceGossip
DO_NOT_SHEATHE = 0x10000000, // no idea, but it used by client
DO_NOT_TARGET_ON_INTERACTION = 0x20000000,
DO_NOT_RENDER_OBJECT_NAME = 0x40000000,
QUEST_BOSS = 0x80000000, // Lua_UnitIsQuestBoss
};

DEFINE_ENUM_FLAG(CreatureTypeFlags);

#endif
4 changes: 2 additions & 2 deletions src/game/Entities/QueryHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recv_data)
data << uint8(0) << uint8(0) << uint8(0); // name2, name3, name4, always empty
data << subName;
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
data << uint32(ci->CreatureTypeFlags); // flags
data << uint32(ci->TypeFlags); // flags
data << uint32(ci->CreatureType); // CreatureType.dbc
data << uint32(ci->Family); // CreatureFamily.dbc
data << uint32(ci->Rank); // Creature Rank (elite, boss, etc)
Expand All @@ -220,7 +220,7 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recv_data)
data << float(ci->PowerMultiplier); // power multiplier
data << uint8(ci->RacialLeader);
for (unsigned int QuestItem : ci->QuestItems)
data << uint32(QuestItem); // itemId[6], quest drop
data << uint32(QuestItem); // itemId[6], quest drop
data << uint32(ci->MovementTemplateId); // CreatureMovementInfo.dbc
SendPacket(data);
DEBUG_LOG("WORLD: Sent SMSG_CREATURE_QUERY_RESPONSE");
Expand Down
30 changes: 14 additions & 16 deletions src/game/Entities/Relations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ bool Unit::IsFriend(const Unit* unit) const
// WotLK+: Special flag overrides reaction
if (GetTypeId() == TYPEID_UNIT)
{
if (static_cast<const Creature*>(this)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_TREAT_AS_IN_RAID)
if (static_cast<const Creature*>(this)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::TREAT_AS_RAID_UNIT_FOR_HELPFUL_SPELLS))
return true;
}
return (GetReactionTo(unit) > REP_NEUTRAL);
Expand Down Expand Up @@ -367,7 +367,7 @@ bool Unit::CanAttack(const Unit* unit) const
// Creatures cannot attack player ghosts, unless it is a specially flagged ghost creature
if (GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && static_cast<const Player*>(unit)->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
{
if (!(static_cast<const Creature*>(this)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_GHOST_VISIBLE))
if (!(static_cast<const Creature*>(this)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::VISIBLE_TO_GHOSTS)))
return false;
}

Expand Down Expand Up @@ -478,7 +478,7 @@ bool Unit::CanAttackNow(const Unit* unit) const
if (IsMounted())
{
// ... unless we are a creature with a special flag
if (GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(this)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT))
if (GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(this)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::ALLOW_MOUNTED_COMBAT)))
return false;
}

Expand Down Expand Up @@ -524,7 +524,7 @@ bool Unit::CanAssist(const Unit* unit, bool ignoreFlags) const
if (GetReactionTo(unit) < REP_FRIENDLY)
{
// ... unless we are a creature with a special flag
if (GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(this)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_TREAT_AS_IN_RAID))
if (GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(this)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::TREAT_AS_RAID_UNIT_FOR_HELPFUL_SPELLS)))
return false;
}

Expand Down Expand Up @@ -566,14 +566,12 @@ bool Unit::CanAssist(const Unit* unit, bool ignoreFlags) const

if (unit->GetTypeId() == TYPEID_UNIT)
{
if (const uint32 flags = static_cast<const Creature*>(unit)->GetCreatureInfo()->CreatureTypeFlags)
{
if (flags & CREATURE_TYPEFLAGS_CAN_ASSIST)
return true;
CreatureInfo const* info = static_cast<const Creature*>(unit)->GetCreatureInfo();
if (info->HasFlag(CreatureTypeFlags::CAN_ASSIST))
return true;

if (flags & CREATURE_TYPEFLAGS_TREAT_AS_IN_RAID)
return true;
}
if (info->HasFlag(CreatureTypeFlags::TREAT_AS_RAID_UNIT_FOR_HELPFUL_SPELLS))
return true;
}
return false;
}
Expand Down Expand Up @@ -668,14 +666,14 @@ bool Unit::CanInteract(const Unit* unit) const
// We can't interact with anyone as a ghost except specially flagged NPCs
if (GetTypeId() == TYPEID_PLAYER && static_cast<const Player*>(this)->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
{
if (unit->GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(unit)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_GHOST_VISIBLE))
if (unit->GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(unit)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::VISIBLE_TO_GHOSTS)))
return false;
}

// WotLK+: personal squire support
if (GetTypeId() == TYPEID_PLAYER && unit->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP) && unit->GetTypeId() == TYPEID_UNIT)
{
if ((static_cast<const Creature*>(unit)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_SQUIRE) && unit->GetOwnerGuid() != GetObjectGuid())
if ((static_cast<const Creature*>(unit)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::INTERACT_ONLY_WITH_CREATOR)) && unit->GetOwnerGuid() != GetObjectGuid())
return false;
}

Expand Down Expand Up @@ -724,7 +722,7 @@ bool Unit::CanInteractNow(const Unit* unit) const
// We can't interact with dead units, unless it's a creature with special flag
if (!unit->IsAlive())
{
if (GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(unit)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_INTERACT_DEAD))
if (GetTypeId() != TYPEID_UNIT || !(static_cast<const Creature*>(unit)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::INTERACT_WHILE_DEAD)))
return false;
}

Expand All @@ -739,7 +737,7 @@ bool Unit::CanInteractNow(const Unit* unit) const
bool interactable = false;

// We can interact with siege weapons in fight
if (!interactable && unit->GetTypeId() == TYPEID_UNIT && (static_cast<const Creature*>(unit)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_SIEGE_WEAPON))
if (!interactable && unit->GetTypeId() == TYPEID_UNIT && (static_cast<const Creature*>(unit)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::ALLOW_INTERACTION_WHILE_IN_COMBAT)))
interactable = true;

// We can interact with UNIT_FLAG2_INTERACT_ANY_REACTION flagged units even in fight
Expand Down Expand Up @@ -1368,7 +1366,7 @@ bool Unit::CanAttackServerside(const Unit* unit, bool ignoreFlagsSource, bool ig
// Creatures cannot attack player ghosts, unless it is a specially flagged ghost creature
if (GetTypeId() == TYPEID_UNIT && unit->GetTypeId() == TYPEID_PLAYER && static_cast<const Player*>(unit)->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST))
{
if (!(static_cast<const Creature*>(this)->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_GHOST_VISIBLE))
if (!(static_cast<const Creature*>(this)->GetCreatureInfo()->HasFlag(CreatureTypeFlags::VISIBLE_TO_GHOSTS)))
return false;
}

Expand Down
Loading

0 comments on commit b6ff3cf

Please sign in to comment.