l2-unlegits/l2detect/UserAI_FolAsi.cpp
2012-02-01 05:25:08 +00:00

203 lines
6.9 KiB
C++

#include "stdafx.h"
#include "UserAI.h"
#include "Logger.h"
#include "PacketInjector.h"
// ìåòîä áóäåò âûçûâàòüñÿ ñàìîå ïîçäíåå ðàç â 250 ìèëëèñåêóíä
void UserAI::UAI_ProcessFollow( class UserAI *cls )
{
if( !cls->folAsiCfg.m_follow_enable ) return;
if( cls->folAsiCfg.m_follow_dist < 0 ) return;
// check time
unsigned int t_now = GetTickCount();
if( (t_now - cls->m_last_follow_time_msec) < 1000 ) return; // follow only once per second
// check party
if( cls->folAsiCfg.m_follow_only_in_party && cls->party.getCount() < 1 ) return;
// get follow target oid
L2Player *plFollow = NULL;
if( cls->m_follow_oid == 0 )
{
log_error( LOG_USERAI, "Follow enabled after [%S], searching for its objectID...\n",
cls->folAsiCfg.m_follow_name );
// ïðèäåòñÿ ïðîéòèñü ïî âñåìó ìàññèâó ÷àðîâ, ñðàâíèâÿ ïî èìåíè
// ýòî íåáûñòðàÿ îïåðàöèÿ, è âäîáàâîê ïðèäåòñÿ äåðæàòü áëîêèðîâêó
// íà âñåì ìàññèâå ÷àðîâ, ÷òîáû íèêàêîé äðóãîé ïîòîê åãî íå èçìåíèë
// ïîêà ìû ïî íåìó ãóëÿåì
unsigned int i = 0, cnt = CharArray_GetCount(), nc = 0;
CharArray_Lock();
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i] )
{
if( _wcsicmp( chars_array[i]->charName, cls->folAsiCfg.m_follow_name ) == 0 )
{
plFollow = chars_array[i];
break;
}
nc++;
}
if( nc >= cnt ) break;
}
CharArray_Unlock(); // ñíèìåì íàêîíåö-òî áëîêèðîâêó
if( !plFollow ) // îáúåêòà öåëè follow íåò â çîíå âèäèìîñòè
{
//log_error( LOG_USERAI, ":( cannot find follow target oid - not in range?\n" );
return;
}
// óðÿ, íàøëè
cls->m_follow_oid = plFollow->objectID; // Çàïîìíèì objectID ÷òîá áîëüøå íå èñêàòü
UAI_Check_Distance_And_Follow( cls, plFollow );
return;
}
else // ìû óæå çíàåì oid öåëè ïðåñëåäîâàíèÿ
{
int idx = -1;
L2OBJECT_TYPE objType = L2OT_NONE;
// à âîò ýòî óæå íå ïîëíûé ïåðåáîð, î ïîèñê ïî objectID â áèíàðíîì äåðåâå, äîâîëüíî áûñòðûé
if( WorldObjectTree_GetInfoByObjectID( cls->m_follow_oid, &objType, &idx ) )
{
if( objType == L2OT_PC )
{
if( idx >= 0 )
UAI_Check_Distance_And_Follow( cls, chars_array[idx] );
}
else log_error( LOG_ERROR, "UAI Follow: follow target objType != L2OT_PC (%d)\n", (int)objType );
}
//else log_error( LOG_USERAI, "Follow: [%S] is not in range\n", cls->folAsiCfg.m_follow_name );
}
}
void UserAI::UAI_Check_Distance_And_Follow( class UserAI *cls, L2Player *followTarget )
{
float dx = (float)( followTarget->x - cls->usr.x );
float dy = (float)( followTarget->y - cls->usr.y );
float dz = (float)( followTarget->z - cls->usr.z );
float dist = sqrtf( dx*dx + dy*dy + dz*dz );
if( dist > 10000.0f ) // êàê-òî óæ ñëèøêîì äàëåêîâàòî, íå îøèáêà ëè?
{
log_error( LOG_USERAI, "!!! Dist to target is %0.2f!!! WTF???\n", dist );
return;
}
if( (int)dist > cls->folAsiCfg.m_follow_dist )
{
cls->m_last_follow_time_msec = GetTickCount();
PGen_MoveBackwardToLocation( followTarget->x, followTarget->y, followTarget->z,
cls->usr.x, cls->usr.y, cls->usr.z );
//log_error( LOG_USERAI, "Following... dist = %0.2f\n", dist );
}
}
void UserAI::followDisable()
{
this->folAsiCfg.m_follow_enable = 0;
this->m_follow_oid = 0;
}
void UserAI::assistDisable()
{
this->folAsiCfg.m_assist_enable = 0;
this->m_assist_oid = 0;
}
void UserAI::UAI_ProcessAssist( class UserAI *cls )
{
if( !cls->folAsiCfg.m_assist_enable ) return;
if( cls->folAsiCfg.m_assist_only_in_party && cls->party.getCount() < 1 ) return;
// íàéäåì oID ÌÀ
L2Player *plAssist = NULL;
if( cls->m_assist_oid == 0 )
{
log_error( LOG_USERAI, "Assist enabled by [%S], searching for its objectID...\n",
cls->folAsiCfg.m_assist_name );
// ïðèäåòñÿ ïðîéòèñü ïî âñåìó ìàññèâó ÷àðîâ, ñðàâíèâÿ ïî èìåíè
// ýòî íåáûñòðàÿ îïåðàöèÿ, è âäîáàâîê ïðèäåòñÿ äåðæàòü áëîêèðîâêó
// íà âñåì ìàññèâå ÷àðîâ, ÷òîáû íèêàêîé äðóãîé ïîòîê åãî íå èçìåíèë
// ïîêà ìû ïî íåìó ãóëÿåì
unsigned int i = 0, cnt = CharArray_GetCount(), nc = 0;
CharArray_Lock();
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i] )
{
if( _wcsicmp( chars_array[i]->charName, cls->folAsiCfg.m_assist_name ) == 0 )
{
plAssist = chars_array[i];
break;
}
nc++;
}
if( nc >= cnt ) break;
}
CharArray_Unlock(); // ñíèìåì íàêîíåö-òî áëîêèðîâêó
if( !plAssist ) // îáúåêòà öåëè assist íåò â çîíå âèäèìîñòè
{
//log_error( LOG_USERAI, ":( cannot find assist target oid - not in range?\n" );
return;
}
// óðÿ, íàøëè
log_error( LOG_USERAI, "Found assist oID: %u\n", plAssist->objectID );
cls->m_assist_oid = plAssist->objectID; // Çàïîìíèì objectID ÷òîá áîëüøå íå èñêàòü
UAI_Check_Target_By_Assist( cls, plAssist );
}
else // ìû óæå çíàåì oid ÌÀ
{
int idx = -1;
L2OBJECT_TYPE objType = L2OT_NONE;
// à âîò ýòî óæå íå ïîëíûé ïåðåáîð, î ïîèñê ïî objectID â áèíàðíîì äåðåâå, äîâîëüíî áûñòðûé
if( WorldObjectTree_GetInfoByObjectID( cls->m_assist_oid, &objType, &idx ) )
{
if( objType == L2OT_PC )
{
if( idx >= 0 )
UAI_Check_Target_By_Assist( cls, chars_array[idx] );
}
else log_error( LOG_ERROR, "UAI Assist: MA objType != L2OT_PC (%d)\n", (int)objType );
}
}
}
void UserAI::UAI_Check_Target_By_Assist( class UserAI *cls, L2Player *assistBy )
{
unsigned int now_time = GetTickCount();
if( (now_time - cls->m_last_assist_time_msec) < 500 ) return; // assist once in 500 msec
if( assistBy->targetObjectID != 0 ) // ó ÌÀ åñòü êòî-òî íà òàðãåòå
{
// ïðîâåðèì êòî íà òàðãåòå ó ÌÀ...
unsigned int targetObjectID = assistBy->targetObjectID;
int idx = -1;
L2OBJECT_TYPE objType = L2OT_NONE;
bool target_valid = false;
L2Player *target = NULL;
if( WorldObjectTree_GetInfoByObjectID( targetObjectID, &objType, &idx ) )
{
if( objType == L2OT_PC && idx >= 0 )
{
target = chars_array[idx];
if( !target ) return;
target_valid = true;
if( cls->folAsiCfg.m_assist_dont_ally )
{
if( cls->party.getCount() > 0 && cls->party.isInParty( targetObjectID, NULL ) ) target_valid = false;
if( target->clanID == cls->usr.clanID ) target_valid = false;
if( target->allyID == cls->usr.allyID ) target_valid = false;
}
//if( target_valid )
// log_error( LOG_USERAI, "Assist: MA targeted %u [%S] (valid)\n", targetObjectID, target->charName );
//else
// log_error( LOG_USERAI, "Assist: MA targeted %u [%S] (invalid)\n", targetObjectID, target->charName );
}
//else if( objType == L2OT_NPC )
// log_error( LOG_USERAI, "Assist: MA targeted NPC (invalid)\n" );
}
if( !target_valid ) return;
if( cls->usr.targetObjectID != targetObjectID ) // íàø òàðãåò != òàðãåòó ÌÀ
{
log_error( LOG_USERAI, "ReAssist: MA targeted %u [%S] (valid)\n", targetObjectID, target->charName );
PGen_Action( targetObjectID, cls->usr.x, cls->usr.y, cls->usr.z, 0 );
cls->m_last_assist_time_msec = now_time; // remember Action time
}
}
}