📄 interface.cpp.svn-base
字号:
//reset waypoint to 0
m_currentWaypoint = 0;
// There isn't any need to do any attacker checks here, as
// they should all be taken care of in DealDamage
//removed by Zack : why do we need to go to our master if we just died ? On next spawn we will be spawned near him after all
/* if(m_AIType == AITYPE_PET)
{
SetUnitToFollow(m_PetOwner);
SetFollowDistance(3.0f);
HandleEvent(EVENT_FOLLOWOWNER, m_Unit, 0);
}*/
if(m_Unit->GetMapMgr())
{
if(m_Unit->GetTypeId() == TYPEID_UNIT && !m_Unit->IsPet())
{
if(m_Unit->GetMapMgr()->pInstance && m_Unit->GetMapMgr()->GetMapInfo()->type != INSTANCE_NONRAID)
{
m_Unit->GetMapMgr()->pInstance->m_killedNpcs.insert( static_cast< MONSTER* >( m_Unit )->GetSQL_id() );
m_Unit->GetMapMgr()->pInstance->SaveToDB();
}
}
}
}break;
}
}
void AIInterface::Update(uint32 p_time)
{
float tdist;
if(m_AIType == AITYPE_TOTEM)
{
assert(totemspell != 0);
if(p_time >= m_totemspelltimer)
{
Spell *pSpell = new Spell(m_Unit, totemspell, true, 0);
SpellCastTargets targets(0);
if(!m_nextTarget ||
(m_nextTarget &&
(!m_Unit->GetMapMgr()->GetUnit(m_nextTarget->GetGUID()) ||
!m_nextTarget->isAlive() ||
!IsInrange(m_Unit,m_nextTarget,pSpell->m_spellInfo->base_range_or_radius_sqr) ||
!isAttackable(m_Unit, m_nextTarget,!(pSpell->m_spellInfo->c_is_flags & SPELL_FLAG_IS_TARGETINGSTEALTHED))
)
)
)
{
//we set no target and see if we managed to fid a new one
m_nextTarget=NULL;
//something happend to our target, pick another one
pSpell->GenerateTargets(&targets);
if(targets.m_targetMask & TARGET_FLAG_UNIT)
m_nextTarget = m_Unit->GetMapMgr()->GetUnit(targets.m_unitTarget);
}
if(m_nextTarget)
{
SpellCastTargets targets(m_nextTarget->GetGUID());
pSpell->prepare(&targets);
// need proper cooldown time!
m_totemspelltimer = m_totemspelltime;
}
else delete pSpell;
// these will *almost always* be AoE, so no need to find a target here.
// SpellCastTargets targets(m_Unit->GetGUID());
// Spell * pSpell = new Spell(m_Unit, totemspell, true, 0);
// pSpell->prepare(&targets);
// need proper cooldown time!
// m_totemspelltimer = m_totemspelltime;
}
else
{
m_totemspelltimer -= p_time;
}
return;
}
_UpdateTimer(p_time);
_UpdateTargets();
if(m_Unit->isAlive() && m_AIState != STATE_IDLE
&& m_AIState != STATE_FOLLOWING && m_AIState != STATE_FEAR
&& m_AIState != STATE_WANDER && m_AIState != STATE_SCRIPTMOVE)
{
if(m_AIType == AITYPE_PET )
{
if(!m_Unit->bInvincible && m_Unit->IsPet())
{
Pet * pPet = static_cast<Pet*>(m_Unit);
if(pPet->GetPetAction() == PET_ACTION_ATTACK || pPet->GetPetState() != PET_STATE_PASSIVE)
{
_UpdateCombat(p_time);
}
}
//we just use any MONSTER as a pet guardian
else if(!m_Unit->IsPet())
{
_UpdateCombat(p_time);
}
}
else
{
_UpdateCombat(p_time);
}
}
_UpdateMovement(p_time);
if(m_AIState==STATE_EVADE)
{
tdist = m_Unit->GetDistanceSq(m_returnX,m_returnY,m_returnZ);
if(tdist <= 4.0f/*2.0*/)
{
m_AIState = STATE_IDLE;
m_returnX = m_returnY = m_returnZ = 0.0f;
m_move = false;
//remowed by zack : in scripted events if we keep reducing this it will bug the world out !
//On Blizz it will return to previous wp but we can accept the fact that it will move on to next one
/*
if(hasWaypoints())
{
if(m_moveBackward)
{
if(m_currentWaypoint != GetWayPointsCount()-1)
m_currentWaypoint++;
}
else
{
if(m_currentWaypoint != 0)
m_currentWaypoint--;
}
}
*/
// Set health to full if they at there last location before attacking
if(m_AIType != AITYPE_PET&&!skip_reset_hp)
m_Unit->SetUInt32Value(UNIT_FIELD_HEALTH,m_Unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH));
}
else
{
if( m_MONSTERState == STOPPED )
{
// return to the home
if( m_returnX == 0.0f && m_returnY == 0.0f )
{
m_returnX = m_Unit->GetSpawnX();
m_returnY = m_Unit->GetSpawnY();
m_returnZ = m_Unit->GetSpawnZ();
}
MoveTo(m_returnX, m_returnY, m_returnZ, m_Unit->GetSpawnO());
}
}
}
if(m_fleeTimer)
{
if(m_fleeTimer > p_time)
{
m_fleeTimer -= p_time;
_CalcDestinationAndMove(m_nextTarget, 5.0f);
}
else
{
m_fleeTimer = 0;
SetNextTarget(FindTargetForSpell(m_nextSpell));
}
}
//Pet Dismiss after a certian ditance away
/*if(m_AIType == AITYPE_PET && m_PetOwner != NULL)
{
float dist = (m_Unit->GetInstanceID() == m_PetOwner->GetInstanceID()) ?
m_Unit->GetDistanceSq(m_PetOwner) : 99999.0f;
if(dist > 8100.0f) //90 yard away we Dismissed
{
DismissPet();
return;
}
}*/
}
void AIInterface::_UpdateTimer(uint32 p_time)
{
if(m_updateAssistTimer > p_time)
{
m_updateAssistTimer -= p_time;
}else
{
m_updateAssist = true;
m_updateAssistTimer = TARGET_UPDATE_INTERVAL * 2 - m_updateAssistTimer - p_time;
}
if(m_updateTargetsTimer > p_time)
{
m_updateTargetsTimer -= p_time;
}else
{
m_updateTargets = true;
m_updateTargetsTimer = TARGET_UPDATE_INTERVAL * 2 - m_updateTargetsTimer - p_time;
}
}
void AIInterface::_UpdateTargets()
{
if( m_Unit->IsPlayer() || (m_AIType != AITYPE_PET && disable_targeting ))
return;
if( ( ( MONSTER* )m_Unit )->GetMONSTERName() && ( ( MONSTER* )m_Unit )->GetMONSTERName()->Type == CRITTER )
return;
AssistTargetSet::iterator i, i2;
TargetMap::iterator itr, it2;
// Find new Assist Targets and remove old ones
if(m_AIState == STATE_FLEEING)
{
FindFriends(100.0f/*10.0*/);
}
else if(m_AIState != STATE_IDLE && m_AIState != STATE_SCRIPTIDLE)
{
FindFriends(16.0f/*4.0f*/);
}
if( m_updateAssist )
{
m_updateAssist = false;
/* deque<Unit*> tokill;
//modified for vs2005 compatibility
for(i = m_assistTargets.begin(); i != m_assistTargets.end(); ++i)
{
if(m_Unit->GetDistanceSq((*i)) > 2500.0f|| !(*i)->isAlive() || !(*i)->CombatStatus.IsInCombat())
{
tokill.push_back(*i);
}
}
for(deque<Unit*>::iterator i2 = tokill.begin(); i2 != tokill.end(); ++i2)
m_assistTargets.erase(*i2);*/
for(i = m_assistTargets.begin(); i != m_assistTargets.end();)
{
i2 = i++;
if((*i2) == NULL || (*i2)->event_GetCurrentInstanceId() != m_Unit->event_GetCurrentInstanceId() ||
!(*i2)->isAlive() || m_Unit->GetDistanceSq((*i2)) >= 2500.0f || !(*i2)->CombatStatus.IsInCombat() )
{
m_assistTargets.erase( i2 );
}
}
}
if( m_updateTargets )
{
m_updateTargets = false;
/*deque<Unit*> tokill;
//modified for vs2005 compatibility
for(itr = m_aiTargets.begin(); itr != m_aiTargets.end();++itr)
{
if(!itr->first->isAlive() || m_Unit->GetDistanceSq(itr->first) >= 6400.0f)
{
tokill.push_back(itr->first);
}
}
for(deque<Unit*>::iterator itr = tokill.begin(); itr != tokill.end(); ++itr)
m_aiTargets.erase((*itr));
tokill.clear();*/
for(itr = m_aiTargets.begin(); itr != m_aiTargets.end();)
{
it2 = itr++;
#ifdef HACKY_CRASH_FIXES
if( !TargetUpdateCheck( it2->first) )
m_aiTargets.erase( it2 );
#else
if( it2->first->event_GetCurrentInstanceId() != m_Unit->event_GetCurrentInstanceId() ||
!it2->first->isAlive() || m_Unit->GetDistanceSq(it2->first) >= 6400.0f )
{
m_aiTargets.erase( it2 );
}
#endif
}
if(m_aiTargets.size() == 0
&& m_AIState != STATE_IDLE && m_AIState != STATE_FOLLOWING
&& m_AIState != STATE_EVADE && m_AIState != STATE_FEAR
&& m_AIState != STATE_WANDER && m_AIState != STATE_SCRIPTIDLE)
{
if(firstLeaveCombat)
{
Unit* target = FindTarget();
if(target)
{
AttackReaction(target, 1, 0);
}else
{
firstLeaveCombat = false;
}
}
/*else
{
HandleEvent(EVENT_LEAVECOMBAT, m_Unit, 0);
}*/
}
else if( m_aiTargets.size() == 0 && (m_AIType == AITYPE_PET && (m_Unit->IsPet() && static_cast<Pet*>(m_Unit)->GetPetState() == PET_STATE_AGGRESSIVE) || (!m_Unit->IsPet() && disable_melee == false ) ) )
{
Unit* target = FindTarget();
if( target )
{
AttackReaction(target, 1, 0);
}
}
}
// Find new Targets when we are ooc
if((m_AIState == STATE_IDLE || m_AIState == STATE_SCRIPTIDLE) && m_assistTargets.size() == 0)
{
Unit* target = FindTarget();
if(target)
{
AttackReaction(target, 1, 0);
}
}
}
///====================================================================
/// Desc: Updates Combat Status of m_Unit
///====================================================================
void AIInterface::_UpdateCombat(uint32 p_time)
{
if( m_AIType != AITYPE_PET && disable_combat )
return;
//just make sure we are not hitting self. This was reported as an exploit.Should never ocure anyway
if( m_nextTarget == m_Unit )
m_nextTarget = GetMostHated();
uint16 agent = m_aiCurrentAgent;
// If MONSTER is very far from spawn point return to spawnpoint
// If at instance dont return -- this is wrong ... instance MONSTERs always returns to spawnpoint, dunno how do you got this ideia.
if( m_AIType != AITYPE_PET
&& (m_outOfCombatRange && m_Unit->GetDistanceSq(m_returnX,m_returnY,m_returnZ) > m_outOfCombatRange)
&& m_AIState != STATE_EVADE
&& m_AIState != STATE_SCRIPTMOVE
&& !m_is_in_instance)
{
HandleEvent( EVENT_LEAVECOMBAT, m_Unit, 0 );
}
else if( m_nextTarget == NULL && m_AIState != STATE_FOLLOWING && m_AIState != STATE_SCRIPTMOVE )
{
// SetNextTarget(FindTargetForSpell(m_nextSpell));
m_nextTarget = GetMostHated();
if( m_nextTarget == NULL )
{
HandleEvent( EVENT_LEAVECOMBAT, m_Unit, 0 );
}
}
#ifdef HACKY_CRASH_FIXES
bool cansee = (m_nextTarget != NULL) ? CheckCurrentTarget() : NULL;
#else
bool cansee;
if(m_nextTarget && m_nextTarget->event_GetCurrentInstanceId() == m_Unit->event_GetCurrentInstanceId())
{
if( m_Unit->GetTypeId() == TYPEID_UNIT )
cansee = static_cast< MONSTER* >( m_Unit )->CanSee( m_nextTarget );
else
cansee = static_cast< Player* >( m_Unit )->CanSee( m_nextTarget );
}
else
{
if( m_nextTarget )
m_nextTarget = NULL; // corupt pointer
cansee = false;
}
#endif
if( cansee && m_nextTarget && m_nextTarget->isAlive() && m_AIState != STATE_EVADE && !m_Unit->isCasting() )
{
if( agent == AGENT_NULL || ( m_AIType == AITYPE_PET && !m_nextSpell ) ) // allow pets autocast
{
if( !m_nextSpell )
m_nextSpell = this->getSpell();
/*
if(!m_nextSpell && waiting_for_cooldown)
{
// don't start ning to the target for melee if we're waiting for a cooldown.
return;
}
*/
if(m_canFlee && !m_hasFleed
&& ((m_Unit->GetUInt32Value(UNIT_FIELD_HEALTH) / m_Unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH)) < m_FleeHealth ))
agent = AGENT_FLEE;
else if(m_canCallForHelp
&& !m_hasCalledForHelp
/*&& (m_CallForHelpHealth > (m_Unit->GetUInt32Value(UNIT_FIELD_HEALTH) / (m_Unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH) > 0 ? m_Unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH) : 1)))*/)
agent = AGENT_CALLFORHELP;
else if(m_nextSpell)
{
if(m_nextSpell->agent != AGENT_NULL)
{
agent = m_nextSpell->agent;
}
else
{
agent = AGENT_MELEE;
}
}
else
{
agent = AGENT_MELEE;
}
}
if(agent == AGENT_RANGED || agent == AGENT_MELEE)
{
if(m_canRangedAttack)
{
agent = AGENT_MELEE;
if(m_nextTarget->GetTypeId() == TYPEID_PLAYER)
{
float dist = m_Unit->GetDistanceSq(m_nextTarget);
if( static_cast< Player* >( m_nextTarget )->m_currentMovement == MOVE_ROOT || dist >= 64.0f )
{
agent = AGENT_RANGED;
}
}
else if( m_nextTarget->m_canMove == false || m_Unit->GetDistanceSq(m_nextTarget) >= 64.0f )
{
agent = AGENT_RANGED;
}
}
else
{
agent = AGENT_MELEE;
}
}
if(this->disable_melee && agent == AGENT_MELEE)
agent = AGENT_NULL;
if(this->disable_ranged && agent == AGENT_RANGED)
agent = AGENT_NULL;
if(this->disable_spell && agent == AGENT_SPELL)
agent = AGENT_NULL;
switch(agent)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -