📄 interface.cpp.svn-base
字号:
{
case AGENT_MELEE:
{
float combatReach[2]; // Calculate Combat Reach
float distance = m_Unit->CalcDistance(m_nextTarget);
combatReach[0] = PLAYER_SIZE;
combatReach[1] = _CalcCombatRange(m_nextTarget, false);
if(
distance >= combatReach[0] &&
distance <= combatReach[1] + DISTANCE_TO_SMALL_TO_WALK) // Target is in Range -> Attack
{
if(UnitToFollow != NULL)
{
UnitToFollow = NULL; //we shouldn't be following any one
m_lastFollowX = m_lastFollowY = 0;
//m_Unit->setAttackTarget(NULL); // remove ourselves from any target that might have been followed
}
FollowDistance = 0.0f;
// m_move = false;
//FIXME: offhand shit
if(m_Unit->isAttackReady(false) && !m_fleeTimer)
{
m_MONSTERState = ATTACKING;
bool infront = m_Unit->isInFront(m_nextTarget);
if(!infront) // set InFront
{
//prevent mob from rotating while stunned
if(!m_Unit->IsStunned ())
{
setInFront(m_nextTarget);
infront = true;
}
}
if(infront)
{
m_Unit->setAttackTimer(0, false);
#ifdef ENABLE_MONSTER_DAZE
//we require to know if strike was succesfull. If there was no dmg then target cannot be dazed by it
uint32 health_before_strike=m_nextTarget->GetUInt32Value(UNIT_FIELD_HEALTH);
#endif
m_Unit->Strike( m_nextTarget, ( agent == AGENT_MELEE ? MELEE : RANGED ), NULL, 0, 0, 0, false, false );
#ifdef ENABLE_MONSTER_DAZE
//now if the target is facing his back to us then we could just cast dazed on him :P
//as far as i know dazed is casted by most of the MONSTERs but feel free to remove this code if you think otherwise
if(m_nextTarget &&
!(m_Unit->m_factionDBC->RepListId == -1 && m_Unit->m_faction->FriendlyMask==0 && m_Unit->m_faction->HostileMask==0) /* neutral MONSTER */
&& m_nextTarget->IsPlayer() && !m_Unit->IsPet() && health_before_strike>m_nextTarget->GetUInt32Value(UNIT_FIELD_HEALTH)
&& Rand(m_Unit->get_chance_to_daze(m_nextTarget)))
{
float our_facing=m_Unit->calcRadAngle(m_Unit->GetPositionX(),m_Unit->GetPositionY(),m_nextTarget->GetPositionX(),m_nextTarget->GetPositionY());
float his_facing=m_nextTarget->GetOrientation();
if(fabs(our_facing-his_facing)<MONSTER_DAZE_TRIGGER_ANGLE && !m_nextTarget->HasNegativeAura(MONSTER_SPELL_TO_DAZE))
{
SpellEntry *info = dbcSpell.LookupEntry(MONSTER_SPELL_TO_DAZE);
Spell *sp = new Spell(m_Unit, info, false, NULL);
SpellCastTargets targets;
targets.m_unitTarget = m_nextTarget->GetGUID();
sp->prepare(&targets);
}
}
#endif
}
}
}
else // Target out of Range -> to it
{
//calculate next move
float dist = combatReach[1]-PLAYER_SIZE;
if(dist < PLAYER_SIZE)
dist = PLAYER_SIZE; //unbelievable how this could happen
if (distance<combatReach[0])
dist = -(distance+combatReach[0]*0.6666f);
m_move = true;
_CalcDestinationAndMove(m_nextTarget, dist);
}
}break;
case AGENT_RANGED:
{
float combatReach[2]; // Calculate Combat Reach
float distance = m_Unit->CalcDistance(m_nextTarget);
combatReach[0] = 8.0f;
combatReach[1] = 30.0f;
if(distance >= combatReach[0] && distance <= combatReach[1]) // Target is in Range -> Attack
{
if(UnitToFollow != NULL)
{
UnitToFollow = NULL; //we shouldn't be following any one
m_lastFollowX = m_lastFollowY = 0;
//m_Unit->setAttackTarget(NULL); // remove ourselves from any target that might have been followed
}
FollowDistance = 0.0f;
// m_move = false;
//FIXME: offhand shit
if(m_Unit->isAttackReady(false) && !m_fleeTimer)
{
m_MONSTERState = ATTACKING;
bool infront = m_Unit->isInFront(m_nextTarget);
if(!infront) // set InFront
{
//prevent mob from rotating while stunned
if(!m_Unit->IsStunned ())
{
setInFront(m_nextTarget);
infront = true;
}
}
if(infront)
{
m_Unit->setAttackTimer(0, false);
SpellEntry *info = dbcSpell.LookupEntry(SPELL_RANGED_GENERAL);
if(info)
{
Spell *sp = new Spell(m_Unit, info, false, NULL);
SpellCastTargets targets;
targets.m_unitTarget = m_nextTarget->GetGUID();
sp->prepare(&targets);
//Lets make spell handle this
//m_Unit->Strike( m_nextTarget, ( agent == AGENT_MELEE ? MELEE : RANGED ), NULL, 0, 0, 0 );
}
}
}
}
else // Target out of Range -> to it
{
//calculate next move
float dist;
if(distance < combatReach[0])// Target is too near
dist = 9.0f;
else
dist = 20.0f;
m_move = true;
_CalcDestinationAndMove(m_nextTarget, dist);
}
}break;
case AGENT_SPELL:
{
if(!m_nextSpell || !m_nextTarget)
return; // this shouldnt happen
/* stop moving so we don't interrupt the spell */
//this the way justly suggested
// if(m_nextSpell->spell->CastingTimeIndex != 1)
//do not stop for instant SKILLS
SpellCastTime *sd = dbcSpellCastTime.LookupEntry(m_nextSpell->spell->CastingTimeIndex);
if(GetCastTime(sd) != 0)
StopMovement(0);
float distance = m_Unit->GetDistanceSq(m_nextTarget);
bool los = true;
#ifdef COLLISION
los = CollideInterface.CheckLOS(m_Unit->GetMapId(), m_Unit->GetPositionNC(),m_nextTarget->GetPositionNC());
#endif
if(los && ((distance <= (m_nextSpell->maxrange*m_nextSpell->maxrange) && distance >= (m_nextSpell->minrange*m_nextSpell->minrange)) || m_nextSpell->maxrange == 0)) // Target is in Range -> Attack
{
SpellEntry* spellInfo = m_nextSpell->spell;
/* if(m_nextSpell->procCount)
m_nextSpell->procCount--;*/
SpellCastTargets targets = setSpellTargets(spellInfo, m_nextTarget);
uint32 targettype = m_nextSpell->spelltargetType;
switch(targettype)
{
case TTYPE_CASTER:
case TTYPE_SINGLETARGET:
{
CastSpell(m_Unit, spellInfo, targets);
break;
}
case TTYPE_SOURCE:
{
m_Unit->CastSpellAoF(targets.m_srcX,targets.m_srcY,targets.m_srcZ, spellInfo, true);
break;
}
case TTYPE_DESTINATION:
{
m_Unit->CastSpellAoF(targets.m_destX,targets.m_destY,targets.m_destZ, spellInfo, true);
break;
}
}
// CastSpell(m_Unit, spellInfo, targets);
if(m_nextSpell&&m_nextSpell->cooldown)
m_nextSpell->cooldowntime = getMSTime() + m_nextSpell->cooldown;
//add pet spell after use to pet owner with some chance
if(m_Unit->IsPet() && m_PetOwner->IsPlayer())
{
Pet * pPet = static_cast<Pet*>(m_Unit);
if(pPet && Rand(10))
pPet->AddPetSpellToOwner(spellInfo->Id);
}
m_nextSpell = NULL;
}
else // Target out of Range -> to it
{
//calculate next move
m_move = true;
if(m_nextSpell->maxrange < 5.0f)
_CalcDestinationAndMove(m_nextTarget, 0.0f);
else
_CalcDestinationAndMove(m_nextTarget, m_nextSpell->maxrange - 5.0f);
/*Destination* dst = _CalcDestination(m_nextTarget, dist);
MoveTo(dst->x, dst->y, dst->z,0);
delete dst;*/
}
}break;
case AGENT_FLEE:
{
//float dist = 5.0f;
m_move = false;
if(m_fleeTimer == 0)
m_fleeTimer = m_FleeDuration;
/*Destination* dst = _CalcDestination(m_nextTarget, dist);
MoveTo(dst->x, dst->y, dst->z,0);
delete dst;*/
_CalcDestinationAndMove(m_nextTarget, 5.0f);
if(!m_hasFleed)
CALL_SCRIPT_EVENT(m_Unit, OnFlee)(m_nextTarget);
m_AIState = STATE_FLEEING;
//removed by Zack : somehow MONSTER starts to attack sefl. Just making sure it is not this one
// m_nextTarget = m_Unit;
// m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, 0);
SetNextTarget(NULL);
WorldPacket data( SMSG_MESSAGECHAT, 100 );
string msg = "%s attempts to away in fear!";
data << (uint8)CHAT_MSG_CHANNEL;
data << (uint32)LANG_UNIVERSAL;
data << (uint32)( strlen( static_cast< MONSTER* >( m_Unit )->GetMONSTERName()->Name ) + 1 );
data << static_cast< MONSTER* >( m_Unit )->GetMONSTERName()->Name;
data << (uint64)0;
data << (uint32)(msg.size() + 1);
data << msg;
data << uint8(0);
m_Unit->SendMessageToSet(&data, false);
//m_Unit->SendChatMessage(CHAT_MSG_MONSTER_EMOTE, LANG_UNIVERSAL, msg);
//sChatHandler.FillMessageData(&data, CHAT_MSG_MONSTER_EMOTE, LANG_UNIVERSAL, msg, m_Unit->GetGUID());
m_hasFleed = true;
}break;
case AGENT_CALLFORHELP:
{
FindFriends( 50.0f /*7.0f*/ );
m_hasCalledForHelp = true; // We only want to call for Help once in a Fight.
if( m_Unit->GetTypeId() == TYPEID_UNIT )
objmgr.HandleMonsterSayEvent( static_cast< MONSTER* >( m_Unit ), MONSTER_SAY_EVENT_CALL_HELP );
CALL_SCRIPT_EVENT( m_Unit, OnCallForHelp )();
}break;
}
}
else if( !m_nextTarget || m_nextTarget->GetInstanceID() != m_Unit->GetInstanceID() || !m_nextTarget->isAlive() || !cansee )
{
SetNextTarget( NULL );
// no more target
//m_Unit->setAttackTarget(NULL);
}
}
void AIInterface::DismissPet()
{
/*
if(m_AIType != AITYPE_PET)
return;
if(!m_PetOwner)
return;
if(m_PetOwner->GetTypeId() != TYPEID_PLAYER)
return;
if(m_Unit->GetUInt32Value(UNIT_CREATED_BY_SPELL) == 0)
static_cast< Player* >( m_PetOwner )->SetFreePetNo(false, (int)m_Unit->GetUInt32Value(UNIT_FIELD_PETNUMBER));
static_cast< Player* >( m_PetOwner )->SetPet(NULL);
static_cast< Player* >( m_PetOwner )->SetPetName("");
//FIXME:Check hunter pet or not
//FIXME:Check enslaved MONSTER
m_PetOwner->SetUInt64Value(UNIT_FIELD_SUMMON, 0);
WorldPacket data;
data.Initialize(SMSG_PET_SKILLS);
data << (uint64)0;
static_cast< Player* >( m_PetOwner )->GetSession()->SendPacket(&data);
sEventMgr.RemoveEvents(((MONSTER*)m_Unit));
if(m_Unit->IsInWorld())
{
m_Unit->RemoveFromWorld();
}
//setup an event to delete the MONSTER
sEventMgr.AddEvent(((MONSTER*)this->m_Unit), &MONSTER::DeleteMe, EVENT_DELETE_TIMER, 1, 1);*/
}
void AIInterface::AttackReaction(Unit* pUnit, uint32 damage_dealt, uint32 spellId)
{
if( m_AIState == STATE_EVADE || m_fleeTimer != 0 || !pUnit || !pUnit->isAlive() || m_Unit->IsPacified() || m_Unit->IsFeared() || m_Unit->IsStunned() || !m_Unit->isAlive() )
{
return;
}
if( m_Unit == pUnit )
{
return;
}
if( m_AIState == STATE_IDLE || m_AIState == STATE_FOLLOWING )
{
WipeTargetList();
HandleEvent(EVENT_ENTERCOMBAT, pUnit, 0);
}
HandleEvent(EVENT_DAMAGETAKEN, pUnit, _CalcThreat(damage_dealt, spellId ? dbcSpell.LookupEntryForced(spellId) : NULL, pUnit));
}
bool AIInterface::HealReaction(Unit* caster, Unit* victim, uint32 amount)
{
if(!caster || !victim)
{
printf("!!!BAD POINTER IN AIInterface::HealReaction!!!\n");
return false;
}
int casterInList = 0, victimInList = 0;
if(m_aiTargets.find(caster) != m_aiTargets.end())
casterInList = 1;
if(m_aiTargets.find(victim) != m_aiTargets.end())
victimInList = 1;
/*for(i = m_aiTargets.begin(); i != m_aiTargets.end(); i++)
{
if(casterInList && victimInList)
{ // no need to check the rest, just break that
break;
}
if(i->target == victim)
{
victimInList = true;
}
if(i->target == caster)
{
casterInList = true;
}
}*/
if(!victimInList && !casterInList) // none of the Casters is in the MONSTERs Threat list
{
return false;
}
if(!casterInList && victimInList) // caster is not yet in Combat but victim is
{
// get caster into combat if he's hostile
if(isHostile(m_Unit, caster))
{
//AI_Target trgt;
//trgt.target = caster;
//trgt.threat = amount;
//m_aiTargets.push_back(trgt);
m_aiTargets.insert(TargetMap::value_type(caster, amount));
return true;
}
return false;
}
else if(casterInList && victimInList) // both are in combat already
{
// mod threat for caster
modThreatByPtr(caster, amount);
return true;
}
else // caster is in Combat already but victim is not
{
modThreatByPtr(caster, amount);
// both are players so they might be in the same group
if( caster->GetTypeId() == TYPEID_PLAYER && victim->GetTypeId() == TYPEID_PLAYER )
{
if( static_cast< Player* >( caster )->GetGroup() == static_cast< Player* >( victim )->GetGroup() )
{
// get victim into combat since they are both
// in the same party
if( isHostile( m_Unit, victim ) )
{
m_aiTargets.insert( TargetMap::value_type( victim, 1 ) );
return true;
}
return false;
}
}
}
return false;
}
void AIInterface::OnDeath(Object* pKiller)
{
if(pKiller->GetTypeId() == TYPEID_PLAYER || pKiller->GetTypeId() == TYPEID_UNIT)
HandleEvent(EVENT_UNITDIED, static_cast<Unit*>(pKiller), 0);
else
HandleEvent(EVENT_UNITDIED, m_Unit, 0);
}
Unit* AIInterface::FindTarget()
{// find nearest hostile Target to attack
if( !m_AllowedToEnterCombat )
return NULL;
Unit* target = NULL;
Unit* critterTarget = NULL;
float distance = 999999.0f; // that should do it.. :p
float crange;
float z_diff;
#ifdef LOS_CHECKS
#ifdef LOS_ONLY_IN_INSTANCE
bool los = true;
bool check_los = true;
if( m_Unit->GetMapMgr()->GetMapInfo()->type == INSTANCE_NULL )
check_los = false;
#endif
#endif
std::set<Object*>::iterator itr, it2;
Object *pObj;
Unit *pUnit;
float dist;
bool pvp=true;
if(m_Unit->GetTypeId()==TYPEID_UNIT&&((MONSTER*)m_Unit)->GetMONSTERName()&&((MONSTER*)m_Unit)->GetMONSTERName()->Civilian)
pvp=false;
//target is immune to all form of attacks, cant attack either.
if(m_Unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
{
return 0;
}
for( itr = m_Unit->GetInRangeOppFactsSetBegin(); itr != m_Unit->GetInRangeOppFactsSetEnd(); )
{
it2 = itr;
++itr;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -