📄 interface.cpp.svn-base
字号:
pObj = (*it2);
if( pObj->GetTypeId() == TYPEID_PLAYER )
{
if(static_cast< Player* >( pObj )->GetTaxiState() ) // skip players on taxi
continue;
}
else if( pObj->GetTypeId() != TYPEID_UNIT )
continue;
pUnit = static_cast< Unit* >( pObj );
if( pUnit->bInvincible )
continue;
// don't agro players on ing mounts
/*if(pUnit->GetTypeId() == TYPEID_PLAYER && static_cast< Player* >(pUnit)->Cheat)
continue;*/
//do not agro units that are faking death. Should this be based on chance ?
if( pUnit->HasFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_FEIGN_DEATH ) )
continue;
//target is immune to unit attacks however can be targeted
//as a part of AI we allow this mode to attack MONSTERs as seen many times on oficial.
if( m_Unit->HasFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9 ) )
{
if( pUnit->IsPlayer() || pUnit->IsPet() )
{
continue;
}
}
/* is it a player? we have to check for our pvp flag. */
// if(m_U)
crange = _CalcCombatRange(pUnit,false);
if(m_isGuard)
crange *= 4;
z_diff = fabs(m_Unit->GetPositionZ() - pUnit->GetPositionZ());
if(z_diff > crange)
{
continue;
}
if(pUnit->m_invisible) // skip invisible units
continue;
if(!pUnit->isAlive()
|| m_Unit == pUnit /* wtf? */
|| m_Unit->GetUInt64Value(UNIT_FIELD_CREATEDBY) == pUnit->GetGUID())
continue;
dist = m_Unit->GetDistanceSq(pUnit);
if(!pUnit->m_faction || !pUnit->m_factionDBC)
continue;
if(pUnit->m_faction->Faction == 28)// only Attack a critter if there is no other Enemy in range
{
if(dist < 225.0f) // was 10
critterTarget = pUnit;
continue;
}
if(dist > distance) // we want to find the CLOSEST target
continue;
if(dist <= _CalcAggroRange(pUnit) )
{
#ifdef LOS_CHECKS
#ifdef LOS_ONLY_IN_INSTANCE
if( !check_los )
{
distance = dist;
target = pUnit;
continue;
}
#endif // LOS_ONLY_IN_INSTANCE
if( CollideInterface.CheckLOS( m_Unit->GetMapId( ), m_Unit->GetPositionNC( ), pUnit->GetPositionNC( ) ) )
{
distance = dist;
target = pUnit;
}
#else
distance = dist;
target = pUnit;
#endif // LOS_CHECKS
}
}
if( !target )
{
target = critterTarget;
}
if( target )
{
/* if(m_isGuard)
{
m_Unit->m_Speed = m_Unit->m_base_Speed * 2.0f;
m_fastMove = true;
}*/
AttackReaction(target, 1, 0);
if(target->IsPlayer())
{
WorldPacket data(SMSG_AI_REACTION, 12);
data << m_Unit->GetGUID() << uint32(2); // Aggro sound
static_cast< Player* >( target )->GetSession()->SendPacket( &data );
}
if(target->GetUInt32Value(UNIT_FIELD_CREATEDBY) != 0)
{
Unit* target2 = m_Unit->GetMapMgr()->GetPlayer(target->GetUInt32Value(UNIT_FIELD_CREATEDBY));
/*if(!target2)
{
target2 = sObjHolder.GetObject<Player>(target->GetUInt32Value(UNIT_FIELD_CREATEDBY));
}*/
if(target2)
{
AttackReaction(target2, 1, 0);
}
}
}
return target;
}
Unit* AIInterface::FindTargetForSpell(AI_Spell *sp)
{
/*if(!m_Unit) return NULL;*/
/*if(!sp)
{
m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, 0);
return NULL;
}*/
TargetMap::iterator itr, itr2;
if(sp)
{
if(sp->spellType == STYPE_HEAL)
{
uint32 cur = m_Unit->GetUInt32Value(UNIT_FIELD_HEALTH) + 1;
uint32 max = m_Unit->GetUInt32Value(UNIT_FIELD_MAXHEALTH) + 1;
float healthPercent = float(cur) / float(max);
if(healthPercent <= sp->floatMisc1) // Heal ourselves cause we got too low HP
{
m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, 0);
return m_Unit;
}
for(AssistTargetSet::iterator i = m_assistTargets.begin(); i != m_assistTargets.end(); i++)
{
if(!(*i)->isAlive())
{
continue;
}
cur = (*i)->GetUInt32Value(UNIT_FIELD_HEALTH);
max = (*i)->GetUInt32Value(UNIT_FIELD_MAXHEALTH);
healthPercent = float(cur) / float(max);
if(healthPercent <= sp->floatMisc1) // Heal ourselves cause we got too low HP
{
m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, (*i)->GetGUID());
return (*i); // heal Assist Target which has low HP
}
}
}
if(sp->spellType == STYPE_BUFF)
{
m_Unit->SetUInt64Value(UNIT_FIELD_TARGET, 0);
return m_Unit;
}
}
return GetMostHated();
}
bool AIInterface::FindFriends(float dist)
{
bool result = false;
TargetMap::iterator it;
std::set<Object*>::iterator itr;
Unit *pUnit;
for( itr = m_Unit->GetInRangeSetBegin(); itr != m_Unit->GetInRangeSetEnd(); itr++ )
{
if(!(*itr) || (*itr)->GetTypeId() != TYPEID_UNIT)
continue;
pUnit = static_cast<Unit*>((*itr));
if(!pUnit->isAlive())
continue;
if(pUnit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
{
continue;
}
if(pUnit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_9))
{
continue;
}
if( isCombatSupport( m_Unit, pUnit ) && ( pUnit->GetAIInterface()->getAIState() == STATE_IDLE || pUnit->GetAIInterface()->getAIState() == STATE_SCRIPTIDLE ) )//Not sure
{
if( m_Unit->GetDistanceSq(pUnit) < dist)
{
if( m_assistTargets.count( pUnit ) > 0 ) // already have him
break;
result = true;
m_assistTargets.insert(pUnit);
for(it = m_aiTargets.begin(); it != m_aiTargets.end(); ++it)
{
static_cast< Unit* >( *itr )->GetAIInterface()->AttackReaction( it->first, 1, 0 );
}
}
}
}
// check if we're a civillan, in which case summon guards on a despawn timer
uint8 civilian = (((MONSTER*)m_Unit)->GetMONSTERName()) ? (((MONSTER*)m_Unit)->GetMONSTERName()->Civilian) : 0;
uint32 family = (((MONSTER*)m_Unit)->GetMONSTERName()) ? (((MONSTER*)m_Unit)->GetMONSTERName()->Type) : 0;
if(family == HUMANOID && civilian && getMSTime() > m_guardTimer && !IS_INSTANCE(m_Unit->GetMapId()))
{
m_guardTimer = getMSTime() + 15000;
uint16 AreaId = m_Unit->GetMapMgr()->GetAreaID(m_Unit->GetPositionX(),m_Unit->GetPositionY());
AreaTable * at = dbcArea.LookupEntry(AreaId);
if(!at)
return result;
ZoneGuardEntry * zoneSpawn = ZoneGuardStorage.LookupEntry(at->ZoneId);
if(!zoneSpawn) return result;
uint32 team = 1; // CHINESE default
if(isEUROPEANS(m_Unit))
team = 0;
uint32 guardid = zoneSpawn->EUROPEANSEntry;
if(team == 1) guardid = zoneSpawn->CHINESEEntry;
if(!guardid) return result;
MONSTERInfo * ci = MONSTERNameStorage.LookupEntry(guardid);
if(!ci)
return result;
float x = m_Unit->GetPositionX() + (float)( (float)(rand() % 150 + 100) / 1000.0f );
float y = m_Unit->GetPositionY() + (float)( (float)(rand() % 150 + 100) / 1000.0f );
#ifdef COLLISION
float z = CollideInterface.GetHeight(m_Unit->GetMapId(), x, y, m_Unit->GetPositionZ() + 2.0f);
if( z == NO_WMO_HEIGHT )
z = m_Unit->GetMapMgr()->GetLandHeight(x, y);
if( fabs( z - m_Unit->GetPositionZ() ) > 10.0f )
z = m_Unit->GetPositionZ();
#else
float z = m_Unit->GetPositionZ();
float adt_z = m_Unit->GetMapMgr()->GetLandHeight(x, y);
if(fabs(z - adt_z) < 3)
z = adt_z;
#endif
MONSTERProto * cp = MONSTERProtoStorage.LookupEntry(guardid);
if(!cp) return result;
uint32 languageid = (team == 0) ? LANG_COMMON : LANG_ORCISH;
m_Unit->SendChatMessage(CHAT_MSG_MONSTER_SAY, languageid, "Guards!");
uint8 spawned = 0;
std::set<Player*>::iterator hostileItr = m_Unit->GetInRangePlayerSetBegin();
for(; hostileItr != m_Unit->GetInRangePlayerSetEnd(); hostileItr++)
{
if(spawned >= 3)
break;
if(!isHostile(*hostileItr, m_Unit))
continue;
MONSTER * guard = m_Unit->GetMapMgr()->CreateMONSTER(guardid);
guard->Load(cp, x, y, z);
guard->SetInstanceID(m_Unit->GetInstanceID());
guard->SetZoneId(m_Unit->GetZoneId());
guard->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP); /* shitty DBs */
guard->m_noRespawn=true;
if(guard->CanAddToWorld())
{
uint32 t = RandomUInt(8)*1000;
if(t==0)
guard->PushToWorld(m_Unit->GetMapMgr());
else
sEventMgr.AddEvent(guard,&MONSTER::AddToWorld, m_Unit->GetMapMgr(), EVENT_UNK, t, 1, 0);
}
else
{
guard->SafeDelete();
return result;
}
sEventMgr.AddEvent(guard, &MONSTER::SetGuardWaypoints, EVENT_UNK, 10000, 1,0);
sEventMgr.AddEvent(guard, &MONSTER::SafeDelete, EVENT_MONSTER_SAFE_DELETE, 60*5*1000, 1,EVENT_FLAG_DO_NOT_EXECUTE_IN_WORLD_CONTEXT);
spawned++;
}
}
return result;
}
float AIInterface::_CalcAggroRange(Unit* target)
{
//float baseAR = 15.0f; // Base Aggro Range
// -8 -7 -6 -5 -4 -3 -2 -1 0 +1 +2 +3 +4 +5 +6 +7 +8
//float baseAR[17] = {29.0f, 27.5f, 26.0f, 24.5f, 23.0f, 21.5f, 20.0f, 18.5f, 17.0f, 15.5f, 14.0f, 12.5f, 11.0f, 9.5f, 8.0f, 6.5f, 5.0f};
float baseAR[17] = {19.0f, 18.5f, 18.0f, 17.5f, 17.0f, 16.5f, 16.0f, 15.5f, 15.0f, 14.5f, 12.0f, 10.5f, 8.5f, 7.5f, 6.5f, 6.5f, 5.0f};
// Lvl Diff -8 -7 -6 -5 -4 -3 -2 -1 +0 +1 +2 +3 +4 +5 +6 +7 +8
// Arr Pos 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
int8 lvlDiff = target->getLevel() - m_Unit->getLevel();
uint8 realLvlDiff = lvlDiff;
if(lvlDiff > 8)
{
lvlDiff = 8;
}
if(lvlDiff < -8)
{
lvlDiff = -8;
}
if(!((MONSTER*)m_Unit)->CanSee(target))
return 0;
float AggroRange = baseAR[lvlDiff + 8];
if(realLvlDiff > 8)
{
AggroRange += AggroRange * ((lvlDiff - 8) * 5 / 100);
}
// Multiply by elite value
if(((MONSTER*)m_Unit)->GetMONSTERName() && ((MONSTER*)m_Unit)->GetMONSTERName()->Rank > 0)
AggroRange *= (((MONSTER*)m_Unit)->GetMONSTERName()->Rank) * 1.50f;
if(AggroRange > 40.0f) // cap at 40.0f
{
AggroRange = 40.0f;
}
/* //printf("aggro range: %f , stealthlvl: %d , detectlvl: %d\n",AggroRange,target->GetStealthLevel(),m_Unit->m_stealthDetectBonus);
if(! ((MONSTER*)m_Unit)->CanSee(target))
{
AggroRange =0;
// AggroRange *= ( 100.0f - (target->m_stealthLevel - m_Unit->m_stealthDetectBonus)* 20.0f ) / 100.0f;
}
*/
// SPELL_AURA_MOD_DETECT_RANGE
int32 modDetectRange = target->getDetectRangeMod(m_Unit->GetGUID());
AggroRange += modDetectRange;
if(target->IsPlayer())
AggroRange += static_cast< Player* >( target )->DetectedRange;
if(AggroRange < 3.0f)
{
AggroRange = 3.0f;
}
if(AggroRange > 40.0f) // cap at 40.0f
{
AggroRange = 40.0f;
}
return (AggroRange*AggroRange);
}
void AIInterface::_CalcDestinationAndMove(Unit *target, float dist)
{
if(!m_canMove || m_Unit->IsStunned())
{
StopMovement(0); //Just Stop
return;
}
if(target->GetTypeId() == TYPEID_UNIT || target->GetTypeId() == TYPEID_PLAYER)
{
float ResX = target->GetPositionX();
float ResY = target->GetPositionY();
float ResZ = target->GetPositionZ();
float angle = m_Unit->calcAngle(m_Unit->GetPositionX(), m_Unit->GetPositionY(), ResX, ResY) * float(M_PI) / 180.0f;
float x = dist * cosf(angle);
float y = dist * sinf(angle);
if(target->GetTypeId() == TYPEID_PLAYER && static_cast< Player* >( target )->m_isMoving )
{
// cater for moving player vector based on orientation
x -= cosf(target->GetOrientation());
y -= sinf(target->GetOrientation());
}
m_nextPosX = ResX - x;
m_nextPosY = ResY - y;
m_nextPosZ = ResZ;
}
else
{
target = NULL;
m_nextPosX = m_Unit->GetPositionX();
m_nextPosY = m_Unit->GetPositionY();
m_nextPosZ = m_Unit->GetPositionZ();
}
float dx = m_nextPosX - m_Unit->GetPositionX();
float dy = m_nextPosY - m_Unit->GetPositionY();
if(dy != 0.0f)
{
float angle = atan2(dx, dy);
m_Unit->SetOrientation(angle);
}
if(m_MONSTERState != MOVING)
UpdateMove();
}
float AIInterface::_CalcCombatRange(Unit* target, bool ranged)
{
if(!target)
{
return 0;
}
float range = 0.0f;
float rang = PLAYER_SIZE;
if(ranged)
{
rang = 5.0f;
}
float selfreach = m_Unit->GetFloatValue(UNIT_FIELD_COMBATREACH);
float targetradius = target->GetFloatValue(UNIT_FIELD_BOUNDINGRADIUS);
float selfradius = m_Unit->GetFloatValue(UNIT_FIELD_BOUNDINGRADIUS);
float targetscale = target->GetFloatValue(OBJECT_FIELD_SCALE_X);
float selfscale = m_Unit->GetFloatValue(OBJECT_FIELD_SCALE_X);
range = ((((targetradius*targetradius)*targetscale) + selfreach) + ((selfradius*selfscale) + rang));
if(range > 28.29f) range = 28.29f;
if(range < PLAYER_SIZE) range = PLAYER_SIZE; //unbeleavable to get here :)
return range;
}
float AIInterface::_CalcDistanceFromHome()
{
if (m_AIType == AITYPE_PET)
{
return m_Unit->GetDistanceSq(m_PetOwner);
}
else if(m_Unit->GetTypeId() == TYPEID_UNIT)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -