Merge branch 'master' into Playerbot

# Conflicts:
#	src/server/apps/worldserver/worldserver.conf.dist
#	src/server/game/Battlegrounds/Battleground.h
#	src/server/game/Entities/Player/Player.cpp
#	src/server/game/World/World.cpp
This commit is contained in:
郑佩茹
2022-07-13 10:31:30 -06:00
123 changed files with 6889 additions and 1214 deletions

View File

@@ -284,6 +284,8 @@ void Creature::AddToWorld()
GetZoneScript()->OnCreatureCreate(this);
}
loot.sourceWorldObjectGUID = GetGUID();
sScriptMgr->OnCreatureAddWorld(this);
}
}
@@ -3438,7 +3440,7 @@ bool Creature::IsMovementPreventedByCasting() const
{
Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL];
// first check if currently a movement allowed channel is active and we're not casting
if (spell && spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive() && spell->GetSpellInfo()->IsMoveAllowedChannel())
if (spell && spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive() && spell->GetSpellInfo()->IsActionAllowedChannel())
{
return false;
}

View File

@@ -383,8 +383,6 @@ public:
void ModifyThreatPercentTemp(Unit* victim, int32 percent, Milliseconds duration);
void ResetFaction() { SetFaction(GetCreatureTemplate()->faction); }
protected:
bool CreateFromProto(ObjectGuid::LowType guidlow, uint32 Entry, uint32 vehId, const CreatureData* data = nullptr);
bool InitEntry(uint32 entry, const CreatureData* data = nullptr);

View File

@@ -29,6 +29,7 @@ GossipMenu::GossipMenu()
{
_menuId = 0;
_locale = DEFAULT_LOCALE;
_senderGUID.Clear();
}
GossipMenu::~GossipMenu()
@@ -188,8 +189,10 @@ void PlayerMenu::ClearMenus()
_questMenu.ClearMenu();
}
void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID) const
void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID)
{
_gossipMenu.SetSenderGUID(objectGUID);
WorldPacket data(SMSG_GOSSIP_MESSAGE, 24 + _gossipMenu.GetMenuItemCount() * 100 + _questMenu.GetMenuItemCount() * 75); // guess size
data << objectGUID;
data << uint32(_gossipMenu.GetMenuId()); // new 2.4.0
@@ -234,8 +237,10 @@ void PlayerMenu::SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID) const
_session->SendPacket(&data);
}
void PlayerMenu::SendCloseGossip() const
void PlayerMenu::SendCloseGossip()
{
_gossipMenu.SetSenderGUID(ObjectGuid::Empty);
WorldPacket data(SMSG_GOSSIP_COMPLETE, 0);
_session->SendPacket(&data);
}

View File

@@ -213,11 +213,15 @@ public:
return _menuItems;
}
void SetSenderGUID(ObjectGuid guid) { _senderGUID = guid; }
[[nodiscard]] ObjectGuid GetSenderGUID() const { return _senderGUID; }
private:
GossipMenuItemContainer _menuItems;
GossipMenuItemDataContainer _menuItemData;
uint32 _menuId;
LocaleConstant _locale;
ObjectGuid _senderGUID;
};
class QuestMenu
@@ -266,8 +270,8 @@ public:
[[nodiscard]] uint32 GetGossipOptionAction(uint32 selection) const { return _gossipMenu.GetMenuItemAction(selection); }
[[nodiscard]] bool IsGossipOptionCoded(uint32 selection) const { return _gossipMenu.IsMenuItemCoded(selection); }
void SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID) const;
void SendCloseGossip() const;
void SendGossipMenu(uint32 titleTextId, ObjectGuid objectGUID);
void SendCloseGossip();
void SendPointOfInterest(uint32 poiId) const;
/*********************************************************/

View File

@@ -159,6 +159,8 @@ void GameObject::AddToWorld()
WorldObject::AddToWorld();
loot.sourceWorldObjectGUID = GetGUID();
sScriptMgr->OnGameObjectAddWorld(this);
}
}
@@ -2054,20 +2056,19 @@ void GameObject::CastSpell(Unit* target, uint32 spellId)
if (!spellInfo)
return;
bool self = false;
bool self = true;
for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
{
if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER)
if (spellInfo->Effects[i].TargetA.GetReferenceType() != TARGET_REFERENCE_TYPE_CASTER || spellInfo->Effects[i].TargetB.GetTarget())
{
self = true;
self = false;
break;
}
}
if (self)
if (self && target && target->GetGUID() != GetGUID())
{
if (target)
target->CastSpell(target, spellInfo, true);
target->CastSpell(target, spellInfo, true);
return;
}

View File

@@ -60,9 +60,9 @@ enum ItemModType
ITEM_MOD_EXPERTISE_RATING = 37,
ITEM_MOD_ATTACK_POWER = 38,
ITEM_MOD_RANGED_ATTACK_POWER = 39,
//ITEM_MOD_FERAL_ATTACK_POWER = 40, not in 3.3
ITEM_MOD_SPELL_HEALING_DONE = 41, // deprecated
ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
//ITEM_MOD_FERAL_ATTACK_POWER = 40, not in 3.3
ITEM_MOD_SPELL_HEALING_DONE = 41, // deprecated
ITEM_MOD_SPELL_DAMAGE_DONE = 42, // deprecated
ITEM_MOD_MANA_REGENERATION = 43,
ITEM_MOD_ARMOR_PENETRATION_RATING = 44,
ITEM_MOD_SPELL_POWER = 45,
@@ -75,7 +75,7 @@ enum ItemModType
enum ItemSpelltriggerType
{
ITEM_SPELLTRIGGER_ON_USE = 0, // use after equip cooldown
ITEM_SPELLTRIGGER_ON_USE = 0, // use after equip cooldown
ITEM_SPELLTRIGGER_ON_EQUIP = 1,
ITEM_SPELLTRIGGER_CHANCE_ON_HIT = 2,
ITEM_SPELLTRIGGER_SOULSTONE = 4,
@@ -85,20 +85,20 @@ enum ItemSpelltriggerType
* other hand the item is destroyed if the aura is removed ("removed on
* death" of spell 57348 makes me think so)
*/
ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5, // no equip cooldown
ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6 // used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1
ITEM_SPELLTRIGGER_ON_NO_DELAY_USE = 5, // no equip cooldown
ITEM_SPELLTRIGGER_LEARN_SPELL_ID = 6 // used in item_template.spell_2 with spell_id with SPELL_GENERIC_LEARN in spell_1
};
#define MAX_ITEM_SPELLTRIGGER 7
enum ItemBondingType
{
NO_BIND = 0,
BIND_WHEN_PICKED_UP = 1,
BIND_WHEN_EQUIPED = 2,
BIND_WHEN_USE = 3,
BIND_QUEST_ITEM = 4,
BIND_QUEST_ITEM1 = 5 // not used in game
NO_BIND = 0,
BIND_WHEN_PICKED_UP = 1,
BIND_WHEN_EQUIPED = 2,
BIND_WHEN_USE = 3,
BIND_QUEST_ITEM = 4,
BIND_QUEST_ITEM1 = 5 // not used in game
};
#define MAX_BIND_TYPE 6
@@ -597,7 +597,7 @@ struct _ItemStat
};
struct _Spell
{
int32 SpellId; // id from Spell.dbc
int32 SpellId; // id from Spell.dbc
uint32 SpellTrigger;
int32 SpellCharges;
float SpellPPMRate;
@@ -701,7 +701,7 @@ struct ItemTemplate
uint32 MinMoneyLoot;
uint32 MaxMoneyLoot;
uint32 FlagsCu;
WorldPacket queryData; // pussywizard
WorldPacket queryData; // pussywizard
// helpers
[[nodiscard]] bool HasSignature() const

View File

@@ -1230,9 +1230,9 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
return distsq < maxdist * maxdist;
}
Position WorldObject::GetHitSpherePointFor(Position const& dest) const
Position WorldObject::GetHitSpherePointFor(Position const& dest, Optional<float> collisionHeight) const
{
G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight());
G3D::Vector3 vThis(GetPositionX(), GetPositionY(), GetPositionZ() + (collisionHeight ? *collisionHeight : GetCollisionHeight()));
G3D::Vector3 vObj(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ());
G3D::Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * std::min(dest.GetExactDist(this), GetCombatReach());
@@ -1341,7 +1341,7 @@ bool WorldObject::IsWithinLOS(float ox, float oy, float oz, VMAP::ModelIgnoreFla
return true;
}
bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags, LineOfSightChecks checks) const
bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags, LineOfSightChecks checks, Optional<float> collisionHeight /*= {}*/) const
{
if (!IsInMap(obj))
return false;
@@ -1353,7 +1353,7 @@ bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlag
oz += obj->GetCollisionHeight();
}
else
obj->GetHitSpherePointFor({ GetPositionX(), GetPositionY(), GetPositionZ() + GetCollisionHeight() }, ox, oy, oz);
obj->GetHitSpherePointFor({ GetPositionX(), GetPositionY(), GetPositionZ() + (collisionHeight ? *collisionHeight : GetCollisionHeight()) }, ox, oy, oz);
float x, y, z;
if (GetTypeId() == TYPEID_PLAYER)
@@ -1362,14 +1362,14 @@ bool WorldObject::IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlag
z += GetCollisionHeight();
}
else
GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z);
GetHitSpherePointFor({ obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ() + obj->GetCollisionHeight() }, x, y, z, collisionHeight);
return GetMap()->isInLineOfSight(x, y, z, ox, oy, oz, GetPhaseMask(), checks, ignoreFlags);
}
void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const
void WorldObject::GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z, Optional<float> collisionHeight) const
{
Position pos = GetHitSpherePointFor(dest);
Position pos = GetHitSpherePointFor(dest, collisionHeight);
x = pos.GetPositionX();
y = pos.GetPositionY();
z = pos.GetPositionZ();

View File

@@ -67,8 +67,8 @@ enum NotifyFlags
enum GOSummonType
{
GO_SUMMON_TIMED_OR_CORPSE_DESPAWN = 0, // despawns after a specified time OR when the summoner dies
GO_SUMMON_TIMED_DESPAWN = 1 // despawns after a specified time
GO_SUMMON_TIMED_OR_CORPSE_DESPAWN = 0, // despawns after a specified time OR when the summoner dies
GO_SUMMON_TIMED_DESPAWN = 1 // despawns after a specified time
};
class WorldPacket;
@@ -463,9 +463,9 @@ public:
bool IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D = true, bool useBoundingRadius = true) const;
bool IsWithinDistInMap(WorldObject const* obj, float dist2compare, bool is3D = true, bool useBoundingRadius = true) const;
[[nodiscard]] bool IsWithinLOS(float x, float y, float z, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS) const;
[[nodiscard]] bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS) const;
[[nodiscard]] Position GetHitSpherePointFor(Position const& dest) const;
void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z) const;
[[nodiscard]] bool IsWithinLOSInMap(WorldObject const* obj, VMAP::ModelIgnoreFlags ignoreFlags = VMAP::ModelIgnoreFlags::Nothing, LineOfSightChecks checks = LINEOFSIGHT_ALL_CHECKS, Optional<float> collisionHeight = { }) const;
[[nodiscard]] Position GetHitSpherePointFor(Position const& dest, Optional<float> collisionHeight = { }) const;
void GetHitSpherePointFor(Position const& dest, float& x, float& y, float& z, Optional<float> collisionHeight = { }) 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;
[[nodiscard]] bool IsInRange2d(float x, float y, float minRange, float maxRange) const;

View File

@@ -23,31 +23,31 @@
#define CONTACT_DISTANCE 0.5f
#define INTERACTION_DISTANCE 5.5f
#define ATTACK_DISTANCE 5.0f
#define VISIBILITY_COMPENSATION 15.0f // increase searchers
#define VISIBILITY_COMPENSATION 15.0f // increase searchers
#define INSPECT_DISTANCE 28.0f
#define VISIBILITY_INC_FOR_GOBJECTS 30.0f // pussywizard
#define SPELL_SEARCHER_COMPENSATION 30.0f // increase searchers size in case we have large npc near cell border
#define VISIBILITY_INC_FOR_GOBJECTS 30.0f // pussywizard
#define SPELL_SEARCHER_COMPENSATION 30.0f // increase searchers size in case we have large npc near cell border
#define TRADE_DISTANCE 11.11f
#define MAX_VISIBILITY_DISTANCE 250.0f // max distance for visible objects, experimental
#define MAX_VISIBILITY_DISTANCE 250.0f // max distance for visible objects, experimental
#define SIGHT_RANGE_UNIT 50.0f
#define MAX_SEARCHER_DISTANCE 150.0f // pussywizard: replace the use of MAX_VISIBILITY_DISTANCE in searchers, because MAX_VISIBILITY_DISTANCE is quite too big for this purpose
#define MAX_SEARCHER_DISTANCE 150.0f // pussywizard: replace the use of MAX_VISIBILITY_DISTANCE in searchers, because MAX_VISIBILITY_DISTANCE is quite too big for this purpose
#define VISIBILITY_DISTANCE_INFINITE 533.0f
#define VISIBILITY_DISTANCE_GIGANTIC 400.0f
#define VISIBILITY_DISTANCE_LARGE 200.0f
#define VISIBILITY_DISTANCE_NORMAL 100.0f
#define VISIBILITY_DISTANCE_SMALL 50.0f
#define VISIBILITY_DISTANCE_TINY 25.0f
#define DEFAULT_VISIBILITY_DISTANCE 100.0f // default visible distance, 100 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards
#define DEFAULT_VISIBILITY_DISTANCE 100.0f // default visible distance, 100 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 170.0f // default visible distance in instances, 170 yards
#define VISIBILITY_DIST_WINTERGRASP 175.0f
#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards
#define DEFAULT_VISIBILITY_BGARENAS 533.0f // default visible distance in BG/Arenas, roughly 533 yards
#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // player size, also currently used (correctly?) for any non Unit world objects
#define DEFAULT_COMBAT_REACH 1.5f
#define MIN_MELEE_REACH 2.0f
#define NOMINAL_MELEE_RANGE 5.0f
#define MELEE_RANGE (NOMINAL_MELEE_RANGE - MIN_MELEE_REACH * 2) //center to center for players
#define DEFAULT_COLLISION_HEIGHT 2.03128f // Most common value in dbc
#define DEFAULT_COLLISION_HEIGHT 2.03128f // Most common value in dbc
// used for creating values for respawn for example
inline uint32 PAIR64_HIPART(uint64 x);

View File

@@ -47,8 +47,8 @@ enum TypeMask
{
TYPEMASK_OBJECT = 0x0001,
TYPEMASK_ITEM = 0x0002,
TYPEMASK_CONTAINER = 0x0006, // TYPEMASK_ITEM | 0x0004
TYPEMASK_UNIT = 0x0008, // creature
TYPEMASK_CONTAINER = 0x0006, // TYPEMASK_ITEM | 0x0004
TYPEMASK_UNIT = 0x0008, // creature
TYPEMASK_PLAYER = 0x0010,
TYPEMASK_GAMEOBJECT = 0x0020,
TYPEMASK_DYNAMICOBJECT = 0x0040,

View File

@@ -42,7 +42,7 @@ struct ObjectPosSelector
float dist; // dist to central point (including central point size)
};
typedef std::multimap<float, UsedPos> UsedPosList; // std::abs(angle)->Node
typedef std::multimap<float, UsedPos> UsedPosList; // std::abs(angle)->Node
ObjectPosSelector(float x, float y, float size, float dist);
@@ -60,7 +60,7 @@ struct ObjectPosSelector
float angle_step2 = GetAngle(nextUsedPos.second);
float next_angle = nextUsedPos.first;
if (nextUsedPos.second.sign * sign < 0) // last node from diff. list (-pi+alpha)
if (nextUsedPos.second.sign * sign < 0) // last node from diff. list (-pi+alpha)
next_angle = 2 * M_PI - next_angle; // move to positive
return std::fabs(angle) + angle_step2 <= next_angle;

View File

@@ -28,9 +28,9 @@ enum ReactStates : uint8;
enum PetType : uint8
{
SUMMON_PET = 0,
HUNTER_PET = 1,
MAX_PET_TYPE = 4
SUMMON_PET = 0,
HUNTER_PET = 1,
MAX_PET_TYPE = 4
};
constexpr auto MAX_PET_STABLES = 4;
@@ -38,54 +38,54 @@ constexpr auto MAX_PET_STABLES = 4;
// stored in character_pet.slot
enum PetSaveMode : int8
{
PET_SAVE_AS_DELETED = -1, // not saved in fact
PET_SAVE_AS_CURRENT = 0, // in current slot (with player)
PET_SAVE_FIRST_STABLE_SLOT = 1,
PET_SAVE_LAST_STABLE_SLOT = MAX_PET_STABLES, // last in DB stable slot index (including), all higher have same meaning as PET_SAVE_NOT_IN_SLOT
PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100
PET_SAVE_AS_DELETED = -1, // not saved in fact
PET_SAVE_AS_CURRENT = 0, // in current slot (with player)
PET_SAVE_FIRST_STABLE_SLOT = 1,
PET_SAVE_LAST_STABLE_SLOT = MAX_PET_STABLES, // last in DB stable slot index (including), all higher have same meaning as PET_SAVE_NOT_IN_SLOT
PET_SAVE_NOT_IN_SLOT = 100 // for avoid conflict with stable size grow will use 100
};
enum HappinessState
{
UNHAPPY = 1,
CONTENT = 2,
HAPPY = 3
UNHAPPY = 1,
CONTENT = 2,
HAPPY = 3
};
enum PetSpellState
{
PETSPELL_UNCHANGED = 0,
PETSPELL_CHANGED = 1,
PETSPELL_NEW = 2,
PETSPELL_REMOVED = 3
PETSPELL_UNCHANGED = 0,
PETSPELL_CHANGED = 1,
PETSPELL_NEW = 2,
PETSPELL_REMOVED = 3
};
enum PetSpellType
{
PETSPELL_NORMAL = 0,
PETSPELL_FAMILY = 1,
PETSPELL_TALENT = 2
PETSPELL_NORMAL = 0,
PETSPELL_FAMILY = 1,
PETSPELL_TALENT = 2
};
enum ActionFeedback
{
FEEDBACK_NONE = 0,
FEEDBACK_PET_DEAD = 1,
FEEDBACK_NOTHING_TO_ATT = 2,
FEEDBACK_CANT_ATT_TARGET = 3
FEEDBACK_NONE = 0,
FEEDBACK_PET_DEAD = 1,
FEEDBACK_NOTHING_TO_ATT = 2,
FEEDBACK_CANT_ATT_TARGET = 3
};
enum PetTalk
{
PET_TALK_SPECIAL_SPELL = 0,
PET_TALK_ATTACK = 1
PET_TALK_SPECIAL_SPELL = 0,
PET_TALK_ATTACK = 1
};
enum PetLoadState
{
PET_LOAD_OK = 0,
PET_LOAD_NO_RESULT = 1,
PET_LOAD_ERROR = 2
PET_LOAD_OK = 0,
PET_LOAD_NO_RESULT = 1,
PET_LOAD_ERROR = 2
};
enum NPCEntries

View File

@@ -813,7 +813,7 @@ int32 Player::getMaxTimer(MirrorTimerType timer)
{
if (!IsAlive() || HasAuraType(SPELL_AURA_WATER_BREATHING) || GetSession()->GetSecurity() >= AccountTypes(sWorld->getIntConfig(CONFIG_DISABLE_BREATHING)))
return DISABLED_MIRROR_TIMER;
int32 UnderWaterTime = static_cast<int32>(sWorld->getFloatConfig(CONFIG_WATER_BREATH_TIMER) * MINUTE * IN_MILLISECONDS);
int32 UnderWaterTime = sWorld->getIntConfig(CONFIG_WATER_BREATH_TIMER);
AuraEffectList const& mModWaterBreathing = GetAuraEffectsByType(SPELL_AURA_MOD_WATER_BREATHING);
for (AuraEffectList::const_iterator i = mModWaterBreathing.begin(); i != mModWaterBreathing.end(); ++i)
AddPct(UnderWaterTime, (*i)->GetAmount());
@@ -13192,7 +13192,7 @@ void Player::StoreLootItem(uint8 lootSlot, Loot* loot)
return;
}
if (!item->AllowedForPlayer(this))
if (!item->AllowedForPlayer(this, loot->sourceWorldObjectGUID))
{
SendLootRelease(GetLootGUID());
return;

View File

@@ -33,7 +33,8 @@ Totem::Totem(SummonPropertiesEntry const* properties, ObjectGuid owner) : Minion
void Totem::Update(uint32 time)
{
if (!GetOwner()->IsAlive() || !IsAlive())
Unit* owner = GetOwner();
if (!owner || !owner->IsAlive() || !IsAlive())
{
UnSummon(); // remove self
return;

View File

@@ -3623,8 +3623,12 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell)
{
// generic spells always break channeled not delayed spells
if (Spell* s = GetCurrentSpell(CURRENT_CHANNELED_SPELL))
if (s->GetSpellInfo()->Id != 69051) // pussywizard: FoS, boss Devourer of Souls, Mirrored Soul, does not have any special attribute
{
if (!s->GetSpellInfo()->IsActionAllowedChannel())
{
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
}
}
// autorepeat breaking
if (m_currentSpells[CURRENT_AUTOREPEAT_SPELL])
@@ -3659,7 +3663,14 @@ void Unit::SetCurrentCastedSpell(Spell* pSpell)
if (pSpell->m_spellInfo->Id != 75)
{
// generic autorepeats break generic non-delayed and channeled non-delayed spells
InterruptSpell(CURRENT_GENERIC_SPELL, false);
if (Spell* s = GetCurrentSpell(CURRENT_CHANNELED_SPELL))
{
if (!s->GetSpellInfo()->IsActionAllowedChannel())
{
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
}
}
InterruptSpell(CURRENT_CHANNELED_SPELL, false);
}
// special action: set first cast flag
@@ -3794,7 +3805,7 @@ bool Unit::IsMovementPreventedByCasting() const
{
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
{
if (spell->GetSpellInfo()->IsMoveAllowedChannel())
if (spell->GetSpellInfo()->IsActionAllowedChannel())
{
return false;
}
@@ -3805,15 +3816,6 @@ bool Unit::IsMovementPreventedByCasting() const
return true;
}
bool Unit::CanMoveDuringChannel() const
{
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
if (spell->getState() != SPELL_STATE_FINISHED)
return spell->GetSpellInfo()->HasAttribute(SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL) && spell->IsChannelActive();
return false;
}
bool Unit::isInFrontInMap(Unit const* target, float distance, float arc) const
{
return IsWithinDistInMap(target, distance) && HasInArc(arc, target);
@@ -13181,7 +13183,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy, uint32 duration)
// xinef: if we somehow engage in combat (scripts, dunno) with player, remove this flag so he can fight back
if (GetTypeId() == TYPEID_UNIT && enemy && IsImmuneToPC() && enemy->GetCharmerOrOwnerPlayerOrPlayerItself())
SetImmuneToPC(true); // unit has engaged in combat, remove immunity so players can fight back
SetImmuneToPC(false); // unit has engaged in combat, remove immunity so players can fight back
if (IsInCombat())
return;
@@ -13203,6 +13205,8 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy, uint32 duration)
if (creature->GetFormation())
creature->GetFormation()->MemberEngagingTarget(creature, enemy);
sScriptMgr->OnUnitEnterCombat(creature, enemy);
}
creature->RefreshSwimmingFlag();
@@ -16375,6 +16379,8 @@ void Unit::SetDisplayId(uint32 modelId)
// Set Gender by modelId
if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
sScriptMgr->OnDisplayIdChange(this, modelId);
}
void Unit::RestoreDisplayId()
@@ -17512,6 +17518,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
if (CreatureAI* ai = creature->AI())
{
ai->JustDied(killer);
sScriptMgr->OnUnitDeath(creature, killer);
}
if (TempSummon* summon = creature->ToTempSummon())

View File

@@ -2031,9 +2031,6 @@ public:
// delayed+channeled spells are always interrupted
void InterruptNonMeleeSpells(bool withDelayed, uint32 spellid = 0, bool withInstant = true, bool bySelf = false);
// Check if our current channel spell has attribute SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL
[[nodiscard]] bool CanMoveDuringChannel() const;
[[nodiscard]] Spell* GetCurrentSpell(CurrentSpellTypes spellType) const { return m_currentSpells[spellType]; }
[[nodiscard]] Spell* GetCurrentSpell(uint32 spellType) const { return m_currentSpells[spellType]; }
[[nodiscard]] Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;

View File

@@ -51,11 +51,11 @@ enum VehicleFlags
enum VehicleSpells
{
VEHICLE_SPELL_RIDE_HARDCODED = 46598,
VEHICLE_SPELL_PARACHUTE = 45472,
VEHICLE_SPELL_RIDE_HARDCODED = 46598,
VEHICLE_SPELL_PARACHUTE = 45472,
VEHICLE_SPELL_GEIST_CONTROL_END = 58119,
VEHICLE_SPELL_SHADE_CONTROL_END = 58664
VEHICLE_SPELL_GEIST_CONTROL_END = 58119,
VEHICLE_SPELL_SHADE_CONTROL_END = 58664
};
enum VehicleNPCs