Merge branch 'azerothcore:master' into Playerbot
This commit is contained in:
@@ -3002,6 +3002,15 @@ ListenRange.TextEmote = 40
|
||||
|
||||
ListenRange.Yell = 300
|
||||
|
||||
#
|
||||
# Creature.RepositionAgainstNpcs
|
||||
# Description: Enables circling and backwards repositioning during NPC versus NPC combat.
|
||||
# Set to 0 to keep the legacy optimization that disables these moves for NPCs.
|
||||
# Default: 1 - (Enabled, uses more CPU, but looks better)
|
||||
# 0 - (Disabled, uses less CPU)
|
||||
|
||||
Creature.RepositionAgainstNpcs = 1
|
||||
|
||||
#
|
||||
# Creature.MovingStopTimeForPlayer
|
||||
# Description: Time (in milliseconds) during which creature will not move after
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "World.h"
|
||||
#include "Vehicle.h"
|
||||
#include "ZoneScript.h"
|
||||
#include <functional>
|
||||
@@ -364,13 +365,18 @@ void CreatureAI::MoveCircleChecks()
|
||||
if (
|
||||
!victim ||
|
||||
!me->IsFreeToMove() || me->HasUnitMovementFlag(MOVEMENTFLAG_ROOT) ||
|
||||
!me->IsWithinMeleeRange(victim) || me == victim->GetVictim() ||
|
||||
(!victim->IsPlayer() && !victim->IsPet()) // only player & pets to save CPU
|
||||
!me->IsWithinMeleeRange(victim) || me == victim->GetVictim()
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* optimization, disable circling movement for NPC vs NPC combat
|
||||
*/
|
||||
if (!sWorld->getBoolConfig(CONFIG_CREATURE_REPOSITION_AGAINST_NPCS) && !victim->IsPlayer() && !victim->IsPet())
|
||||
return;
|
||||
|
||||
me->GetMotionMaster()->MoveCircleTarget(me->GetVictim());
|
||||
}
|
||||
|
||||
@@ -378,8 +384,13 @@ void CreatureAI::MoveBackwardsChecks()
|
||||
{
|
||||
Unit *victim = me->GetVictim();
|
||||
|
||||
if (!victim || !me->IsFreeToMove() || me->HasUnitMovementFlag(MOVEMENTFLAG_ROOT) ||
|
||||
(!victim->IsPlayer() && !victim->IsPet()))
|
||||
if (!victim || !me->IsFreeToMove() || me->HasUnitMovementFlag(MOVEMENTFLAG_ROOT))
|
||||
return;
|
||||
|
||||
/**
|
||||
* optimization, disable backwards movement for NPC vs NPC combat
|
||||
*/
|
||||
if (!sWorld->getBoolConfig(CONFIG_CREATURE_REPOSITION_AGAINST_NPCS) && !victim->IsPlayer() && !victim->IsPet())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ class Unit;
|
||||
class Creature;
|
||||
class Player;
|
||||
class SpellInfo;
|
||||
enum SpellFinishReason : uint8;
|
||||
|
||||
typedef std::vector<AreaBoundary const*> CreatureBoundary;
|
||||
|
||||
@@ -146,6 +147,9 @@ public:
|
||||
// Called when spell hits a target
|
||||
virtual void SpellHitTarget(Unit* /*target*/, SpellInfo const* /*spell*/) {}
|
||||
|
||||
// Called when a spell either finishes, interrupts or cancels a spell cast
|
||||
virtual void OnSpellCastFinished(SpellInfo const* /*spell*/, SpellFinishReason /*reason*/) {}
|
||||
|
||||
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
|
||||
virtual void AttackedBy(Unit* /*attacker*/) {}
|
||||
virtual bool IsEscorted() { return false; }
|
||||
|
||||
@@ -1846,6 +1846,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
|
||||
WorldObject* target = nullptr;
|
||||
|
||||
SAIBool isForced = !e.action.moveToPos.disableForceDestination;
|
||||
|
||||
switch (e.GetTargetType())
|
||||
{
|
||||
case SMART_TARGET_POSITION:
|
||||
@@ -1855,7 +1857,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
if (TransportBase* trans = me->GetDirectTransport())
|
||||
trans->CalculatePassengerPosition(dest.x, dest.y, dest.z);
|
||||
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, true,
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, dest.x, dest.y, dest.z, true, isForced,
|
||||
isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE, e.target.o);
|
||||
|
||||
break;
|
||||
@@ -1873,7 +1875,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
randomPoint.m_positionY,
|
||||
randomPoint.m_positionZ,
|
||||
true,
|
||||
true,
|
||||
isForced,
|
||||
isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE
|
||||
);
|
||||
|
||||
@@ -1898,7 +1900,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
else if (e.action.moveToPos.ContactDistance)
|
||||
target->GetNearPoint(me, x, y, z, e.action.moveToPos.ContactDistance, 0, target->GetAngle(me));
|
||||
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
me->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, x + e.target.x, y + e.target.y, z + e.target.z, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1912,8 +1914,10 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
|
||||
{
|
||||
if (IsCreature(target))
|
||||
{
|
||||
SAIBool isForced = !e.action.moveToPosTarget.disableForceDestination;
|
||||
|
||||
Creature* ctarget = target->ToCreature();
|
||||
ctarget->GetMotionMaster()->MovePoint(e.action.moveToPos.pointId, e.target.x, e.target.y, e.target.z, true, true, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
ctarget->GetMotionMaster()->MovePoint(e.action.moveToPosTarget.pointId, e.target.x, e.target.y, e.target.z, true, isForced, isControlled ? MOTION_SLOT_CONTROLLED : MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -855,7 +855,7 @@ bool SmartAIMgr::CheckUnusedActionParams(SmartScriptHolder const& e)
|
||||
case SMART_ACTION_SET_HOVER: return sizeof(SmartAction::setHover);
|
||||
case SMART_ACTION_SET_HEALTH_PCT: return sizeof(SmartAction::setHealthPct);
|
||||
// case SMART_ACTION_CREATE_CONVERSATION: return sizeof(SmartAction::raw);
|
||||
case SMART_ACTION_MOVE_TO_POS_TARGET: return sizeof(SmartAction::moveToPos);
|
||||
case SMART_ACTION_MOVE_TO_POS_TARGET: return sizeof(SmartAction::moveToPosTarget);
|
||||
case SMART_ACTION_EXIT_VEHICLE: return NO_PARAMS;
|
||||
case SMART_ACTION_SET_UNIT_MOVEMENT_FLAGS: return sizeof(SmartAction::movementFlag);
|
||||
case SMART_ACTION_SET_COMBAT_DISTANCE: return sizeof(SmartAction::combatDistance);
|
||||
|
||||
@@ -1216,8 +1216,15 @@ struct SmartAction
|
||||
uint32 controlled;
|
||||
uint32 ContactDistance;
|
||||
uint32 combatReach;
|
||||
SAIBool disableForceDestination;
|
||||
} moveToPos;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 pointId;
|
||||
SAIBool disableForceDestination;
|
||||
} moveToPosTarget;
|
||||
|
||||
struct
|
||||
{
|
||||
uint32 gossipMenuId;
|
||||
|
||||
@@ -692,7 +692,6 @@ struct ItemTemplate
|
||||
uint32 MinMoneyLoot;
|
||||
uint32 MaxMoneyLoot;
|
||||
ItemFlagsCustom FlagsCu;
|
||||
WorldPacket queryData; // pussywizard
|
||||
|
||||
// helpers
|
||||
[[nodiscard]] bool HasSignature() const
|
||||
@@ -828,8 +827,6 @@ struct ItemTemplate
|
||||
[[nodiscard]] bool HasFlag(ItemFlags flag) const { return (Flags & flag) != 0; }
|
||||
[[nodiscard]] bool HasFlag2(ItemFlags2 flag) const { return (Flags2 & flag) != 0; }
|
||||
[[nodiscard]] bool HasFlagCu(ItemFlagsCustom flag) const { return (FlagsCu & flag) != 0; }
|
||||
|
||||
void InitializeQueryData();
|
||||
};
|
||||
|
||||
// Benchmarked: Faster than std::map (insert/find)
|
||||
|
||||
@@ -4138,6 +4138,9 @@ void Unit::InterruptSpell(CurrentSpellTypes spellType, bool withDelayed, bool wi
|
||||
if (ai->CanChaseOnInterrupt())
|
||||
ai->SetCombatMove(true);
|
||||
}
|
||||
|
||||
if (IsCreature() && IsAIEnabled)
|
||||
ToCreature()->AI()->OnSpellCastFinished(spell->GetSpellInfo(), SPELL_FINISHED_CANCELED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3443,9 +3443,6 @@ void ObjectMgr::LoadItemTemplates()
|
||||
}
|
||||
}
|
||||
|
||||
for (ItemTemplateContainer::iterator itr = _itemTemplateStore.begin(); itr != _itemTemplateStore.end(); ++itr)
|
||||
itr->second.InitializeQueryData();
|
||||
|
||||
// Check if item templates for DBC referenced character start outfit are present
|
||||
std::set<uint32> notFoundOutfit;
|
||||
for (uint32 i = 1; i < sCharStartOutfitStore.GetNumRows(); ++i)
|
||||
|
||||
@@ -385,135 +385,6 @@ bool ItemTemplate::HasSpellPowerStat() const
|
||||
return invalid;
|
||||
}
|
||||
|
||||
void ItemTemplate::InitializeQueryData()
|
||||
{
|
||||
queryData.Initialize(SMSG_ITEM_QUERY_SINGLE_RESPONSE, 1);
|
||||
|
||||
queryData << ItemId;
|
||||
queryData << Class;
|
||||
queryData << SubClass;
|
||||
queryData << SoundOverrideSubclass;
|
||||
queryData << Name1;
|
||||
queryData << uint8(0x00); //pProto->Name2; // blizz not send name there, just uint8(0x00); <-- \0 = empty string = empty name...
|
||||
queryData << uint8(0x00); //pProto->Name3; // blizz not send name there, just uint8(0x00);
|
||||
queryData << uint8(0x00); //pProto->Name4; // blizz not send name there, just uint8(0x00);
|
||||
queryData << DisplayInfoID;
|
||||
queryData << Quality;
|
||||
queryData << Flags;
|
||||
queryData << Flags2;
|
||||
queryData << BuyPrice;
|
||||
queryData << SellPrice;
|
||||
queryData << InventoryType;
|
||||
queryData << AllowableClass;
|
||||
queryData << AllowableRace;
|
||||
queryData << ItemLevel;
|
||||
queryData << RequiredLevel;
|
||||
queryData << RequiredSkill;
|
||||
queryData << RequiredSkillRank;
|
||||
queryData << RequiredSpell;
|
||||
queryData << RequiredHonorRank;
|
||||
queryData << RequiredCityRank;
|
||||
queryData << RequiredReputationFaction;
|
||||
queryData << RequiredReputationRank;
|
||||
queryData << int32(MaxCount);
|
||||
queryData << int32(Stackable);
|
||||
queryData << ContainerSlots;
|
||||
queryData << StatsCount; // item stats count
|
||||
for (uint32 i = 0; i < StatsCount; ++i)
|
||||
{
|
||||
queryData << ItemStat[i].ItemStatType;
|
||||
queryData << ItemStat[i].ItemStatValue;
|
||||
}
|
||||
queryData << ScalingStatDistribution; // scaling stats distribution
|
||||
queryData << ScalingStatValue; // some kind of flags used to determine stat values column
|
||||
for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
|
||||
{
|
||||
queryData << Damage[i].DamageMin;
|
||||
queryData << Damage[i].DamageMax;
|
||||
queryData << Damage[i].DamageType;
|
||||
}
|
||||
|
||||
// resistances (7)
|
||||
queryData << Armor;
|
||||
queryData << HolyRes;
|
||||
queryData << FireRes;
|
||||
queryData << NatureRes;
|
||||
queryData << FrostRes;
|
||||
queryData << ShadowRes;
|
||||
queryData << ArcaneRes;
|
||||
|
||||
queryData << Delay;
|
||||
queryData << AmmoType;
|
||||
queryData << RangedModRange;
|
||||
|
||||
for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
|
||||
{
|
||||
// send DBC data for cooldowns in same way as it used in Spell::SendSpellCooldown
|
||||
// use `item_template` or if not set then only use spell cooldowns
|
||||
SpellInfo const* spell = sSpellMgr->GetSpellInfo(Spells[s].SpellId);
|
||||
if (spell)
|
||||
{
|
||||
bool db_data = Spells[s].SpellCooldown >= 0 || Spells[s].SpellCategoryCooldown >= 0;
|
||||
|
||||
queryData << Spells[s].SpellId;
|
||||
queryData << Spells[s].SpellTrigger;
|
||||
queryData << int32(Spells[s].SpellCharges);
|
||||
|
||||
if (db_data)
|
||||
{
|
||||
queryData << uint32(Spells[s].SpellCooldown);
|
||||
queryData << uint32(Spells[s].SpellCategory);
|
||||
queryData << uint32(Spells[s].SpellCategoryCooldown);
|
||||
}
|
||||
else
|
||||
{
|
||||
queryData << uint32(spell->RecoveryTime);
|
||||
queryData << uint32(spell->GetCategory());
|
||||
queryData << uint32(spell->CategoryRecoveryTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
queryData << uint32(0);
|
||||
queryData << uint32(0);
|
||||
queryData << uint32(0);
|
||||
queryData << uint32(-1);
|
||||
queryData << uint32(0);
|
||||
queryData << uint32(-1);
|
||||
}
|
||||
}
|
||||
queryData << Bonding;
|
||||
queryData << Description;
|
||||
queryData << PageText;
|
||||
queryData << LanguageID;
|
||||
queryData << PageMaterial;
|
||||
queryData << StartQuest;
|
||||
queryData << LockID;
|
||||
queryData << int32(Material);
|
||||
queryData << Sheath;
|
||||
queryData << RandomProperty;
|
||||
queryData << RandomSuffix;
|
||||
queryData << Block;
|
||||
queryData << ItemSet;
|
||||
queryData << MaxDurability;
|
||||
queryData << Area;
|
||||
queryData << Map; // Added in 1.12.x & 2.0.1 client branch
|
||||
queryData << BagFamily;
|
||||
queryData << TotemCategory;
|
||||
for (int s = 0; s < MAX_ITEM_PROTO_SOCKETS; ++s)
|
||||
{
|
||||
queryData << Socket[s].Color;
|
||||
queryData << Socket[s].Content;
|
||||
}
|
||||
queryData << socketBonus;
|
||||
queryData << GemProperties;
|
||||
queryData << RequiredDisenchantSkill;
|
||||
queryData << ArmorDamageModifier;
|
||||
queryData << Duration; // added in 2.4.2.8209, duration (seconds)
|
||||
queryData << ItemLimitCategory; // WotLK, ItemLimitCategory
|
||||
queryData << HolidayId; // Holiday.dbc?
|
||||
}
|
||||
|
||||
// Only _static_ data send in this packet !!!
|
||||
void WorldSession::HandleItemQuerySingleOpcode(WorldPacket& recvData)
|
||||
{
|
||||
|
||||
@@ -4112,6 +4112,12 @@ void Spell::_cast(bool skipCheck)
|
||||
sScriptMgr->OnSpellCast(this, m_caster, m_spellInfo, skipCheck);
|
||||
|
||||
SetExecutedCurrently(false);
|
||||
|
||||
// Call CreatureAI hook OnSpellCastFinished
|
||||
if (m_originalCaster)
|
||||
if (Creature* caster = m_originalCaster->ToCreature())
|
||||
if (caster->IsAIEnabled)
|
||||
caster->AI()->OnSpellCastFinished(GetSpellInfo(), SPELL_FINISHED_SUCCESSFUL_CAST);
|
||||
}
|
||||
|
||||
void Spell::handle_immediate()
|
||||
@@ -4463,6 +4469,11 @@ void Spell::update(uint32 difftime)
|
||||
SendChannelUpdate(0);
|
||||
|
||||
finish();
|
||||
|
||||
// We call the hook here instead of in Spell::finish because we only want to call it for completed channeling. Everything else is handled by interrupts
|
||||
if (Creature* creatureCaster = m_caster->ToCreature())
|
||||
if (creatureCaster->IsAIEnabled)
|
||||
creatureCaster->AI()->OnSpellCastFinished(m_spellInfo, SPELL_FINISHED_CHANNELING_COMPLETE);
|
||||
}
|
||||
// Xinef: Dont update channeled target list on last tick, allow auras to update duration properly
|
||||
// Xinef: Added this strange check because of diffrent update routines for players / creatures
|
||||
|
||||
@@ -92,6 +92,13 @@ enum SpellRangeFlag
|
||||
SPELL_RANGE_RANGED = 2, //hunter range and ranged weapon
|
||||
};
|
||||
|
||||
enum SpellFinishReason : uint8
|
||||
{
|
||||
SPELL_FINISHED_SUCCESSFUL_CAST = 0, // spell has sucessfully launched
|
||||
SPELL_FINISHED_CANCELED = 1, // spell has been canceled (interrupts)
|
||||
SPELL_FINISHED_CHANNELING_COMPLETE = 2 // spell channeling has been finished
|
||||
};
|
||||
|
||||
struct SpellDestination
|
||||
{
|
||||
SpellDestination();
|
||||
|
||||
@@ -459,6 +459,7 @@ void WorldConfig::BuildConfigCache()
|
||||
SetConfigValue<uint32>(CONFIG_ARENA_QUEUE_ANNOUNCER_DETAIL, "Arena.QueueAnnouncer.Detail", 3);
|
||||
|
||||
SetConfigValue<bool>(CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN, "OffhandCheckAtSpellUnlearn", true);
|
||||
SetConfigValue<bool>(CONFIG_CREATURE_REPOSITION_AGAINST_NPCS, "Creature.RepositionAgainstNpcs", true);
|
||||
SetConfigValue<uint32>(CONFIG_CREATURE_STOP_FOR_PLAYER, "Creature.MovingStopTimeForPlayer", 180000);
|
||||
|
||||
SetConfigValue<uint32>(CONFIG_WATER_BREATH_TIMER, "WaterBreath.Timer", 180000, ConfigValueCache::Reloadable::Yes, [](uint32 const& value) { return value > 0; }, "> 0");
|
||||
|
||||
@@ -78,6 +78,7 @@ enum ServerConfigs
|
||||
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
|
||||
CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
|
||||
CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN,
|
||||
CONFIG_CREATURE_REPOSITION_AGAINST_NPCS,
|
||||
CONFIG_VMAP_INDOOR_CHECK,
|
||||
CONFIG_PET_LOS,
|
||||
CONFIG_START_CUSTOM_SPELLS,
|
||||
|
||||
@@ -2033,12 +2033,8 @@ enum StrengthenAncientsMisc
|
||||
{
|
||||
SAY_WALKER_FRIENDLY = 0,
|
||||
SAY_WALKER_ENEMY = 1,
|
||||
SAY_LOTHALOR = 0,
|
||||
|
||||
SPELL_CREATE_ITEM_BARK = 47550,
|
||||
SPELL_CONFUSED = 47044,
|
||||
|
||||
NPC_LOTHALOR = 26321
|
||||
};
|
||||
|
||||
class spell_q12096_q12092_dummy : public SpellScript
|
||||
@@ -2082,27 +2078,6 @@ class spell_q12096_q12092_dummy : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
class spell_q12096_q12092_bark : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_q12096_q12092_bark);
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Creature* lothalor = GetHitCreature();
|
||||
if (!lothalor || lothalor->GetEntry() != NPC_LOTHALOR)
|
||||
return;
|
||||
|
||||
lothalor->AI()->Talk(SAY_LOTHALOR);
|
||||
lothalor->RemoveAura(SPELL_CONFUSED);
|
||||
lothalor->DespawnOrUnsummon(4000);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_q12096_q12092_bark::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
/*#####
|
||||
# npc_torturer_lecraft
|
||||
#####*/
|
||||
@@ -2320,7 +2295,6 @@ void AddSC_dragonblight()
|
||||
new npc_spiritual_insight();
|
||||
new npc_commander_eligor_dawnbringer();
|
||||
RegisterSpellScript(spell_q12096_q12092_dummy);
|
||||
RegisterSpellScript(spell_q12096_q12092_bark);
|
||||
new npc_torturer_lecraft();
|
||||
RegisterSpellScript(spell_dragonblight_corrosive_spit);
|
||||
RegisterSpellScript(spell_handover_reins);
|
||||
|
||||
Reference in New Issue
Block a user