mirror of
https://github.com/mangosfour/server.git
synced 2026-01-02 01:37:05 +00:00
Merge remote branch 'origin/master' into 330
This commit is contained in:
commit
c745c5072f
31 changed files with 1000 additions and 760 deletions
|
|
@ -348,7 +348,8 @@ enum SummonPropType
|
|||
SUMMON_PROP_TYPE_PHASING = 8, // something todo with DK prequest line, 2 spells in 3.0.3 "%s's Opponent"
|
||||
SUMMON_PROP_TYPE_SIEGE_VEH = 9, // summon different vehicles, 14 spells in 3.0.3 "%s's Vehicle"
|
||||
SUMMON_PROP_TYPE_DRAKE_VEH = 10, // summon drake (vehicle), 3 spells
|
||||
SUMMON_PROP_TYPE_LIGHTWELL = 11 // summon lightwell, 6 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_LIGHTWELL = 11, // summon lightwell, 6 spells in 3.0.3
|
||||
SUMMON_PROP_TYPE_REPAIR_BOT = 12 // summon repir bot, 1 spells in 3.2.2a
|
||||
};
|
||||
|
||||
// SummonProperties.dbc, col 5
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ enum GossipOptionIcon
|
|||
//POI icons. Many more exist, list not complete.
|
||||
enum Poi_Icon
|
||||
{
|
||||
ICON_POI_BLANK = 0, // Blank (not visible)
|
||||
ICON_POI_BLANK = 0, // Blank (not visible), in 2.4.3 have value 15 with 1..15 values in 0..14 range
|
||||
ICON_POI_GREY_AV_MINE = 1, // Grey mine lorry
|
||||
ICON_POI_RED_AV_MINE = 2, // Red mine lorry
|
||||
ICON_POI_BLUE_AV_MINE = 3, // Blue mine lorry
|
||||
|
|
|
|||
|
|
@ -1026,9 +1026,12 @@ void WorldSession::HandleMoveTimeSkippedOpcode( WorldPacket & recv_data )
|
|||
*/
|
||||
}
|
||||
|
||||
void WorldSession::HandleFeatherFallAck(WorldPacket &/*recv_data*/)
|
||||
void WorldSession::HandleFeatherFallAck(WorldPacket &recv_data)
|
||||
{
|
||||
DEBUG_LOG("WORLD: CMSG_MOVE_FEATHER_FALL_ACK");
|
||||
|
||||
// no used
|
||||
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
|
||||
}
|
||||
|
||||
void WorldSession::HandleMoveUnRootAck(WorldPacket& recv_data)
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@ void WorldSession::HandleMovementOpcodes( WorldPacket & recv_data )
|
|||
if (movementInfo.HasMovementFlag(MOVEMENTFLAG_ONTRANSPORT))
|
||||
{
|
||||
// transports size limited
|
||||
// (also received at zeppelin leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
|
||||
if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 50 )
|
||||
// (also received at zeppelin/lift leave by some reason with t_* as absolute in continent coordinates, can be safely skipped)
|
||||
if( movementInfo.t_x > 50 || movementInfo.t_y > 50 || movementInfo.t_z > 100 )
|
||||
{
|
||||
recv_data.rpos(recv_data.wpos()); // prevent warnings spam
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -667,6 +667,12 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer * data, UpdateMask *
|
|||
if (!((Creature*)this)->isCanTrainingOf(target, false))
|
||||
appendValue &= ~(UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS | UNIT_NPC_FLAG_TRAINER_PROFESSION);
|
||||
}
|
||||
|
||||
if (appendValue & UNIT_NPC_FLAG_STABLEMASTER)
|
||||
{
|
||||
if (target->getClass() != CLASS_HUNTER)
|
||||
appendValue &= ~UNIT_NPC_FLAG_STABLEMASTER;
|
||||
}
|
||||
}
|
||||
|
||||
*data << uint32(appendValue);
|
||||
|
|
|
|||
|
|
@ -7315,6 +7315,10 @@ bool PlayerCondition::Meets(Player const * player) const
|
|||
}
|
||||
return false;
|
||||
}
|
||||
case CONDITION_RACE_CLASS:
|
||||
if ((!value1 || (player->getRaceMask() & value1)) && (!value2 || (player->getClassMask() & value2)))
|
||||
return true;
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
@ -7468,6 +7472,27 @@ bool PlayerCondition::IsValid(ConditionType condition, uint32 value1, uint32 val
|
|||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_RACE_CLASS:
|
||||
{
|
||||
if (!value1 && !value2)
|
||||
{
|
||||
sLog.outErrorDb("Race_class condition has both values like 0, skipped");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value1 && !(value1 & RACEMASK_ALL_PLAYABLE))
|
||||
{
|
||||
sLog.outErrorDb("Race_class condition has invalid player class %u, skipped", value1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value2 && !(value2 & CLASSMASK_ALL_PLAYABLE))
|
||||
{
|
||||
sLog.outErrorDb("Race_class condition has invalid race mask %u, skipped", value2);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONDITION_NONE:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -319,11 +319,12 @@ enum ConditionType
|
|||
CONDITION_QUESTTAKEN = 9, // quest_id 0, for condition true while quest active.
|
||||
CONDITION_AD_COMMISSION_AURA = 10, // 0 0, for condition true while one from AD commission aura active
|
||||
CONDITION_NO_AURA = 11, // spell_id effindex
|
||||
CONDITION_ACTIVE_EVENT = 12, // event_id
|
||||
CONDITION_AREA_FLAG = 13 // area_flag area_flag_not
|
||||
CONDITION_ACTIVE_EVENT = 12, // event_id 0
|
||||
CONDITION_AREA_FLAG = 13, // area_flag area_flag_not
|
||||
CONDITION_RACE_CLASS = 14, // race_mask class_mask
|
||||
};
|
||||
|
||||
#define MAX_CONDITION 14 // maximum value in ConditionType enum
|
||||
#define MAX_CONDITION 15 // maximum value in ConditionType enum
|
||||
|
||||
struct PlayerCondition
|
||||
{
|
||||
|
|
|
|||
|
|
@ -414,8 +414,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
|
|||
<< curmana << ", "
|
||||
<< GetPower(POWER_HAPPINESS) << ", '";
|
||||
|
||||
// save only spell slots from action bar
|
||||
for(uint32 i = ACTION_BAR_INDEX_PET_SPELL_START; i < ACTION_BAR_INDEX_PET_SPELL_END; ++i)
|
||||
for(uint32 i = ACTION_BAR_INDEX_START; i < ACTION_BAR_INDEX_END; ++i)
|
||||
{
|
||||
ss << uint32(m_charmInfo->GetActionBarEntry(i)->GetType()) << " "
|
||||
<< uint32(m_charmInfo->GetActionBarEntry(i)->GetAction()) << " ";
|
||||
|
|
|
|||
|
|
@ -324,23 +324,59 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
|
|||
}
|
||||
|
||||
count = (recv_data.size() == 24) ? 2 : 1;
|
||||
|
||||
uint32 position[2];
|
||||
uint32 data[2];
|
||||
bool move_command = false;
|
||||
|
||||
for(uint8 i = 0; i < count; ++i)
|
||||
{
|
||||
uint32 position;
|
||||
uint32 data;
|
||||
recv_data >> position[i];
|
||||
recv_data >> data[i];
|
||||
|
||||
recv_data >> position;
|
||||
recv_data >> data;
|
||||
|
||||
uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data);
|
||||
uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data);
|
||||
|
||||
sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position, spell_id, uint32(act_state));
|
||||
uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]);
|
||||
|
||||
//ignore invalid position
|
||||
if(position >= MAX_UNIT_ACTION_BAR_INDEX)
|
||||
if(position[i] >= MAX_UNIT_ACTION_BAR_INDEX)
|
||||
return;
|
||||
|
||||
// in the normal case, command and reaction buttons can only be moved, not removed
|
||||
// at moving count ==2, at removing count == 1
|
||||
// ignore attempt to remove command|reaction buttons (not possible at normal case)
|
||||
if (act_state == ACT_COMMAND || act_state == ACT_REACTION)
|
||||
{
|
||||
if (count == 1)
|
||||
return;
|
||||
|
||||
move_command = true;
|
||||
}
|
||||
}
|
||||
|
||||
// check swap
|
||||
if (move_command)
|
||||
{
|
||||
uint8 act_state_0 = UNIT_ACTION_BUTTON_TYPE(data[0]);
|
||||
uint32 spell_id_0 = UNIT_ACTION_BUTTON_ACTION(data[0]);
|
||||
UnitActionBarEntry const* actionEntry_1 = charmInfo->GetActionBarEntry(position[1]);
|
||||
if (!actionEntry_1 || spell_id_0 != actionEntry_1->GetAction() ||
|
||||
act_state_0 != actionEntry_1->GetType())
|
||||
return;
|
||||
|
||||
uint8 act_state_1 = UNIT_ACTION_BUTTON_TYPE(data[1]);
|
||||
uint32 spell_id_1 = UNIT_ACTION_BUTTON_ACTION(data[1]);
|
||||
UnitActionBarEntry const* actionEntry_0 = charmInfo->GetActionBarEntry(position[0]);
|
||||
if (!actionEntry_0 || spell_id_1 != actionEntry_0->GetAction() ||
|
||||
act_state_1 != actionEntry_0->GetType())
|
||||
return;
|
||||
}
|
||||
|
||||
for(uint8 i = 0; i < count; ++i)
|
||||
{
|
||||
uint32 spell_id = UNIT_ACTION_BUTTON_ACTION(data[i]);
|
||||
uint8 act_state = UNIT_ACTION_BUTTON_TYPE(data[i]);
|
||||
|
||||
sLog.outDetail( "Player %s has changed pet spell action. Position: %u, Spell: %u, State: 0x%X", _player->GetName(), position[i], spell_id, uint32(act_state));
|
||||
|
||||
//if it's act for spell (en/disable/cast) and there is a spell given (0 = remove spell) which pet doesn't know, don't add
|
||||
if(!((act_state == ACT_ENABLED || act_state == ACT_DISABLED || act_state == ACT_PASSIVE) && spell_id && !pet->HasSpell(spell_id)))
|
||||
{
|
||||
|
|
@ -361,7 +397,7 @@ void WorldSession::HandlePetSetAction( WorldPacket & recv_data )
|
|||
((Pet*)pet)->ToggleAutocast(spell_id, false);
|
||||
}
|
||||
|
||||
charmInfo->SetActionBar(position,spell_id,ActiveStates(act_state));
|
||||
charmInfo->SetActionBar(position[i],spell_id,ActiveStates(act_state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2088,6 +2088,12 @@ Creature* Player::GetNPCIfCanInteractWith(uint64 guid, uint32 npcflagmask)
|
|||
if (npcflagmask && !unit->HasFlag( UNIT_NPC_FLAGS, npcflagmask ))
|
||||
return NULL;
|
||||
|
||||
if (npcflagmask == UNIT_NPC_FLAG_STABLEMASTER)
|
||||
{
|
||||
if (getClass() != CLASS_HUNTER)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if a dead unit should be able to talk - the creature must be alive and have special flags
|
||||
if (!unit->isAlive())
|
||||
return NULL;
|
||||
|
|
@ -5008,8 +5014,8 @@ void Player::SetRegularAttackTime()
|
|||
{
|
||||
for(int i = 0; i < MAX_ATTACK; ++i)
|
||||
{
|
||||
Item *tmpitem = GetWeaponForAttack(WeaponAttackType(i));
|
||||
if(tmpitem && !tmpitem->IsBroken())
|
||||
Item *tmpitem = GetWeaponForAttack(WeaponAttackType(i),true,false);
|
||||
if (tmpitem)
|
||||
{
|
||||
ItemPrototype const *proto = tmpitem->GetProto();
|
||||
if(proto->Delay)
|
||||
|
|
@ -5215,7 +5221,7 @@ void Player::UpdateWeaponSkill (WeaponAttackType attType)
|
|||
{
|
||||
case BASE_ATTACK:
|
||||
{
|
||||
Item *tmpitem = GetWeaponForAttack(attType,true);
|
||||
Item *tmpitem = GetWeaponForAttack(attType,true,true);
|
||||
|
||||
if (!tmpitem)
|
||||
UpdateSkill(SKILL_UNARMED,weapon_skill_gain);
|
||||
|
|
@ -5226,7 +5232,7 @@ void Player::UpdateWeaponSkill (WeaponAttackType attType)
|
|||
case OFF_ATTACK:
|
||||
case RANGED_ATTACK:
|
||||
{
|
||||
Item *tmpitem = GetWeaponForAttack(attType,true);
|
||||
Item *tmpitem = GetWeaponForAttack(attType,true,true);
|
||||
if (tmpitem)
|
||||
UpdateSkill(tmpitem->GetSkill(),weapon_skill_gain);
|
||||
break;
|
||||
|
|
@ -7034,8 +7040,8 @@ void Player::UpdateEquipSpellsAtFormChange()
|
|||
|
||||
void Player::CastItemCombatSpell(Unit* Target, WeaponAttackType attType)
|
||||
{
|
||||
Item *item = GetWeaponForAttack(attType, false);
|
||||
if(!item || item->IsBroken())
|
||||
Item *item = GetWeaponForAttack(attType, true, false);
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
ItemPrototype const *proto = item->GetProto();
|
||||
|
|
@ -7355,8 +7361,8 @@ bool Player::CheckAmmoCompatibility(const ItemPrototype *ammo_proto) const
|
|||
return false;
|
||||
|
||||
// check ranged weapon
|
||||
Item *weapon = GetWeaponForAttack( RANGED_ATTACK );
|
||||
if(!weapon || weapon->IsBroken() )
|
||||
Item *weapon = GetWeaponForAttack( RANGED_ATTACK, true, false );
|
||||
if (!weapon)
|
||||
return false;
|
||||
|
||||
ItemPrototype const* weapon_proto = weapon->GetProto();
|
||||
|
|
@ -8173,14 +8179,14 @@ void Player::SetSheath( SheathState sheathed )
|
|||
break;
|
||||
case SHEATH_STATE_MELEE: // prepared melee weapon
|
||||
{
|
||||
SetVirtualItemSlot(0,GetWeaponForAttack(BASE_ATTACK,true));
|
||||
SetVirtualItemSlot(1,GetWeaponForAttack(OFF_ATTACK,true));
|
||||
SetVirtualItemSlot(0,GetWeaponForAttack(BASE_ATTACK,true,true));
|
||||
SetVirtualItemSlot(1,GetWeaponForAttack(OFF_ATTACK,true,true));
|
||||
SetVirtualItemSlot(2,NULL);
|
||||
}; break;
|
||||
case SHEATH_STATE_RANGED: // prepared ranged weapon
|
||||
SetVirtualItemSlot(0,NULL);
|
||||
SetVirtualItemSlot(1,NULL);
|
||||
SetVirtualItemSlot(2,GetWeaponForAttack(RANGED_ATTACK,true));
|
||||
SetVirtualItemSlot(2,GetWeaponForAttack(RANGED_ATTACK,true,true));
|
||||
break;
|
||||
default:
|
||||
SetVirtualItemSlot(0,NULL);
|
||||
|
|
@ -8551,7 +8557,7 @@ Item* Player::GetItemByPos( uint8 bag, uint8 slot ) const
|
|||
return NULL;
|
||||
}
|
||||
|
||||
Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) const
|
||||
Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool nonbroken, bool useable) const
|
||||
{
|
||||
uint16 slot;
|
||||
switch (attackType)
|
||||
|
|
@ -8566,10 +8572,10 @@ Item* Player::GetWeaponForAttack(WeaponAttackType attackType, bool useable) cons
|
|||
if (!item || item->GetProto()->Class != ITEM_CLASS_WEAPON)
|
||||
return NULL;
|
||||
|
||||
if(!useable)
|
||||
return item;
|
||||
if (useable && !IsUseEquipedWeapon(attackType==BASE_ATTACK))
|
||||
return NULL;
|
||||
|
||||
if( item->IsBroken() || !IsUseEquipedWeapon(attackType==BASE_ATTACK) )
|
||||
if (nonbroken && item->IsBroken())
|
||||
return NULL;
|
||||
|
||||
return item;
|
||||
|
|
@ -12491,7 +12497,7 @@ void Player::OnGossipSelect(WorldObject* pSource, uint32 gossipListId, uint32 me
|
|||
uint32 Player::GetGossipTextId(WorldObject *pSource)
|
||||
{
|
||||
if (!pSource || pSource->GetTypeId() != TYPEID_UNIT || !((Creature*)pSource)->GetDBTableGUIDLow())
|
||||
return 0;
|
||||
return DEFAULT_GOSSIP_MESSAGE;
|
||||
|
||||
if (uint32 pos = sObjectMgr.GetNpcGossip(((Creature*)pSource)->GetDBTableGUIDLow()))
|
||||
return pos;
|
||||
|
|
@ -19638,7 +19644,7 @@ bool Player::IsAtGroupRewardDistance(WorldObject const* pRewardSource) const
|
|||
|
||||
uint32 Player::GetBaseWeaponSkillValue (WeaponAttackType attType) const
|
||||
{
|
||||
Item* item = GetWeaponForAttack(attType,true);
|
||||
Item* item = GetWeaponForAttack(attType,true,true);
|
||||
|
||||
// unarmed only with base attack
|
||||
if(attType != BASE_ATTACK && !item)
|
||||
|
|
|
|||
|
|
@ -1163,7 +1163,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
|||
Item* GetItemByGuid( uint64 guid ) const;
|
||||
Item* GetItemByPos( uint16 pos ) const;
|
||||
Item* GetItemByPos( uint8 bag, uint8 slot ) const;
|
||||
Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const;
|
||||
Item* GetWeaponForAttack(WeaponAttackType attackType) const { return GetWeaponForAttack(attackType,false,false); }
|
||||
Item* GetWeaponForAttack(WeaponAttackType attackType, bool nonbroken, bool useable) const;
|
||||
Item* GetShield(bool useable = false) const;
|
||||
static uint32 GetAttackBySlot( uint8 slot ); // MAX_ATTACK if not weapon slot
|
||||
std::vector<Item *> &GetItemUpdateQueue() { return m_itemUpdateQueue; }
|
||||
|
|
|
|||
|
|
@ -686,6 +686,9 @@ void Spell::prepareDataForTriggerSystem()
|
|||
// Clearcasting trigger need do it
|
||||
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000200000000) && m_spellInfo->SpellFamilyFlags2 & 0x8)
|
||||
m_canTrigger = true;
|
||||
// Replenish Mana, item spell with triggered cases (Mana Agate, etc mana gems)
|
||||
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000010000000000))
|
||||
m_canTrigger = true;
|
||||
break;
|
||||
case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Seed of Corruption triggers need do it
|
||||
if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000800000000060))
|
||||
|
|
@ -2417,11 +2420,10 @@ void Spell::cancel()
|
|||
{
|
||||
Unit* unit = m_caster->GetGUID()==(*ihit).targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
|
||||
if( unit && unit->isAlive() )
|
||||
unit->RemoveAurasDueToSpell(m_spellInfo->Id);
|
||||
unit->RemoveAurasByCasterSpell(m_spellInfo->Id,m_caster->GetGUID());
|
||||
}
|
||||
}
|
||||
|
||||
m_caster->RemoveAurasDueToSpell(m_spellInfo->Id);
|
||||
SendChannelUpdate(0);
|
||||
SendInterrupted(0);
|
||||
SendCastResult(SPELL_FAILED_INTERRUPTED);
|
||||
|
|
@ -3441,6 +3443,13 @@ void Spell::SendChannelUpdate(uint32 time)
|
|||
{
|
||||
if(time == 0)
|
||||
{
|
||||
m_caster->RemoveAurasByCasterSpell(m_spellInfo->Id,m_caster->GetGUID());
|
||||
|
||||
if(uint64 target_guid = m_caster->GetChannelObjectGUID())
|
||||
if(target_guid != m_caster->GetGUID() && IS_UNIT_GUID(target_guid))
|
||||
if(Unit* target = ObjectAccessor::GetUnit(*m_caster, target_guid))
|
||||
target->RemoveAurasByCasterSpell(m_spellInfo->Id,m_caster->GetGUID());
|
||||
|
||||
m_caster->SetChannelObjectGUID(0);
|
||||
m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
|
||||
}
|
||||
|
|
@ -5563,8 +5572,8 @@ SpellCastResult Spell::CheckItems()
|
|||
if(m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_TARGET_NOT_PLAYER;
|
||||
if( m_attackType != RANGED_ATTACK )
|
||||
break;
|
||||
Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(m_attackType);
|
||||
if(!pItem || pItem->IsBroken())
|
||||
Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true,false);
|
||||
if (!pItem)
|
||||
return SPELL_FAILED_EQUIPPED_ITEM;
|
||||
|
||||
switch(pItem->GetProto()->SubClass)
|
||||
|
|
|
|||
|
|
@ -628,27 +628,20 @@ void Aura::Update(uint32 diff)
|
|||
return;
|
||||
}
|
||||
|
||||
// Get spell range
|
||||
float radius;
|
||||
SpellModOp mod;
|
||||
if (m_spellProto->EffectRadiusIndex[GetEffIndex()])
|
||||
// need check distance for channeled target only
|
||||
if (caster->GetChannelObjectGUID() == m_target->GetGUID())
|
||||
{
|
||||
radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellProto->EffectRadiusIndex[GetEffIndex()]));
|
||||
mod = SPELLMOD_RADIUS;
|
||||
}
|
||||
else
|
||||
{
|
||||
radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
|
||||
mod = SPELLMOD_RANGE;
|
||||
}
|
||||
// Get spell range
|
||||
float max_range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellProto->rangeIndex));
|
||||
|
||||
if(Player* modOwner = caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(GetId(), mod, radius, NULL);
|
||||
if(Player* modOwner = caster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(GetId(), SPELLMOD_RANGE, max_range, NULL);
|
||||
|
||||
if(!caster->IsWithinDistInMap(m_target, radius))
|
||||
{
|
||||
m_target->RemoveAura(GetId(), GetEffIndex());
|
||||
return;
|
||||
if(!caster->IsWithinDistInMap(m_target, max_range))
|
||||
{
|
||||
m_target->RemoveAura(GetId(), GetEffIndex());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1331,7 +1324,7 @@ bool Aura::isAffectedOnSpell(SpellEntry const *spell) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void Aura::ReapplyAffectedPassiveAuras( Unit* target )
|
||||
void Aura::ReapplyAffectedPassiveAuras( Unit* target, bool owner_mode )
|
||||
{
|
||||
std::set<uint32> affectedSelf;
|
||||
std::set<uint32> affectedAuraCaster;
|
||||
|
|
@ -1339,16 +1332,17 @@ void Aura::ReapplyAffectedPassiveAuras( Unit* target )
|
|||
for(Unit::AuraMap::const_iterator itr = target->GetAuras().begin(); itr != target->GetAuras().end(); ++itr)
|
||||
{
|
||||
// permanent passive or permanent area aura
|
||||
if (itr->second->IsPermanent() && (itr->second->IsPassive() || itr->second->IsAreaAura()) &&
|
||||
// passive spells can be affected only by own or owner spell mods)
|
||||
if (itr->second->IsPermanent() && (owner_mode && itr->second->IsPassive() || itr->second->IsAreaAura()) &&
|
||||
// non deleted and not same aura (any with same spell id)
|
||||
!itr->second->IsDeleted() && itr->second->GetId() != GetId() &&
|
||||
// and affected by aura
|
||||
isAffectedOnSpell(itr->second->GetSpellProto()))
|
||||
{
|
||||
// only applied by self or aura caster
|
||||
if(itr->second->GetCasterGUID() == target->GetGUID())
|
||||
if (itr->second->GetCasterGUID() == target->GetGUID())
|
||||
affectedSelf.insert(itr->second->GetId());
|
||||
else if(itr->second->GetCasterGUID() == GetCasterGUID())
|
||||
else if (itr->second->GetCasterGUID() == GetCasterGUID())
|
||||
affectedAuraCaster.insert(itr->second->GetId());
|
||||
}
|
||||
}
|
||||
|
|
@ -1429,25 +1423,26 @@ void Aura::HandleAddModifier(bool apply, bool Real)
|
|||
((Player*)m_target)->AddSpellMod(m_spellmod, apply);
|
||||
|
||||
// reapply talents to own passive persistent auras
|
||||
ReapplyAffectedPassiveAuras(m_target);
|
||||
ReapplyAffectedPassiveAuras(m_target, true);
|
||||
|
||||
// re-apply talents/passives/area auras applied to pet (it affected by player spellmods)
|
||||
if(Pet* pet = m_target->GetPet())
|
||||
ReapplyAffectedPassiveAuras(pet);
|
||||
ReapplyAffectedPassiveAuras(pet, true);
|
||||
|
||||
// re-apply talents/passives/area auras applied to totems (it affected by player spellmods)
|
||||
for(int i = 0; i < MAX_TOTEM; ++i)
|
||||
if(m_target->m_TotemSlot[i])
|
||||
if(Creature* totem = m_target->GetMap()->GetCreature(m_target->m_TotemSlot[i]))
|
||||
ReapplyAffectedPassiveAuras(totem);
|
||||
ReapplyAffectedPassiveAuras(totem, true);
|
||||
|
||||
// re-apply talents/passives/area auras applied to group members (it affected by player spellmods)
|
||||
if (Group* group = ((Player*)m_target)->GetGroup())
|
||||
for(GroupReference *itr = group->GetFirstMember(); itr != NULL; itr = itr->next())
|
||||
if (Player* member = itr->getSource())
|
||||
if (member != m_target && member->IsInMap(m_target))
|
||||
ReapplyAffectedPassiveAuras(member);
|
||||
ReapplyAffectedPassiveAuras(member, false);
|
||||
}
|
||||
|
||||
void Aura::HandleAddTargetTrigger(bool apply, bool /*Real*/)
|
||||
{
|
||||
// Use SpellModifier structure for check
|
||||
|
|
@ -5295,7 +5290,7 @@ void Aura::HandleAuraModCritPercent(bool apply, bool Real)
|
|||
if(Real)
|
||||
{
|
||||
for(int i = 0; i < MAX_ATTACK; ++i)
|
||||
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
|
||||
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i),true,false))
|
||||
((Player*)m_target)->_ApplyWeaponDependentAuraCritMod(pItem, WeaponAttackType(i), this, apply);
|
||||
}
|
||||
|
||||
|
|
@ -5495,7 +5490,7 @@ void Aura::HandleModDamageDone(bool apply, bool Real)
|
|||
if(Real && m_target->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
for(int i = 0; i < MAX_ATTACK; ++i)
|
||||
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
|
||||
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i),true,false))
|
||||
((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply);
|
||||
}
|
||||
|
||||
|
|
@ -5578,7 +5573,7 @@ void Aura::HandleModDamagePercentDone(bool apply, bool Real)
|
|||
if(Real && m_target->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
for(int i = 0; i < MAX_ATTACK; ++i)
|
||||
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i)))
|
||||
if(Item* pItem = ((Player*)m_target)->GetWeaponForAttack(WeaponAttackType(i),true,false))
|
||||
((Player*)m_target)->_ApplyWeaponDependentAuraDamageMod(pItem, WeaponAttackType(i), this, apply);
|
||||
}
|
||||
|
||||
|
|
@ -5897,7 +5892,7 @@ void Aura::HandleShapeshiftBoosts(bool apply)
|
|||
|
||||
void Aura::HandleSpellSpecificBoosts(bool apply)
|
||||
{
|
||||
bool cast_at_remove = false; // if spell must be casted at aura remove
|
||||
bool cast_at_remove = false; // if spell must be casted at last aura from stack remove
|
||||
uint32 spellId1 = 0;
|
||||
uint32 spellId2 = 0;
|
||||
uint32 spellId3 = 0;
|
||||
|
|
@ -5905,9 +5900,21 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
|
|||
|
||||
switch(GetSpellProto()->SpellFamilyName)
|
||||
{
|
||||
case SPELLFAMILY_GENERIC:
|
||||
{
|
||||
// Illusionary Barrier
|
||||
if(GetId() == 57350 && !apply && m_target->getPowerType() == POWER_MANA)
|
||||
{
|
||||
cast_at_remove = true;
|
||||
spellId1 = 60242; // Darkmoon Card: Illusion
|
||||
}
|
||||
else
|
||||
return;
|
||||
break;
|
||||
}
|
||||
case SPELLFAMILY_MAGE:
|
||||
{
|
||||
// Ice Barrier
|
||||
// Ice Barrier (non stacking from one caster)
|
||||
if (m_spellProto->SpellIconID == 32)
|
||||
{
|
||||
if (!apply && (m_removeMode == AURA_REMOVE_BY_DISPEL || (m_removeMode == AURA_REMOVE_BY_DEFAULT && !GetModifier()->m_amount)))
|
||||
|
|
@ -5954,7 +5961,7 @@ void Aura::HandleSpellSpecificBoosts(bool apply)
|
|||
break;
|
||||
}
|
||||
case SPELLFAMILY_WARLOCK:
|
||||
// Fear
|
||||
// Fear (non stacking)
|
||||
if (m_spellProto->SpellFamilyFlags & UI64LIT(0x0000040000000000))
|
||||
{
|
||||
if(!apply)
|
||||
|
|
@ -6632,7 +6639,11 @@ void Aura::PeriodicTick()
|
|||
|
||||
// send critical in hit info for threat calculation
|
||||
if (isCrit)
|
||||
{
|
||||
cleanDamage.hitOutCome = MELEE_HIT_CRIT;
|
||||
// Resilience - reduce crit damage
|
||||
pdamage -= m_target->GetSpellCritDamageReduction(pdamage);
|
||||
}
|
||||
|
||||
// only from players
|
||||
// FIXME: need use SpellDamageBonus instead?
|
||||
|
|
|
|||
|
|
@ -352,7 +352,7 @@ class MANGOS_DLL_SPEC Aura
|
|||
void PeriodicDummyTick();
|
||||
|
||||
bool IsCritFromAbilityAura(Unit* caster, uint32& damage);
|
||||
void ReapplyAffectedPassiveAuras(Unit* target);
|
||||
void ReapplyAffectedPassiveAuras(Unit* target, bool owner_mode);
|
||||
|
||||
Modifier m_modifier;
|
||||
SpellModifier *m_spellmod;
|
||||
|
|
|
|||
|
|
@ -2223,10 +2223,10 @@ void Spell::EffectTriggerSpell(uint32 effIndex)
|
|||
// main hand weapon required
|
||||
if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
|
||||
{
|
||||
Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
|
||||
Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK, true, false);
|
||||
|
||||
// skip spell if no weapon in slot or broken
|
||||
if (!item || item->IsBroken() )
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
// skip spell if weapon not fit to triggered spell
|
||||
|
|
@ -2237,10 +2237,10 @@ void Spell::EffectTriggerSpell(uint32 effIndex)
|
|||
// offhand hand weapon required
|
||||
if (spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
|
||||
{
|
||||
Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
|
||||
Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK, true, false);
|
||||
|
||||
// skip spell if no weapon in slot or broken
|
||||
if (!item || item->IsBroken() )
|
||||
if (!item)
|
||||
return;
|
||||
|
||||
// skip spell if weapon not fit to triggered spell
|
||||
|
|
@ -3442,6 +3442,7 @@ void Spell::EffectSummonType(uint32 i)
|
|||
break;
|
||||
}
|
||||
case SUMMON_PROP_TYPE_CRITTER:
|
||||
case SUMMON_PROP_TYPE_REPAIR_BOT:
|
||||
{
|
||||
EffectSummonCritter(i, summon_prop->FactionId);
|
||||
break;
|
||||
|
|
@ -4586,7 +4587,7 @@ void Spell::EffectWeaponDmg(uint32 i)
|
|||
// Whirlwind, single only spell with 2 weapon white damage apply if have
|
||||
if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x00000400000000)))
|
||||
{
|
||||
if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
|
||||
if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK, true, true))
|
||||
spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
|
||||
}
|
||||
// Devastate bonus and sunder armor refresh
|
||||
|
|
@ -4646,7 +4647,7 @@ void Spell::EffectWeaponDmg(uint32 i)
|
|||
// Fan of Knives
|
||||
else if (m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0004000000000000)))
|
||||
{
|
||||
Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true);
|
||||
Item* weapon = ((Player*)m_caster)->GetWeaponForAttack(m_attackType,true,true);
|
||||
if (weapon && weapon->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_DAGGER)
|
||||
totalDamagePercentMod *= 1.5f; // 150% to daggers
|
||||
}
|
||||
|
|
@ -4821,13 +4822,13 @@ void Spell::EffectWeaponDmg(uint32 i)
|
|||
// take ammo
|
||||
if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
{
|
||||
Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
|
||||
Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK, true, false);
|
||||
|
||||
// wands don't have ammo
|
||||
if(!pItem || pItem->IsBroken() || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
|
||||
if (!pItem || pItem->GetProto()->SubClass == ITEM_SUBCLASS_WEAPON_WAND)
|
||||
return;
|
||||
|
||||
if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
|
||||
if (pItem->GetProto()->InventoryType == INVTYPE_THROWN)
|
||||
{
|
||||
if(pItem->GetMaxStackCount()==1)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -483,7 +483,7 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
|
|||
break;
|
||||
}
|
||||
} break;
|
||||
case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from bas point sign (negative -> negative)
|
||||
case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from base point sign (negative -> negative)
|
||||
case SPELL_AURA_MOD_STAT:
|
||||
case SPELL_AURA_MOD_SKILL:
|
||||
case SPELL_AURA_MOD_HEALING_PCT:
|
||||
|
|
@ -496,8 +496,10 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
|
|||
return false;
|
||||
break;
|
||||
case SPELL_AURA_MOD_SPELL_CRIT_CHANCE:
|
||||
case SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT:
|
||||
case SPELL_AURA_MOD_DAMAGE_PERCENT_DONE:
|
||||
if(spellproto->CalculateSimpleValue(effIndex) > 0)
|
||||
return true; // some expected positive spells have SPELL_ATTR_EX_NEGATIVE
|
||||
return true; // some expected positive spells have SPELL_ATTR_EX_NEGATIVE or unclear target modes
|
||||
break;
|
||||
case SPELL_AURA_ADD_TARGET_TRIGGER:
|
||||
return true;
|
||||
|
|
@ -573,6 +575,8 @@ bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
|
|||
// some spells negative
|
||||
switch(spellproto->Id)
|
||||
{
|
||||
case 802: // Mutate Bug, wrongly negative by target modes
|
||||
return true;
|
||||
case 36900: // Soul Split: Evil!
|
||||
case 36901: // Soul Split: Good
|
||||
case 36893: // Transporter Malfunction (decrease size case)
|
||||
|
|
|
|||
1192
src/game/Unit.cpp
1192
src/game/Unit.cpp
File diff suppressed because it is too large
Load diff
|
|
@ -1247,7 +1247,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
void RemoveAurasByCasterSpell(uint32 spellId, uint32 effindex, uint64 casterGUID);
|
||||
void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer);
|
||||
void RemoveAurasDueToSpellByCancel(uint32 spellId);
|
||||
void RemoveAurasAtChanneledTarget(SpellEntry const* spellInfo);
|
||||
|
||||
// removing unknown aura stacks by diff reasons and selections
|
||||
void RemoveNotOwnSingleTargetAuras(uint32 newPhase = 0x0);
|
||||
|
|
@ -1618,6 +1617,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
|
|||
uint32 m_lastManaUseTimer;
|
||||
|
||||
private:
|
||||
void CleanupDeletedAuars();
|
||||
|
||||
bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent );
|
||||
bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
|
||||
bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
|
||||
|
|
|
|||
|
|
@ -45,18 +45,20 @@ alter table creature_movement add `wpguid` int(11) default '0';
|
|||
//-----------------------------------------------//
|
||||
void WaypointMovementGenerator<Creature>::LoadPath(Creature &c)
|
||||
{
|
||||
sLog.outDetail("LoadPath: loading waypoint path for creature %d,%d", c.GetGUIDLow(), c.GetDBTableGUIDLow());
|
||||
sLog.outDetail("LoadPath: loading waypoint path for creature %u, %u", c.GetGUIDLow(), c.GetDBTableGUIDLow());
|
||||
|
||||
i_path = sWaypointMgr.GetPath(c.GetDBTableGUIDLow());
|
||||
if(!i_path)
|
||||
|
||||
if (!i_path)
|
||||
{
|
||||
sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %d) doesn't have waypoint path",
|
||||
sLog.outErrorDb("WaypointMovementGenerator::LoadPath: creature %s (Entry: %u GUID: %u) doesn't have waypoint path",
|
||||
c.GetName(), c.GetEntry(), c.GetDBTableGUIDLow());
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 node_count = i_path->size();
|
||||
i_hasDone.resize(node_count);
|
||||
|
||||
for(uint32 i = 0; i < node_count-1; ++i)
|
||||
i_hasDone[i] = false;
|
||||
|
||||
|
|
@ -78,22 +80,23 @@ void WaypointMovementGenerator<Creature>::Initialize()
|
|||
|
||||
bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint32 &diff)
|
||||
{
|
||||
if(!&creature)
|
||||
if (!&creature)
|
||||
return true;
|
||||
|
||||
// Waypoint movement can be switched on/off
|
||||
// This is quite handy for escort quests and other stuff
|
||||
if(creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED | UNIT_STAT_DIED))
|
||||
if (creature.hasUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DISTRACTED | UNIT_STAT_DIED))
|
||||
return true;
|
||||
|
||||
// prevent a crash at empty waypoint path.
|
||||
if(!i_path || i_path->empty())
|
||||
if (!i_path || i_path->empty())
|
||||
return true;
|
||||
|
||||
// i_path was modified by chat commands for example
|
||||
if(i_path->size() != i_hasDone.size())
|
||||
if (i_path->size() != i_hasDone.size())
|
||||
i_hasDone.resize(i_path->size());
|
||||
if(i_currentNode >= i_path->size())
|
||||
|
||||
if (i_currentNode >= i_path->size())
|
||||
i_currentNode = 0;
|
||||
|
||||
CreatureTraveller traveller(creature);
|
||||
|
|
@ -104,56 +107,67 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3
|
|||
// creature has been stopped in middle of the waypoint segment
|
||||
if (!i_destinationHolder.HasArrived() && creature.IsStopped())
|
||||
{
|
||||
if( i_nextMoveTime.Passed()) // Timer has elapsed, meaning this part controlled it
|
||||
// Timer has elapsed, meaning this part controlled it
|
||||
if (i_nextMoveTime.Passed())
|
||||
{
|
||||
SetStoppedByPlayer(false);
|
||||
// Now we re-set destination to same node and start travel
|
||||
|
||||
creature.addUnitState(UNIT_STAT_ROAMING);
|
||||
|
||||
if (creature.canFly())
|
||||
creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY);
|
||||
|
||||
// Now we re-set destination to same node and start travel
|
||||
const WaypointNode &node = i_path->at(i_currentNode);
|
||||
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
|
||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
||||
}
|
||||
else // if( !i_nextMoveTime.Passed())
|
||||
{ // unexpected end of timer && creature stopped && not at end of segment
|
||||
{
|
||||
// unexpected end of timer && creature stopped && not at end of segment
|
||||
if (!IsStoppedByPlayer())
|
||||
{ // Put 30 seconds delay
|
||||
{
|
||||
// Put 30 seconds delay
|
||||
i_destinationHolder.IncreaseTravelTime(STOP_TIME_FOR_PLAYER);
|
||||
i_nextMoveTime.Reset(STOP_TIME_FOR_PLAYER);
|
||||
SetStoppedByPlayer(true); // Mark we did it
|
||||
SetStoppedByPlayer(true); // Mark we did it
|
||||
}
|
||||
}
|
||||
return true; // Abort here this update
|
||||
return true; // Abort here this update
|
||||
}
|
||||
|
||||
if( creature.IsStopped())
|
||||
if (creature.IsStopped())
|
||||
{
|
||||
uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;
|
||||
|
||||
if (!i_hasDone[idx])
|
||||
{
|
||||
if (i_path->at(idx).orientation !=100)
|
||||
if (i_path->at(idx).orientation != 100)
|
||||
creature.SetOrientation(i_path->at(idx).orientation);
|
||||
|
||||
if(WaypointBehavior *behavior = i_path->at(idx).behavior)
|
||||
if (WaypointBehavior *behavior = i_path->at(idx).behavior)
|
||||
{
|
||||
if(behavior->emote != 0)
|
||||
creature.SetUInt32Value(UNIT_NPC_EMOTESTATE,behavior->emote);
|
||||
if(behavior->spell != 0)
|
||||
creature.CastSpell(&creature,behavior->spell, false);
|
||||
if(behavior->model1 != 0)
|
||||
if (behavior->emote != 0)
|
||||
creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, behavior->emote);
|
||||
|
||||
if (behavior->spell != 0)
|
||||
creature.CastSpell(&creature, behavior->spell, false);
|
||||
|
||||
if (behavior->model1 != 0)
|
||||
creature.SetDisplayId(behavior->model1);
|
||||
if(behavior->textid[0])
|
||||
|
||||
if (behavior->textid[0])
|
||||
{
|
||||
// Not only one text is set
|
||||
if( behavior->textid[1] )
|
||||
if (behavior->textid[1])
|
||||
{
|
||||
// Select one from max 5 texts (0 and 1 laready checked)
|
||||
// Select one from max 5 texts (0 and 1 already checked)
|
||||
int i = 2;
|
||||
for( ; i < MAX_WAYPOINT_TEXT; ++i )
|
||||
if( !behavior->textid[i] )
|
||||
for(; i < MAX_WAYPOINT_TEXT; ++i)
|
||||
{
|
||||
if (!behavior->textid[i])
|
||||
break;
|
||||
}
|
||||
|
||||
creature.Say(behavior->textid[rand() % i], 0, 0);
|
||||
}
|
||||
|
|
@ -167,37 +181,46 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3
|
|||
} // HasDone == false
|
||||
} // i_creature.IsStopped()
|
||||
|
||||
if( i_nextMoveTime.Passed() ) // This is at the end of waypoint segment or has been stopped by player
|
||||
// This is at the end of waypoint segment or has been stopped by player
|
||||
if (i_nextMoveTime.Passed())
|
||||
{
|
||||
if( creature.IsStopped() ) // If stopped then begin a new move segment
|
||||
// If stopped then begin a new move segment
|
||||
if (creature.IsStopped())
|
||||
{
|
||||
creature.addUnitState(UNIT_STAT_ROAMING);
|
||||
|
||||
if (creature.canFly())
|
||||
creature.AddMonsterMoveFlag(MONSTER_MOVE_FLY);
|
||||
|
||||
const WaypointNode &node = i_path->at(i_currentNode);
|
||||
i_destinationHolder.SetDestination(traveller, node.x, node.y, node.z);
|
||||
i_nextMoveTime.Reset(i_destinationHolder.GetTotalTravelTime());
|
||||
|
||||
uint32 idx = i_currentNode > 0 ? i_currentNode-1 : i_path->size()-1;
|
||||
|
||||
if (i_path->at(idx).orientation !=100)
|
||||
if (i_path->at(idx).orientation != 100)
|
||||
creature.SetOrientation(i_path->at(idx).orientation);
|
||||
|
||||
if(WaypointBehavior *behavior = i_path->at(idx).behavior )
|
||||
if (WaypointBehavior *behavior = i_path->at(idx).behavior)
|
||||
{
|
||||
i_hasDone[idx] = false;
|
||||
if(behavior->model2 != 0)
|
||||
|
||||
if (behavior->model2 != 0)
|
||||
creature.SetDisplayId(behavior->model2);
|
||||
|
||||
creature.SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
|
||||
}
|
||||
}
|
||||
else // If not stopped then stop it and set the reset of TimeTracker to waittime
|
||||
else
|
||||
{
|
||||
// If not stopped then stop it and set the reset of TimeTracker to waittime
|
||||
creature.StopMoving();
|
||||
SetStoppedByPlayer(false);
|
||||
|
||||
i_nextMoveTime.Reset(i_path->at(i_currentNode).delay);
|
||||
++i_currentNode;
|
||||
if( i_currentNode >= i_path->size() )
|
||||
|
||||
if (i_currentNode >= i_path->size())
|
||||
i_currentNode = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -206,7 +229,7 @@ bool WaypointMovementGenerator<Creature>::Update(Creature &creature, const uint3
|
|||
|
||||
void WaypointMovementGenerator<Creature>::MovementInform(Creature &unit)
|
||||
{
|
||||
if(unit.AI())
|
||||
if (unit.AI())
|
||||
unit.AI()->MovementInform(WAYPOINT_MOTION_TYPE, i_currentNode);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue