📄 interface.cpp.svn-base
字号:
#include "StdAfx.h"
// only enable with COLLISION define.
#ifdef COLLISION
#define LOS_CHECKS 1
//#define LOS_ONLY_IN_INSTANCE 1
#endif
#ifdef WIN32
#define HACKY_CRASH_FIXES 1 // SEH stuff
#endif
AIInterface::AIInterface()
{
m_waypoints=NULL;
m_canMove = true;
m_destinationX = m_destinationY = m_destinationZ = 0;
m_nextPosX = m_nextPosY = m_nextPosZ = 0;
UnitToFollow = NULL;
FollowDistance = 0.0f;
m_fallowAngle = float(M_PI/2);
m_timeToMove = 0;
m_timeMoved = 0;
m_moveTimer = 0;
m_WayPointsShowing = false;
m_WayPointsShowBackwards = false;
m_currentWaypoint = 0;
m_moveBackward = false;
m_moveType = 0;
m_move = false;
m_moveSprint = false;
m_move = false;
m_MONSTERState = STOPPED;
m_canCallForHelp = false;
m_hasCalledForHelp = false;
m_fleeTimer = 0;
m_FleeDuration = 0;
m_canFlee = false;
m_hasFleed = false;
m_canRangedAttack = false;
m_FleeHealth = m_CallForHelpHealth = 0.0f;
m_AIState = STATE_IDLE;
m_updateAssist = false;
m_updateTargets = false;
m_updateAssistTimer = 1;
m_updateTargetsTimer = TARGET_UPDATE_INTERVAL;
m_nextSpell = NULL;
m_nextTarget = NULL;
totemspell = NULL;
m_Unit = NULL;
m_PetOwner = NULL;
m_aiCurrentAgent = AGENT_NULL;
m_Speed = 0.0f;
m_Speed = 0.0f;
UnitToFear = NULL;
firstLeaveCombat = true;
m_outOfCombatRange = 2500;
tauntedBy = NULL;
isTaunted = false;
soullinkedWith = NULL;
isSoulLinked = false;
m_AllowedToEnterCombat = true;
m_totalMoveTime = 0;
m_lastFollowX = m_lastFollowY = 0;
m_FearTimer = 0;
m_WanderTimer = 0;
m_totemspelltime = 0;
m_totemspelltimer = 0;
m_formationFollowAngle = 0.0f;
m_formationFollowDistance = 0.0f;
m_formationLinkTarget = 0;
m_formationLinkSqlId = 0;
m_currentHighestThreat = 0;
disable_combat = false;
disable_melee = false;
disable_ranged = false;
disable_spell = false;
disable_targeting = false;
next_spell_time = 0;
waiting_for_cooldown = false;
UnitToFollow_backup = NULL;
m_isGuard = false;
m_is_in_instance=false;
skip_reset_hp=false;
}
void AIInterface::Init(Unit *un, AIType at, MovementType mt)
{
ASSERT(at != AITYPE_PET);
m_AIType = at;
m_MovementType = mt;
m_AIState = STATE_IDLE;
m_MovementState = MOVEMENTSTATE_STOP;
m_Unit = un;
m_walkSpeed = m_Unit->m_walkSpeed*0.001f;//move distance per ms time
m_Speed = m_Unit->m_Speed*0.001f;//move distance per ms time
m_Speed = m_Unit->m_Speed * 0.001f;
/*if(!m_DefaultMeleeSpell)
{
m_DefaultMeleeSpell = new AI_Spell;
m_DefaultMeleeSpell->entryId = 0;
m_DefaultMeleeSpell->spellType = 0;
m_DefaultMeleeSpell->agent = AGENT_MELEE;
m_DefaultSpell = m_DefaultMeleeSpell;
}*/
m_sourceX = un->GetPositionX();
m_sourceY = un->GetPositionY();
m_sourceZ = un->GetPositionZ();
m_guardTimer = getMSTime();
}
AIInterface::~AIInterface()
{
for(list<AI_Spell*>::iterator itr = m_SKILLS.begin(); itr != m_SKILLS.end(); ++itr)
if((*itr)->custom_pointer)
delete (*itr);
}
void AIInterface::Init(Unit *un, AIType at, MovementType mt, Unit *owner)
{
ASSERT(at == AITYPE_PET || at == AITYPE_TOTEM);
m_AIType = at;
m_MovementType = mt;
m_AIState = STATE_IDLE;
m_MovementState = MOVEMENTSTATE_STOP;
m_Unit = un;
m_PetOwner = owner;
m_walkSpeed = m_Unit->m_walkSpeed*0.001f;//move distance per ms time
m_Speed = m_Unit->m_Speed*0.001f;//move/ms
m_Speed = m_Unit->m_Speed*0.001f;
m_sourceX = un->GetPositionX();
m_sourceY = un->GetPositionY();
m_sourceZ = un->GetPositionZ();
}
void AIInterface::HandleEvent(uint32 event, Unit* pUnit, uint32 misc1)
{
if( m_Unit == NULL ) return;
if(m_AIState != STATE_EVADE)
{
switch(event)
{
case EVENT_ENTERCOMBAT:
{
if( pUnit == NULL ) return;
/* send the message */
if( m_Unit->GetTypeId() == TYPEID_UNIT )
{
if( static_cast< MONSTER* >( m_Unit )->has_combat_text )
objmgr.HandleMonsterSayEvent( static_cast< MONSTER* >( m_Unit ), MONSTER_SAY_EVENT_ENTER_COMBAT );
CALL_SCRIPT_EVENT(m_Unit, OnCombatStart)(pUnit);
if( static_cast< MONSTER* >( m_Unit )->m_spawn && ( static_cast< MONSTER* >( m_Unit )->m_spawn->channel_target_go || static_cast< MONSTER* >( m_Unit )->m_spawn->channel_target_MONSTER))
{
m_Unit->SetUInt32Value(UNIT_CHANNEL_SPELL, 0);
m_Unit->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
}
}
// Stop the emote
m_Unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, 0);
m_returnX = m_Unit->GetPositionX();
m_returnY = m_Unit->GetPositionY();
m_returnZ = m_Unit->GetPositionZ();
m_move = true; // to the target
// dismount if mounted
m_Unit->SetUInt32Value(UNIT_FIELD_MOUNTDISPLAYID, 0);
if(m_AIState != STATE_ATTACKING)
StopMovement(0);
m_AIState = STATE_ATTACKING;
firstLeaveCombat = true;
if(pUnit && pUnit->GetInstanceID() == m_Unit->GetInstanceID())
{
m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, pUnit->GetGUID());
}
if(m_Unit->GetMapMgr()->GetMapInfo() && m_Unit->GetMapMgr()->GetMapInfo()->type == INSTANCE_RAID)
{
if(m_Unit->GetTypeId() == TYPEID_UNIT)
{
if(static_cast<MONSTER*>(m_Unit)->GetMONSTERName() && static_cast<MONSTER*>(m_Unit)->GetMONSTERName()->Rank == 3)
{
m_Unit->GetMapMgr()->AddCombatInProgress(m_Unit->GetGUID());
}
}
}
}break;
case EVENT_LEAVECOMBAT:
{
if( pUnit == NULL ) return;
if( pUnit->IsMONSTER() )
pUnit->RemoveNegativeAuras();
//cancel SKILLS that we are casting. Should remove bug where MONSTERs cast a spell after they died
// CancelSpellCast();
// restart emote
if(m_Unit->GetTypeId() == TYPEID_UNIT)
{
if( static_cast< MONSTER* >( m_Unit )->has_combat_text )
objmgr.HandleMonsterSayEvent( static_cast< MONSTER* >( m_Unit ), MONSTER_SAY_EVENT_ON_COMBAT_STOP );
if(static_cast<MONSTER*>(m_Unit)->original_emotestate)
m_Unit->SetUInt32Value(UNIT_NPC_EMOTESTATE, static_cast< MONSTER* >( m_Unit )->original_emotestate);
if(static_cast<MONSTER*>(m_Unit)->m_spawn && (static_cast< MONSTER* >( m_Unit )->m_spawn->channel_target_go || static_cast< MONSTER* >( m_Unit )->m_spawn->channel_target_MONSTER ) )
{
if(static_cast<MONSTER*>(m_Unit)->m_spawn->channel_target_go)
sEventMgr.AddEvent( static_cast< MONSTER* >( m_Unit ), &MONSTER::ChannelLinkUpGO, static_cast< MONSTER* >( m_Unit )->m_spawn->channel_target_go, EVENT_MONSTER_CHANNEL_LINKUP, 1000, 5, 0 );
if(static_cast<MONSTER*>(m_Unit)->m_spawn->channel_target_MONSTER)
sEventMgr.AddEvent( static_cast< MONSTER* >( m_Unit ), &MONSTER::ChannelLinkUpMONSTER, static_cast< MONSTER* >( m_Unit )->m_spawn->channel_target_MONSTER, EVENT_MONSTER_CHANNEL_LINKUP, 1000, 5, 0 );
}
}
//reset ProcCount
//ResetProcCounts();
m_move = true;
m_aiTargets.clear();
m_fleeTimer = 0;
m_hasFleed = false;
m_hasCalledForHelp = false;
m_nextSpell = NULL;
SetNextTarget(NULL);
m_Unit->CombatStatus.Vanished();
if(m_AIType == AITYPE_PET)
{
m_AIState = STATE_FOLLOWING;
UnitToFollow = m_PetOwner;
FollowDistance = 3.0f;
m_lastFollowX = m_lastFollowY = 0;
if(m_Unit->IsPet())
{
((Pet*)m_Unit)->SetPetAction(PET_ACTION_FOLLOW);
if( m_Unit->GetEntry() == 416 && m_Unit->isAlive() && m_Unit->IsInWorld() )
{
((Pet*)m_Unit)->HandleAutoCastEvent(AUTOCAST_EVENT_LEAVE_COMBAT);
}
}
HandleEvent(EVENT_FOLLOWOWNER, 0, 0);
}
else
{
m_AIState = STATE_EVADE;
Unit* SavedFollow = UnitToFollow;
UnitToFollow = NULL;
FollowDistance = 0.0f;
m_lastFollowX = m_lastFollowY = 0;
if(m_Unit->isAlive())
{
if(m_returnX != 0.0f && m_returnY != 0.0f && m_returnZ != 0.0f)
MoveTo(m_returnX,m_returnY,m_returnZ,m_Unit->GetOrientation());
else
{
MoveTo(m_Unit->GetSpawnX(),m_Unit->GetSpawnY(),m_Unit->GetSpawnZ(),m_Unit->GetSpawnO());
m_returnX=m_Unit->GetSpawnX();
m_returnY=m_Unit->GetSpawnY();
m_returnZ=m_Unit->GetSpawnZ();
}
MONSTER *aiowner = static_cast<MONSTER*>(m_Unit);
//clear tagger.
aiowner->Tagged = false;
aiowner->TaggerGuid = 0;
aiowner->SetUInt32Value(UNIT_DYNAMIC_FLAGS,aiowner->GetUInt32Value(UNIT_DYNAMIC_FLAGS) & ~(U_DYN_FLAG_TAGGED_BY_OTHER |U_DYN_FLAG_LOOTABLE));
aiowner->m_lootMethod = -1;
}
CALL_SCRIPT_EVENT(m_Unit, OnCombatStop)(SavedFollow);
}
if(m_Unit->GetMapMgr()->GetMapInfo() && m_Unit->GetMapMgr()->GetMapInfo()->type == INSTANCE_RAID)
{
if(m_Unit->GetTypeId() == TYPEID_UNIT)
{
if(static_cast<MONSTER*>(m_Unit)->GetMONSTERName() && static_cast<MONSTER*>(m_Unit)->GetMONSTERName()->Rank == 3)
{
m_Unit->GetMapMgr()->RemoveCombatInProgress(m_Unit->GetGUID());
}
}
}
// Remount if mounted
if(m_Unit->GetTypeId() == TYPEID_UNIT)
{
if( static_cast< MONSTER* >( m_Unit )->proto )
m_Unit->SetUInt32Value( UNIT_FIELD_MOUNTDISPLAYID, static_cast< MONSTER* >( m_Unit )->proto->MountedDisplayID );
}
}break;
case EVENT_DAMAGETAKEN:
{
if( pUnit == NULL ) return;
if( static_cast< MONSTER* >( m_Unit )->has_combat_text )
objmgr.HandleMonsterSayEvent( static_cast< MONSTER* >( m_Unit ), MONSTER_SAY_EVENT_ON_DAMAGE_TAKEN );
CALL_SCRIPT_EVENT(m_Unit, OnDamageTaken)(pUnit, float(misc1));
if(!modThreatByPtr(pUnit, misc1))
{
m_aiTargets.insert(TargetMap::value_type(pUnit, misc1));
}
m_Unit->CombatStatus.OnDamageDealt(pUnit);
}break;
case EVENT_FOLLOWOWNER:
{
m_AIState = STATE_FOLLOWING;
if(m_Unit->IsPet())
((Pet*)m_Unit)->SetPetAction(PET_ACTION_FOLLOW);
UnitToFollow = m_PetOwner;
m_lastFollowX = m_lastFollowY = 0;
FollowDistance = 4.0f;
m_aiTargets.clear();
m_fleeTimer = 0;
m_hasFleed = false;
m_hasCalledForHelp = false;
m_nextSpell = NULL;
SetNextTarget(NULL);
m_move = true;
}break;
case EVENT_FEAR:
{
if( pUnit == NULL ) return;
m_FearTimer = 0;
SetUnitToFear(pUnit);
CALL_SCRIPT_EVENT(m_Unit, OnFear)(pUnit, 0);
m_AIState = STATE_FEAR;
StopMovement(1);
UnitToFollow_backup = UnitToFollow;
UnitToFollow = NULL;
m_lastFollowX = m_lastFollowY = 0;
FollowDistance_backup = FollowDistance;
FollowDistance = 0.0f;
m_aiTargets.clear(); // we'll get a new target after we are unfeared
m_fleeTimer = 0;
m_hasFleed = false;
m_hasCalledForHelp = false;
// update speed
m_move = true;
getMoveFlags();
SetNextSpell(NULL);
SetNextTarget(NULL);
}break;
case EVENT_UNFEAR:
{
UnitToFollow = UnitToFollow_backup;
FollowDistance = FollowDistance_backup;
m_AIState = STATE_IDLE; // we need this to prevent permanent fear, wander, and other problems
SetUnitToFear(NULL);
StopMovement(1);
}break;
case EVENT_WANDER:
{
if( pUnit == NULL ) return;
m_WanderTimer = 0;
//CALL_SCRIPT_EVENT(m_Unit, OnWander)(pUnit, 0); FIXME
m_AIState = STATE_WANDER;
StopMovement(1);
UnitToFollow_backup = UnitToFollow;
UnitToFollow = NULL;
m_lastFollowX = m_lastFollowY = 0;
FollowDistance_backup = FollowDistance;
FollowDistance = 0.0f;
m_aiTargets.clear(); // we'll get a new target after we are unwandered
m_fleeTimer = 0;
m_hasFleed = false;
m_hasCalledForHelp = false;
// update speed
m_move = true;
getMoveFlags();
SetNextSpell(NULL);
SetNextTarget(NULL);
}break;
case EVENT_UNWANDER:
{
UnitToFollow = UnitToFollow_backup;
FollowDistance = FollowDistance_backup;
m_AIState = STATE_IDLE; // we need this to prevent permanent fear, wander, and other problems
StopMovement(1);
}break;
default:
{
}break;
}
}
//Should be able to do this stuff even when evading
switch(event)
{
case EVENT_UNITDIED:
{
if( pUnit == NULL ) return;
if( static_cast< MONSTER* >( m_Unit )->has_combat_text )
objmgr.HandleMonsterSayEvent( static_cast< MONSTER* >( m_Unit ), MONSTER_SAY_EVENT_ON_DIED );
CALL_SCRIPT_EVENT(m_Unit, OnDied)(pUnit);
m_AIState = STATE_IDLE;
StopMovement(0);
m_aiTargets.clear();
UnitToFollow = NULL;
m_lastFollowX = m_lastFollowY = 0;
UnitToFear = NULL;
FollowDistance = 0.0f;
m_fleeTimer = 0;
m_hasFleed = false;
m_hasCalledForHelp = false;
m_nextSpell = NULL;
SetNextTarget(NULL);
//reset ProcCount
//ResetProcCounts();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -