203 lines
6.9 KiB
C++
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
|
|
}
|
|
}
|
|
}
|