Skip to content

Commit

Permalink
Merge 3.3.5 to npcbots_3.3.5
Browse files Browse the repository at this point in the history
  • Loading branch information
Github Actions committed May 24, 2024
2 parents c4cd4ef + d8240fb commit e73202c
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 54 deletions.
17 changes: 3 additions & 14 deletions src/server/game/Entities/Creature/Creature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3445,21 +3445,10 @@ void Creature::DoNotReacquireSpellFocusTarget()

bool Creature::IsMovementPreventedByCasting() const
{
// first check if currently a movement allowed channel is active and we're not casting
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
{
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
if (spell->GetSpellInfo()->IsMoveAllowedChannel())
return false;
}

if (HasSpellFocus())
return true;

if (HasUnitState(UNIT_STATE_CASTING))
return true;
if (!Unit::IsMovementPreventedByCasting() && !HasSpellFocus())
return false;

return false;
return true;
}

void Creature::StartPickPocketRefillTimer()
Expand Down
12 changes: 5 additions & 7 deletions src/server/game/Entities/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5882,18 +5882,18 @@ void Player::UpdateWeaponSkill(Unit* victim, WeaponAttackType attType)

void Player::UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool defense)
{
uint8 plevel = GetLevel(); // if defense than victim == attacker
uint8 greylevel = Trinity::XP::GetGrayLevel(plevel);
uint8 moblevel = victim->GetLevelForTarget(this);
int32 plevel = GetLevel(); // if defense than victim == attacker
int32 greylevel = Trinity::XP::GetGrayLevel(plevel);
int32 moblevel = victim->GetLevelForTarget(this);

if (moblevel > plevel + 5)
moblevel = plevel + 5;

uint8 lvldif = moblevel - greylevel;
int32 lvldif = moblevel - greylevel;
if (lvldif < 3)
lvldif = 3;

uint32 skilldif = 5 * plevel - (defense ? GetBaseDefenseSkillValue() : GetBaseWeaponSkillValue(attType));
int32 skilldif = 5 * plevel - int32(defense ? GetBaseDefenseSkillValue() : GetBaseWeaponSkillValue(attType));
if (skilldif <= 0)
return;

Expand All @@ -5911,8 +5911,6 @@ void Player::UpdateCombatSkills(Unit* victim, WeaponAttackType attType, bool def
else
UpdateWeaponSkill(victim, attType);
}
else
return;
}

void Player::ModifySkillBonus(uint32 skillid, int32 val, bool talent)
Expand Down
5 changes: 5 additions & 0 deletions src/server/game/Entities/Unit/Unit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3315,6 +3315,11 @@ bool Unit::IsMovementPreventedByCasting() const
if (!HasUnitState(UNIT_STATE_CASTING))
return false;

if (Spell* spell = m_currentSpells[CURRENT_GENERIC_SPELL])
if (spell->getState() == SPELL_STATE_FINISHED ||
!(spell->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
return false;

// channeled spells during channel stage (after the initial cast timer) allow movement with a specific spell attribute
if (Spell* spell = m_currentSpells[CURRENT_CHANNELED_SPELL])
if (spell->getState() != SPELL_STATE_FINISHED && spell->IsChannelActive())
Expand Down
15 changes: 15 additions & 0 deletions src/server/game/Movement/MovementDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ enum MovementGeneratorType : uint8
MAX_MOTION_TYPE // SKIP
};

constexpr bool CanStopMovementForSpellCasting(MovementGeneratorType type)
{
// MovementGenerators that don't check Unit::IsMovementPreventedByCasting
switch (type)
{
case HOME_MOTION_TYPE:
case FLIGHT_MOTION_TYPE:
case EFFECT_MOTION_TYPE: // knockbacks, jumps, falling, land/takeoff transitions
return false;
default:
break;
}
return true;
}

enum MovementGeneratorMode : uint8
{
MOTION_MODE_DEFAULT = 0,
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/Scripting/ScriptMgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ class CreatureGameObjectScriptRegistrySwapHooks
}
};

AIFunctionMapWorker<typename std::decay<decltype(evaluator)>::type> worker(std::move(evaluator));
AIFunctionMapWorker<std::decay_t<decltype(evaluator)>> worker(std::move(evaluator));
TypeContainerVisitor<decltype(worker), MapStoredObjectTypesContainer> containerVisitor(worker);

containerVisitor.Visit(map->GetObjectsStore());
Expand Down
71 changes: 43 additions & 28 deletions src/server/game/Spells/Spell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "Item.h"
#include "Log.h"
#include "LootMgr.h"
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Opcodes.h"
Expand Down Expand Up @@ -3244,19 +3245,9 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const
else
m_casttime = m_spellInfo->CalcCastTime(this);

// don't allow channeled spells / spells with cast time to be cast while moving
// exception are only channeled spells that have no casttime and SPELL_ATTR5_CAN_CHANNEL_WHEN_MOVING
// (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)
if ((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TYPEID_PLAYER && !(m_caster->ToPlayer()->IsCharmed() && m_caster->ToPlayer()->GetCharmerGUID().IsCreature()) && m_caster->ToPlayer()->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
{
// 1. Has casttime, 2. Or doesn't have flag to allow movement during channel
if (m_casttime || !m_spellInfo->IsMoveAllowedChannel())
{
SendCastResult(SPELL_FAILED_MOVING);
finish(false);
return SPELL_FAILED_MOVING;
}
}
SpellCastResult movementResult = SPELL_CAST_OK;
if (m_caster->IsUnit() && m_caster->ToUnit()->isMoving())
movementResult = CheckMovement();

// Creatures focus their target when possible
if (m_casttime && m_caster->IsCreature() && !m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_caster->ToUnit()->HasUnitFlag(UNIT_FLAG_POSSESSED))
Expand All @@ -3269,6 +3260,24 @@ SpellCastResult Spell::prepare(SpellCastTargets const& targets, AuraEffect const
m_caster->ToCreature()->SetSpellFocus(this, nullptr);
}

if (movementResult != SPELL_CAST_OK)
{
if (m_caster->ToUnit()->IsControlledByPlayer() || !CanStopMovementForSpellCasting(m_caster->ToUnit()->GetMotionMaster()->GetCurrentMovementGeneratorType()))
{
SendCastResult(movementResult);
finish(movementResult);
return movementResult;
}
else
{
// Creatures (not controlled) give priority to spell casting over movement.
// We assume that the casting is always valid and the current movement
// is stopped immediately (because spells are updated before movement, so next Unit::Update would cancel the spell before stopping movement)
// and future attempts are stopped by by Unit::IsMovementPreventedByCasting in movement generators to prevent casting interruption.
m_caster->ToUnit()->StopMoving();
}
}

// set timer base at cast time
ReSetTimer();

Expand Down Expand Up @@ -3922,21 +3931,9 @@ void Spell::update(uint32 difftime)
return;
}

// check if the player caster has moved before the spell finished
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0 &&
m_caster->ToPlayer()->isMoving() && m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT &&
(!m_spellInfo->HasEffect(SPELL_EFFECT_STUCK) || !m_caster->ToPlayer()->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)))
{
// don't cancel for melee, autorepeat, triggered and instant spells
if (!m_spellInfo->IsNextMeleeSwingSpell() && !IsAutoRepeat() && !IsTriggered() && !(IsChannelActive() && m_spellInfo->IsMoveAllowedChannel()))
{
// if charmed by creature, trust the AI not to cheat and allow the cast to proceed
// @todo this is a hack, "creature" movesplines don't differentiate turning/moving right now
// however, checking what type of movement the spline is for every single spline would be really expensive
if (!m_caster->ToPlayer()->GetCharmerGUID().IsCreature())
cancel();
}
}
// check if the unit caster has moved before the spell finished
if (m_timer != 0 && m_caster->IsUnit() && m_caster->ToUnit()->isMoving() && CheckMovement() != SPELL_CAST_OK)
cancel();

switch (m_spellState)
{
Expand Down Expand Up @@ -6600,6 +6597,24 @@ int32 Spell::CalculateDamage(SpellEffectInfo const& spellEffectInfo) const
return m_caster->CalculateSpellDamage(spellEffectInfo, m_spellValue->EffectBasePoints + spellEffectInfo.EffectIndex);
}

SpellCastResult Spell::CheckMovement() const
{
if (IsTriggered())
return SPELL_CAST_OK;

if (getState() == SPELL_STATE_PREPARING)
{
if (m_casttime > 0)
if (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT)
return SPELL_FAILED_MOVING;
}
else if (getState() == SPELL_STATE_CASTING)
if (!m_spellInfo->IsMoveAllowedChannel())
return SPELL_FAILED_MOVING;

return SPELL_CAST_OK;
}

bool Spell::CanAutoCast(Unit* target)
{
if (!target)
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Spells/Spell.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ class TC_GAME_API Spell
SpellCastResult CheckPower() const;
SpellCastResult CheckRuneCost(uint32 runeCostID) const;
SpellCastResult CheckCasterAuras(uint32* param1) const;
SpellCastResult CheckMovement() const;

bool CheckSpellCancelsAuraEffect(AuraType auraType, uint32* param1) const;
bool CheckSpellCancelsCharm(uint32* param1) const;
Expand Down
4 changes: 0 additions & 4 deletions src/server/game/Spells/SpellEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4526,10 +4526,6 @@ void Spell::EffectKnockBack()
if (unitTarget->HasUnitState(UNIT_STATE_ROOT))
return;

// Instantly interrupt non melee spells being cast
if (unitTarget->IsNonMeleeSpellCast(true))
unitTarget->InterruptNonMeleeSpells(true);

float ratio = 0.1f;
float speedxy = float(effectInfo->MiscValue) * ratio;
float speedz = float(damage) * ratio;
Expand Down

0 comments on commit e73202c

Please sign in to comment.