l2-unlegits/l2detect/UserAI.cpp
alexey.min 4c4ea452d7 Intercept conect on start again
l2c_getUserSkills() done (usage example in sources)
2012-05-12 19:14:08 +00:00

320 lines
11 KiB
C++

#include "stdafx.h"
#include "UserAI.h"
#include "Logger.h"
#include "RadarDllWnd.h"
//
UserAI::UserAI()
{
m_last_npc_html = NULL;
clear();
}
UserAI::~UserAI()
{
clear();
}
void UserAI::clear()
{
usr.clear();
inv.clear();
buffs.clear();
party.clear();
healItems.clear();
invisGM.clear();
cfgQuickTarg.clear();
targetManager.clear();
folAsiCfg.clear();
//
state = UAI_IDLE;
//
hThread = NULL;
dwThreadID = 0;
// heal items
healItems.enableHealHP = healItems.enableHealMP = healItems.enableHealCP = true;
// offparty bd, sws
offBDSWS_nextBDInvTime = offBDSWS_nextSWSInvTime = offBDSWS_nextBDDisTime = offBDSWS_nextSWSDisTime = 0;
offBD_inrange = offSWS_inrange = false;
// sound alerts
soundAlert_enabled = true;
soundAlert_fileNameCritical[0] = soundAlert_fileNameWarning[0] = soundAlert_fileNameInfo[0] = 0;
soundAlert_alertOnClanWar = 0; // 0 - none, 1 - info, 2 - warning, 3 - critical
soundAlert_alertOnTargeted = 0;
soundAlert_alertOnInvisGM = 0;
soundAlert_noPartyTargetAlert = soundAlert_noClanTargetAlert = 1;
soundAlert_screenMessage = 0;
// follow / asi
m_last_follow_time_msec = 0;
m_follow_oid = 0;
m_assist_oid = 0;
m_last_assist_time_msec = 0;
// npc html
m_last_npc_html_npcOid = 0;
if( m_last_npc_html )
{
free( m_last_npc_html );
m_last_npc_html = NULL;
}
}
void UserAI::userLogout()
{
usr.clear();
inv.clear();
buffs.clear();
party.clear();
healItems.clear();
invisGM.clear();
cfgQuickTarg.clear();
targetManager.clear();
folAsiCfg.clear();
m_follow_oid = 0;
m_assist_oid = 0;
//
state = UAI_IDLE;
//
CharArray_DeleteAll();
NpcArray_DeleteAll();
GIArray::getInstance()->DeleteAll();
log_error( LOG_USERAI, "UserAI: Logout OK, User logged out (notified)\n" );
RadarWnd_ForceUpdateCharsList();
RadarWnd_ForceUpdateNpcsList();
RadarWnd_UpdateChecksState();
}
void UserAI::init()
{
clear();
// load all config
healItems.LoadFromFile( "L2Detect_healItems.ini" );
off_BD_SWS.readFromFile( "L2Detect_offp_BDSWS.ini" );
setOffpartyBDSWS_Enable( off_BD_SWS.allEnabled ); // process...
cfgQuickTarg.loadFromFile( "L2Detect_quickTarg.ini" );
targetManager.clear();
loadSoundAlertsCfgFromFile( "L2Detect_soundAlerts.ini" );
folAsiCfg.loadFromFile( "L2Detect_folAsi.ini" );
// force radar window to set all checks from our confg
RadarWnd_UpdateChecksState();
}
void UserAI::notifyEvent( int event_id )
{
switch( event_id )
{
case UAI_EVENT_START:
{
log_error( LOG_USERAI, "UserAI::notifyEvent(): START\n" );
if( hThread == NULL )
{
dwThreadID = 0;
hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))UserAIThread, (void *)this, 0,
(unsigned int *)&dwThreadID );
if( hThread )
log_error( LOG_USERAI, "UserAI::notifyEvent(): START OK %u\n", dwThreadID );
else
log_error( LOG_ERROR, "UserAI::notifyEvent(): START ERROR %d\n", GetLastError() );
}
else
log_error( LOG_ERROR, "UserAI::notifyEvent(): START: already running\n" );
} break;
case UAI_EVENT_STOP:
{
log_error( LOG_USERAI, "UserAI::notifyEvent(): STOPPING %u...\n", dwThreadID );
if( hThread != NULL )
{
if( !PostThreadMessage( dwThreadID, WM_CLOSE, 0, 0 ) )
{
log_error( LOG_ERROR, "UserAI::notifyEvent(): STOP: PostThreadMessage() error %u\n",
(unsigned int)GetLastError );
return;
}
Sleep( 100 );
while( hThread )
{
log_error_np( LOG_OK, "." );
Sleep( 250 );
}
log_error( LOG_USERAI, "\nUserAI::notifyEvent(): STOP WAIT OK\n" );
}
else
log_error( LOG_ERROR, "UserAI::notifyEvent(): STOP: not running\n" );
} break;
}
}
void UserAI::notifyEventPacket( int event_id, const unsigned char *bytes, unsigned int length )
{
if( !bytes || (length<1) ) return;
L2GamePacket *p = new L2GamePacket( bytes, length );
if( !p ) return;
#ifdef _DEBUG
BOOL ret = PostThreadMessage( dwThreadID, WM_KEYDOWN, event_id, (LPARAM)p );
if( !ret )
{
DWORD le = GetLastError();
ErrorLogger_LogLastError( "UserAI::notifyEventPacket(): PostThreadMessage() failed", le );
log_error( LOG_ERROR, "tid = %u\n", dwThreadID );
}
#else
PostThreadMessage( dwThreadID, WM_KEYDOWN, event_id, (LPARAM)p );
#endif
}
void UserAI::notifyUIKeyUp( int vkey )
{
PostThreadMessage( dwThreadID, WM_KEYUP, (WPARAM)vkey, (LPARAM)0 );
}
DWORD WINAPI UserAI::UserAIThread( LPVOID lpParam )
{
class UserAI *cls = (class UserAI *)lpParam;
if( !cls ) return 12345;
MSG msg;
// create thread's message queue
PeekMessage( &msg, NULL, WM_USER, WM_USER, PM_NOREMOVE );
// now message queue for this thread is created
log_error( LOG_USERAI, "UserAIThread(): started, created message queue\n" );
//
int shouldExit = 0;
int was_message = 0;
do
{
was_message = 0;
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
was_message = 1;
//log_error( LOG_OK, "UserAIThread(): GotMessage %u\n", msg.message );
switch( msg.message )
{
//case WM_CREATE: { /*log_error( LOG_DEBUG, "UserAIThread(): WM_CREATE\n" );*/ } break;
case WM_CLOSE: { /*log_error( LOG_DEBUG, "UserAIThread(): WM_CLOSE\n" );*/ shouldExit = 1; } break;
case WM_KEYDOWN: UAI_ParsePacket( cls, msg.wParam, msg.lParam ); break;
case WM_KEYUP: cls->UAI_handle_keyboard( (int)msg.wParam ); break;
}
}
if( shouldExit ) break;
if( !was_message ) Sleep( 100 );
// process all L2Character moves in visible area, also process user move
// process buff ticks, skill reuses
UAI_ProcessWorld( cls );
// check HP,MP,CP
if( cls->healItems.enableHealHP ) UAI_CheckHP( cls );
if( cls->healItems.enableHealMP ) UAI_CheckMP( cls );
if( cls->healItems.enableHealCP ) UAI_CheckCP( cls );
// check if enabled offparty bd, sws invite/dismiss
if( cls->off_BD_SWS.allEnabled ) UAI_ProcessOffpartyBDSWS( cls );
// process follow/assist
if( cls->folAsiCfg.m_follow_enable ) UAI_ProcessFollow( cls );
if( cls->folAsiCfg.m_assist_enable ) UAI_ProcessAssist( cls );
}
while( !shouldExit );
//
log_error( LOG_USERAI, "UserAIThread(): ending\n" );
//
CloseHandle( cls->hThread );
cls->hThread = NULL;
cls->dwThreadID = 0;
return 0;
}
void UserAI::UAI_ParsePacket( class UserAI *cls, WPARAM wParam, LPARAM lParam )
{
if( lParam == 0 ) return;
L2GamePacket *p = (L2GamePacket *)lParam;
int event_id = (int)wParam;
//
try
{
//
switch( event_id )
{
case UAI_PEVENT_USERINFO: cls->usr.parse_UserInfo( p ); break;
case UAI_PEVENT_STATUSUPDATE: cls->UAI_Parse_StatusUpdate( cls, p ); break;
case UAI_PEVENT_ITEMLIST: cls->inv.parse_ItemList( p ); break;
case UAI_PEVENT_INVENTORYUPDATE: cls->inv.parse_InventoryUpdate( p ); break;
case UAI_PEVENT_MOVETOLOCATION: cls->UAI_Parse_MoveToLocation( cls, p ); break;
case UAI_PEVENT_STOPMOVE: cls->UAI_Parse_StopMove( cls, p ); break;
case UAI_PEVENT_TELEPORTTOLOCATION: cls->UAI_Parse_TeleportToLocation( cls, p ); break;
case UAI_PEVENT_PLEDGERECEIVEWARLIST: cls->warList.parse_PledgeReceiveWarList( p ); break;
case UAI_PEVENT_NPCINFO: cls->UAI_Parse_NpcInfo( cls, p ); break;
case UAI_PEVENT_DELETEOBJECT: cls->UAI_Parse_DeleteObject( cls, p ); break;
case UAI_PEVENT_CHARINFO: cls->UAI_Parse_CharInfo( cls, p ); break;
case UAI_PEVENT_TARGETSELECTED: cls->UAI_Parse_TargetSelected( cls, p ); break;
case UAI_PEVENT_TARGETUNSELECTED: cls->UAI_Parse_TargetUnselected( cls, p ); break;
case UAI_PEVENT_RELATIONCHANGED: cls->UAI_Parse_RelationChanged( cls, p ); break;
case UAI_PEVENT_MYTARGETSELECTED: cls->UAI_Parse_MyTargetSelected( cls, p ); break;
// party
case UAI_PEVENT_PARTYADD: cls->UAI_Parse_PartySmallWindowAdd( cls, p ); break;
case UAI_PEVENT_PARTYALL: cls->UAI_Parse_PartySmallWindowAll( cls, p ); break;
case UAI_PEVENT_PARTYDEL: cls->UAI_Parse_PartySmallWindowDelete( cls, p ); break;
case UAI_PEVENT_PARTYDELALL: cls->UAI_Parse_PartySmallWindowDeleteAll( cls, p ); break;
case UAI_PEVENT_PARTYUPDATE: cls->UAI_Parse_PartySmallWindowUpdate( cls, p ); break;
case UAI_PEVENT_PARTYSPELLED: cls->UAI_Parse_PartySpelled( cls, p ); break;
// die/revive
case UAI_PEVENT_DIE: cls->UAI_Parse_Die( cls, p ); break;
case UAI_PEVENT_REVIVE: cls->UAI_Parse_Revive( cls, p ); break;
// buffs
case UAI_PEVENT_ABNORMALSTATUSUPDATE: cls->UAI_Parse_AbnormalStatusUpdate( cls, p ); break;
case UAI_PEVENT_SHORTBUFFSTATUSUPDATE: cls->UAI_Parse_ShortBuffStatusUpdate( cls, p ); break;
// skills
case UAI_PEVENT_SETUPGAUGE: cls->UAI_Parse_SetupGauge( cls, p ); break;
case UAI_PEVENT_SKILLLIST: cls->UAI_Parse_SkillList( cls, p ); break;
case UAI_PEVENT_SKILLCOOLTIME: cls->UAI_Parse_SkillCoolTime( cls, p ); break;
case UAI_PEVENT_MAGICSKILLUSE: cls->UAI_Parse_MagicSkillUse( cls, p ); break;
case UAI_PEVENT_MAGICSKILLCANCELLED: cls->UAI_Parse_MagicSkillCancelled( cls, p ); break;
// items
case UAI_PEVENT_DROPITEM: cls->UAI_Parse_DropItem( cls, p ); break;
case UAI_PEVENT_SPAWNITEM: cls->UAI_Parse_SpawnItem( cls, p ); break;
}
//
} // try
catch( L2P_Exception& e )
{
log_error( LOG_ERROR, "L2P_Exception in UAI_ParsePacket (event_id = %d):\n%s\n",
event_id, e.what() );
}
//
delete p;
}
void UserAI::setHealItemsTable( const HealItemsTable *other )
{
if( !other ) return;
// possible decision - reload table from saved file
//this->healItems.LoadFromFile( "L2Detect_healItems.ini" );
// other way - full memcpy :)
memcpy( (void *)(&(this->healItems)), (const void *)other, sizeof(class HealItemsTable) );
}
void UserAI::setOffpartyBDSWS_Config( const UserAI_OffpartyBDSWS *other )
{
if( !other ) return;
memcpy( (void *)(&(this->off_BD_SWS)), (const void *)other, sizeof(class UserAI_OffpartyBDSWS) );
}
void UserAI::setOffpartyBDSWS_Enable( int bEnable )
{
if( (bEnable != 0) /*&& (this->off_BD_SWS.allEnabled == 0)*/ )
{
this->off_BD_SWS.allEnabled = 1;
this->offBDSWS_nextBDInvTime = GetTickCount() + 500; // ~ current time
this->offBDSWS_nextSWSInvTime = this->offBDSWS_nextBDInvTime;
// next dismiss time = next invite time + dismiss timeout
this->offBDSWS_nextBDDisTime = this->offBDSWS_nextBDInvTime + (this->off_BD_SWS.dismiss_bd_secs * 1000);
this->offBDSWS_nextSWSDisTime = this->offBDSWS_nextSWSInvTime + (this->off_BD_SWS.dismiss_sws_secs * 1000);
log_error( LOG_USERAI, "Enabled offparty BD/SWS invite\n" );
return;
}
if( (bEnable == 0) /*&& (this->off_BD_SWS.allEnabled == 1)*/ )
{
this->off_BD_SWS.allEnabled = 0;
log_error( LOG_USERAI, "Disabled offparty BD/SWS invite\n" );
}
}