Initial MSVC 2008 projects workspace

This commit is contained in:
alexey.min
2012-02-01 05:25:08 +00:00
commit 03de3bdc95
1446 changed files with 476853 additions and 0 deletions

103
l2ooghelper/Account.cpp Normal file
View File

@@ -0,0 +1,103 @@
#include "StdAfx.h"
#include "Account.h"
#include "Logger.h"
Account::Account()
{
account_version = 2;
clear();
}
Account::~Account()
{
clear();
}
void Account::clear()
{
login[0] = pass[0] = 0;
loginServerIP[0] = 0;
charSelectName[0] = configFileName[0] = 0;
loginServerPort = 2106;
gameserverID = 1;
gameserverSelectManual = 0;
charSelectManual = 0;
strcpy( loginServerIP, "127.0.0.1" );
protocolVersion = 12;
serverVersion = 2;
useDefaultProtocolVersion = 1;
}
Account::Account( const Account& other )
{
wcscpy( login, other.login );
wcscpy( pass, other.pass );
wcscpy( charSelectName, other.charSelectName );
wcscpy( configFileName, other.configFileName );
strcpy( loginServerIP, other.loginServerIP );
loginServerPort = other.loginServerPort;
gameserverID = other.gameserverID;
gameserverSelectManual = other.gameserverSelectManual;
charSelectManual = other.charSelectManual;
protocolVersion = other.protocolVersion;
serverVersion = other.serverVersion;
useDefaultProtocolVersion = other.useDefaultProtocolVersion;
}
Account& Account::operator=( const Account& other )
{
wcscpy( login, other.login );
wcscpy( pass, other.pass );
wcscpy( charSelectName, other.charSelectName );
wcscpy( configFileName, other.configFileName );
strcpy( loginServerIP, other.loginServerIP );
loginServerPort = other.loginServerPort;
gameserverID = other.gameserverID;
gameserverSelectManual = other.gameserverSelectManual;
charSelectManual = other.charSelectManual;
protocolVersion = other.protocolVersion;
serverVersion = other.serverVersion;
useDefaultProtocolVersion = other.useDefaultProtocolVersion;
return (*this);
}
L2_VERSION Account::getL2Version() const
{
L2_VERSION ret = L2_VERSION_T1;
switch( serverVersion )
{
case 0: ret = L2_VERSION_T1; break;
case 1: ret = L2_VERSION_T15; break;
case 2: ret = L2_VERSION_T2; break;
case 3: ret = L2_VERSION_T22; break;
case 4: ret = L2_VERSION_T23; break;
case 5: ret = L2_VERSION_T24; break;
default:
log_error( LOG_WARNING, "Account::getL2Version(): unknown serverVersion %d\n",
serverVersion );
break;
}
return ret;
}
bool Account::loadFromFile( const wchar_t *fileName )
{
HANDLE hFile = CreateFileW( fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE ) return false;
DWORD dwRead = 0;
ReadFile( hFile, (void *)this, sizeof(class Account), &dwRead, NULL );
CloseHandle( hFile );
return (dwRead == sizeof(class Account) );
}
bool Account::saveToFile( const wchar_t *fileName )
{
HANDLE hFile = CreateFileW( fileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE ) return false;
DWORD dwWritten = 0;
WriteFile( hFile, (const void *)this, sizeof(class Account), &dwWritten, NULL );
CloseHandle( hFile );
return (dwWritten == sizeof(class Account));
}

35
l2ooghelper/Account.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef H_ACCOUNT
#define H_ACCOUNT
class Account
{
public:
Account();
Account( const Account& other );
Account& operator=( const Account& other );
~Account();
public:
void clear();
public:
bool loadFromFile( const wchar_t *fileName );
bool saveToFile( const wchar_t *fileName );
protected:
unsigned int account_version;
public:
L2_VERSION getL2Version() const;
public:
wchar_t login[32];
wchar_t pass[32];
char loginServerIP[32];
int loginServerPort;
int gameserverID;
int gameserverSelectManual;
int charSelectManual;
wchar_t charSelectName[32];
wchar_t configFileName[512];
unsigned int protocolVersion;
int serverVersion; // 0 - t1, 1 - t1.5, 2 - t2, 3 - t2.2, 4 - t2.3
int useDefaultProtocolVersion;
};
#endif

236
l2ooghelper/AccountDlg.cpp Normal file
View File

@@ -0,0 +1,236 @@
#include "StdAfx.h"
#include "AccountDlg.h"
#include "Resource.h"
extern HINSTANCE g_hInst;
bool AccountDlg::run( HWND hWndParent )
{
INT_PTR ret = DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_ACCOUNT), hWndParent,
AccountDlgProc, (LPARAM)&(this->account) );
if( ret == IDOK ) return true;
return false;
}
void AccountDlg_SetMembers( HWND hDlg, class Account *acc )
{
//class Account *acc = (class Account *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !acc ) return;
HWND hwndCB = NULL;
SetDlgItemTextW( hDlg, IDC_E_LOGIN, acc->login );
SetDlgItemTextW( hDlg, IDC_E_PASS, acc->pass );
SetDlgItemTextA( hDlg, IDC_E_IP, acc->loginServerIP );
SetDlgItemInt( hDlg, IDC_E_PORT, acc->loginServerPort, TRUE );
SetDlgItemInt( hDlg, IDC_E_GSID, acc->gameserverID, FALSE );
SetDlgItemTextW( hDlg, IDC_E_CHARNAME, acc->charSelectName );
if( acc->gameserverSelectManual )
{
CheckDlgButton( hDlg, IDC_C_GAME_MANUAL, TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_E_GSID ), FALSE );
}
else
{
CheckDlgButton( hDlg, IDC_C_GAME_MANUAL, FALSE );
EnableWindow( GetDlgItem( hDlg, IDC_E_GSID ), TRUE );
}
if( acc->charSelectManual )
{
CheckDlgButton( hDlg, IDC_C_CHAR_MANUAL, TRUE );
EnableWindow( GetDlgItem( hDlg, IDC_E_CHARNAME ), FALSE );
}
else
{
CheckDlgButton( hDlg, IDC_C_CHAR_MANUAL, FALSE );
EnableWindow( GetDlgItem( hDlg, IDC_E_CHARNAME ), TRUE );
}
// combobox server version
hwndCB = GetDlgItem( hDlg, IDC_CB_L2VER );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("CT1 The Kamael") );
ComboBox_AddString( hwndCB, TEXT("CT1.5 Hellbound") );
ComboBox_AddString( hwndCB, TEXT("CT2 Gracia") );
ComboBox_AddString( hwndCB, TEXT("CT2.2 Gracia Part 2") );
ComboBox_AddString( hwndCB, TEXT("CT2.3 Gracia Final") );
ComboBox_AddString( hwndCB, TEXT("CT2.4 Gracia Epilogue") );
ComboBox_SetCurSel( hwndCB, acc->serverVersion );
if( acc->useDefaultProtocolVersion )
{
EnableWindow( GetDlgItem( hDlg, IDC_E_PROTO ), FALSE );
SetDlgItemText( hDlg, IDC_E_PROTO, TEXT("auto") );
CheckDlgButton( hDlg, IDC_C_PROTOAUTO, TRUE );
}
else
{
CheckDlgButton( hDlg, IDC_C_PROTOAUTO, FALSE );
EnableWindow( GetDlgItem( hDlg, IDC_E_PROTO ), TRUE );
SetDlgItemInt( hDlg, IDC_E_PROTO, acc->protocolVersion, FALSE );
}
// config files
hwndCB = GetDlgItem( hDlg, IDC_CB_CONFIG );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("<none>") );
if( acc->configFileName[0] == 0 ) ComboBox_SetCurSel( hwndCB, 0 );
// scan folder "..\configs" for pattern "*.config"
WIN32_FIND_DATA fdata;
HANDLE hFind = FindFirstFile( TEXT(".\\configs\\*.config"), &fdata );
if( hFind != INVALID_HANDLE_VALUE )
{
int add_idx = ComboBox_AddString( hwndCB, fdata.cFileName );
if( _tcscmp( fdata.cFileName, acc->configFileName ) == 0 ) ComboBox_SetCurSel( hwndCB, add_idx );
while( FindNextFile( hFind, &fdata ) )
{
add_idx = ComboBox_AddString( hwndCB, fdata.cFileName );
if( _tcscmp( fdata.cFileName, acc->configFileName ) == 0 ) ComboBox_SetCurSel( hwndCB, add_idx );
}
FindClose( hFind );
}
}
Account AccountDlg_GetMembers( HWND hDlg )
{
HWND hwndCB = NULL;
Account acc;
GetDlgItemTextW( hDlg, IDC_E_LOGIN, acc.login, 31 );
GetDlgItemTextW( hDlg, IDC_E_PASS, acc.pass, 31 );
GetDlgItemTextA( hDlg, IDC_E_IP, acc.loginServerIP, 31 );
acc.loginServerPort = GetDlgItemInt( hDlg, IDC_E_PORT, NULL, TRUE );
acc.gameserverID = GetDlgItemInt( hDlg, IDC_E_GSID, NULL, FALSE );
GetDlgItemTextW( hDlg, IDC_E_CHARNAME, acc.charSelectName, 31 );
acc.gameserverSelectManual = IsDlgButtonChecked( hDlg, IDC_C_GAME_MANUAL );
acc.charSelectManual = IsDlgButtonChecked( hDlg, IDC_C_CHAR_MANUAL );
hwndCB = GetDlgItem( hDlg, IDC_CB_L2VER );
acc.serverVersion = ComboBox_GetCurSel( hwndCB );
if( IsDlgButtonChecked( hDlg, IDC_C_PROTOAUTO ) ) acc.useDefaultProtocolVersion = 1;
else
{
acc.useDefaultProtocolVersion = 0;
acc.protocolVersion = GetDlgItemInt( hDlg, IDC_E_PROTO, NULL, FALSE );
}
// config file name
acc.configFileName[0] = 0;
hwndCB = GetDlgItem( hDlg, IDC_CB_CONFIG );
int cur_sel = ComboBox_GetCurSel( hwndCB );
// >= 1 because string 0 is always "<none>", meaning that config file is not set
if( cur_sel >= 1 ) GetWindowText( hwndCB, acc.configFileName, 511 );
return acc;
}
void AccountDlg_UpdateEnabledWindows( HWND hDlg )
{
if( IsDlgButtonChecked( hDlg, IDC_C_GAME_MANUAL ) ) EnableWindow( GetDlgItem( hDlg, IDC_E_GSID ), FALSE );
else EnableWindow( GetDlgItem( hDlg, IDC_E_GSID ), TRUE );
if( IsDlgButtonChecked( hDlg, IDC_C_CHAR_MANUAL ) ) EnableWindow( GetDlgItem( hDlg, IDC_E_CHARNAME ), FALSE );
else EnableWindow( GetDlgItem( hDlg, IDC_E_CHARNAME ), TRUE );
if( IsDlgButtonChecked( hDlg, IDC_C_PROTOAUTO ) )
{
EnableWindow( GetDlgItem( hDlg, IDC_E_PROTO ), FALSE );
SetDlgItemText( hDlg, IDC_E_PROTO, TEXT("auto") );
}
else
{
EnableWindow( GetDlgItem( hDlg, IDC_E_PROTO ), TRUE );
SetDlgItemInt( hDlg, IDC_E_PROTO, 12, FALSE );
}
}
INT_PTR CALLBACK AccountDlg::AccountDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
AccountDlg_SetMembers( hDlg, (class Account *)lParam );
} break;
case WM_COMMAND:
{
switch( LOWORD( wParam ) )
{
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
case IDOK:
{
class Account *acc = (class Account *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
Account accCurrent = AccountDlg_GetMembers( hDlg );
(*acc) = accCurrent;
EndDialog( hDlg, IDOK );
} break;
case IDC_C_CHAR_MANUAL: AccountDlg_UpdateEnabledWindows( hDlg ); break;
case IDC_C_GAME_MANUAL: AccountDlg_UpdateEnabledWindows( hDlg ); break;
case IDC_C_PROTOAUTO: AccountDlg_UpdateEnabledWindows( hDlg ); break;
case IDC_LOAD:
{
// change subdir to '.\accounts'
wchar_t curDir[256] = {0};
wchar_t newDir[256] = {0};
GetCurrentDirectoryW( 200, curDir );
wsprintfW( newDir, L"%s\\accounts", curDir );
SetCurrentDirectoryW( newDir );
//
wchar_t fileName[256] = {0};
OPENFILENAMEW ofn;
memset( &ofn, 0, sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = g_hInst;
ofn.lpstrFilter = TEXT("Acc files\0*.account\0All files\0*.*\0\0");
ofn.lpstrFile = fileName;
ofn.nMaxFile = 255;
ofn.lpstrTitle = TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
ofn.lpstrInitialDir = newDir;
ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if( GetOpenFileNameW( &ofn ) )
{
// restore cur dir (required to scan for configs, for example)
SetCurrentDirectoryW( curDir );
Account accLoaded;
if( !accLoaded.loadFromFile( fileName ) )
{
MessageBox( hDlg, TEXT("Load failed!"), TEXT("Error!"), MB_ICONSTOP );
}
AccountDlg_SetMembers( hDlg, &accLoaded );
}
// restore cur dir (required to load maps, for example)
SetCurrentDirectoryW( curDir );
} break;
case IDC_SAVE:
{
// change subdir to '.\accounts'
wchar_t curDir[256] = {0};
wchar_t newDir[256] = {0};
GetCurrentDirectoryW( 200, curDir );
wsprintfW( newDir, L"%s\\accounts", curDir );
SetCurrentDirectoryW( newDir );
//
wchar_t fileName[256] = {0};
OPENFILENAMEW ofn;
memset( &ofn, 0, sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = g_hInst;
ofn.lpstrFilter = TEXT("Acc files\0*.account\0All files\0*.*\0\0");
ofn.lpstrFile = fileName;
ofn.nMaxFile = 255;
ofn.lpstrTitle = TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?");
ofn.lpstrInitialDir = newDir;
ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if( GetSaveFileNameW( &ofn ) )
{
// restore cur dir (required to load maps, for example)
SetCurrentDirectoryW( curDir );
if( wcsstr( fileName, L".account" ) == NULL ) wcscat( fileName, L".account" );
Account accCurrent = AccountDlg_GetMembers( hDlg );
if( !accCurrent.saveToFile( fileName ) )
{
MessageBox( hDlg, TEXT("Save failed!"), TEXT("Error!"), MB_ICONSTOP );
}
}
// restore cur dir (required to load maps, for example)
SetCurrentDirectoryW( curDir );
} break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}

21
l2ooghelper/AccountDlg.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef H_ACCOUNT_DLG
#define H_ACCOUNT_DLG
#include "Account.h"
class AccountDlg
{
public:
AccountDlg() {}
~AccountDlg() {}
public:
void setAccount( const class Account& acc ) { account = acc; }
Account getAccount() const { return account; }
public:
bool run( HWND hWndParent );
protected:
static INT_PTR CALLBACK AccountDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
Account account;
};
#endif

434
l2ooghelper/BinTree.cpp Normal file
View File

@@ -0,0 +1,434 @@
#include "stdafx.h"
#include "BinTree.h"
BinTreeNode::BinTreeNode()
{
parent = left = right = NULL;
key = 0;
}
BinTreeNode::BinTreeNode( unsigned int keyInit )
{
parent = left = right = NULL;
key = keyInit;
//printf( "BinTreeNode() constructed with key %u\n", key );
}
BinTreeNode::~BinTreeNode()
{
//printf( "~BinTreeNode: destoyed %u\n", key );
}
//=============================================================
//=============================================================
//=============================================================
BinTree::~BinTree()
{
deleteAll();
}
void BinTree::deleteAll()
{
if( root )
{
del_recursive( root );
delete root;
root = NULL;
}
}
void BinTree::del_recursive( BinTreeNode *node )
{
if( !node ) return;
if( node->left )
{
//printf( "cur %u; delete left\n", node->key );
del_recursive( node->left );
delete node->left;
}
if( node->right )
{
//printf( "cur %u; delete right\n", node->key );
del_recursive( node->right );
delete node->right;
}
/*node->left = NULL;
node->right = NULL;
node->key = 0;*/
}
bool BinTree::addNode( BinTreeNode *node )
{
if( !node ) return false;
if( !root )
{
root = node;
root->parent = NULL;
return true;
}
BinTreeNode *cur = root;
//BinTreeNode *prev = root;
while( true )
{
//prev = cur;
if( node->key > cur->key )
{
if( cur->right == NULL )
{
//add to right
node->parent = cur;
cur->right = node;
return true;
}
else
{
cur = cur->right;
}
}
else if( node->key < cur->key )
{
if( cur->left == NULL )
{
// add to left
node->parent = cur;
cur->left = node;
return true;
}
else
{
cur = cur->left;
}
}
else if( node->key == cur->key )
{
return false;
}
}
// never executed!
return true;
}
#ifdef _DEBUG
bool BinTree::addNodeDebug( BinTreeNode *node, FILE *f )
{
if( !node )
{
fprintf( f, "BinTree::addNode(): node == NULL!\n" );
return false;
}
if( !root )
{
root = node;
root->parent = NULL;
fprintf( f, "BinTree::addNodeDebug(): added node key %u to root\n", node->key );
return true;
}
BinTreeNode *cur = root;
//BinTreeNode *prev = root;
while( true )
{
//prev = cur;
if( node->key > cur->key )
{
if( cur->right == NULL )
{
//add to right
node->parent = cur;
cur->right = node;
fprintf( f, "BinTree::addNodeDebug(): added node key %u to right of key %u\n",
node->key, cur->key );
return true;
}
else
{
cur = cur->right;
}
}
else if( node->key < cur->key )
{
if( cur->left == NULL )
{
// add to left
node->parent = cur;
cur->left = node;
fprintf( f, "BinTree::addNodeDebug(): added node key %u to left of key %u\n",
node->key, cur->key );
return true;
}
else
{
cur = cur->left;
}
}
else if( node->key == cur->key )
{
fprintf( f, "BinTree::addNodeDebug(): key %u already exists\n", node->key );
return false;
}
}
printf( "BinTree::addNode(): never executed!\n" );
return true;
}
#endif
BinTreeNode *BinTree::findNode( unsigned int key )
{
if( !root ) return NULL;
BinTreeNode *cur = root;
while( cur )
{
if( cur->key == key ) return cur;
if( key > cur->key ) cur = cur->right;
else if( key < cur->key ) cur = cur->left;
}
return cur;
}
bool BinTree::delNode( BinTreeNode *node )
{
if( !node ) return false;
if( (node->left == NULL) && (node->right == NULL) )
{
if( node->parent )
{
if( node->parent->left == node ) node->parent->left = NULL;
if( node->parent->right == node ) node->parent->right = NULL;
}
else root = NULL;
delete node;
return true;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( node->left && (node->right == NULL) )
{
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->left = node->left;
}
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->right = node->left;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->left->parent = node->parent;
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
root = node->left;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->left->parent = NULL;
}
delete node;
return true;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( node->right && (node->left == NULL) )
{
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->left = node->right;
}
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->right = node->right;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->right->parent = node->parent;
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
root = node->right;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->right->parent = NULL;
}
delete node;
return true;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( node->left && node->right )
{
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>...
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
node->left->parent = node->parent;
if( node->parent->left == node ) node->parent->left = node->left;
if( node->parent->right == node ) node->parent->right = node->left;
}
else
{
root = node->left;
node->left->parent = NULL;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
addNode( node->right );
delete node;
}
return true;
}
bool BinTree::delNode( unsigned int key )
{
if( !root ) return false;
BinTreeNode *node = findNode( key );
if( node ) return delNode( node );
return false;
}
#ifdef _DEBUG
BinTreeNode *BinTree::findNodeDebug( unsigned int key, FILE *f )
{
if( !f ) return NULL;
if( !root ) return NULL;
fprintf( f, "BinTree::findNodeDebug( int key = %u )\n", key );
BinTreeNode *cur = root;
while( cur )
{
fprintf( f, "cur = 0x%p (key %u)\n", cur, cur->key );
if( cur->key == key ) { fprintf( f, "found key %u\n", cur->key ); return cur; }
if( key > cur->key ) { fprintf( f, "... > %u; right\n", cur->key ); cur = cur->right; continue; }
if( key < cur->key ) { fprintf( f, "... < %u; left\n", cur->key ); cur = cur->left; continue; }
}
if( cur ) fprintf( f, "returning 0x%p key %u\n", cur, cur->key );
else fprintf( f, "key %u not found\n", key );
return cur;
}
bool BinTree::delNodeDebug( unsigned int key, FILE *f )
{
if( !f || !root ) return false;
BinTreeNode *del = findNodeDebug( key, f );
if( del ) return delNodeDebug( del, f );
return false;
}
bool BinTree::delNodeDebug( BinTreeNode *node, FILE *f )
{
if( !node || !f ) return false;
fprintf( f, "delNodeDebug: del node key %u, parent = 0x%p\n", node->key, node->parent );
if( (node->left == NULL) && (node->right == NULL) )
{
fprintf( f, "case 0: no children\n" );
if( node->parent )
{
if( node->parent->left == node ) node->parent->left = NULL;
if( node->parent->right == node ) node->parent->right = NULL;
}
else root = NULL;
delete node;
return true;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( node->left && (node->right == NULL) )
{
fprintf( f, "case 1: left exists\n" );
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->left = node->left;
}
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->right = node->left;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->left->parent = node->parent;
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
root = node->left;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->left->parent = NULL;
}
delete node;
return true;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( node->right && (node->left == NULL) )
{
fprintf( f, "case 2: right exists\n" );
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
if( node->parent->left == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->left = node->right;
}
if( node->parent->right == node ) // <20><><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
node->parent->right = node->right;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->right->parent = node->parent;
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
root = node->right;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
node->right->parent = NULL;
}
delete node;
return true;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if( node->left && node->right )
{
fprintf( f, "case 3: left and right exist\n" );
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>...
if( node->parent ) // <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
node->left->parent = node->parent;
if( node->parent->left == node ) node->parent->left = node->left;
if( node->parent->right == node ) node->parent->right = node->left;
}
else
{
root = node->left;
node->left->parent = NULL;
}
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
addNodeDebug( node->right, f );
delete node;
}
return true;
}
void printTreeNode( FILE *f, int recur_count, BinTreeNode *node )
{
if( !node ) return;
int i;
//fprintf( f, "\n" );
if( node->parent )
{
if( node->parent->left == node ) fprintf( f, "LEFT " );
else if( node->parent->right == node ) fprintf( f, "RIGHT " );
else fprintf( f, "Parent unknown??? " );
}
else fprintf( f, "ROOT " );
for( i=0; i<recur_count; i++ ) fprintf( f, "." );
fprintf( f, "%d (0x%p)\n", node->key, node );
//fprintf( f, "\n" );
if( node->left ) printTreeNode( f, recur_count+1, node->left );
if( node->right ) printTreeNode( f, recur_count+1, node->right );
}
void BinTree::printTree( FILE *f )
{
if( !f ) return;
if( !root ) fprintf( f, "BinTree is empty!\n" );
printTreeNode( f, 1, root );
}
#endif

47
l2ooghelper/BinTree.h Normal file
View File

@@ -0,0 +1,47 @@
#ifndef BINTREE_H_
#define BINTREE_H_
class BinTreeNode
{
public:
BinTreeNode();
BinTreeNode( unsigned int keyInit );
virtual ~BinTreeNode();
public:
BinTreeNode *parent;
BinTreeNode *left;
BinTreeNode *right;
unsigned int key;
};
class BinTree
{
public:
BinTree() { root = NULL; }
virtual ~BinTree();
public:
bool addNode( BinTreeNode *node );
BinTreeNode *findNode( unsigned int key );
bool delNode( BinTreeNode *node );
bool delNode( unsigned int key );
void deleteAll();
BinTreeNode *getRoot() const { return this->root; }
#ifdef _DEBUG
public:
bool addNodeDebug( BinTreeNode *node, FILE *f );
BinTreeNode *findNodeDebug( unsigned int key, FILE *f );
bool delNodeDebug( unsigned int key, FILE *f );
bool delNodeDebug( BinTreeNode *node, FILE *f );
void printTree( FILE *f );
#endif
protected:
void del_recursive( BinTreeNode *node );
protected:
BinTreeNode *root;
};
#endif /* BINTREE_H_ */

276
l2ooghelper/BotCfgDlg.cpp Normal file
View File

@@ -0,0 +1,276 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
#include "logger.h"
#include "L2Client.h"
#include "IL2Client.h"
#include "BotCfgDlg.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK BotCfgDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
void BotCfgDlg_Run( HWND hWndParent, L2Client *pcl )
{
DialogBoxParamW( g_hInst, MAKEINTRESOURCE(IDD_BOTCONFIG), hWndParent, BotCfgDlgProc, (LPARAM)pcl );
}
#define NUM_CHILD_TABS 6
#define T_SELF 1
#define T_SELF_HEAL 2
#define T_SELF_BUFFS 3
#define T_PARTY 4
#define T_PARTY_HEAL 5
#define T_PARTY_BUFFS 6
struct BotCfgDlgSt
{
L2Client *cl;
BotConfig myCfg;
HWND hWndChildTab[ NUM_CHILD_TABS + 1 ];
// tree items
// self
HTREEITEM htiSelf;
//HTREEITEM htiSelfHeal;
// party
HTREEITEM htiParty;
};
void BotCfg_InitChildTabs( HWND hDlg, BotCfgDlgSt *st );
void BotCfg_DestroyChildTabs( HWND hDlg, BotCfgDlgSt *st );
void BotCfg_InitTree( HWND hDlg, BotCfgDlgSt *st );
BOOL BotCfg_OnNotify( HWND hDlg, LPARAM lParam );
BOOL BotCfg_OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam );
void BotCfg_OnOK( HWND hDlg, BotCfgDlgSt *st );
void BotCfg_OnApply( HWND hDlg, BotCfgDlgSt *st );
void BotCfg_OnLoad( HWND hDlg, BotCfgDlgSt *st );
void BotCfg_OnSave( HWND hDlg, BotCfgDlgSt *st );
INT_PTR CALLBACK BotCfgDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
BotCfgDlgSt *st = (BotCfgDlgSt *)HeapAlloc( GetProcessHeap(), 0, sizeof(BotCfgDlgSt) );
st->cl = (L2Client *)lParam;
st->myCfg = st->cl->getConfig(); // create copy of client config
SetWindowLongPtrW( hDlg, GWLP_USERDATA, (LONG_PTR)st );
BotCfg_InitChildTabs( hDlg, st );
BotCfg_InitTree( hDlg, st );
} break;
case WM_DESTROY:
{
BotCfgDlgSt *st = (BotCfgDlgSt *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
SetWindowLongPtrW( hDlg, GWLP_USERDATA, 0 ); // no user-data now
BotCfg_DestroyChildTabs( hDlg, st );
HeapFree( GetProcessHeap(), 0, st ); // delete struct
//log_error( LOG_OK, "BotCfgDlgProc() WM_DESTROY\n" );
return FALSE; // call default handler
} break;
case WM_COMMAND: return BotCfg_OnCommand( hDlg, wParam, lParam ); break;
case WM_NOTIFY: return BotCfg_OnNotify( hDlg, lParam ); break;
default: return FALSE; break;
}
return TRUE;
}
BOOL BotCfg_OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(lParam);
BotCfgDlgSt *st = (BotCfgDlgSt *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
int ctrlID = LOWORD(wParam);
switch( ctrlID )
{
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
case IDOK: BotCfg_OnOK( hDlg, st ); break;
case IDC_APPLY: BotCfg_OnApply( hDlg, st ); break;
case IDC_LOAD: BotCfg_OnLoad( hDlg, st ); break;
case IDC_SAVE: BotCfg_OnSave( hDlg, st ); break;
default: return FALSE; break; // call default handler
}
return TRUE;
}
void BotCfg_InitChildTabs( HWND hDlg, BotCfgDlgSt *st )
{
int i;
for( i=0; i<=NUM_CHILD_TABS; i++ ) st->hWndChildTab[i] = NULL;
// create individual children, passing pointer to our copy of config
st->hWndChildTab[ T_SELF ] = BotCfgDlg_Self_Create( hDlg, &(st->myCfg) );
st->hWndChildTab[ T_SELF_HEAL ] = BotCfgDlg_SelfHeal_Create( hDlg, &(st->myCfg) );
st->hWndChildTab[ T_PARTY ] = BotCfgDlg_Party_Create( hDlg, &(st->myCfg) );
// resize all children to fit
RECT r, rd;
int tree_x = 0, tree_y = 0;
int tree_w = 0;
int right_w = 0;
int h = 0;
HWND htv = GetDlgItem( hDlg, IDC_TREE1 );
GetWindowRect( htv, &r );
GetClientRect( hDlg, &rd );
tree_x = 10;
tree_y = 10;
tree_w = r.right - r.left;
right_w = rd.right - rd.left - tree_w - tree_x - 10;
h = r.bottom - r.top;
for( i=1; i<=NUM_CHILD_TABS; i++ )
{
if( st->hWndChildTab[i] )
MoveWindow( st->hWndChildTab[i], tree_x + tree_w + 5, tree_y, right_w, h, TRUE );
}
}
void BotCfg_DestroyChildTabs( HWND hDlg, BotCfgDlgSt *st )
{
UNREFERENCED_PARAMETER(hDlg);
int i = NUM_CHILD_TABS;
while( i > 0 )
{
if( st->hWndChildTab[i] ) DestroyWindow( st->hWndChildTab[i] );
st->hWndChildTab[i] = 0;
i--;
}
}
void BotCfg_InitTree( HWND hDlg, BotCfgDlgSt *st )
{
HWND hwndTV = GetDlgItem( hDlg, IDC_TREE1 );
// self
st->htiSelf = WUTV_InsertItem( hwndTV, NULL, TVI_LAST, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), T_SELF, true, true, true );
/*st->htiSelfHeal = */
WUTV_InsertItem( hwndTV, st->htiSelf, TVI_LAST, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), T_SELF_HEAL, false, false, false );
// party
st->htiParty = WUTV_InsertItem( hwndTV, NULL, TVI_LAST, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), T_PARTY, true, true, true );
}
BOOL BotCfg_OnNotify( HWND hDlg, LPARAM lParam )
{
BotCfgDlgSt *st = (BotCfgDlgSt *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
LPNMHDR pnmh = (LPNMHDR)lParam;
HWND hwndTV = GetDlgItem( hDlg, IDC_TREE1 );
if( pnmh == NULL ) return FALSE; // default handler
switch( pnmh->code )
{
case TVN_SELCHANGING:
{
if( pnmh->hwndFrom == hwndTV )
{
LPNMTREEVIEW p = (LPNMTREEVIEW)lParam;
int idx = (int)(p->itemOld.lParam);
if( (idx >= 1) && (idx <= NUM_CHILD_TABS) )
{
if( st->hWndChildTab[idx] ) ShowWindow( st->hWndChildTab[idx], SW_HIDE );
}
}
} break;
case TVN_SELCHANGED:
{
if( pnmh->hwndFrom == hwndTV )
{
LPNMTREEVIEW p = (LPNMTREEVIEW)lParam;
int idx = (int)(p->itemNew.lParam);
if( (idx >= 1) && (idx <= NUM_CHILD_TABS) )
{
if( st->hWndChildTab[idx] ) ShowWindow( st->hWndChildTab[idx], SW_SHOW );
}
}
} break;
default: return FALSE; break; // call default handler
}
return TRUE;
}
void BotCfg_OnOK( HWND hDlg, BotCfgDlgSt *st )
{
BotCfg_OnApply( hDlg, st );
EndDialog( hDlg, IDOK );
}
void BotCfg_OnApply( HWND hDlg, BotCfgDlgSt *st )
{
UNREFERENCED_PARAMETER(hDlg);
// pass APPLY to all child windows
int i = 0;
for( i=1; i<=NUM_CHILD_TABS; i++ )
{
if( st->hWndChildTab[i] ) SendMessage( st->hWndChildTab[i], WM_COMMAND, IDC_APPLY, 0 );
}
// save our copy of config to L2Client
st->cl->setBotConfig( st->myCfg );
}
void BotCfg_OnLoad( HWND hDlg, BotCfgDlgSt *st )
{
// change subdir to '.\configs'
char curDir[256] = {0};
char newDir[256] = {0};
GetCurrentDirectoryA( 200, curDir );
wsprintfA( newDir, "%s\\configs", curDir );
SetCurrentDirectoryA( newDir );
//
char fileName[256] = {0};
OPENFILENAMEA ofn;
memset( &ofn, 0, sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = g_hInst;
ofn.lpstrFilter = "Config files\0*.config\0All files\0*.*\0\0";
ofn.lpstrFile = fileName;
ofn.nMaxFile = 255;
ofn.lpstrTitle = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?";
ofn.lpstrInitialDir = newDir;
ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if( GetOpenFileNameA( &ofn ) )
{
if( !st->myCfg.readConfig( fileName ) )
{
MessageBox( hDlg, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"), MB_ICONSTOP );
}
else // update all child tabs
{
// pass APPLY to all child windows
int i = 0;
for( i=1; i<=NUM_CHILD_TABS; i++ )
{
if( st->hWndChildTab[i] )
SendMessage( st->hWndChildTab[i], WM_COMMAND, IDC_LOAD, 0 );
}
}
}
// restore cur dir (required to load maps, for example)
SetCurrentDirectoryA( curDir );
}
void BotCfg_OnSave( HWND hDlg, BotCfgDlgSt *st )
{
// change subdir to '.\configs'
char curDir[256] = {0};
char newDir[256] = {0};
GetCurrentDirectoryA( 200, curDir );
wsprintfA( newDir, "%s\\configs", curDir );
SetCurrentDirectoryA( newDir );
//
char fileName[256] = {0};
OPENFILENAMEA ofn;
memset( &ofn, 0, sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = g_hInst;
ofn.lpstrFilter = "Config files\0*.config\0All files\0*.*\0\0";
ofn.lpstrFile = fileName;
ofn.nMaxFile = 255;
ofn.lpstrTitle = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>?";
ofn.lpstrInitialDir = newDir;
ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if( GetSaveFileNameA( &ofn ) )
{
if( strstr( fileName, ".config" ) == NULL ) strcat( fileName, ".config" );
if( !st->myCfg.saveConfig( fileName ) )
{
MessageBox( hDlg, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!"), MB_ICONSTOP );
}
}
// restore cur dir (required to load maps, for example)
SetCurrentDirectoryA( curDir );
}

13
l2ooghelper/BotCfgDlg.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef H_BOTCFGDLG
#define H_BOTCFGDLG
void BotCfgDlg_Run( HWND hWndParent, L2Client *pcl );
// children tabs create funcs
// self
HWND BotCfgDlg_Self_Create( HWND hWndParent, BotConfig *pcfg );
HWND BotCfgDlg_SelfHeal_Create( HWND hWndParent, BotConfig *pcfg );
// party
HWND BotCfgDlg_Party_Create( HWND hWndParent, BotConfig *pcfg );
#endif

View File

@@ -0,0 +1,93 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
#include "logger.h"
#include "L2Client.h"
#include "IL2Client.h"
#include "BotCfgDlg.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK BotCfg_Party_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
HWND BotCfgDlg_Party_Create( HWND hWndParent, BotConfig *pcfg )
{
return CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_BOTCFG_PARTY),
hWndParent, BotCfg_Party_DlgProc, (LPARAM)pcfg );
}
void BotCfg_Party_init( HWND hDlg, BotConfig *cfg );
void BotCfg_Party_apply( HWND hDlg, BotConfig *cfg );
INT_PTR CALLBACK BotCfg_Party_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
BotConfig *cfg = (BotConfig *)lParam;
SetWindowLongPtrW( hDlg, GWLP_USERDATA, (LONG_PTR)cfg );
BotCfg_Party_init( hDlg, cfg );
} break;
case WM_COMMAND:
{
BotConfig *cfg = (BotConfig *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
int ctrlID = LOWORD(wParam);
switch( ctrlID )
{
case IDC_APPLY: BotCfg_Party_apply( hDlg, cfg ); break;
case IDC_LOAD: BotCfg_Party_init( hDlg, cfg ); break;
default: return FALSE; break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}
void BotCfg_Party_init( HWND hDlg, BotConfig *cfg )
{
// init loot combobox
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_PARTY_LOOT );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>") );
int loot = cfg->getValInt( "party_loot" );
ComboBox_SetCurSel( hwndCB, loot );
//
CheckDlgButton( hDlg, IDC_C_PARTY_AUTO_ACCEPT, cfg->getValInt( "party_auto_accept_enable" ) );
SetDlgItemTextA( hDlg, IDC_E_PARTY_AUTO_ACCEPT, cfg->getValStr( "party_auto_accept_names" ) );
CheckDlgButton( hDlg, IDC_C_PARTY_AUTO_INVITE, cfg->getValInt( "party_auto_invite_enable" ) );
SetDlgItemTextA( hDlg, IDC_E_PARTY_AUTO_INVITE, cfg->getValStr( "party_auto_invite_names" ) );
//
CheckDlgButton( hDlg, IDC_C_FOLLOW_ENABLE, cfg->getValInt( "follow_enable" ) );
SetDlgItemTextA( hDlg, IDC_E_FOLLOW_NAME, cfg->getValStr( "follow_name" ) );
SetDlgItemInt( hDlg, IDC_E_FOLLOW_DIST, cfg->getValInt( "follow_dist" ), TRUE );
//
CheckDlgButton( hDlg, IDC_C_PARTY_ASSIST, cfg->getValInt( "party_assist_enable" ) );
}
void BotCfg_Party_apply( HWND hDlg, BotConfig *cfg )
{
char atext[512] = {0};
// loot CB
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_PARTY_LOOT );
cfg->setValInt( "party_loot", ComboBox_GetCurSel( hwndCB ) );
//
cfg->setValInt( "party_auto_accept_enable", IsDlgButtonChecked( hDlg, IDC_C_PARTY_AUTO_ACCEPT ) );
GetDlgItemTextA( hDlg, IDC_E_PARTY_AUTO_ACCEPT, atext, 255 );
cfg->setValStr( "party_auto_accept_names", atext );
cfg->setValInt( "party_auto_invite_enable", IsDlgButtonChecked( hDlg, IDC_C_PARTY_AUTO_INVITE ) );
GetDlgItemTextA( hDlg, IDC_E_PARTY_AUTO_INVITE, atext, 255 );
cfg->setValStr( "party_auto_invite_names", atext );
//
cfg->setValInt( "follow_enable", IsDlgButtonChecked( hDlg, IDC_C_FOLLOW_ENABLE ) );
GetDlgItemTextA( hDlg, IDC_E_FOLLOW_NAME, atext, 255 );
cfg->setValStr( "follow_name", atext );
cfg->setValInt( "follow_dist", GetDlgItemInt( hDlg, IDC_E_FOLLOW_DIST, NULL, TRUE ) );
//
cfg->setValInt( "party_assist_enable", IsDlgButtonChecked( hDlg, IDC_C_PARTY_ASSIST ) );
}

View File

@@ -0,0 +1,68 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
#include "logger.h"
#include "L2Client.h"
#include "IL2Client.h"
#include "BotCfgDlg.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK BotCfg_Self_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
HWND BotCfgDlg_Self_Create( HWND hWndParent, BotConfig *pcfg )
{
return CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_BOTCFG_SELF),
hWndParent, BotCfg_Self_DlgProc, (LPARAM)pcfg );
}
void BotCfg_Self_init( HWND hDlg, BotConfig *cfg );
void BotCfg_Self_apply( HWND hDlg, BotConfig *cfg );
INT_PTR CALLBACK BotCfg_Self_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
BotConfig *cfg = (BotConfig *)lParam;
SetWindowLongPtrW( hDlg, GWLP_USERDATA, (LONG_PTR)cfg );
//
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_AI_MODEL );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_SetCurSel( hwndCB, 0 );
//
BotCfg_Self_init( hDlg, cfg );
} break;
case WM_COMMAND:
{
BotConfig *cfg = (BotConfig *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
int ctrlID = LOWORD(wParam);
switch( ctrlID )
{
case IDC_APPLY: BotCfg_Self_apply( hDlg, cfg ); break;
case IDC_LOAD: BotCfg_Self_init( hDlg, cfg ); break;
default: return FALSE; break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}
void BotCfg_Self_init( HWND hDlg, BotConfig *cfg )
{
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_AI_MODEL );
ComboBox_SetCurSel( hwndCB, cfg->getValInt( "ai_model" ) );
}
void BotCfg_Self_apply( HWND hDlg, BotConfig *cfg )
{
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_AI_MODEL );
cfg->setValInt( "ai_model", ComboBox_GetCurSel( hwndCB ) );
}

View File

@@ -0,0 +1,606 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
#include "logger.h"
#include "L2Client.h"
#include "IL2Client.h"
#include "BotCfgDlg.h"
#include "Dlg_FindInDB.h"
#include "DBLayer.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK BotCfg_SelfHeal_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
HWND BotCfgDlg_SelfHeal_Create( HWND hWndParent, BotConfig *pcfg )
{
return CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_BOTCFG_SELFHEAL),
hWndParent, BotCfg_SelfHeal_DlgProc, (LPARAM)pcfg );
}
void BotCfg_SelfHeal_initLV( HWND hDlg );
void BotCfg_SelfHeal_init( HWND hDlg, BotConfig *cfg );
void BotCfg_SelfHeal_apply( HWND hDlg, BotConfig *cfg );
void BotCfg_SelfHeal_fill_LV( HWND hDlg, BotConfig *cfg );
void BotCfg_SelfHeal_apply_LV( HWND hDlg, BotConfig *cfg );
void BotCfg_SelfHeal_OnAddHealCond( HWND hDlg, BotConfig *cfg );
void BotCfg_SelfHeal_OnEditHealCond( HWND hDlg, BotConfig *cfg );
void BotCfg_SelfHeal_OnDelHealCond( HWND hDlg, BotConfig *cfg );
INT_PTR CALLBACK BotCfg_SelfHeal_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
BotConfig *cfg = (BotConfig *)lParam;
SetWindowLongPtrW( hDlg, GWLP_USERDATA, (LONG_PTR)cfg );
BotCfg_SelfHeal_initLV( hDlg );
BotCfg_SelfHeal_init( hDlg, cfg );
} break;
case WM_COMMAND:
{
BotConfig *cfg = (BotConfig *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
int ctrlID = LOWORD(wParam);
switch( ctrlID )
{
case IDC_APPLY: BotCfg_SelfHeal_apply( hDlg, cfg ); break;
case IDC_LOAD: BotCfg_SelfHeal_init( hDlg, cfg ); break;
case IDC_B_ADD: BotCfg_SelfHeal_OnAddHealCond( hDlg, cfg ); break;
case IDC_B_EDIT: BotCfg_SelfHeal_OnEditHealCond( hDlg, cfg ); break;
case IDC_B_DEL: BotCfg_SelfHeal_OnDelHealCond( hDlg, cfg ); break;
case IDC_COMBO2: BotCfg_SelfHeal_fill_LV( hDlg, cfg ); break;
default: return FALSE; break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}
void BotCfg_SelfHeal_init( HWND hDlg, BotConfig *cfg )
{
int sit_hp = cfg->getValInt( "self_heal_sit_hp" );
int sit_mp = cfg->getValInt( "self_heal_sit_mp" );
int stand_hp = cfg->getValInt( "self_heal_stand_hp" );
int stand_mp = cfg->getValInt( "self_heal_stand_mp" );
int sit_hp_enable = cfg->getValInt( "self_heal_sit_hp_enable" );
int sit_mp_enable = cfg->getValInt( "self_heal_sit_mp_enable" );
int stand_hp_enable = cfg->getValInt( "self_heal_stand_hp_enable" );
int stand_mp_enable = cfg->getValInt( "self_heal_stand_mp_enable" );
//
SetDlgItemInt( hDlg, IDC_E_SITHP, sit_hp, TRUE );
SetDlgItemInt( hDlg, IDC_E_SITMP, sit_mp, TRUE );
SetDlgItemInt( hDlg, IDC_E_STANDHP, stand_hp, TRUE );
SetDlgItemInt( hDlg, IDC_E_STANDMP, stand_mp, TRUE );
CheckDlgButton( hDlg, IDC_C_SITHP, sit_hp_enable );
CheckDlgButton( hDlg, IDC_C_SITMP, sit_mp_enable );
CheckDlgButton( hDlg, IDC_C_STANDHP, stand_hp_enable );
CheckDlgButton( hDlg, IDC_C_STANDMP, stand_mp_enable );
//
BotCfg_SelfHeal_fill_LV( hDlg, cfg );
}
void BotCfg_SelfHeal_apply( HWND hDlg, BotConfig *cfg )
{
//log_error( LOG_OK, "BotCfg_SelfHeal_apply\n" );
int sit_hp = GetDlgItemInt( hDlg, IDC_E_SITHP, NULL, TRUE );
int sit_mp = GetDlgItemInt( hDlg, IDC_E_SITMP, NULL, TRUE );
int stand_hp = GetDlgItemInt( hDlg, IDC_E_STANDHP, NULL, TRUE );
int stand_mp = GetDlgItemInt( hDlg, IDC_E_STANDMP, NULL, TRUE );
int sit_hp_enable = IsDlgButtonChecked( hDlg, IDC_C_SITHP );
int sit_mp_enable = IsDlgButtonChecked( hDlg, IDC_C_SITMP );
int stand_hp_enable = IsDlgButtonChecked( hDlg, IDC_C_STANDHP );
int stand_mp_enable = IsDlgButtonChecked( hDlg, IDC_C_STANDMP );
//
cfg->setValInt( "self_heal_sit_hp", sit_hp );
cfg->setValInt( "self_heal_sit_mp", sit_mp );
cfg->setValInt( "self_heal_stand_hp", stand_hp );
cfg->setValInt( "self_heal_stand_mp", stand_mp );
cfg->setValInt( "self_heal_sit_hp_enable", sit_hp_enable );
cfg->setValInt( "self_heal_sit_mp_enable", sit_mp_enable );
cfg->setValInt( "self_heal_stand_hp_enable", stand_hp_enable );
cfg->setValInt( "self_heal_stand_mp_enable", stand_mp_enable );
//
BotCfg_SelfHeal_apply_LV( hDlg, cfg );
}
void BotCfg_SelfHeal_initLV( HWND hDlg )
{
HWND hwndCB = GetDlgItem( hDlg, IDC_COMBO2 );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_SetCurSel( hwndCB, 0 );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 100, 0 );
WULV_InsertColumn( hwndLV, TEXT("HP<>"), 50, 1 );
WULV_InsertColumn( hwndLV, TEXT("HP%"), 40, 2 );
WULV_InsertColumn( hwndLV, TEXT("MP<>"), 50, 3 );
WULV_InsertColumn( hwndLV, TEXT("MP%"), 40, 4 );
WULV_InsertColumn( hwndLV, TEXT("CP<>"), 50, 5 );
WULV_InsertColumn( hwndLV, TEXT("CP%"), 40, 6 );
WULV_InsertColumn( hwndLV, TEXT("delay,ms"), 60, 7 );
}
void BotCfg_SelfHeal_fill_LV( HWND hDlg, BotConfig *cfg )
{
HWND hwndCB = GetDlgItem( hDlg, IDC_COMBO2 );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
int cur_sel = ComboBox_GetCurSel( hwndCB );
ListView_DeleteAllItems( hwndLV );
int i;
char valname[256];
char valname_base[256];
int num_cond = 0;
if( cur_sel == 0 ) // items
{
strcpy( valname_base, "self_heal_use_item" );
num_cond = cfg->getValInt( "self_heal_use_item_nConds" );
}
else if( cur_sel == 1 ) // skills
{
strcpy( valname_base, "self_heal_use_skill" );
num_cond = cfg->getValInt( "self_heal_use_skill_nConds" );
}
else return;
for( i=0; i<num_cond; i++ )
{
sprintf( valname, "%s_[%d]_id", valname_base, i );
int id = cfg->getValInt( valname );
sprintf( valname, "%s_[%d]_hp_cond", valname_base, i );
const char *hpcond = cfg->getValStr( valname );
sprintf( valname, "%s_[%d]_mp_cond", valname_base, i );
const char *mpcond = cfg->getValStr( valname );
sprintf( valname, "%s_[%d]_cp_cond", valname_base, i );
const char *cpcond = cfg->getValStr( valname );
sprintf( valname, "%s_[%d]_hp", valname_base, i );
int hpp = cfg->getValInt( valname );
sprintf( valname, "%s_[%d]_mp", valname_base, i );
int mpp = cfg->getValInt( valname );
sprintf( valname, "%s_[%d]_cp", valname_base, i );
int cpp = cfg->getValInt( valname );
sprintf( valname, "%s_[%d]_delayms", valname_base, i );
int delayms = cfg->getValInt( valname );
// item/skill name
TCHAR text[256] = {0};
if( cur_sel == 0 ) DBLayer_getItemName( id, text, 255 );
if( cur_sel == 1 ) DBLayer_getSkillName( id, text, 255 );
int inserted_iid = WULV_InsertItem( hwndLV, text, 0, (LPARAM)id );
// hp cond
_tcscpy( text, _T("=") );
if( strcmp( hpcond, "lt" ) == 0 ) _tcscpy( text, _T("<") );
else if( strcmp( hpcond, "le" ) == 0 ) _tcscpy( text, _T("<=") );
else if( strcmp( hpcond, "gt" ) == 0 ) _tcscpy( text, _T(">") );
else if( strcmp( hpcond, "ge" ) == 0 ) _tcscpy( text, _T(">=") );
WULV_SetItem( hwndLV, text, inserted_iid, 1 );
// hp
wsprintf( text, TEXT("%d"), hpp );
WULV_SetItem( hwndLV, text, inserted_iid, 2 );
// mp cond
_tcscpy( text, _T("=") );
if( strcmp( mpcond, "lt" ) == 0 ) _tcscpy( text, _T("<") );
else if( strcmp( mpcond, "le" ) == 0 ) _tcscpy( text, _T("<=") );
else if( strcmp( mpcond, "gt" ) == 0 ) _tcscpy( text, _T(">") );
else if( strcmp( mpcond, "ge" ) == 0 ) _tcscpy( text, _T(">=") );
WULV_SetItem( hwndLV, text, inserted_iid, 3 );
// mp
wsprintf( text, TEXT("%d"), mpp );
WULV_SetItem( hwndLV, text, inserted_iid, 4 );
// cp cond
_tcscpy( text, _T("=") );
if( strcmp( cpcond, "lt" ) == 0 ) _tcscpy( text, _T("<") );
else if( strcmp( cpcond, "le" ) == 0 ) _tcscpy( text, _T("<=") );
else if( strcmp( cpcond, "gt" ) == 0 ) _tcscpy( text, _T(">") );
else if( strcmp( cpcond, "ge" ) == 0 ) _tcscpy( text, _T(">=") );
WULV_SetItem( hwndLV, text, inserted_iid, 5 );
// cp
wsprintf( text, TEXT("%d"), cpp );
WULV_SetItem( hwndLV, text, inserted_iid, 6 );
// delay, ms
wsprintf( text, TEXT("%d"), delayms );
WULV_SetItem( hwndLV, text, inserted_iid, 7 );
//
}
}
void BotCfg_SelfHeal_apply_LV( HWND hDlg, BotConfig *cfg )
{
HWND hwndCB = GetDlgItem( hDlg, IDC_COMBO2 );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
int cur_sel_cb = ComboBox_GetCurSel( hwndCB );
int i;
char valname[256];
char valname_base[256];
int num_cond = ListView_GetItemCount( hwndLV );
if( cur_sel_cb == 0 ) // items
{
strcpy( valname_base, "self_heal_use_item" );
cfg->setValInt( "self_heal_use_item_nConds", num_cond );
}
else if( cur_sel_cb == 1 ) // skills
{
strcpy( valname_base, "self_heal_use_skill" );
cfg->setValInt( "self_heal_use_skill_nConds", num_cond );
}
else return;
int iItem = -1;
i = 0;
while( (iItem = ListView_GetNextItem( hwndLV, iItem, LVNI_ALL )) != -1 )
{
TCHAR text[256] = {0};
int ival = 0;
char strval[32] = {0};
// id
WULV_GetItemText( hwndLV, iItem, 0, text, 255 );
int id = (int)WULV_GetItemLPARAM( hwndLV, iItem );
//log_error( LOG_OK, "BotCfg_SelfHeal_apply_LV[%d] %S id %u\n", iItem, text, id );
sprintf( valname, "%s_[%d]_id", valname_base, i );
cfg->setValInt( valname, id );
// hp_cond
WULV_GetItemText( hwndLV, iItem, 1, text, 255 );
strcpy( strval, "eq" );
if( _tcscmp( text, _T("<") ) == 0 ) strcpy( strval, "lt" );
else if( _tcscmp( text, _T("<=") ) == 0 ) strcpy( strval, "le" );
else if( _tcscmp( text, _T(">") ) == 0 ) strcpy( strval, "gt" );
else if( _tcscmp( text, _T(">=") ) == 0 ) strcpy( strval, "ge" );
sprintf( valname, "%s_[%d]_hp_cond", valname_base, i );
cfg->setValStr( valname, strval );
// hp
WULV_GetItemText( hwndLV, iItem, 2, text, 255 );
_stscanf( text, _T("%d"), &ival );
sprintf( valname, "%s_[%d]_hp", valname_base, i );
cfg->setValInt( valname, ival );
// mp_cond
WULV_GetItemText( hwndLV, iItem, 3, text, 255 );
strcpy( strval, "eq" );
if( _tcscmp( text, _T("<") ) == 0 ) strcpy( strval, "lt" );
else if( _tcscmp( text, _T("<=") ) == 0 ) strcpy( strval, "le" );
else if( _tcscmp( text, _T(">") ) == 0 ) strcpy( strval, "gt" );
else if( _tcscmp( text, _T(">=") ) == 0 ) strcpy( strval, "ge" );
sprintf( valname, "%s_[%d]_mp_cond", valname_base, i );
cfg->setValStr( valname, strval );
// mp
WULV_GetItemText( hwndLV, iItem, 4, text, 255 );
_stscanf( text, _T("%d"), &ival );
sprintf( valname, "%s_[%d]_mp", valname_base, i );
cfg->setValInt( valname, ival );
// cp_cond
WULV_GetItemText( hwndLV, iItem, 5, text, 255 );
strcpy( strval, "eq" );
if( _tcscmp( text, _T("<") ) == 0 ) strcpy( strval, "lt" );
else if( _tcscmp( text, _T("<=") ) == 0 ) strcpy( strval, "le" );
else if( _tcscmp( text, _T(">") ) == 0 ) strcpy( strval, "gt" );
else if( _tcscmp( text, _T(">=") ) == 0 ) strcpy( strval, "ge" );
sprintf( valname, "%s_[%d]_cp_cond", valname_base, i );
cfg->setValStr( valname, strval );
// cp
WULV_GetItemText( hwndLV, iItem, 6, text, 255 );
_stscanf( text, _T("%d"), &ival );
sprintf( valname, "%s_[%d]_cp", valname_base, i );
cfg->setValInt( valname, ival );
// delay, ms
WULV_GetItemText( hwndLV, iItem, 7, text, 255 );
_stscanf( text, _T("%d"), &ival );
sprintf( valname, "%s_[%d]_delayms", valname_base, i );
cfg->setValInt( valname, ival );
//
i++;
}
}
class self_heal_cond
{
public:
bool used;
int type; // 0 - item; 1 - skill
int id; // skill or item ID
int hp;
int hp_cond; // < <= = > >= ||| in cfg: 'lt' 'le' 'eq' 'gt' 'ge'
int mp;
int mp_cond;
int cp;
int cp_cond;
int delayms;
};
// < <= = > >= ||| in cfg: 'lt' 'le' 'eq' 'gt' 'ge'
void getCondTextByNum( int n, char *outHR, char *outASM )
{
if( outHR ) outHR[0] = 0;
if( outASM ) outASM[0] = 0;
switch( n )
{
case 0:
{
if( outHR ) strcpy( outHR, "<" );
if( outASM ) strcpy( outASM, "lt" );
} break;
case 1:
{
if( outHR ) strcpy( outHR, "<=" );
if( outASM ) strcpy( outASM, "le" );
} break;
case 2:
{
if( outHR ) strcpy( outHR, "=" );
if( outASM ) strcpy( outASM, "eq" );
} break;
case 3:
{
if( outHR ) strcpy( outHR, ">" );
if( outASM ) strcpy( outASM, "gt" );
} break;
case 4:
{
if( outHR ) strcpy( outHR, ">=" );
if( outASM ) strcpy( outASM, "ge" );
} break;
}
}
bool BotCfg_SelfHeal_CondDlgRun( HWND hWndParent, self_heal_cond *st );
void BotCfg_SelfHeal_OnAddHealCond( HWND hDlg, BotConfig *cfg )
{
HWND hwndCB = GetDlgItem( hDlg, IDC_COMBO2 );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
int cur_sel = ComboBox_GetCurSel( hwndCB );
self_heal_cond st;
st.type = cur_sel;
st.used = false;
st.delayms = 0;
st.id = 0;
st.hp = st.mp = st.cp = 0;
st.hp_cond = st.mp_cond = st.cp_cond = 0;
if( BotCfg_SelfHeal_CondDlgRun( hDlg, &st ) )
{
char name[256] = {0};
wchar_t namew[256] = {0};
switch( st.type )
{
case 0: DBLayer_getItemName( st.id, namew, 255 ); break;
case 1: DBLayer_getSkillName( st.id, namew, 255 ); break;
}
// name
int added_idx = WULV_InsertItem( hwndLV, namew, 999, st.id );
// hp cond
getCondTextByNum( st.hp_cond, name, NULL );
MultiByteToWideChar( CP_ACP, 0, name, -1, namew, 255 );
WULV_SetItem( hwndLV, namew, added_idx, 1 );
wsprintfW( namew, L"%d", st.hp );
WULV_SetItem( hwndLV, namew, added_idx, 2 );
// mp cond
getCondTextByNum( st.mp_cond, name, NULL );
MultiByteToWideChar( CP_ACP, 0, name, -1, namew, 255 );
WULV_SetItem( hwndLV, namew, added_idx, 3 );
wsprintfW( namew, L"%d", st.mp );
WULV_SetItem( hwndLV, namew, added_idx, 4 );
// cp cond
getCondTextByNum( st.cp_cond, name, NULL );
MultiByteToWideChar( CP_ACP, 0, name, -1, namew, 255 );
WULV_SetItem( hwndLV, namew, added_idx, 5 );
wsprintfW( namew, L"%d", st.cp );
WULV_SetItem( hwndLV, namew, added_idx, 6 );
// delay ms
wsprintfW( namew, L"%d", st.delayms );
WULV_SetItem( hwndLV, namew, added_idx, 7 );
}
BotCfg_SelfHeal_apply_LV( hDlg, cfg );
//BotCfg_SelfHeal_fill_LV( hDlg, cfg ); // update LV
}
void BotCfg_SelfHeal_OnEditHealCond( HWND hDlg, BotConfig *cfg )
{
HWND hwndCB = GetDlgItem( hDlg, IDC_COMBO2 );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
int cur_sel_cb = ComboBox_GetCurSel( hwndCB );
int cur_sel_lv = ListView_GetNextItem( hwndLV, -1, LVNI_SELECTED );
if( cur_sel_lv < 0 ) return;
self_heal_cond st;
st.type = cur_sel_cb;
// fill struct with existing info
TCHAR text[256];
// id
st.id = (int)WULV_GetItemLPARAM( hwndLV, cur_sel_lv );
// hp_cond
WULV_GetItemText( hwndLV, cur_sel_lv, 1, text, 255 );
st.hp_cond = 2; // eq
if( _tcscmp( text, _T("<") ) == 0 ) st.hp_cond = 0;
else if( _tcscmp( text, _T("<=") ) == 0 ) st.hp_cond = 1;
else if( _tcscmp( text, _T(">") ) == 0 ) st.hp_cond = 3;
else if( _tcscmp( text, _T(">=") ) == 0 ) st.hp_cond = 4;
// hp
WULV_GetItemText( hwndLV, cur_sel_lv, 2, text, 255 );
_stscanf( text, _T("%d"), &(st.hp) );
// mp_cond
WULV_GetItemText( hwndLV, cur_sel_lv, 3, text, 255 );
st.mp_cond = 2; // eq
if( _tcscmp( text, _T("<") ) == 0 ) st.mp_cond = 0;
else if( _tcscmp( text, _T("<=") ) == 0 ) st.mp_cond = 1;
else if( _tcscmp( text, _T(">") ) == 0 ) st.mp_cond = 3;
else if( _tcscmp( text, _T(">=") ) == 0 ) st.mp_cond = 4;
// mp
WULV_GetItemText( hwndLV, cur_sel_lv, 4, text, 255 );
_stscanf( text, _T("%d"), &(st.mp) );
// cp_cond
WULV_GetItemText( hwndLV, cur_sel_lv, 5, text, 255 );
st.cp_cond = 2; // eq
if( _tcscmp( text, _T("<") ) == 0 ) st.cp_cond = 0;
else if( _tcscmp( text, _T("<=") ) == 0 ) st.cp_cond = 1;
else if( _tcscmp( text, _T(">") ) == 0 ) st.cp_cond = 3;
else if( _tcscmp( text, _T(">=") ) == 0 ) st.cp_cond = 4;
// cp
WULV_GetItemText( hwndLV, cur_sel_lv, 6, text, 255 );
_stscanf( text, _T("%d"), &(st.cp) );
// delayms
WULV_GetItemText( hwndLV, cur_sel_lv, 7, text, 255 );
_stscanf( text, _T("%d"), &(st.delayms) );
// run dialog
if( BotCfg_SelfHeal_CondDlgRun( hDlg, &st ) )
{
// get name from DB
char name[256] = {0};
wchar_t namew[256] = {0};
switch( st.type )
{
case 0: DBLayer_getItemName( st.id, namew, 255 ); break;
case 1: DBLayer_getSkillName( st.id, namew, 255 ); break;
}
// del existing item, then insert new with new values :)
ListView_DeleteItem( hwndLV, cur_sel_lv );
// name
int added_idx = WULV_InsertItem( hwndLV, namew, 999, st.id );
// hp cond
getCondTextByNum( st.hp_cond, name, NULL );
MultiByteToWideChar( CP_ACP, 0, name, -1, namew, 255 );
WULV_SetItem( hwndLV, namew, added_idx, 1 );
wsprintfW( namew, L"%d", st.hp );
WULV_SetItem( hwndLV, namew, added_idx, 2 );
// mp cond
getCondTextByNum( st.mp_cond, name, NULL );
MultiByteToWideChar( CP_ACP, 0, name, -1, namew, 255 );
WULV_SetItem( hwndLV, namew, added_idx, 3 );
wsprintfW( namew, L"%d", st.mp );
WULV_SetItem( hwndLV, namew, added_idx, 4 );
// cp cond
getCondTextByNum( st.cp_cond, name, NULL );
MultiByteToWideChar( CP_ACP, 0, name, -1, namew, 255 );
WULV_SetItem( hwndLV, namew, added_idx, 5 );
wsprintfW( namew, L"%d", st.cp );
WULV_SetItem( hwndLV, namew, added_idx, 6 );
// delay ms
wsprintfW( namew, L"%d", st.delayms );
WULV_SetItem( hwndLV, namew, added_idx, 7 );
}
//
BotCfg_SelfHeal_apply_LV( hDlg, cfg );
//BotCfg_SelfHeal_fill_LV( hDlg, cfg ); // update LV
}
void BotCfg_SelfHeal_OnDelHealCond( HWND hDlg, BotConfig *cfg )
{
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
int cur_sel_lv = ListView_GetNextItem( hwndLV, -1, LVNI_SELECTED );
ListView_DeleteItem( hwndLV, cur_sel_lv );
BotCfg_SelfHeal_apply_LV( hDlg, cfg );
BotCfg_SelfHeal_fill_LV( hDlg, cfg ); // update LV
}
INT_PTR CALLBACK BotCfg_SelfHeal_CondDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
bool BotCfg_SelfHeal_CondDlgRun( HWND hWndParent, self_heal_cond *st )
{
INT_PTR ret = DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_BOTCFG_SELFHEAL_COND), hWndParent,
BotCfg_SelfHeal_CondDlgProc, (LPARAM)st );
if( ret == IDOK ) return true;
return false;
}
INT_PTR CALLBACK BotCfg_SelfHeal_CondDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
self_heal_cond *st = (self_heal_cond *)lParam;
SetWindowLongPtrW( hDlg, GWLP_USERDATA, (LONG_PTR)st );
// comboboxes
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_HP );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("<") );
ComboBox_AddString( hwndCB, TEXT("<=") );
ComboBox_AddString( hwndCB, TEXT("=") );
ComboBox_AddString( hwndCB, TEXT(">") );
ComboBox_AddString( hwndCB, TEXT(">=") );
ComboBox_SetCurSel( hwndCB, st->hp_cond );
hwndCB = GetDlgItem( hDlg, IDC_CB_MP );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("<") );
ComboBox_AddString( hwndCB, TEXT("<=") );
ComboBox_AddString( hwndCB, TEXT("=") );
ComboBox_AddString( hwndCB, TEXT(">") );
ComboBox_AddString( hwndCB, TEXT(">=") );
ComboBox_SetCurSel( hwndCB, st->mp_cond );
hwndCB = GetDlgItem( hDlg, IDC_CB_CP );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("<") );
ComboBox_AddString( hwndCB, TEXT("<=") );
ComboBox_AddString( hwndCB, TEXT("=") );
ComboBox_AddString( hwndCB, TEXT(">") );
ComboBox_AddString( hwndCB, TEXT(">=") );
ComboBox_SetCurSel( hwndCB, st->cp_cond );
// item/skill id
SetDlgItemInt( hDlg, IDC_E_ITEMID, st->id, TRUE );
if( st->id > 0 )
{
wchar_t skillName[256] = {0};
DBLayer_getSkillName( (unsigned int)st->id, skillName, 256 );
SetDlgItemTextW( hDlg, IDC_E_ITEM, skillName );
}
// hp, mp, cp values
SetDlgItemInt( hDlg, IDC_E_HP, st->hp, TRUE );
SetDlgItemInt( hDlg, IDC_E_MP, st->mp, TRUE );
SetDlgItemInt( hDlg, IDC_E_CP, st->cp, TRUE );
// delay ms
SetDlgItemInt( hDlg, IDC_E_DELAYMS, st->delayms, TRUE );
//
return TRUE;
} break;
case WM_COMMAND:
{
self_heal_cond *st = (self_heal_cond *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
switch( LOWORD( wParam ) )
{
case IDOK:
{
// get all fields from dialog
// hp,mp,cp cond & val
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_HP );
st->hp_cond = ComboBox_GetCurSel( hwndCB );
st->hp = GetDlgItemInt( hDlg, IDC_E_HP, NULL, TRUE );
hwndCB = GetDlgItem( hDlg, IDC_CB_MP );
st->mp_cond = ComboBox_GetCurSel( hwndCB );
st->mp = GetDlgItemInt( hDlg, IDC_E_MP, NULL, TRUE );
hwndCB = GetDlgItem( hDlg, IDC_CB_CP );
st->cp_cond = ComboBox_GetCurSel( hwndCB );
st->cp = GetDlgItemInt( hDlg, IDC_E_CP, NULL, TRUE );
// skill id
st->id = GetDlgItemInt( hDlg, IDC_E_ITEMID, NULL, TRUE );
// delay ms
st->delayms = GetDlgItemInt( hDlg, IDC_E_DELAYMS, NULL, TRUE );
//
st->used = true;
EndDialog( hDlg, IDOK );
return TRUE;
} break;
case IDCANCEL:
{
st->used = false;
EndDialog( hDlg, IDCANCEL );
return TRUE;
} break;
case IDC_B_FIND:
{
Dlg_FindInDB *dlg = NULL;
switch( st->type )
{
case 0: dlg = new Dlg_FindInDB( Dlg_FindInDB::MODE_ITEM ); break;
case 1: dlg = new Dlg_FindInDB( Dlg_FindInDB::MODE_SKILL ); break;
}
if( !dlg ) return FALSE;
if( dlg->runDialog( hDlg ) )
{
SetDlgItemTextW( hDlg, IDC_E_ITEM, dlg->itemNameW );
SetDlgItemInt( hDlg, IDC_E_ITEMID, dlg->itemID, FALSE );
}
delete dlg;
} break;
}
return FALSE;
} break;
}
return FALSE;
}

321
l2ooghelper/BotConfig.cpp Normal file
View File

@@ -0,0 +1,321 @@
#include "stdafx.h"
#include "BotConfig.h"
char botconfig_dummy_str_buffer[2];
void BotConfigValue::clear()
{
m_name[0] = 0; // clear name :)
clearVal();
}
void BotConfigValue::clearVal()
{
if( (type == CFG_TYPE_STR) && str ) free( str );
type = CFG_TYPE_NONE;
str = NULL;
i = 0;
d = 0.0;
}
void BotConfigValue::setStr( const char *stringValue )
{
clearVal();
str = NULL;
if( stringValue ) str = _strdup( stringValue );
type = CFG_TYPE_STR;
}
void BotConfigValue::setInt( int iVal )
{
clearVal();
i = iVal;
type = CFG_TYPE_INT;
}
void BotConfigValue::setFlt( double dVal )
{
clearVal();
d = dVal;
type = CFG_TYPE_FLT;
}
// always returns non-NULL value
const char *BotConfigValue::getStr() const
{
if( (type != CFG_TYPE_STR) )
{
botconfig_dummy_str_buffer[0] = botconfig_dummy_str_buffer[1] = 0;
return (const char *)botconfig_dummy_str_buffer;
}
if( !str )
{
botconfig_dummy_str_buffer[0] = botconfig_dummy_str_buffer[1] = 0;
return (const char *)botconfig_dummy_str_buffer;
}
return str;
}
BotConfigValue::BotConfigValue( const BotConfigValue& other )
{
type = CFG_TYPE_NONE;
this->operator=( other );
}
BotConfigValue& BotConfigValue::operator=( const BotConfigValue& other )
{
this->d = other.d;
this->i = other.i;
this->str = NULL; if( other.str ) this->str = _strdup( other.str );
this->type = other.type;
this->m_name[0] = 0; if( other.m_name[0] ) strcpy( this->m_name, other.m_name );
return (*this);
}
void BotConfigValue::setName( const char *valName )
{
memset( m_name, 0, sizeof(m_name) );
strncpy( m_name, valName, sizeof(m_name)-1 );
}
BotConfig::BotConfig()
{
removeAllValues();
}
BotConfig::~BotConfig()
{
removeAllValues();
}
BotConfig::BotConfig( const BotConfig& other )
{
this->operator=( other );
}
BotConfig& BotConfig::operator=( const BotConfig& other )
{
removeAllValues();
int i;
for( i=0; i<MAX_VALUES; i++ ) this->value[i] = other.value[i];
return (*this);
}
void BotConfig::removeAllValues()
{
int i;
for( i=0; i<BotConfig::MAX_VALUES; i++ ) value[i].clear();
}
int BotConfig::findValueIndex( const char *valName ) const
{
if( !valName ) return -1;
if( valName[0] == 0 ) return -1;
int i = 0;
for( i=0; i<MAX_VALUES; i++ )
{
if( strcmp( valName, value[i].name() ) == 0 ) return i;
}
return -1;
}
int BotConfig::findFreeIndex() const
{
int i;
for( i=0; i<MAX_VALUES; i++ ) if( value[i].getType() == CFG_TYPE_NONE ) return i;
return -1;
}
bool BotConfig::addValue( BotConfigValue& val )
{
int idx = findFreeIndex();
if( idx == -1 )
{
MessageBox( NULL, TEXT("Cannot add var to config: overflow?"), TEXT("BotConfig"), MB_ICONWARNING );
return false;
}
value[idx] = val;
return true;
}
CFG_VALTYPE BotConfig::getValType( const char *valName ) const
{
int idx = findValueIndex( valName );
if( idx == -1 ) return CFG_TYPE_NONE;
return value[idx].getType();
}
int BotConfig::getValInt( const char *valName ) const
{
int idx = findValueIndex( valName );
if( idx == -1 ) return 0;
return value[idx].getInt();
}
double BotConfig::getValFlt( const char *valName ) const
{
int idx = findValueIndex( valName );
if( idx == -1 ) return 0.0;
return value[idx].getFlt();
}
const char *BotConfig::getValStr( const char *valName ) const
{
int idx = findValueIndex( valName );
if( idx == -1 )
{
botconfig_dummy_str_buffer[0] = botconfig_dummy_str_buffer[1] = 0;
return botconfig_dummy_str_buffer;
}
return value[idx].getStr();
}
BotConfigValue BotConfig::getVal( const char *valName ) const
{
BotConfigValue val;
int idx = findValueIndex( valName );
if( idx == -1 ) return val;
val = value[idx];
return val;
}
const BotConfigValue& BotConfig::getValByIdx( int idx ) const
{
if( (idx<0) || (idx>=MAX_VALUES) )
{
return value[0];
}
return value[idx];
}
void BotConfig::setValue( const char *valName, BotConfigValue &val )
{
int idx = findValueIndex( valName );
if( idx == -1 ) addValue( val );
else value[idx] = val;
}
void BotConfig::setValInt( const char *valName, int i )
{
BotConfigValue val; val.setName( valName ); val.setInt( i );
setValue( valName, val );
}
void BotConfig::setValFlt( const char *valName, double d )
{
BotConfigValue val; val.setName( valName ); val.setFlt( d );
setValue( valName, val );
}
void BotConfig::setValStr( const char *valName, const char *str )
{
BotConfigValue val; val.setName( valName ); val.setStr( str );
setValue( valName, val );
}
bool BotConfig::valExists( const char *valName ) const
{
int idx = findValueIndex( valName );
return ( idx != -1 );
}
bool BotConfig::readConfig( const char *fileName, bool clearExistingConfig /*= true*/ )
{
FILE *f = fopen( fileName, "rt" );
if( !f ) return false;
if( clearExistingConfig ) removeAllValues();
char line[2048];
while( !feof( f ) )
{
memset( line, 0, sizeof(line) );
fgets( line, sizeof(line)-1, f );
if( line[0] == 0 ) continue;
// pass comments
if( (line[0] == '#') || ((line[0] == '/') && (line[1] == '/') ) ) continue;
//
size_t ll = strlen( line );
if( (line[ll-1] == '\r') || (line[ll-1] == '\n') ) line[ll-1] = 0;
if( (line[ll-2] == '\r') || (line[ll-2] == '\n') ) line[ll-2] = 0;
//
char *valVal = strchr( line, '=' );
if( !valVal ) continue;
(*valVal) = 0;
valVal++;
char valType = line[0];
char *valName = line+1;
switch( valType )
{
case 'I':
{
int i = 0;
sscanf( valVal, "%d", &i );
BotConfigValue val;
val.setInt( i );
val.setName( valName );
setValue( valName, val );
} break;
case 'F':
{
double d = 0;
sscanf( valVal, "%f", &d );
BotConfigValue val;
val.setFlt( d );
val.setName( valName );
setValue( valName, val );
} break;
case 'S':
{
BotConfigValue val;
val.setStr( valVal );
val.setName( valName );
setValue( valName, val );
} break;
}
}
fclose( f );
return true;
}
bool BotConfig::saveConfig( const char *fileName ) const
{
FILE *f = fopen( fileName, "wt" );
if( !f ) return false;
int i;
for( i=0; i<MAX_VALUES; i++ )
{
if( value[i].getType() == CFG_TYPE_NONE ) continue;
switch( value[i].getType() )
{
case CFG_TYPE_INT:
{
fprintf( f, "I%s=%d\n", value[i].name(), value[i].getInt() );
} break;
case CFG_TYPE_FLT:
{
fprintf( f, "F%s=%0.6f\n", value[i].name(), value[i].getFlt() );
} break;
case CFG_TYPE_STR:
{
fprintf( f, "S%s=%s\n", value[i].name(), value[i].getStr() );
} break;
}
}
fclose( f );
return true;
}
bool BotConfig::readConfig( const wchar_t *fileName, bool clearExistingConfig /*= true*/ )
{
char aFileName[256] = {0};
WideCharToMultiByte( CP_ACP, 0, fileName, -1, aFileName, 255, NULL, NULL );
aFileName[255] = 0;
return readConfig( aFileName, clearExistingConfig );
}
bool BotConfig::saveConfig( const wchar_t *fileName ) const
{
char aFileName[256] = {0};
WideCharToMultiByte( CP_ACP, 0, fileName, -1, aFileName, 255, NULL, NULL );
aFileName[255] = 0;
return saveConfig( aFileName );
}

76
l2ooghelper/BotConfig.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef H_BOT_CONFIG
#define H_BOT_CONFIG
#include "BotConfigIDList.h"
typedef enum eCFG_VALTYPE { CFG_TYPE_NONE, CFG_TYPE_INT, CFG_TYPE_FLT, CFG_TYPE_STR } CFG_VALTYPE;
class BotConfigValue
{
public:
BotConfigValue() { type = CFG_TYPE_NONE; clear(); }
~BotConfigValue() { clear(); }
BotConfigValue( const BotConfigValue& other );
BotConfigValue& operator=( const BotConfigValue& other );
public:
void clear();
void clearVal();
public:
void setStr( const char *stringValue );
void setInt( int iVal );
void setFlt( double dVal );
public:
const char *getStr() const;
int getInt() const { return i; }
double getFlt() const { return d; }
CFG_VALTYPE getType() const { return type; }
public:
const char *name() const { return (const char *)m_name; }
void setName( const char *valName );
protected:
char m_name[64];
CFG_VALTYPE type;
char *str;
double d;
int i;
};
class BotConfig
{
public:
BotConfig();
~BotConfig();
BotConfig( const BotConfig& other );
BotConfig& operator=( const BotConfig& other );
public:
void removeAllValues();
public:
static const int MAX_VALUES = 512;
public:
bool readConfig( const char *fileName, bool clearExistingConfig = true );
bool saveConfig( const char *fileName ) const;
// unicode
bool readConfig( const wchar_t *fileName, bool clearExistingConfig = true );
bool saveConfig( const wchar_t *fileName ) const;
public:
CFG_VALTYPE getValType( const char *valName ) const;
int getValInt( const char *valName ) const;
double getValFlt( const char *valName ) const;
const char *getValStr( const char *valName ) const;
BotConfigValue getVal( const char *valName ) const;
const BotConfigValue& getValByIdx( int idx ) const;
bool valExists( const char *valName ) const;
public:
void setValue( const char *valName, BotConfigValue &val );
void setValInt( const char *valName, int i );
void setValFlt( const char *valName, double d );
void setValStr( const char *valName, const char *str );
protected:
int findValueIndex( const char *valName ) const;
int findFreeIndex() const;
bool addValue( BotConfigValue& val );
protected:
BotConfigValue value[MAX_VALUES];
};
#endif

View File

@@ -0,0 +1,36 @@
#include "stdafx.h"
bool BotCfg_IsInList( const char *id, const char *list )
{
if( !id || !list ) return false;
// olny one id in list, which is equal to what we need?
if( _stricmp( id, list ) == 0 ) return true;
// make copies
char *idc = _strdup( id );
char *listc = _strdup( list );
// lowercase!
_strlwr( idc );
_strlwr( listc );
//
bool ret = false;
char test_id[256];
// id is in the beginning
sprintf( test_id, "%s;", idc );
if( strstr( listc, idc ) == listc ) ret = true;
// id in the end
if( !ret )
{
sprintf( test_id, "%;s", idc );
if( strstr( listc, idc ) ) ret = true;
}
// in the middle?
if( !ret )
{
sprintf( test_id, "%;s;", idc );
if( strstr( listc, idc ) ) ret = true;
}
//
free( idc );
free( listc );
return ret;
}

View File

@@ -0,0 +1,6 @@
#ifndef H_BOTCFG_IDLIST
#define H_BOTCFG_IDLIST
bool BotCfg_IsInList( const char *id, const char *list );
#endif

415
l2ooghelper/BuySellDlg.cpp Normal file
View File

@@ -0,0 +1,415 @@
#include "stdafx.h"
#include "Resource.h"
#include "BuySellDlg.h"
#include "logger.h"
#include "windowUtils.h"
#include "DBLayer.h"
extern HINSTANCE g_hInst;
extern HWND g_hWnd;
BuySellDlg::BuySellDlg( HWND hWndNotify, UINT uMessage, int type, TradeItemsList *list )
{
m_hWndNotify = hWndNotify;
m_uNotifyMesasage = uMessage;
m_type = type;
m_list_src = list;
m_list_result = new TradeItemsList();
m_list_result->listID = list->listID; // save listID! important
}
BuySellDlg::~BuySellDlg()
{
delete m_list_src;
m_list_src = NULL;
m_list_result = NULL; // this list is deleted by L2Client reply message receiver
log_error( LOG_DEBUG, "BuySellDlg::~BuySellDlg()\n" );
}
void BuySellDlg::run()
{
DWORD dwTID = 0;
HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))BuySellDlg_Thread, (void *)this,
0, (unsigned int *)&dwTID );
if( hThread ) CloseHandle( hThread );
}
DWORD WINAPI BuySellDlg::BuySellDlg_Thread( LPVOID lpParam )
{
class BuySellDlg *pcls = (BuySellDlg *)lpParam;
HWND hDlg = CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_TRADEITEMS),
g_hWnd, BuySell_DlgProc, (LPARAM)pcls );
ShowWindow( hDlg, SW_SHOW );
MSG msg;
//while( GetMessage( &msg, hDlg, 0, 0 ) )
while( GetMessage( &msg, NULL, 0, 0 ) )
{
if( !IsDialogMessage( hDlg, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
log_error( LOG_DEBUG, "BuySellDlg_Thread(): ended window loop\n" );
DestroyWindow( hDlg );
return 0;
}
INT_PTR CALLBACK BuySellDlg::BuySell_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
OnInitDialog( hDlg, lParam );
} break;
case WM_COMMAND: OnCommand( hDlg, wParam, lParam ); break;
case WM_NOTIFY: OnNotify( hDlg, wParam, lParam ); break;
case WM_DESTROY: { OnDestroy( hDlg ); return FALSE; } break;
default: return FALSE; break;
}
return TRUE;
}
void BuySellDlg::FillListViews( HWND hDlg, BuySellDlg *pcls )
{
long long int downAdena = 0;
HWND hwndLV = NULL;
int i = 0;
// up LV
hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
ListView_DeleteAllItems( hwndLV );
for( i=0; i<pcls->m_list_src->itemCount; i++ )
{
TradeItem it;
it = pcls->m_list_src->item[i];
wchar_t wstr[256] = {0};
DBLayer_getItemName( it.itemID, wstr, 255 );
int added_iid = 0;
if( it.enchantLevel == 0 )
{
added_iid = WULV_InsertItem( hwndLV, wstr, 0, i ); // lParam is just index
}
else
{
wchar_t descr[256] = {0};
swprintf( descr, 255, L"+%d %s", it.enchantLevel, wstr );
added_iid = WULV_InsertItem( hwndLV, descr, 0, i ); // lParam is just index
}
if( added_iid == -1 ) continue;
wsprintfW( wstr, L"%I64d", it.price );
WULV_SetItem( hwndLV, wstr, added_iid, 1 );
wsprintfW( wstr, L"%I64d", it.count );
WULV_SetItem( hwndLV, wstr, added_iid, 2 );
wsprintfW( wstr, L"%u", it.itemID );
WULV_SetItem( hwndLV, wstr, added_iid, 3 );
wsprintfW( wstr, L"%u", it.objectID );
WULV_SetItem( hwndLV, wstr, added_iid, 4 );
}
// down LV
hwndLV = GetDlgItem( hDlg, IDC_LIST2 );
ListView_DeleteAllItems( hwndLV );
for( i=0; i<pcls->m_list_result->itemCount; i++ )
{
TradeItem it;
it = pcls->m_list_result->item[i];
wchar_t wstr[256] = {0};
DBLayer_getItemName( it.itemID, wstr, 255 );
int added_iid = 0;
if( it.enchantLevel == 0 )
{
added_iid = WULV_InsertItem( hwndLV, wstr, 0, i ); // lParam is just index
}
else
{
wchar_t descr[256] = {0};
swprintf( descr, 255, L"+%d %s", it.enchantLevel, wstr );
added_iid = WULV_InsertItem( hwndLV, descr, 0, i ); // lParam is just index
}
if( added_iid == -1 ) continue;
wsprintfW( wstr, L"%I64d", it.price );
WULV_SetItem( hwndLV, wstr, added_iid, 1 );
wsprintfW( wstr, L"%I64d", it.count );
WULV_SetItem( hwndLV, wstr, added_iid, 2 );
wsprintfW( wstr, L"%u", it.itemID );
WULV_SetItem( hwndLV, wstr, added_iid, 3 );
wsprintfW( wstr, L"%u", it.objectID );
WULV_SetItem( hwndLV, wstr, added_iid, 4 );
//
downAdena += (it.count * it.price);
}
// update adena counters
WU_SetDlgItemInt64( hDlg, IDC_EDIT1, downAdena, TRUE );
WU_SetDlgItemInt64( hDlg, IDC_EDIT2, pcls->m_list_src->curMoney, TRUE );
}
void BuySellDlg::OnInitDialog( HWND hDlg, LPARAM lParam )
{
log_error( LOG_DEBUG, "BuySellDlg::OnInitDialog()\n" );
// init LV upper
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("Item"), 150, 0 );
WULV_InsertColumn( hwndLV, TEXT("$"), 60, 1 );
WULV_InsertColumn( hwndLV, TEXT("cnt"), 50, 2 );
WULV_InsertColumn( hwndLV, TEXT("itemID"), 50, 3 );
WULV_InsertColumn( hwndLV, TEXT("objectID"), 50, 4 );
// init LV down
hwndLV = GetDlgItem( hDlg, IDC_LIST2 );
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("Item"), 150, 0 );
WULV_InsertColumn( hwndLV, TEXT("$"), 60, 1 );
WULV_InsertColumn( hwndLV, TEXT("cnt"), 50, 2 );
WULV_InsertColumn( hwndLV, TEXT("itemID"), 50, 3 );
WULV_InsertColumn( hwndLV, TEXT("objectID"), 50, 4 );
//
BuySellDlg *pcls = (BuySellDlg *)lParam;
//
switch( pcls->m_type )
{
case BuySellDlg::TYPE_BUYLIST:
{
SetDlgItemText( hDlg, IDC_ST_UPPER, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
SetDlgItemText( hDlg, IDC_ST_DOWN, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
} break;
case BuySellDlg::TYPE_SELLLIST:
{
SetDlgItemText( hDlg, IDC_ST_UPPER, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
SetDlgItemText( hDlg, IDC_ST_DOWN, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
} break;
case BuySellDlg::TYPE_PRIVATESTOREBUYLIST:
{
TCHAR text[256];
wsprintf( text, TEXT("%s <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"), pcls->m_list_src->message );
SetDlgItemText( hDlg, IDC_ST_UPPER, text );
SetDlgItemText( hDlg, IDC_ST_DOWN, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>:") );
} break;
case BuySellDlg::TYPE_PRIVATESTORESELLLIST:
{
TCHAR text[256];
wsprintf( text, TEXT("%s <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"), pcls->m_list_src->message );
if( pcls->m_list_src->packageSale )
wsprintf( text, TEXT("%s <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>(!!!!!!) <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>:"), pcls->m_list_src->message );
SetDlgItemText( hDlg, IDC_ST_UPPER, text );
SetDlgItemText( hDlg, IDC_ST_DOWN, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>:") );
} break;
}
// UpdateUI
FillListViews( hDlg, pcls );
}
void BuySellDlg::OnDestroy( HWND hDlg )
{
log_error( LOG_DEBUG, "BuySellDlg::OnDestroy()\n" );
BuySellDlg *pcls = (BuySellDlg *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
delete pcls;
}
void BuySellDlg::OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(lParam);
BuySellDlg *pcls = (BuySellDlg *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
switch( LOWORD( wParam ) )
{
case IDOK:
{
if( pcls->m_list_result->itemCount == 0 )
{
log_error( LOG_DEBUG, "BuySellDlg(): OnOk: Did not buy/sell anything!\n" );
delete pcls->m_list_result;
pcls->m_list_result = NULL;
}
PostMessage( pcls->m_hWndNotify, pcls->m_uNotifyMesasage, (WPARAM)(pcls->m_type),
(LPARAM)(pcls->m_list_result) );
PostMessage( hDlg, WM_QUIT, 0, 0 );
} break;
case IDCANCEL:
{
delete pcls->m_list_result;
pcls->m_list_result = NULL;
PostMessage( pcls->m_hWndNotify, pcls->m_uNotifyMesasage, (WPARAM)(pcls->m_type), 0 );
PostMessage( hDlg, WM_QUIT, 0, 0 );
} break;
}
}
// forward decl
// returns 0 if cancelled
long long int BuySellDlg_RequestItemCount( HWND hDlg, TradeItem *it );
void BuySellDlg::OnNotify( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(wParam);
BuySellDlg *pcls = (BuySellDlg *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
LPNMHDR pnmh = (LPNMHDR)lParam;
HWND hwndLV1 = GetDlgItem( hDlg, IDC_LIST1 );
HWND hwndLV2 = GetDlgItem( hDlg, IDC_LIST2 );
if( pnmh->code == NM_DBLCLK )
{
// The iItem, iSubItem, and ptAction members of this structure contain information about the item.
LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
if( lpnmitem->iSubItem != 0 ) return;
if( pnmh->hwndFrom == hwndLV1 )
{
TradeItemsList *tl = pcls->m_list_src;
TradeItemsList *tl2 = pcls->m_list_result;
int clicked_iid = lpnmitem->iItem;
int idx = (int)WULV_GetItemLPARAM( pnmh->hwndFrom, clicked_iid );
TradeItem it( tl->item[idx] );
long long int cnt = BuySellDlg_RequestItemCount( hDlg, &it );
if( cnt > 0 )
{
// add to second list (increase)
int existing_idx = tl2->findItemIdxByItemId( it.itemID );
if( (existing_idx != -1) && it.isStackableGuess() )
{
//log_error( LOG_OK, "Updating existing item idx %d: add count %d\n", existing_idx, cnt );
tl2->item[existing_idx].count += cnt;
}
else
{
//log_error( LOG_OK, "Adding new item to idx %d: count %d\n", tl2->itemCount, cnt );
it.count = cnt;
tl2->addItem( it );
}
// update first list
switch( pcls->m_type )
{
case BuySellDlg::TYPE_BUYLIST: tl->item[idx].count = 0; break;
case BuySellDlg::TYPE_SELLLIST:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
default:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
}
}
}
if( pnmh->hwndFrom == hwndLV2 )
{
TradeItemsList *tl = pcls->m_list_result;
TradeItemsList *tl2 = pcls->m_list_src;
int clicked_iid = lpnmitem->iItem;
int idx = (int)WULV_GetItemLPARAM( pnmh->hwndFrom, clicked_iid );
TradeItem it( tl->item[idx] );
long long int cnt = BuySellDlg_RequestItemCount( hDlg, &it );
if( cnt > 0 )
{
// add to first list (increase)
int existing_idx = tl2->findItemIdxByItemId( it.itemID );
if( (existing_idx != -1) && it.isStackableGuess() )
{
//log_error( LOG_OK, "Updating existing item in Lv 1 idx %d: add count %d\n", existing_idx, cnt );
switch( pcls->m_type )
{
case BuySellDlg::TYPE_BUYLIST: tl2->item[existing_idx].count = 0; break;
default: tl2->item[existing_idx].count += cnt; break;
}
}
else
{
//log_error( LOG_OK, "Adding new item to Lv 1 to idx %d: count %d\n", tl2->itemCount, cnt );
it.count = cnt;
tl2->addItem( it );
}
// remove from second list (decrease) TODO: remove on PrivateStoreBuy
switch( pcls->m_type )
{
case BuySellDlg::TYPE_BUYLIST:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
case BuySellDlg::TYPE_SELLLIST:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
default:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
}
}
}
// update list-views contents
FillListViews( hDlg, pcls );
} // NM_DBLCLICK
}
INT_PTR CALLBACK BuySellDlg_RequestItemCount_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
// returns 0 if cancelled
long long int BuySellDlg_RequestItemCount( HWND hDlg, TradeItem *it )
{
long long int save_count = it->count;
INT_PTR ret = DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_USERINV_ITEMCOUNT),
hDlg, BuySellDlg_RequestItemCount_Proc, (LPARAM)it );
if( ret == IDCANCEL )
{
it->count = save_count;
return 0;
}
long long int ret_count = it->count;
it->count = save_count;
return ret_count;
}
INT_PTR CALLBACK BuySellDlg_RequestItemCount_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtrW( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
TradeItem *it = (TradeItem *)lParam;
wchar_t wstr[256] = {0};
DBLayer_getItemName( it->itemID, wstr, 255 );
SetDlgItemTextW( hDlg, IDC_ST_ITEMNAME, wstr );
WU_SetDlgItemInt64( hDlg, IDC_E_COUNT, it->count, TRUE );
} break;
case WM_COMMAND:
{
TradeItem *it = (TradeItem *)GetWindowLongPtrW( hDlg, GWLP_USERDATA );
switch( LOWORD( wParam ) )
{
case IDC_B_ALL:
{
WU_SetDlgItemInt64( hDlg, IDC_E_COUNT, it->count, TRUE );
} break;
case IDOK:
{
long long int count = WU_GetDlgItemInt64( hDlg, IDC_E_COUNT, TRUE );
long long int max_count = it->count;
if( max_count == 0 ) max_count = 0x00FFFFFF;
// validate inputted value
if( (count >= 0) && (count <= max_count) )
{
it->count = count; // save inputted value
EndDialog( hDlg, IDOK );
}
else
{
TCHAR text[256] = {0};
wsprintf( text, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: [0..%I64d]"), max_count );
MessageBox( hDlg, text, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>!"), MB_ICONINFORMATION );
}
} break;
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}

34
l2ooghelper/BuySellDlg.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef H_BUYSELLDLG
#define H_BUYSELLDLG
#include "BuySellList.h"
class BuySellDlg
{
public:
static const int TYPE_BUYLIST = 0;
static const int TYPE_SELLLIST = 1;
static const int TYPE_PRIVATESTOREBUYLIST = 2;
static const int TYPE_PRIVATESTORESELLLIST = 3;
public:
BuySellDlg( HWND hWndNotify, UINT uMessage, int type, TradeItemsList *list );
~BuySellDlg();
void run();
protected:
HWND m_hWndNotify;
UINT m_uNotifyMesasage;
int m_type;
TradeItemsList *m_list_src;
TradeItemsList *m_list_result;
protected:
static DWORD WINAPI BuySellDlg_Thread( LPVOID lpParam );
static INT_PTR CALLBACK BuySell_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static void OnInitDialog( HWND hDlg, LPARAM lParam );
static void OnDestroy( HWND hDlg );
static void OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnNotify( HWND hDlg, WPARAM wParam, LPARAM lParam );
protected:
static void FillListViews( HWND hDlg, BuySellDlg *pcls );
};
#endif

128
l2ooghelper/BuySellList.cpp Normal file
View File

@@ -0,0 +1,128 @@
#include "stdafx.h"
#include "BuySellList.h"
TradeItem::TradeItem()
{
setUnused();
}
TradeItem::~TradeItem()
{
setUnused();
}
TradeItem::TradeItem( const TradeItem& other )
{
setUnused();
this->operator=( other );
}
TradeItem& TradeItem::operator=( const TradeItem& other )
{
this->itemID = other.itemID;
this->objectID = other.objectID;
this->count = other.count;
this->price = other.price;
this->storePrice = other.storePrice;
this->enchantLevel = other.enchantLevel;
this->attributeAtkType = other.attributeAtkType;
this->attributeAtkValue = other.attributeAtkValue;
this->attributeDefFire = other.attributeDefFire;
this->attributeDefWater = other.attributeDefWater;
this->attributeDefWind = other.attributeDefWind;
this->attributeDefEarth = other.attributeDefEarth;
this->attributeDefHoly = other.attributeDefHoly;
this->attributeDefUnholy = other.attributeDefUnholy;
this->type1 = other.type1;
this->type2 = other.type2;
this->bodyPart = other.bodyPart;
//this->packageSale = other.packageSale;
return (*this);
}
void TradeItem::setUnused()
{
//packageSale = false;
type1 = type2 = bodyPart = 0;
itemID = objectID = 0;
count = price = storePrice = enchantLevel = 0;
attributeAtkType = attributeAtkValue = 0;
attributeDefFire = attributeDefWater = attributeDefWind =
attributeDefEarth = attributeDefHoly = attributeDefUnholy = 0;
}
bool TradeItem::isStackableGuess()
{
// analyze item type
// item type1 0-weapon/ring/earring/necklace 1-armor/shield 4-item/questitem/adena
// item type2 0-weapon 1-shield/armor 2-ring/earring/necklace 3-questitem 4-adena 5-item
//
// usually weapons, jewelry, armors, shields are not stackable
// items (usually) and adena are stackable
// some quest items can be stackable, this is unknown
//
// TODO: TradeItem::isStackableGuess(): we can try also analyse bodyPart
// FIXED: try to use only type2 to detect stakability
//if( (type1 == 0) || (type1 == 1) ) return false; // WeapArmShldJew
if( (type2 == 0) || (type2 == 1) || (type2 == 2) ) return false; // WeapArmShldJew
if( type2 == 4 ) return true; // Adena is always stackable :)
// for quest items and items think that they are stackable >_<
return true;
}
//static const int MAX_TRADE_ITEMS = 128;
TradeItemsList::TradeItemsList()
{
clear();
}
TradeItemsList::~TradeItemsList()
{
clear();
}
void TradeItemsList::clear()
{
packageSale = 0;
isCommonCraft = 0;
listID = 0;
curMoney = 0;
itemCount = 0;
int i;
for( i=0; i<MAX_TRADE_ITEMS; i++ ) item[i].setUnused();
message[0] = 0;
}
void TradeItemsList::addItem( const TradeItem& it )
{
if( itemCount >= MAX_TRADE_ITEMS ) return;
item[itemCount] = it;
itemCount++;
}
int TradeItemsList::findItemIdxByItemId( unsigned int itemID )
{
int i;
for( i=0; i<MAX_TRADE_ITEMS; i++ )
{
if( item[i].itemID == itemID ) return i;
}
return -1;
}
void TradeItemsList::removeCellAndShift( int cell_idx )
{
if( (cell_idx<0) || (cell_idx>=MAX_TRADE_ITEMS) ) return;
item[cell_idx].setUnused();
int i;
for( i=cell_idx; i<(MAX_TRADE_ITEMS-1); i++ ) item[i] = item[i+1];
item[i].setUnused();
this->itemCount--;
}
/*unsigned int listID;
int curMoney;
int itemCount;
TradeItem item[MAX_TRADE_ITEMS];*/

58
l2ooghelper/BuySellList.h Normal file
View File

@@ -0,0 +1,58 @@
#ifndef H_BUYSELLLIST
#define H_BUYSELLLIST
class TradeItem
{
public:
TradeItem();
TradeItem( const TradeItem& other );
~TradeItem();
TradeItem& operator=( const TradeItem& other );
public:
void setUnused();
bool isUnused() { return ((itemID == 0) && (objectID == 0)); }
bool isStackableGuess();
public:
unsigned int itemID;
unsigned int objectID;
long long int count;
long long int price;
long long int storePrice;
int enchantLevel;
int attributeAtkType;
int attributeAtkValue;
int attributeDefFire;
int attributeDefWater;
int attributeDefWind;
int attributeDefEarth;
int attributeDefHoly;
int attributeDefUnholy;
int type1;
int type2;
int bodyPart;
};
class TradeItemsList
{
public:
static const int MAX_TRADE_ITEMS = 128;
public:
TradeItemsList();
~TradeItemsList();
public:
void clear();
void addItem( const TradeItem& it );
public:
int findItemIdxByItemId( unsigned int itemID );
void removeCellAndShift( int cell_idx );
public:
unsigned int listID; // may be seller/buyer objectID for private stores
long long int curMoney;
int itemCount;
TradeItem item[MAX_TRADE_ITEMS];
int packageSale;
wchar_t message[128]; // here is seller/buyer name for private stores
int isCommonCraft;
};
#endif

237
l2ooghelper/CharArray.cpp Normal file
View File

@@ -0,0 +1,237 @@
#include "stdafx.h"
#include "Logger.h"
#include "CharArray.h"
void CharArray::Init()
{
charArray_count = 0;
charArray_updateHWND = NULL;
charArray_updateMSG = 0;
InitializeCriticalSection( &charArray_cs );
EnterCriticalSection( &charArray_cs );
int i;
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
chars_array[i] = new L2Player();
chars_array[i]->setUnused();
}
LeaveCriticalSection( &charArray_cs );
}
void CharArray::Lock() { EnterCriticalSection( &charArray_cs ); }
void CharArray::Unlock() { LeaveCriticalSection( &charArray_cs ); }
void CharArray::SetUpdateCommand( HWND hWnd, UINT uMsg )
{
charArray_updateHWND = hWnd;
charArray_updateMSG = uMsg;
}
void CharArray::PostUpdateMessage()
{
if( !charArray_updateHWND ) return;
if( charArray_updateMSG < WM_USER ) return;
PostMessage( charArray_updateHWND, charArray_updateMSG, 0, 0 );
}
void CharArray::Free()
{
int i;
Lock();
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i] ) delete chars_array[i];
chars_array[i] = NULL;
}
Unlock();
charArray_count = 0;
}
int CharArray::AddCharInfo( L2Player *cha )
{
if( !cha ) return -1;
Lock();
int idx = FindFreeIndex();
if( idx >= 0 )
{
memcpy( chars_array[idx], cha, sizeof(class L2Player) );
charArray_count++;
//log_error( LOG_USERAI, "Char: added new [%S] to idx[%d]\n", cha->charName, idx );
}
else
{
log_error( LOG_ERROR, "Error adding character [%S] to chars array! idx = %d\n", cha->getName(), idx );
}
Unlock();
PostUpdateMessage();
return idx;
}
void CharArray::UpdateCharInfo( int idx, L2Player *cha )
{
Lock();
// update info on existing
if( !chars_array[idx] )
{
log_error( LOG_ERROR, "CharArray_AddCharInfo(): "
"char oid [%S] [%u] found in L2World, but its index [%d] is empty!\n",
cha->charName, cha->objectID, idx );
Unlock();
return;
}
// save old move vectors (since by default unused CharInfo is not moving)
int xDst = chars_array[idx]->xDst;
int yDst = chars_array[idx]->yDst;
int zDst = chars_array[idx]->zDst;
//
memcpy( chars_array[idx], cha, sizeof(class L2Player) );
// restore old move vectors (since by default unused CharInfo is not moving)
chars_array[idx]->xDst = xDst;
chars_array[idx]->yDst = yDst;
chars_array[idx]->zDst = zDst;
//
Unlock();
PostUpdateMessage();
//log_error( LOG_USERAI, "Char: Updated idx [%d] [%S]\n", idx, cha->name() );
}
/*void CharArray::DeleteCharByObjectID( unsigned int objectID )
{
Lock();
BOOL bDelOK = 0;
int idx = FindCharByObjectID( objectID );
if( (idx>=0) && (idx<CHARARRAY_MAX_CHARS) )
{
chars_array[idx]->setUnused();
bDelOK = TRUE;
charArray_count--;
}
Unlock();
if( bDelOK ) PostUpdateMessage();
}*/
void CharArray::DeleteCharByArrayIdx( int idx )
{
BOOL bDelOK = FALSE;
Lock();
if( (idx>=0) && (idx<CHARARRAY_MAX_CHARS) )
{
if( chars_array[idx] )
{
//unsigned int objectID = chars_array[idx]->objectID;
//log_error( LOG_USERAI, "Char: Deleted [%S] from [%d]\n", chars_array[idx]->charName, idx );
chars_array[idx]->setUnused();
bDelOK = TRUE;
charArray_count--;
}
else log_error( LOG_ERROR, "Char: index[%d] is NULL while deleting char ny idx\n", idx );
}
Unlock();
if( bDelOK ) PostUpdateMessage();
}
void CharArray::DeleteAll()
{
Lock();
int i;
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i] ) chars_array[i]->setUnused();
}
charArray_count = 0;
Unlock();
PostUpdateMessage();
}
unsigned int CharArray::GetCount() { return charArray_count; }
int CharArray::FindCharByObjectID( unsigned int objectID )
{
int ret = -1;
int i;
Lock();
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i] == NULL ) continue;
if( chars_array[i]->objectID == objectID )
{
ret = i;
break;
}
}
Unlock();
return ret;
}
int CharArray::FindFreeIndex()
{
int i;
Lock();
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i] == NULL )
{
chars_array[i] = new L2Player(); // allocate new
chars_array[i]->setUnused(); // and set as unused
Unlock();
return i;
}
if( chars_array[i]->isUnused() )
{
Unlock(); // just return index...
return i;
}
}
Unlock();
log_error( LOG_ERROR, "CharArray_FindFreeIndex(): cannot find free index! limit is %d\n",
CHARARRAY_MAX_CHARS );
return -1;
}
void CharArray::Display( FILE *f )
{
if( !f ) return;
Lock();
int i;
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i]->isUnused() ) continue;
fprintf( f, "%d: %S\n", i, chars_array[i]->charName );
}
Unlock();
}
void CharArray::DumpToFile( const char *filename )
{
FILE *f = fopen( filename, "wt" );
if( !f ) return;
Display( f );
fclose( f );
}
void CharArray::DisplayToConsole()
{
int i = 0;
unsigned int nCharsDisplayed = 0;
log_error( LOG_USERAI, "=== Chars: %d ===\n", this->charArray_count );
if( this->charArray_count > 0 )
{
Lock();
for( i=0; i<CHARARRAY_MAX_CHARS; i++ )
{
if( chars_array[i]->isUnused() )
log_error( LOG_USERAI, "Chars: %2d: <unused>\n", i );
else
{
log_error( LOG_USERAI, "Chars: %2d: [%S] [%S] [%s]\n", i,
chars_array[i]->charName, chars_array[i]->charTitle,
L2Data_getClass( chars_array[i]->classID ) );
nCharsDisplayed++;
}
if( nCharsDisplayed >= this->charArray_count ) break;
}
Unlock();
}
log_error( LOG_USERAI, "=== Chars End ===\n" );
}

43
l2ooghelper/CharArray.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef CHARLIST_H_
#define CHARLIST_H_
class CharArray
{
public:
CharArray() { Init(); }
~CharArray() { Free(); }
public:
static const int CHARARRAY_MAX_CHARS = 512;
L2Player *chars_array[CHARARRAY_MAX_CHARS];
public:
void Init();
void Free();
public:
void Lock();
void Unlock();
public:
int AddCharInfo( L2Player *cha );
void UpdateCharInfo( int idx, L2Player *cha );
//void DeleteCharByObjectID( unsigned int objectID );
void DeleteCharByArrayIdx( int idx );
void DeleteAll();
public:
int FindCharByObjectID( unsigned int objectID );
int FindFreeIndex();
public:
void SetUpdateCommand( HWND hWnd, UINT uMsg );
unsigned int GetCount();
public:
void Display( FILE *f );
void DumpToFile( const char *filename );
void DisplayToConsole();
protected:
void PostUpdateMessage();
protected:
CRITICAL_SECTION charArray_cs;
HWND charArray_updateHWND;
UINT charArray_updateMSG;
UINT charArray_count;
};
#endif /* CHARLIST_H_ */

View File

@@ -0,0 +1,127 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK ChooseCharDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
typedef struct ChooseChar_st
{
int sel;
L2Game_CharSelectionInfoBlock *chars;
int nCount;
} CHOOSECHAR;
// -1 on cancel
int ChooseChar( HWND hWndParent, L2Game_CharSelectionInfoBlock *chars, int nCount )
{
CHOOSECHAR st;
st.nCount = nCount;
st.chars = chars;
st.sel = -1;
INT_PTR dlgRet = DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_CHOOSECHAR),
hWndParent, ChooseCharDlgProc, (LPARAM)&st );
if( dlgRet == IDOK ) return st.sel;
return -1;
}
INT_PTR CALLBACK ChooseCharDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
CHOOSECHAR *st = (CHOOSECHAR *)lParam;
TCHAR text[256];
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
WULV_SetExtStyle( hwndLV, true, true );
// insert columns
WULV_InsertColumn( hwndLV, TEXT("#"), 30, 0 );
WULV_InsertColumn( hwndLV, TEXT("name"), 130, 1 );
WULV_InsertColumn( hwndLV, TEXT("level"), 40, 2 );
WULV_InsertColumn( hwndLV, TEXT("class"), 100, 3 );
WULV_InsertColumn( hwndLV, TEXT("del_secs"), 60, 4 );
// populate data
int i;
for( i=0; i<st->nCount; i++ )
{
// add item
// #
wsprintf( text, TEXT("%d"), i );
int added_item = WULV_InsertItem( hwndLV, text, 0, i );
if( added_item == -1 ) continue;
// name
WULV_SetItem( hwndLV, st->chars[i].charName, added_item, 1 );
// level
wsprintf( text, TEXT("%u"), st->chars[i].level );
WULV_SetItem( hwndLV, text, added_item, 2 );
// class
wsprintf( text, TEXT("%S"), L2Data_getClass( st->chars[i].classID ) );
WULV_SetItem( hwndLV, text, added_item, 3 );
// del days
if( st->chars[i].deleteSeconds > 0 )
wsprintf( text, TEXT("%u"), st->chars[i].deleteSeconds );
else
text[0] = 0;
WULV_SetItem( hwndLV, text, added_item, 4 );
}
} break;
case WM_COMMAND:
{
CHOOSECHAR *st = (CHOOSECHAR *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
switch( LOWORD( wParam ) )
{
case IDOK:
{
int cur_sel = WULV_GetCurSelItem( hwndLV );
if( cur_sel >= 0 )
{
st->sel = WULV_GetItemLPARAM( hwndLV, cur_sel );
EndDialog( hDlg, IDOK );
}
} break;
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
case IDC_CHARDEL: // request delete char
{
int cur_sel = WULV_GetCurSelItem( hwndLV );
if( cur_sel >= 0 )
{
st->sel = WULV_GetItemLPARAM( hwndLV, cur_sel ) + 1000;
EndDialog( hDlg, IDOK );
}
} break;
case IDC_CHARLDELCANCEL: // request cancel character deletion
{
int cur_sel = WULV_GetCurSelItem( hwndLV );
if( cur_sel >= 0 )
{
st->sel = WULV_GetItemLPARAM( hwndLV, cur_sel ) + 2000;
EndDialog( hDlg, IDOK );
}
} break;
case IDC_CHARCREATE: // request create char
{
st->sel = 10000;
EndDialog( hDlg, IDOK );
} break;
}
} break;
case WM_NOTIFY:
{
CHOOSECHAR *st = (CHOOSECHAR *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
LPNMHDR pnmh = (LPNMHDR)lParam;
if( pnmh->code == NM_DBLCLK )
{
LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
st->sel = WULV_GetItemLPARAM( hwndLV, lpnmitem->iItem );
EndDialog( hDlg, IDOK );
}
} break;
default: return FALSE; break;
}
return TRUE;
}

View File

@@ -0,0 +1,9 @@
#ifndef H_CHOOSECHAR_DLG
#define H_CHOOSECHAR_DLG
// returns: index of selected char in array 'chars': [0 .. (nCount-1)]
//
// -1 on cancel
int ChooseChar( HWND hWndParent, L2Game_CharSelectionInfoBlock *chars, int nCount );
#endif

View File

@@ -0,0 +1,97 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK ChooseServerDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
typedef struct ChooseServer_st
{
int sel;
L2GameServerInfo *servers;
int nCount;
} CHOOSESERVER;
// -1 on cancel
int ChooseServer( HWND hWndParent, L2GameServerInfo *servers, int nCount )
{
CHOOSESERVER st;
st.nCount = nCount;
st.servers = servers;
st.sel = -1;
INT_PTR dlgRet = DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_CHOOSESERVER),
hWndParent, ChooseServerDlgProc, (LPARAM)&st );
if( dlgRet == IDOK ) return st.sel;
return -1;
}
INT_PTR CALLBACK ChooseServerDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
CHOOSESERVER *st = (CHOOSESERVER *)lParam;
TCHAR text[256];
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
WULV_SetExtStyle( hwndLV, true, true );
// insert columns
WULV_InsertColumn( hwndLV, TEXT("id"), 50, 0 );
WULV_InsertColumn( hwndLV, TEXT("addr"), 150, 1 );
WULV_InsertColumn( hwndLV, TEXT("online"), 80, 2 );
// populate
int i;
for( i=0; i<st->nCount; i++ )
{
// #
wsprintf( text, TEXT("%d"), (int)st->servers[i].gsID );
int added_item = WULV_InsertItem( hwndLV, text, 0, i );
if( added_item == -1 ) continue;
// addr
wsprintf( text, TEXT("%d.%d.%d.%d:%d"),
(int)st->servers[i].gsIP[0], (int)st->servers[i].gsIP[1],
(int)st->servers[i].gsIP[2], (int)st->servers[i].gsIP[3],
(int)st->servers[i].gsPort );
WULV_SetItem( hwndLV, text, added_item, 1 );
// online
wsprintf( text, TEXT("%d / %d"),
(int)st->servers[i].gsPlayersOnline, (int)st->servers[i].gsPlayersMax );
WULV_SetItem( hwndLV, text, added_item, 2 );
}
} break;
case WM_COMMAND:
{
switch( LOWORD( wParam ) )
{
case IDOK:
{
CHOOSESERVER *st = (CHOOSESERVER *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
int cur_sel = WULV_GetCurSelItem( hwndLV );
if( cur_sel >= 0 )
{
st->sel = WULV_GetItemLPARAM( hwndLV, cur_sel );
EndDialog( hDlg, IDOK );
}
} break;
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
}
} break;
case WM_NOTIFY:
{
CHOOSESERVER *st = (CHOOSESERVER *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
LPNMHDR pnmh = (LPNMHDR)lParam;
if( pnmh->code == NM_DBLCLK )
{
LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
st->sel = WULV_GetItemLPARAM( hwndLV, lpnmitem->iItem );
EndDialog( hDlg, IDOK );
}
} break;
default: return FALSE; break;
}
return TRUE;
}

View File

@@ -0,0 +1,9 @@
#ifndef H_CHOOSESERVER_DLG
#define H_CHOOSESERVER_DLG
// returns: index of selected server in array 'servers': [0 .. (nCount-1)]
//
// -1 on cancel
int ChooseServer( HWND hWndParent, L2GameServerInfo *servers, int nCount );
#endif

244
l2ooghelper/ClanList.cpp Normal file
View File

@@ -0,0 +1,244 @@
#include "stdafx.h"
#include "Logger.h"
#include "ClanList.h"
#include "ClanTreeNode.h"
void ClanList::Init()
{
clanList_count = 0;
clanList_updateHWND = NULL;
clanList_updateMSG = 0;
InitializeCriticalSection( &clanList_cs );
EnterCriticalSection( &clanList_cs );
if( bt_clans == NULL )
{
//log_error( LOG_DEBUG, "ClanList_Init(): create bintree\n" );
bt_clans = new BinTree();
}
else
{
//log_error( LOG_DEBUG, "ClanList_Init(): clear bintree\n" );
bt_clans->deleteAll();
}
LeaveCriticalSection( &clanList_cs );
}
void ClanList::Lock() { EnterCriticalSection( &clanList_cs ); }
void ClanList::Unlock() { LeaveCriticalSection( &clanList_cs ); }
void ClanList::SetUpdateCommand( HWND hWnd, UINT uMsg )
{
clanList_updateHWND = hWnd;
clanList_updateMSG = uMsg;
}
void ClanList::PostUpdate()
{
if( !clanList_updateHWND ) return;
if( clanList_updateMSG < WM_USER ) return;
PostMessage( clanList_updateHWND, clanList_updateMSG, 0, 0 );
}
void ClanList::Free()
{
if( !bt_clans ) log_error( LOG_DEBUG, "ClanList_Free() - already NULL\n" );
else
{
Lock();
delete bt_clans;
bt_clans = NULL;
Unlock();
PostUpdate();
log_error( LOG_DEBUG, "ClanList_Free() - freed\n" );
}
clanList_count = 0;
}
void ClanList::Add( unsigned int clanID, const wchar_t *clanName, const wchar_t *allyName )
{
if( !clanName || !allyName ) return;
log_error( LOG_DEBUG, "ClanList_Add: [%S] (id %u) [%S]... ", clanName, clanID, allyName );
Lock();
if( !bt_clans )
{
log_error( LOG_DEBUG, " (BinTree created)... \n" );
bt_clans = new BinTree();
}
ClanTreeNode *node = new ClanTreeNode( clanID, clanName, allyName );
// first try to find existing char
BinTreeNode *existing = bt_clans->findNode( clanID );
if( existing )
{
// update info on existing
ClanTreeNode *cl = (ClanTreeNode *)existing;
cl->setClanName( clanName );
cl->setAllyName( allyName );
cl->setClanID( clanID );
//printf( "Updated info for [%S]\n", clanName );
}
else // add new
{
//if( bt_clans->addNodeDebug( node, stdout ) ) log_error_np( LOG_DEBUG, "OK\n" );
if( bt_clans->addNode( node ) )
{
clanList_count++;
log_error_np( LOG_DEBUG, "OK\n" );
}
else
{
log_error_np( LOG_DEBUG, "FAILED\n" );
log_error( LOG_ERROR, "Error adding clan [%S] to clan list!\n", clanName );
delete node;
}
}
Unlock();
PostUpdate();
}
void ClanList::Delete( unsigned int clanID )
{
if( !bt_clans ) return;
log_error( LOG_DEBUG, "ClanList_Delete( %u )... ", clanID );
//if( bt_clans->delNodeDebug( oid, stdout ) ) log_error_np( LOG_DEBUG, "OK\n" );
Lock();
if( bt_clans->delNode( clanID ) )
{
clanList_count--;
log_error_np( LOG_DEBUG, "OK\n" );
}
else
{
log_error_np( LOG_DEBUG, "FAILED\n" );
//log_error( LOG_ERROR, "Error deleting object %u from chars list!\n", oid );
}
Unlock();
PostUpdate();
}
void ClanList::DeleteAll()
{
if( !bt_clans ) return;
Lock();
bt_clans->deleteAll();
clanList_count = 0;
Unlock();
PostUpdate();
}
void ClanList_displayNode( FILE *f, BinTreeNode *node )
{
if( !f || !node ) return;
ClanTreeNode *btn = (ClanTreeNode *)node;
fprintf( f, " %S Ally %S [%u]\n", btn->clanName(), btn->allyName(), btn->clanID() );
if( node->left ) ClanList_displayNode( f, node->left );
if( node->right ) ClanList_displayNode( f, node->right );
}
void ClanList::Display( FILE *f )
{
if( !f || !bt_clans ) return;
Lock();
fprintf( f, "===== Clans list =====\n" );
BinTreeNode *root = bt_clans->getRoot();
if( !root ) fprintf( f, "Clans list empty!\n" );
else ClanList_displayNode( f, root );
fprintf( f, "======================\n" );
//bt_clans->printTree( f );
Unlock();
}
void ClanList_displayNodeConsole( BinTreeNode *node )
{
if( !node ) return;
ClanTreeNode *btn = (ClanTreeNode *)node;
log_error( LOG_USERAI, "Clan: [%S] Ally [%S] [%u]\n", btn->clanName(), btn->allyName(), btn->clanID() );
if( node->left ) ClanList_displayNodeConsole( node->left );
if( node->right ) ClanList_displayNodeConsole( node->right );
}
void ClanList::DisplayConsole()
{
if( !bt_clans ) return;
Lock();
log_error( LOG_USERAI, "===== Clans list %d =====\n", clanList_count );
BinTreeNode *root = bt_clans->getRoot();
if( !root ) log_error( LOG_USERAI, "Clans list empty!\n" );
else ClanList_displayNodeConsole( root );
log_error( LOG_USERAI, "======================\n" );
//bt_clans->printTree( f );
Unlock();
}
//unsigned int ClanList_GetCount() { return clanList_count; }
/*void ClanList_GetClansArray_ProcessNode( ClanTreeNode **clans_array, int *pi, BinTreeNode *cur )
{
if( !cur || !clans_array || !pi ) return;
ClanTreeNode *cl = (ClanTreeNode *)cur;
clans_array[(*pi)] = new ClanTreeNode( (*cl) );
clans_array[(*pi)]->left = clans_array[(*pi)]->right = NULL;
(*pi) = (*pi) + 1;
if( cur->left ) ClanList_GetClansArray_ProcessNode( clans_array, pi, cur->left );
if( cur->right ) ClanList_GetClansArray_ProcessNode( clans_array, pi, cur->right );
}
void *ClanList_GetClansArray()
{
if( !bt_clans ) return NULL;
if( clanList_count <= 0 )
{
clanList_count = 0;
return NULL;
}
ClanTreeNode **clans_array = (ClanTreeNode **)malloc( (sizeof(void *) * clanList_count ) );
if( !clans_array ) return NULL;
int i;
for( i=0; i<(int)clanList_count; i++ ) clans_array[i] = NULL;
BinTreeNode *cur;
ClanList_Lock();
cur = bt_clans->getRoot();
if( !cur )
{
ClanList_Unlock();
free( clans_array );
return NULL;
}
i = 0;
ClanList_GetClansArray_ProcessNode( clans_array, &i, cur );
ClanList_Unlock();
return clans_array;
}
void ClanList_FreeClansArray( void *p )
{
if( !p ) return;
free( p );
}*/
bool ClanList::GetClanNameByID( unsigned int clanID, TCHAR *out )
{
if( !out || !bt_clans ) return false;
out[0] = 0;
Lock();
ClanTreeNode *cl = (ClanTreeNode *)bt_clans->findNode( clanID );
if( !cl )
{
Unlock();
return false;
}
#if defined(UNICODE) || defined(_UNICODE)
lstrcpy( out, cl->clanName() );
#else
WideCharToMultiByte( CP_ACP, 0, cl->clanName(), -1, out, 127, NULL, NULL );
#endif
Unlock();
return true;
}

41
l2ooghelper/ClanList.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef CLANLIST_H_
#define CLANLIST_H_
#include "ClanTreeNode.h"
class ClanList
{
public:
ClanList() { bt_clans = NULL; Init(); }
~ClanList() { Free(); }
public:
void Init();
void Free();
public:
void Lock();
void Unlock();
public:
void Add( unsigned int clanID, const wchar_t *clanName, const wchar_t *allyName );
void Delete( unsigned int clanID );
void DeleteAll();
public:
unsigned int GetCount() { return clanList_count; }
//void *GetClansArray();
//void FreeClansArray( void *p );
public:
bool GetClanNameByID( unsigned int clanID, TCHAR *out );
public:
void Display( FILE *f );
void DisplayConsole();
void SetUpdateCommand( HWND hWnd, UINT uMsg );
protected:
void PostUpdate();
protected:
BinTree *bt_clans;
HWND clanList_updateHWND;
UINT clanList_updateMSG;
CRITICAL_SECTION clanList_cs;
UINT clanList_count;
};
#endif /* CLANLIST_H_ */

View File

@@ -0,0 +1,54 @@
#include "stdafx.h"
#include "ClanTreeNode.h"
ClanTreeNode::ClanTreeNode(): BinTreeNode()
{
m_clanID = 0;
m_clanName[0] = m_allyName[0] = 0;
//
//wcscpy( m_str_null, L"NULL" );
}
ClanTreeNode::ClanTreeNode( unsigned int clanID,
const wchar_t *clanName,
const wchar_t *allyName ): BinTreeNode()
{
key = clanID;
m_clanID = clanID;
setClanName( clanName );
setAllyName( allyName );
//
//wcscpy( m_str_null, L"NULL" );
}
ClanTreeNode::~ClanTreeNode()
{
m_clanID = 0;
m_clanName[0] = m_allyName[0] = 0;
}
void ClanTreeNode::setClanName( const wchar_t *clanName )
{
m_clanName[0] = 0;
if( clanName ) wcsncpy( m_clanName, clanName, 127 );
m_clanName[127] = 0;
}
void ClanTreeNode::setAllyName( const wchar_t *allyName )
{
m_allyName[0] = 0;
if( allyName ) wcsncpy( m_allyName, allyName, 127 );
m_allyName[127] = 0;
}
const wchar_t *ClanTreeNode::clanName() const
{
((class ClanTreeNode *)this)->m_clanName[127] = 0; // for safe
return m_clanName;
}
const wchar_t *ClanTreeNode::allyName() const
{
((class ClanTreeNode *)this)->m_allyName[127] = 0; // for safe
return m_allyName;
}

View File

@@ -0,0 +1,33 @@
#ifndef BINTREENODE_CLAN_H_
#define BINTREENODE_CLAN_H_
#include "BinTree.h"
class ClanTreeNode : public BinTreeNode
{
public:
ClanTreeNode();
ClanTreeNode( unsigned int clanID,
const wchar_t *clanName,
const wchar_t *allyName );
virtual ~ClanTreeNode();
public:
void setClanID( unsigned int clanID ) { m_clanID = clanID; }
void setClanName( const wchar_t *clanName );
void setAllyName( const wchar_t *allyName );
public:
unsigned int clanID() const { return m_clanID; }
const wchar_t *clanName() const;
const wchar_t *allyName() const;
protected:
unsigned int m_clanID;
wchar_t m_clanName[128];
wchar_t m_allyName[128];
//protected:
//wchar_t m_str_null[16];
};
#endif /* BINTREENODE_CLAN_H_ */

View File

@@ -0,0 +1,134 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
#include "Logger.h"
#include "CreateCharDlg.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK CreateCharDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
struct CREATECHARDLGSTRUCT
{
CreateCharDialogResult *pResult;
L2Game_NewCharacterTemplate *templates;
int templatesCount;
};
void CreateCharDialog( HWND hWndParent,
L2Game_NewCharacterTemplate *templates,
int templatesCount,
CreateCharDialogResult *pResult )
{
//
pResult->createCharName[0] = 0;
pResult->createTemplateIndex = -1;
pResult->createHairStyle = -1;
pResult->createHairColor = -1;
pResult->createFace = -1;
pResult->createGender = -1;
//
CREATECHARDLGSTRUCT st;
st.pResult = pResult;
st.templates = templates;
st.templatesCount = templatesCount;
//
INT_PTR ret = DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_CREATECHAR), hWndParent,
CreateCharDlgProc, (LPARAM)&st );
//
if( ret == IDCANCEL )
{
pResult->createCharName[0] = 0;
pResult->createTemplateIndex = -1;
}
}
INT_PTR CALLBACK CreateCharDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
CREATECHARDLGSTRUCT *st = (CREATECHARDLGSTRUCT *)lParam;
// insert races/classes
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_CLASS );
ComboBox_ResetContent( hwndCB );
int i;
for( i=0; i<st->templatesCount; i++ )
{
wchar_t wstr[128] = {0};
wsprintfW( wstr, L"%S (%S)",
L2Data_getRace( st->templates[i].race ),
L2Data_getClass( st->templates[i].classID ) );
ComboBox_AddString( hwndCB, wstr );
}
ComboBox_SetCurSel( hwndCB, 0 );
// insert hair styles
hwndCB = GetDlgItem( hDlg, IDC_CB_HSTYLE );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("A") );
ComboBox_AddString( hwndCB, TEXT("B") );
ComboBox_AddString( hwndCB, TEXT("C") );
ComboBox_AddString( hwndCB, TEXT("D") );
ComboBox_AddString( hwndCB, TEXT("E") );
ComboBox_AddString( hwndCB, TEXT("F (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>)") );
ComboBox_AddString( hwndCB, TEXT("G (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>)") );
ComboBox_SetCurSel( hwndCB, 0 );
// insert hair colors
hwndCB = GetDlgItem( hDlg, IDC_CB_HCOLOR );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("A") );
ComboBox_AddString( hwndCB, TEXT("B") );
ComboBox_AddString( hwndCB, TEXT("C") );
ComboBox_AddString( hwndCB, TEXT("D (<28><><EFBFBD><EFBFBD><EFBFBD> Kamael)") );
ComboBox_SetCurSel( hwndCB, 0 );
// insert faces
hwndCB = GetDlgItem( hDlg, IDC_CB_FSTYLE );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("A") );
ComboBox_AddString( hwndCB, TEXT("B") );
ComboBox_AddString( hwndCB, TEXT("C") );
ComboBox_SetCurSel( hwndCB, 0 );
// insert genders
hwndCB = GetDlgItem( hDlg, IDC_CB_GENDER );
ComboBox_ResetContent( hwndCB );
ComboBox_AddString( hwndCB, TEXT("M<EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_AddString( hwndCB, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>") );
ComboBox_SetCurSel( hwndCB, 0 );
} break;
case WM_COMMAND:
{
CREATECHARDLGSTRUCT *st = (CREATECHARDLGSTRUCT *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
switch( LOWORD(wParam) )
{
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
case IDOK:
{
// get char name
GetDlgItemTextW( hDlg, IDC_EDIT1, st->pResult->createCharName, 255 );
st->pResult->createCharName[255] = 0;
// get race & class, template index
HWND hwndCB = GetDlgItem( hDlg, IDC_CB_CLASS );
st->pResult->createTemplateIndex = ComboBox_GetCurSel( hwndCB );
// get hair style
hwndCB = GetDlgItem( hDlg, IDC_CB_HSTYLE );
st->pResult->createHairStyle = ComboBox_GetCurSel( hwndCB );
// get hair color
hwndCB = GetDlgItem( hDlg, IDC_CB_HCOLOR );
st->pResult->createHairColor = ComboBox_GetCurSel( hwndCB );
// get face
hwndCB = GetDlgItem( hDlg, IDC_CB_FSTYLE );
st->pResult->createFace = ComboBox_GetCurSel( hwndCB );
// get gender
hwndCB = GetDlgItem( hDlg, IDC_CB_GENDER );
st->pResult->createGender = ComboBox_GetCurSel( hwndCB );
//
EndDialog( hDlg, IDOK );
} break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}

View File

@@ -0,0 +1,19 @@
#ifndef H_CREATECHAR_DLG
#define H_CREATECHAR_DLG
struct CreateCharDialogResult
{
int createTemplateIndex;
wchar_t createCharName[256];
int createHairStyle;
int createHairColor;
int createFace;
int createGender;
};
void CreateCharDialog( HWND hWndParent,
L2Game_NewCharacterTemplate *templates,
int templatesCount,
CreateCharDialogResult *pResult );
#endif

351
l2ooghelper/DBLayer.cpp Normal file
View File

@@ -0,0 +1,351 @@
#include "stdafx.h"
#include "DBLayer.h"
#include "Logger.h"
// limits
//sqlite> select max(id) from items: 20062
//sqlite> select max(id) from skills: 26073
//sqlite> select max(id) from mobs: 36599
const unsigned int dbl_max_npc_id = 40000;
const unsigned int dbl_max_skill_id = 27000;
const unsigned int dbl_max_item_id = 25000;
TCHAR **dbl_npc_names = NULL;
TCHAR **dbl_npc_titles = NULL;
TCHAR **dbl_skill_names = NULL;
TCHAR **dbl_item_names = NULL;
int dbl_cache_hits = 0;
int dbl_cache_misses = 0;
int dbl_npcs_cached = 0;
int dbl_skills_cached = 0;
int dbl_items_cached = 0;
void DBLayer_init()
{
log_error( LOG_DEBUG, "DB Layer: init database...\n" );
//
char errmsg[256] = {0};
bool open_ok = L2Data_DB_Init( errmsg,
".\\data\\L2Detect_items.sqlite3db",
".\\data\\L2Detect_mobs.sqlite3db",
".\\data\\L2Detect_skills.sqlite3db" );
if( errmsg[0] )
{
log_error( LOG_ERROR, "L2Data_DB_Init(): says: %s\n", errmsg );
MessageBoxA( NULL, errmsg, "L2Data_DB_Init():", MB_ICONWARNING );
}
if( !open_ok )
{
log_error( LOG_ERROR, "DB Layer: database open error!\n" );
return;
}
//
log_error( LOG_OK, "DB Layer: database opened\n" );
//
dbl_cache_hits = 0;
dbl_cache_misses = 0;
dbl_npcs_cached = 0;
dbl_skills_cached = 0;
dbl_items_cached = 0;
// allocate mem
// NULL
dbl_npc_names = NULL;
dbl_npc_titles = NULL;
dbl_skill_names = NULL;
dbl_item_names = NULL;
// malloc npc names
dbl_npc_names = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_npc_id );
if( !dbl_npc_names )
{
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (1)\n" );
return;
}
// malloc npc titles
dbl_npc_titles = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_npc_id );
if( !dbl_npc_titles )
{
free( dbl_npc_names );
dbl_npc_names = NULL;
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (2)\n" );
return;
}
// malloc skill names
dbl_skill_names = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_skill_id );
if( !dbl_skill_names )
{
free( dbl_npc_names );
free( dbl_npc_titles );
dbl_npc_names = NULL;
dbl_npc_titles = NULL;
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (3)\n" );
return;
}
// malloc item names
dbl_item_names = (TCHAR **)malloc( sizeof(TCHAR *) * dbl_max_item_id );
if( !dbl_item_names )
{
free( dbl_npc_names );
free( dbl_npc_titles );
free( dbl_skill_names );
dbl_npc_names = NULL;
dbl_npc_titles = NULL;
dbl_skill_names = NULL;
log_error( LOG_ERROR, "DB Layer: cannot allocate mem (4)\n" );
return;
}
//
log_error( LOG_DEBUG, "DB cache created\n" );
int i;
for( i=0; i<dbl_max_npc_id; i++ )
{
dbl_npc_names[i] = NULL;
dbl_npc_titles[i] = NULL;
}
for( i=0; i<dbl_max_item_id; i++ ) dbl_item_names[i] = NULL;
for( i=0; i<dbl_max_skill_id; i++ ) dbl_skill_names[i] = NULL;
//
log_error( LOG_DEBUG, "DB Layer: init database end.\n" );
}
void DBLayer_free()
{
log_error( LOG_DEBUG, "DB Layer: closing database..\n" );
int i = 0;
int nfreed = 0;
// free npc names
if( dbl_npc_names )
{
nfreed = 0;
for( i=0; i<dbl_max_npc_id; i++ )
{
if( dbl_npc_names[i] )
{
free( dbl_npc_names[i] );
dbl_npc_names[i] = NULL;
nfreed++;
}
}
free( dbl_npc_names );
dbl_npc_names = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached npc names\n", nfreed );
}
// free npc titles
if( dbl_npc_titles )
{
nfreed = 0;
for( i=0; i<dbl_max_npc_id; i++ )
{
if( dbl_npc_titles[i] )
{
free( dbl_npc_titles[i] );
dbl_npc_titles[i] = NULL;
nfreed++;
}
}
free( dbl_npc_titles );
dbl_npc_titles = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached npc titles\n", nfreed );
}
// free skill names
if( dbl_skill_names )
{
nfreed = 0;
for( i=0; i<dbl_max_skill_id; i++ )
{
if( dbl_skill_names[i] )
{
free( dbl_skill_names[i] );
dbl_skill_names[i] = NULL;
nfreed++;
}
}
free( dbl_skill_names );
dbl_skill_names = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached skill names\n", nfreed );
}
// free item names
if( dbl_item_names )
{
nfreed = 0;
for( i=0; i<dbl_max_item_id; i++ )
{
if( dbl_item_names[i] )
{
free( dbl_item_names[i] );
dbl_item_names[i] = NULL;
nfreed++;
}
}
free( dbl_item_names );
dbl_item_names = NULL;
log_error( LOG_OK, "DB Layer: freed %d cached item names\n", nfreed );
}
// close db files
L2Data_DB_Free();
log_error( LOG_DEBUG, "DB Layer: database files closed.\n" );
}
#if defined(UNICODE) || defined(_UNICODE)
// needed as analog to _strdup/_wcsdup but converting from ansi string to unicode
wchar_t *ansi_to_unicode_dup( const char *ansi )
{
if( !ansi ) return NULL;
size_t len = strlen( ansi );
wchar_t *wstr = (wchar_t *)malloc( len*2 + 2 );
if( !wstr ) return NULL;
swprintf( wstr, len*2 + 2, L"%S", ansi );
wstr[len] = 0;
return wstr;
}
#endif
void DBLayer_getItemName( unsigned int itemID, TCHAR *out, size_t maxCount )
{
if( itemID >= dbl_max_item_id )
{
log_error( LOG_ERROR, "DBLayer_getItemName(): item ID %u is above max limit %u\n",
itemID, dbl_max_item_id );
return;
}
if( dbl_item_names )
{
// check cache
if( dbl_item_names[itemID] )
{
// found in cache
_tcsncpy( out, dbl_item_names[itemID], maxCount );
out[maxCount-1] = 0;
dbl_cache_hits++;
return;
}
// not in cache :( request DB
char aname[256] = {0};
if( L2Data_DB_GetItemNamePicByID( itemID, aname, NULL ) )
{
dbl_cache_misses++;
dbl_items_cached++;
#if defined(UNICODE) || defined(_UNICODE)
dbl_item_names[itemID] = ansi_to_unicode_dup( aname );
#else
dbl_item_names[itemID] = _strdup( aname );
#endif
_tcsncpy( out, dbl_item_names[itemID], maxCount );
out[maxCount-1] = 0;
}
else log_error( LOG_ERROR, "DB: item %u not in DB!\n", itemID );
}
else log_error( LOG_ERROR, "DB Layer: no mem allocated for item names, DB init error?\n" );
}
void DBLayer_getSkillName( unsigned int skillID, TCHAR *out, size_t maxCount )
{
if( skillID >= dbl_max_skill_id )
{
log_error( LOG_ERROR, "DBLayer_getSkillName(): skill ID %u is above max limit %u\n",
skillID, dbl_max_skill_id );
return;
}
if( dbl_skill_names )
{
// check cache
if( dbl_skill_names[skillID] )
{
// found in cache
_tcsncpy( out, dbl_skill_names[skillID], maxCount );
out[maxCount-1] = 0;
dbl_cache_hits++;
return;
}
// not in cache :( request DB
char aname[256] = {0};
if( L2Data_DB_GetSkillNameByID( skillID, aname ) )
{
dbl_cache_misses++;
dbl_skills_cached++;
#if defined(UNICODE) || defined(_UNICODE)
dbl_skill_names[skillID] = ansi_to_unicode_dup( aname );
#else
dbl_skill_names[skillID] = _strdup( aname );
#endif
_tcsncpy( out, dbl_skill_names[skillID], maxCount );
out[maxCount-1] = 0;
}
else log_error( LOG_ERROR, "DB: skill %u not in DB!\n", skillID );
}
else log_error( LOG_ERROR, "DB Layer: no mem allocated for skill names, DB init error?\n" );
}
void DBLayer_getNpcNameTitle(
unsigned int npcID,
TCHAR *npcName, size_t npcNameMaxCount,
TCHAR *npcTitle, size_t npcTitleMaxCount )
{
if( npcID >= dbl_max_npc_id )
{
log_error( LOG_ERROR, "DBLayer_getNpcNameTitle(): npc ID %u is above max limit %u\n",
npcID, dbl_max_npc_id );
return;
}
if( dbl_npc_names && dbl_npc_titles )
{
// check cache
if( dbl_npc_names[npcID] )
{
// found in cache
_tcsncpy( npcName, dbl_npc_names[npcID], npcNameMaxCount );
npcName[npcNameMaxCount-1] = 0;
npcTitle[0] = 0;
// npc title can be NULL
if( dbl_npc_titles[npcID] )
{
_tcsncpy( npcTitle, dbl_npc_titles[npcID], npcTitleMaxCount );
npcTitle[npcTitleMaxCount-1] = 0;
}
dbl_cache_hits++;
return;
}
// not in cache :( request DB
char aname[256] = {0};
char atitle[256] = {0};
if( L2Data_DB_GetNPCNameTitleByID( npcID, aname, atitle ) )
{
dbl_cache_misses++;
dbl_npcs_cached++;
#if defined(UNICODE) || defined(_UNICODE)
dbl_npc_names[npcID] = ansi_to_unicode_dup( aname );
if( atitle[0] )
dbl_npc_titles[npcID] = ansi_to_unicode_dup( atitle );
#else
dbl_npc_names[npcID] = _strdup( aname );
if( atitle[0] )
dbl_npc_titles[npcID] = _strdup( atitle );
#endif
// out
_tcsncpy( npcName, dbl_npc_names[npcID], npcNameMaxCount );
npcName[npcNameMaxCount-1] = 0;
npcTitle[0] = 0;
// npc title can be NULL
if( dbl_npc_titles[npcID] )
{
_tcsncpy( npcTitle, dbl_npc_titles[npcID], npcTitleMaxCount );
npcTitle[npcTitleMaxCount-1] = 0;
}
}
else log_error( LOG_ERROR, "DB: NPC %u not in DB!\n", npcID );
}
else log_error( LOG_ERROR, "DB Layer: no mem allocated for "
"NPC names & titles, DB init error?\n" );
}
void DBLayer_printStats()
{
log_error_np( LOG_OK, "[DB] ===== Stats info: ======\n" );
log_error_np( LOG_OK, "[DB] cached (NPCs, Skills, Items) : %d, %d, %d\n",
dbl_npcs_cached, dbl_skills_cached, dbl_items_cached );
log_error_np( LOG_OK, "[DB] Cache: MISS / HIT : %d / %d\n",
dbl_cache_misses, dbl_cache_hits );
log_error_np( LOG_OK, "[DB] ===== Stats info end =====\n" );
}

18
l2ooghelper/DBLayer.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef H_DB_LAYER
#define H_DB_LAYER
void DBLayer_init();
void DBLayer_free();
void DBLayer_getItemName( unsigned int itemID, TCHAR *out, size_t maxCount );
void DBLayer_getSkillName( unsigned int skillID, TCHAR *out, size_t maxCount );
void DBLayer_getNpcNameTitle(
unsigned int npcID,
TCHAR *npcName, size_t npcNameMaxCount,
TCHAR *npcTitle, size_t npcTitleMaxCount );
void DBLayer_printStats();
#endif

View File

@@ -0,0 +1,171 @@
#include "stdafx.h"
#include "Dlg_FindInDB.h"
#include "Resource.h"
extern HINSTANCE g_hInst;
Dlg_FindInDB::Dlg_FindInDB( MODE mode )
{
m_mode = mode;
itemID = 0;
itemName[0] = 0;
itemNameW[0] = 0;
}
Dlg_FindInDB::~Dlg_FindInDB()
{
itemID = 0;
itemName[0] = 0;
itemNameW[0] = 0;
}
INT_PTR CALLBACK Dlg_FindInDB_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
bool Dlg_FindInDB::runDialog( HWND hWndParent )
{
INT_PTR ret = DialogBoxParam( g_hInst,
MAKEINTRESOURCE(IDD_FINDINDB), hWndParent, Dlg_FindInDB_Proc, (LPARAM)this );
if( ret == IDOK ) return true;
return false;
}
void Dlg_FindInDB_OnInitDialog( HWND hDlg, LPARAM lParam );
void Dlg_FindInDB_OnOK( HWND hDlg );
void Dlg_FindInDB_OnFind( HWND hDlg );
INT_PTR CALLBACK Dlg_FindInDB_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG: Dlg_FindInDB_OnInitDialog( hDlg, lParam ); break;
case WM_COMMAND:
{
switch( LOWORD( wParam ) )
{
case IDOK: Dlg_FindInDB_OnOK( hDlg ); break;
case IDCANCEL: EndDialog( hDlg, IDCANCEL ); break;
case IDC_FIND: Dlg_FindInDB_OnFind( hDlg ); break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}
void Dlg_FindInDB_OnInitDialog( HWND hDlg, LPARAM lParam )
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
class Dlg_FindInDB *cls = (class Dlg_FindInDB *)lParam;
switch( cls->getMode() )
{
case Dlg_FindInDB::MODE_ITEM:
{
SetWindowText( hDlg, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>") );
} break;
case Dlg_FindInDB::MODE_NPC:
{
SetWindowText( hDlg, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> NPC <20> <20><><EFBFBD><EFBFBD>") );
} break;
case Dlg_FindInDB::MODE_SKILL:
{
SetWindowText( hDlg, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>") );
} break;
}
CheckDlgButton( hDlg, IDC_R_CONTAINS, BST_CHECKED );
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
DWORD dwLvExStyle = LVS_EX_DOUBLEBUFFER | LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES;
SendMessage( hwndLV, LVM_SETEXTENDEDLISTVIEWSTYLE, (WPARAM)dwLvExStyle, (LPARAM)dwLvExStyle );
TCHAR text[256] = {0};
LVCOLUMN lvc;
lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH | LVCF_SUBITEM;
lvc.fmt = LVCFMT_LEFT;
lvc.cx = 60;
lvc.iSubItem = 0;
lvc.pszText = text;
lstrcpy( text, TEXT("id") );
ListView_InsertColumn( hwndLV, 0, &lvc );
lvc.cx = 200;
lvc.iSubItem = 1;
lstrcpy( text, TEXT("<EFBFBD><EFBFBD><EFBFBD>") );
ListView_InsertColumn( hwndLV, 1, &lvc );
}
void Dlg_FindInDB_OnOK( HWND hDlg )
{
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
int iSel = ListView_GetNextItem( hwndLV, -1, LVNI_SELECTED );
if( iSel == -1 ) return;
class Dlg_FindInDB *cls = (class Dlg_FindInDB *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !cls ) return;
TCHAR text[256];
LVITEM lvi;
lvi.iItem = iSel;
lvi.iSubItem = 0;
lvi.mask = LVIF_TEXT;
lvi.pszText = text;
lvi.cchTextMax = 255;
ListView_GetItem( hwndLV, &lvi );
_stscanf( lvi.pszText, _T("%d"), &(cls->itemID) );
lvi.iSubItem = 1;
lvi.mask = LVIF_TEXT;
lvi.pszText = text;
lvi.cchTextMax = 255;
ListView_GetItem( hwndLV, &lvi );
#ifdef UNICODE
wcscpy( cls->itemNameW, lvi.pszText );
sprintf( cls->itemName, "%S", lvi.pszText );
#else
strcpy( cls->itemName, lvi.pszText );
wsprintfW( cls->itemNameW, L"%S", lvi.pszText );
#endif
EndDialog( hDlg, IDOK );
}
void Dlg_FindInDB_OnFind( HWND hDlg )
{
class Dlg_FindInDB *cls = (class Dlg_FindInDB *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
TCHAR text[256] = {0};
char toFind[256] = {0};
char queryString[256] = {0};
GetDlgItemTextA( hDlg, IDC_EDITNAME, toFind, 255 );
toFind[255] = 0;
HWND hwndLV = GetDlgItem( hDlg, IDC_LISTITEMS );
int starts_with = IsDlgButtonChecked( hDlg, IDC_R_STWITH );
int contains = IsDlgButtonChecked( hDlg, IDC_R_CONTAINS );
int ends_with = IsDlgButtonChecked( hDlg, IDC_R_ENWITH );
if( contains ) sprintf( queryString, "%%%s%%", toFind );
if( ends_with ) sprintf( queryString, "%%%s", toFind );
if( starts_with ) sprintf( queryString, "%s%%", toFind );
L2Data_DB_Result res;
res.inMaxRowsToGet = 64;
bool bRet = false;
switch( cls->getMode() )
{
case Dlg_FindInDB::MODE_ITEM: bRet = L2Data_DB_Query_Items_ByName( queryString, &res ); break;
case Dlg_FindInDB::MODE_NPC: bRet = L2Data_DB_Query_NPCs_ByName( queryString, &res ); break;
case Dlg_FindInDB::MODE_SKILL: bRet = L2Data_DB_Query_Skills_ByName( queryString, &res ); break;
}
if( bRet )
{
ListView_DeleteAllItems( hwndLV );
int nr = res.rowCount;
int i;
for( i=0; i<nr; i++ )
{
LVITEM lvi;
lvi.mask = LVIF_TEXT;
lvi.iItem = 999;
lvi.iSubItem = 0;
lvi.pszText = text;
wsprintf( text, TEXT("%S"), res.rows[i][0] );
int added_item = ListView_InsertItem( hwndLV, &lvi );
lvi.iItem = added_item;
lvi.iSubItem = 1;
lvi.pszText = text;
wsprintf( text, TEXT("%S"), res.rows[i][1] );
ListView_SetItem( hwndLV, &lvi );
}
L2Data_DB_Free_Result( &res );
}
}

View File

@@ -0,0 +1,31 @@
#ifndef H_DLG_FINDINDB
#define H_DLG_FINDINDB
class Dlg_FindInDB
{
public:
typedef enum eMODE
{
//MODE_NONE = 0,
MODE_ITEM = 1,
MODE_NPC,
MODE_SKILL
} MODE;
public:
Dlg_FindInDB( MODE mode );
~Dlg_FindInDB();
public:
bool runDialog( HWND hWndParent );
Dlg_FindInDB::MODE getMode() const { return this->m_mode; }
public: // results
unsigned int itemID;
char itemName[256];
wchar_t itemNameW[256];
protected:
MODE m_mode;
};
#endif

201
l2ooghelper/GIArray.cpp Normal file
View File

@@ -0,0 +1,201 @@
#include "stdafx.h"
#include "Logger.h"
#include "GIArray.h"
#include "DBLayer.h"
void GIArray::Init()
{
giArray_updateHWND = NULL;
giArray_updateMSG = 0;
giArray_count = 0;
InitializeCriticalSection( &cs_gi_array );
int i;
for( i=0; i<GA_MAX_ITEMS; i++ ) gi_array[i] = new GroundItem();
}
void GIArray::Free()
{
Lock();
int i;
for( i=0; i<GA_MAX_ITEMS; i++ )
{
if( gi_array[i] != NULL )
{
delete gi_array[i];
gi_array[i] = NULL;
}
}
giArray_count = 0;
Unlock();
DeleteCriticalSection( &cs_gi_array );
}
int GIArray::AddGIInfo( GroundItem *pItemInfo )
{
Lock();
// Add new npc info
int idx = FindFreeIndex();
if( idx == -1 )
{
Unlock();
return -1;
}
if( !gi_array[idx] ) gi_array[idx] = new GroundItem();
if( !gi_array[idx] )
{
Unlock();
return -1;
}
memcpy( gi_array[idx], pItemInfo, sizeof(class GroundItem) );
giArray_count++;
Unlock();
PostUpdateMessage();
//log_error( LOG_OK, "GIArray: Added new[%d]: [%S] [%S] (%d,%d,%d) tpml %u, oid %u\n",
// idx,
// name, title, x,y,z, templateID, objectID );
return idx;
}
void GIArray::UpdateGIInfo( int idx, GroundItem *pItemInfo )
{
Lock();
// update info on existing
if( !gi_array[idx] )
{
log_error( LOG_ERROR, "GIArray_UpdateGIInfo(): idx[%d] is free!\n", idx );
// try to allocate!
gi_array[idx] = new GroundItem();
if( !gi_array[idx] )
{
Unlock();
return;
}
}
if( gi_array[idx]->isUnused() ) log_error( LOG_ERROR, "GIArray_UpdateGIInfo(): idx[%d] is unused!\n", idx );
memcpy( gi_array[idx], pItemInfo, sizeof(class GroundItem) );
Unlock();
PostUpdateMessage();
//log_error( LOG_OK, "GIArray: Updated[%d]: [%S] [%S] (%d,%d,%d) tpml %u, oid %u\n",
// idx,
// name, title, x,y,z, templateID, objectID );
}
void GIArray::DelGIByArrayIdx( int idx )
{
if( idx<0 || (idx>=GA_MAX_ITEMS) ) return;
Lock();
if( gi_array[idx] )
{
gi_array[idx]->setUnused();
giArray_count--;
//log_error( LOG_OK, "GIArray: deleted %u from index OK\n", objectID, idx );
}
Unlock();
PostUpdateMessage();
}
void GIArray::DeleteAll()
{
Lock();
int i;
for( i=0; i<GA_MAX_ITEMS; i++ )
{
if( gi_array[i] ) gi_array[i]->setUnused();
}
giArray_count = 0;
Unlock();
PostUpdateMessage();
}
void GIArray::Lock()
{
EnterCriticalSection( &cs_gi_array );
}
void GIArray::Unlock()
{
LeaveCriticalSection( &cs_gi_array );
}
int GIArray::FindGIByObjectID( unsigned int objectID )
{
int ret = -1;
int i;
Lock();
for( i=0; i<GA_MAX_ITEMS; i++ )
{
if( gi_array[i] == NULL ) continue;
if( gi_array[i]->objectID == objectID )
{
ret = i;
break;
}
}
Unlock();
return ret;
}
int GIArray::FindFreeIndex()
{
int i;
Lock();
for( i=0; i<GA_MAX_ITEMS; i++ )
{
if( gi_array[i] == NULL )
{
gi_array[i] = new GroundItem(); // allocate new
gi_array[i]->setUnused(); // and set as unused
Unlock();
return i;
}
if( gi_array[i]->isUnused() )
{
Unlock();
return i;
}
}
Unlock();
log_error( LOG_ERROR, "GIArray_FindFreeIndex(): canot find free index, limit is %d!\n", GA_MAX_ITEMS );
return -1;
}
void GIArray::SetUpdateCommand( HWND hWnd, UINT uMsg )
{
giArray_updateHWND = hWnd;
giArray_updateMSG = uMsg;
}
void GIArray::PostUpdateMessage()
{
if( !giArray_updateHWND ) return;
if( giArray_updateMSG < WM_USER ) return;
PostMessage( giArray_updateHWND, giArray_updateMSG, 0, 0 );
}
void GIArray::DisplayToConsole()
{
int i = 0;
unsigned int nDisplayed = 0;
log_error( LOG_USERAI, "=== Ground items: %d ===\n", giArray_count );
if( giArray_count > 0 )
{
Lock();
for( i=0; i<GA_MAX_ITEMS; i++ )
{
if( gi_array[i]->isUnused() )
log_error( LOG_USERAI, "GI: %2d: <unused>\n", i );
else
{
wchar_t itemName[256] = {0};
DBLayer_getItemName( gi_array[i]->itemID, itemName, 255 );
log_error( LOG_USERAI, "GI: %2d: itemID %u, objectID %u, count %d [%s]\n", i,
gi_array[i]->itemID, gi_array[i]->objectID,
gi_array[i]->count, itemName );
nDisplayed++;
}
if( nDisplayed >= giArray_count ) break;
}
Unlock();
}
log_error( LOG_USERAI, "=== Ground items End ===\n" );
}

40
l2ooghelper/GIArray.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef H_GI_ARRAY
#define H_GI_ARRAY
#include "GroundItem.h"
class GIArray
{
public:
GIArray() { Init(); }
~GIArray() { Free(); }
public:
static const int GA_MAX_ITEMS = 512;
GroundItem *gi_array[GA_MAX_ITEMS];
public:
void Init();
void Free();
public:
int AddGIInfo( GroundItem *pGIInfo );
void UpdateGIInfo( int idx, GroundItem *pGIInfo );
void DelGIByArrayIdx( int idx );
void DeleteAll();
public:
void Lock();
void Unlock();
public:
int FindGIByObjectID( unsigned int objectID );
int FindFreeIndex();
public:
void SetUpdateCommand( HWND hWnd, UINT uMsg );
unsigned int getCount() const { return giArray_count; }
void DisplayToConsole();
protected:
void PostUpdateMessage();
protected:
unsigned int giArray_count;
CRITICAL_SECTION cs_gi_array;
HWND giArray_updateHWND;
UINT giArray_updateMSG;
};
#endif

View File

@@ -0,0 +1,220 @@
#include "stdafx.h"
#include "Resource.h"
#include "logger.h"
#include "GlobalMapImages.h"
#include "PngJpegImage.h"
GlobalMapImages::GlobalMapImages()
{
InitializeCriticalSection( &m_cs );
EnterCriticalSection( &m_cs );
int i, j;
for( i=0; i<GEO_W; i++ )
{
for( j=0; j<GEO_H; j++ )
{
m_geo_hdc[i][j] = NULL;
m_width[i][j] = m_height[i][j] = 0;
}
}
m_nLoadedCount = 0;
m_mapsDir[0] = 0;
LeaveCriticalSection( &m_cs );
}
GlobalMapImages::~GlobalMapImages()
{
unloadAllSquares();
DeleteCriticalSection( &m_cs );
}
void GlobalMapImages::setMapsDir( const char *dir )
{
strcpy( m_mapsDir, dir );
}
bool GlobalMapImages::isValidGeoXY( int geo_x, int geo_y )
{
if( (geo_x>=GEO_X_MIN) && (geo_x<=GEO_X_MAX) &&
(geo_y>=GEO_Y_MIN) && (geo_y<=GEO_Y_MAX) ) return true;
return false;
}
bool GlobalMapImages::preloadSquare( int geo_x, int geo_y )
{
Lock();
if( !isValidGeoXY( geo_x, geo_y ) ) { UnLock(); return false; }
if( isSquareLoaded( geo_x, geo_y ) ) { UnLock(); return false; }
// check maps dir
if( m_mapsDir[0] == 0 )
{
char aCurDir[256] = {0};
GetCurrentDirectoryA( 255, aCurDir );
strcat( aCurDir, "\\maps" );
strcpy( m_mapsDir, aCurDir );
}
// first try to load image
char filename[256];
sprintf( filename, "%s\\%d_%d.jpg", m_mapsDir, geo_x, geo_y );
PngJpegImage *img = new PngJpegImage();
if( !img->readFile_JPEG( filename ) )
{
// try another file name
sprintf( filename, "%s\\%d_%d_1.jpg", m_mapsDir, geo_x, geo_y );
if( !img->readFile_JPEG( filename ) )
{
log_error( LOG_ERROR, "GlobalMapImages::preloadSquare( %d, %d ): could not readFile_JPEG( %s ): %u\n",
geo_x, geo_y, filename, GetLastError() );
UnLock();
return false;
}
// here loaded XX_XX_1.jpg
}
// image size
int w = 0, h = 0;
img->getParams( &w, &h, NULL, NULL );
//
HWND hWnd = GetDesktopWindow();
HDC hWindowDC = GetDC( hWnd );
HDC hdc = CreateCompatibleDC( hWindowDC );
if( !hdc )
{
log_error( LOG_ERROR, "GlobalMapImages::preloadSquare( %d, %d ): could not CreateCompatibleDC(): %u\n",
geo_x, geo_y, GetLastError() );
delete img;
UnLock();
return false;
}
HBITMAP hbm = CreateCompatibleBitmap( hWindowDC, w, h );
ReleaseDC( hWnd, hWindowDC ); // now we don't need desktop window DC
if( hbm == NULL )
{
log_error( LOG_ERROR, "GlobalMapImages::preloadSquare( %d, %d ): could not CreateCompatibleBitmap(): %u\n",
geo_x, geo_y, GetLastError() );
delete img;
DeleteDC( hdc );
UnLock();
return false;
}
SelectObject( hdc, (HGDIOBJ)hbm );
img->displayOn( hdc, 0, 0 ); // print image to HDC
delete img;
SetStretchBltMode( hdc, HALFTONE );
geo_XY_to_array_index( geo_x, geo_y );
m_geo_hdc[ geo_x ][ geo_y ] = hdc; // save loaded HDC in array
m_width[ geo_x ][ geo_y ] = w;
m_height[ geo_x ][ geo_y ] = h;
m_nLoadedCount++; // inc loaded count
UnLock();
//log_error_np( LOG_OK, "[GlobalMap] loaded %d_%d\n", geo_x+GEO_X_MIN, geo_y+GEO_Y_MIN );
return true;
}
bool GlobalMapImages::unloadSquare( int geo_x, int geo_y )
{
Lock();
if( !isSquareLoaded( geo_x, geo_y ) ) { UnLock(); return false; }
geo_XY_to_array_index( geo_x, geo_y );
// first get current DC bitmap
HBITMAP hbm = (HBITMAP)GetCurrentObject( m_geo_hdc[geo_x][geo_y], OBJ_BITMAP );
// then delete DC
DeleteDC( m_geo_hdc[geo_x][geo_y] );
m_geo_hdc[geo_x][geo_y] = NULL; // mark as not loaded
m_width[ geo_x ][ geo_y ] = m_height[ geo_x ][ geo_y ] = 0;
// then delete bitmap
if( hbm ) DeleteObject( (HGDIOBJ)hbm );
m_nLoadedCount--; // dec loaded count
UnLock();
return true;
}
void GlobalMapImages::preloadAllSquares()
{
Lock();
int i, j;
for( i=GEO_X_MIN; i<=GEO_X_MAX; i++ )
{
for( j=GEO_Y_MIN; j<=GEO_Y_MAX; j++ )
{
preloadSquare( i, j );
}
}
UnLock();
}
void GlobalMapImages::unloadAllSquares()
{
Lock();
int i, j;
for( i=GEO_X_MIN; i<=GEO_X_MAX; i++ )
{
for( j=GEO_Y_MIN; j<=GEO_Y_MAX; j++ )
{
unloadSquare( i, j );
}
}
UnLock();
}
bool GlobalMapImages::isSquareLoaded( int geo_x, int geo_y ) const
{
if( !isValidGeoXY( geo_x, geo_y ) ) return false;
geo_XY_to_array_index( geo_x, geo_y );
if( m_geo_hdc[ geo_x ][ geo_y ] != NULL ) return true;
return false;
}
HDC GlobalMapImages::getSquareHDC( int geo_x, int geo_y ) const
{
if( !isValidGeoXY( geo_x, geo_y ) ) return NULL;
geo_XY_to_array_index( geo_x, geo_y );
return m_geo_hdc[ geo_x ][ geo_y ];
}
void GlobalMapImages::getSquareWH( int geo_x, int geo_y, int& w, int &h ) const
{
if( !isValidGeoXY( geo_x, geo_y ) ) return;
geo_XY_to_array_index( geo_x, geo_y );
w = m_width[ geo_x ][ geo_y ];
h = m_height[ geo_x ][ geo_y ];
}
/*
protected:
CRITICAL_SECTION m_cs;
int m_nLoadedCount;
HDC m_geo_hdc[GEO_W][GEO_H];
};
*/
void GlobalMapImages::GetGeoSquareStartL2Coords( int geo_x, int geo_y, int *l2_x, int *l2_y )
{
const int geo_square_x_0 = 20;
const int geo_square_y_0 = 18;
if( (geo_x<16) || (geo_x>26) || (geo_y<10) || (geo_y>25) ) return;
(*l2_x) = (geo_x - geo_square_x_0) * GlobalMapImages::GEO_BOX_L2_SIZE;
(*l2_y) = (geo_y - geo_square_y_0) * GlobalMapImages::GEO_BOX_L2_SIZE;
}
void GlobalMapImages::GetGeoMapSquareXYByL2Coords( int l2_x, int l2_y, int *geo_x, int *geo_y )
{
const int geo_square_x_0 = 20;
const int geo_square_y_0 = 18;
int nSquaresFrom_0_x = l2_x / GlobalMapImages::GEO_BOX_L2_SIZE;
int nSquaresFrom_0_y = l2_y / GlobalMapImages::GEO_BOX_L2_SIZE;
int geo_square_x = geo_square_x_0 + nSquaresFrom_0_x;
int geo_square_y = geo_square_y_0 + nSquaresFrom_0_y;
// fix negative offset coords
if( l2_x < 0 ) geo_square_x--;
if( l2_y < 0 ) geo_square_y--;
//
if( (geo_square_x < 16) || (geo_square_x > 26) || (geo_square_y < 10) || (geo_square_y > 25) )
{
log_error_np( LOG_ERROR, "[GlobalMap]: GetGeoMapSquareXYByL2Coords(): error overflow!\n" );
return;
}
if( geo_x ) (*geo_x) = geo_square_x;
if( geo_y ) (*geo_y) = geo_square_y;
}

View File

@@ -0,0 +1,47 @@
#ifndef H_GLOBAL_MAP_IMAGES
#define H_GLOBAL_MAP_IMAGES
class GlobalMapImages
{
public:
static const int GEO_X_MIN = 16;
static const int GEO_Y_MIN = 10;
static const int GEO_X_MAX = 26;
static const int GEO_Y_MAX = 25;
static const int GEO_W = 10;
static const int GEO_H = 15;
static const int GEO_BOX_L2_SIZE = 32760; // originally was 33333
public:
GlobalMapImages();
~GlobalMapImages();
public:
void setMapsDir( const char *dir );
public:
bool preloadSquare( int geo_x, int geo_y );
void preloadAllSquares();
bool unloadSquare( int geo_x, int geo_y );
void unloadAllSquares();
bool isSquareLoaded( int geo_x, int geo_y ) const;
HDC getSquareHDC( int geo_x, int geo_y ) const;
void getSquareWH( int geo_x, int geo_y, int& w, int &h ) const;
public:
static void GetGeoSquareStartL2Coords( int geo_x, int geo_y, int *l2_x, int *l2_y );
static void GetGeoMapSquareXYByL2Coords( int l2_x, int l2_y, int *geo_x, int *geo_y );
public:
int getLoadedCount() const { return m_nLoadedCount; }
protected:
void Lock() { EnterCriticalSection( &m_cs ); }
void UnLock() { LeaveCriticalSection( &m_cs ); }
protected:
static bool isValidGeoXY( int geo_x, int geo_y );
static void geo_XY_to_array_index( int& geo_x, int& geo_y ) { geo_x -= GEO_X_MIN; geo_y -= GEO_Y_MIN; }
protected:
CRITICAL_SECTION m_cs;
int m_nLoadedCount;
HDC m_geo_hdc[GEO_W][GEO_H];
int m_width[GEO_W][GEO_H];
int m_height[GEO_W][GEO_H];
char m_mapsDir[256];
};
#endif

View File

@@ -0,0 +1,19 @@
#include "stdafx.h"
#include "GroundItem.h"
/*void GroundItem::db_query()
{
if( itemName[0] == 0 )
{
L2Data_DB_GetItemNamePicByID( itemID, itemName, NULL );
if( itemName[0] == 0 ) sprintf( itemName, "item_%u", itemID );
}
}*/
void GroundItem::setUnused()
{
L2Object::setUnused();
itemID = 0;
stackable = 0;
count = 0;
}

17
l2ooghelper/GroundItem.h Normal file
View File

@@ -0,0 +1,17 @@
#ifndef H_GROUNDITEM
#define H_GROUNDITEM
class GroundItem: public L2Object
{
public:
GroundItem() { setUnused(); }
~GroundItem() { setUnused(); }
public:
virtual void setUnused();
public:
unsigned int itemID;
int stackable;
unsigned long long int count;
};
#endif

253
l2ooghelper/HWID.cpp Normal file
View File

@@ -0,0 +1,253 @@
#include "stdafx.h"
#include "Logger.h"
#include "base64.h"
#include "HWID.h"
//#define VERIFY_HWID
#ifndef VERIFY_HWID
bool verifyHWID()
{
return true;
}
bool verifyTimeLimit()
{
return true;
}
#else
const int max_pbsi = 3;
struct partial_boot_sector_info
{
LPSTR Fs; // file system name
DWORD FsOffs; // offset of file system name in the boot sector
DWORD SerialOffs; // offset of the serialnumber in the boot sector
};
void read_MBR( unsigned char *outbuffer )
{
//HANDLE hFile = CreateFileW( L"\\\\.\\PhysicalDrive0",
HANDLE hFile = CreateFileW( L"\\\\.\\c:",
GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
DWORD le = GetLastError();
log_error( LOG_ERROR, "read_MBR(): CreateFile failed, errCode = %u\n", (unsigned)le );
return;
}
DWORD dwRead = 0;
if( ReadFile( hFile, outbuffer, 512, &dwRead, NULL ) == 0 )
{
DWORD le = GetLastError();
log_error( LOG_ERROR, "read_MBR(): ReadFile failed, errCode = %u\n", (unsigned)le );
}
CloseHandle( hFile );
}
void getHDDInfo( char *volumeSN, char *hwSN, char *fsName )
{
char szVolumeName[256] = {0};
char szFSName[256] = {0};
unsigned long dwVolumeSN = 0, dwMaxComponentLen = 0, dwFSFlags = 0;
if( !GetVolumeInformationA( "C:\\", szVolumeName, 256, &dwVolumeSN,
&dwMaxComponentLen, &dwFSFlags, szFSName, 256 ) ) return;
unsigned char MBR[512];
memset( MBR, 0, sizeof(MBR) );
read_MBR( MBR );
partial_boot_sector_info pbsi[max_pbsi] =
{
{"FAT32", 0x52, 0x43},
{"FAT", 0x36, 0x27},
{"NTFS", 0x03, 0x48}
};
// try to search for a valid boot sector
int i = 0;
for( i=0; i<max_pbsi; i++)
{
//char to_cmp[12];
//strncpy( to_cmp, (const char *)(MBR + pbsi[i].FsOffs), 3 );
//to_cmp[3] = 0;
//printf( "Cmp %d: [%s]==[%s]...\n", i, pbsi[i].Fs, to_cmp );
if( strncmp( pbsi[i].Fs, (const char *)(MBR + pbsi[i].FsOffs), strlen( pbsi[i].Fs ) ) == 0 )
{
// we found a valid signature
//printf( "found FS: %s; index %d\n", pbsi[i].Fs, i );
break;
}
}
if( i >= max_pbsi )
{
log_error( LOG_ERROR, "ERROR: Cannot get serial number of this file system!\n" );
return;
}
DWORD dwHWSN = 0;
memcpy( (void *)(&dwHWSN), (const void *)(MBR + pbsi[i].SerialOffs), sizeof(dwHWSN) );
// out data
sprintf( volumeSN, "%08X", dwVolumeSN );
sprintf( hwSN, "%08X", dwHWSN );
strcpy( fsName, szFSName );
}
void getBIOSInfo( char *out_ver )
{
out_ver[0] = 0;
HKEY hKey = NULL;
char systemBIOSdate[256];
char systemBIOSversion[1024];
//char out_ver[1024] = {0};
memset( systemBIOSdate, 0, sizeof(systemBIOSdate) );
memset( systemBIOSversion, 0, sizeof(systemBIOSversion) );
if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System", 0, KEY_READ, &hKey ) == 0 )
{
DWORD dwType = REG_SZ;
DWORD dwCbData = sizeof(systemBIOSdate);
// bios date
if( RegQueryValueExA( hKey, "SystemBiosDate", NULL, &dwType, (LPBYTE)systemBIOSdate, &dwCbData ) == 0 )
{
strcat( out_ver, systemBIOSdate );
strcat( out_ver, "; " );
} else log_error( LOG_ERROR, "RegQueryValueExA(): error!\n" );
// bios version
dwType = REG_MULTI_SZ;
dwCbData = sizeof(systemBIOSversion);
if( RegQueryValueExA( hKey, "SystemBiosVersion", NULL, &dwType, (LPBYTE)systemBIOSversion, &dwCbData ) == 0 )
{
strcat( out_ver, systemBIOSversion );
char *pstr = systemBIOSversion + strlen(systemBIOSversion) + 1;
if( *pstr )
{
strcat( out_ver, "; " );
strcat( out_ver, pstr );
}
} else log_error( LOG_ERROR, "RegQueryValueExA(): error!\n" );
RegCloseKey( hKey );
}
else log_error( LOG_ERROR, "RegOpenKeyExA(): error!\n" );
}
void getOSInfo( char *os_info )
{
OSVERSIONINFOEXA os;
memset( &os, 0, sizeof(os) );
os.dwOSVersionInfoSize = sizeof(os);
if( GetVersionExA( (OSVERSIONINFOA *)&os ) )
{
sprintf( os_info, "%d.%d.%d sp %d.%d",
os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber,
(int)os.wServicePackMajor, (int)os.wServicePackMinor );
}
else log_error( LOG_ERROR, "GetVersionExA(): error!\n" );
}
void getCPUInfo( char *cpu )
{
cpu[0] = 0;
HKEY hKey = NULL;
char str[512] = {0};
if( RegOpenKeyExA( HKEY_LOCAL_MACHINE, "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey ) == 0 )
{
DWORD dwType = REG_SZ;
DWORD dwCbData = sizeof(str);
// vendor id
if( RegQueryValueExA( hKey, "VendorIdentifier", NULL, &dwType, (LPBYTE)str, &dwCbData ) == 0 )
{
strcat( cpu, str );
strcat( cpu, " " );
} else log_error( LOG_ERROR, "RegQueryValueExA(): error!\n" );
// name
dwType = REG_SZ;
dwCbData = sizeof(str);
if( RegQueryValueExA( hKey, "ProcessorNameString", NULL, &dwType, (LPBYTE)str, &dwCbData ) == 0 )
{
strcat( cpu, str );
} else log_error( LOG_ERROR, "RegQueryValueExA(): error!\n" );
// id
dwType = REG_SZ;
dwCbData = sizeof(str);
if( RegQueryValueExA( hKey, "Identifier", NULL, &dwType, (LPBYTE)str, &dwCbData ) == 0 )
{
strcat( cpu, str );
} else log_error( LOG_ERROR, "RegQueryValueExA(): error!\n" );
RegCloseKey( hKey );
}
else log_error( LOG_ERROR, "RegOpenKeyExA(): error!\n" );
}
int calcHWID( char *out )
{
char globalIDString[4096] = {0};
char based[4096] = {0};
char volumeSN[256] = {0}, hwSN[256] = {0}, fsName[256] = {0};
char biosInfo[1024] = {0};
char os_info[1024] = {0};
char cpu_info[1024] = {0};
getHDDInfo( volumeSN, hwSN, fsName );
getBIOSInfo( biosInfo );
getOSInfo( os_info );
getCPUInfo( cpu_info );
sprintf( globalIDString, "%s|%s|%s|%s|%s|%s", volumeSN, hwSN, fsName, biosInfo, os_info, cpu_info );
base64_encode_string( globalIDString, strlen(globalIDString), based );
strcpy( out, based );
return 1;
}
// Bunny
/*static const char g_hardcoded_HWID[] =
"RDBDQTk0NkR8RDBDQTk0NkR8TlRGU3wwNy8yMC8wNzsg////////IC0gNzAwMDcyMDsgQklPUyBEYXRl"
"OiAwNy8yMC8wNyAxMToyMjo1OCBWZXI6IDA4LjAwLjEwfDUuMS4yNjAwIHNwIDMuMHxHZW51aW5lSW50"
"ZWwgICAgICAgICAgICAgICBJbnRlbChSKSBQZW50aXVtKFIpIEQgQ1BVIDMuMDBHSHp4ODYgRmFtaWx5"
"IDE1IE1vZGVsIDYgU3RlcHBpbmcgMg==";*/
// me
/*static const char g_hardcoded_HWID[] =
"MDRCNDhEM0V8MDRCNDhEM0V8TlRGU3wwNi8yOS8wOTsgMDYyOTA5IC0gMjAwOTA2Mjk7IEJJT1MgRGF0"
"ZTogMDYvMjkvMDkgMjA6Mjc6MjkgVmVyOiAwOC4wMC4xNXw1LjEuMjYwMCBzcCAzLjB8QXV0aGVudGlj"
"QU1EIEFNRCBBdGhsb24odG0pIElJIFgyIDI0MCBQcm9jZXNzb3J4ODYgRmFtaWx5IDE2IE1vZGVsIDYg"
"U3RlcHBpbmcgMg==";*/
// Disilon
static const char g_hardcoded_HWID[] =
"MDQzNjVBNTJ8MDQzNjVBNTJ8TlRGU3wwMi8xOS8wOTsgQV9NX0lfIC0gMjAwMDkxOTsgQklPUyBEYXRl"
"OiAwMi8xOS8wOSAxNzo1NzozNCBWZXI6IDA4LjAwLjEyfDUuMS4yNjAwIHNwIDIuMHxHZW51aW5lSW50"
"ZWwgSW50ZWwoUikgQ29yZShUTSkyIER1byBDUFUgICAgIEU4NDAwICBAIDMuMDBHSHp4ODYgRmFtaWx5"
"IDYgTW9kZWwgMjMgU3RlcHBpbmcgNg==";
bool verifyHWID()
{
char hwid[4096] = {0};
memset( hwid, 0, sizeof(hwid) );
calcHWID( hwid );
if( strcmp( hwid, g_hardcoded_HWID ) == 0 ) return true;
log_error( LOG_ERROR, "failed to verify HWID!\n" );
return false;
}
bool verifyTimeLimit()
{
SYSTEMTIME st;
GetLocalTime( &st );
if( st.wDay >= 30 || st.wMonth >= 10 || st.wYear >= 2010 )
{
log_error( LOG_ERROR, "Usage time limit exceeded [ hi, Dis? :) ]\n" );
return false;
}
return true;
}
#endif

7
l2ooghelper/HWID.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef H_HWID
#define H_HWID
bool verifyHWID();
bool verifyTimeLimit();
#endif

427
l2ooghelper/IL2Client.cpp Normal file
View File

@@ -0,0 +1,427 @@
#include "stdafx.h"
#include "logger.h"
#include "IL2Client.h"
#include "L2Client.h"
IL2Client::IL2Client( void *pvL2Client )
{
m_pcl = pvL2Client;
m_lastNPCHTML = NULL;
m_lastNPCHTMLoid = 0;
}
IL2Client::~IL2Client()
{
m_pcl = NULL;
if( m_lastNPCHTML )
{
free( m_lastNPCHTML );
m_lastNPCHTML = NULL;
}
m_lastNPCHTMLoid = 0;
}
BotConfig *IL2Client::get_BotConfig()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->botcfg);
}
bool IL2Client::isBotCombatEnabled() const
{
L2Client *cl = (L2Client *)m_pcl;
if( cl->bot_combat_enabled ) return true;
return false;
}
void IL2Client::botCombatEnable( bool bEnable )
{
L2Client *cl = (L2Client *)m_pcl;
cl->bottingCombatEnable( bEnable );
}
int IL2Client::is_IN_GAME()
{
L2Client *cl = (L2Client *)m_pcl;
return (cl->getState() == L2Client::STATE_IN_GAME ? 1 : 0);
}
// user info
UserInfo *IL2Client::get_UserInfo()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->usr);
}
UserStorageMaxCount *IL2Client::get_StorageMaxCount()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->storageMaxCount);
}
UserInventory *IL2Client::get_Inventory()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->inv);
}
UserSkills *IL2Client::get_Skills()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->skills);
}
UserEtcStatus *IL2Client::get_EtcStatus()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->etcStatus);
}
UserBuffs *IL2Client::get_Buffs()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->buffs);
}
UserParty *IL2Client::get_Party()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->party);
}
// world state
WorldObjectTree *IL2Client::get_WorldObjectTree()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->world_tree);
}
CharArray *IL2Client::get_WorldChars()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->world_chars);
}
NpcArray *IL2Client::get_WorldNpcs()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->world_npcs);
}
GIArray *IL2Client::get_WorldItems()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->world_ground_items);
}
ClanList *IL2Client::get_WorldClans()
{
L2Client *cl = (L2Client *)m_pcl;
return &(cl->world_clans);
}
void IL2Client::game_Party_Accept( bool bAccept )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestAnswerJoinParty( bAccept ? 1 : 0 );
}
void IL2Client::game_Party_InvitePlayer( const wchar_t *playerName, unsigned int partyLoot )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestJoinParty( playerName, partyLoot );
}
void IL2Client::game_Party_Leave()
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestWithdrawalParty();
}
void IL2Client::game_Party_KickPlayer( const wchar_t *playerName )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestOustPartyMember( playerName );
}
void IL2Client::game_Party_ChangeLeader( const wchar_t *playerName )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestChangePartyLeader( playerName );
}
// chat
void IL2Client::game_Say( unsigned int channel, const wchar_t *text )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_Say2( channel, text, NULL );
}
void IL2Client::game_SayPm( const wchar_t *text, const wchar_t *to )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_Say2( L2_CHAT_MESSAGE::TELL, text, to );
}
void IL2Client::game_SendBypass( const wchar_t *bypass )
{
if( !bypass ) return;
L2Client *cl = (L2Client *)m_pcl;
if( wcsstr( bypass, L"bypass -h " ) )
{
cl->send_RequestBypassToServer( bypass + 10 /*wcslen( L"bypass -h " )*/ );
}
else if( wcsstr( bypass, L"link " ) )
{
cl->send_RequestLinkHtml( bypass + 5 /*wcslen( L"link " )*/ );
}
else
{
log_error( LOG_WARNING, "IL2Client::game_SendBypass(): string must start with \"bypass -h \"!\n" );
}
}
// move
void IL2Client::game_MoveBackwardToLocation( int xDst, int yDst, int zDst )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_MoveBackwardToLocation( xDst, yDst, zDst );
}
void IL2Client::game_MoveToDelta( int dx, int dy, int dz )
{
L2Client *cl = (L2Client *)m_pcl;
cl->game_MoveToDelta( dx, dy, dz );
}
void IL2Client::game_SitStand()
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestActionUse( 0 ); // 0 - sit/stand
}
void IL2Client::game_RunWalk()
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestActionUse( 1 ); // 1 - run/walk
}
// use skill, item
void IL2Client::game_SkillUse( unsigned int skillID, unsigned int ctrlPressed, unsigned char shiftPressed )
{
L2Client *cl = (L2Client *)m_pcl;
UserSkill skill;
cl->skills.getSkillInfoBySkillId( skillID, &skill );
if( skill.level > 0 ) cl->send_RequestMagicSkillUse( skillID, ctrlPressed, shiftPressed );
}
int IL2Client::game_getSkillLevel( unsigned int skillID ) // 0 if no such skill
{
L2Client *cl = (L2Client *)m_pcl;
UserSkill skill;
cl->skills.getSkillInfoBySkillId( skillID, &skill );
return skill.level;
}
void IL2Client::game_UseItemByItemId( unsigned int itemID )
{
L2Client *cl = (L2Client *)m_pcl;
UserInventoryItem it;
cl->inv.getItemInfoByItemId( itemID, &it );
if( it.objectID > 0 && it.count > 0 )
cl->send_UseItem( it.objectID );
}
void IL2Client::game_UseItemByObjectId( unsigned int objectID )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_UseItem( objectID );
}
unsigned long long int IL2Client::game_getItemCount( unsigned int itemID ) // 0 if no such item in inv
{
L2Client *cl = (L2Client *)m_pcl;
UserInventoryItem it;
cl->inv.getItemInfoByItemId( itemID, &it );
return it.count;
}
void IL2Client::game_DestroyItem( unsigned int objectID, long long int count )
{
L2Client *cl = (L2Client *)m_pcl;
UserInventoryItem it;
cl->inv.getItemInfoByObjectId( objectID, &it );
if( it.count >= (unsigned int)count ) cl->send_RequestDestroyItem( objectID, count );
}
void IL2Client::game_DropItem( unsigned int objectID, long long int count, int x, int y, int z )
{
L2Client *cl = (L2Client *)m_pcl;
UserInventoryItem it;
cl->inv.getItemInfoByObjectId( objectID, &it );
if( it.count >= (unsigned int)count ) cl->send_RequestDropItem( objectID, count, x, y, z );
}
void IL2Client::game_CrystallizeItem( unsigned int objectID, long long int count )
{
L2Client *cl = (L2Client *)m_pcl;
UserInventoryItem it;
cl->inv.getItemInfoByObjectId( objectID, &it );
if( it.count >= (unsigned int)count ) cl->send_RequestCrystallizeItem( objectID, count );
}
void IL2Client::game_GiveItemToPet( unsigned int objectID, long long int count )
{
L2Client *cl = (L2Client *)m_pcl;
UserInventoryItem it;
cl->inv.getItemInfoByObjectId( objectID, &it );
if( it.count >= (unsigned int)count ) cl->send_RequestGiveItemToPet( objectID, count );
}
// attack, target
void IL2Client::game_Action( unsigned int objectID )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_Action( objectID );
}
void IL2Client::game_TargetByName( const wchar_t *name )
{
//L2Client *cl = (L2Client *)m_pcl;
UserInfo *usr = get_UserInfo();
CharArray *ca = get_WorldChars();
NpcArray *na = get_WorldNpcs();
unsigned int nPassed = 0, i = 0, count = ca->GetCount();
unsigned int objectID = 0;
if( _wcsicmp( name, usr->charName ) == 0 )
{
objectID = usr->objectID;
}
if( objectID == 0 )
{
// try chars
count = ca->GetCount();
nPassed = 0;
if( count > 0 )
{
ca->Lock();
for( i=0; i<CharArray::CHARARRAY_MAX_CHARS; i++ )
{
if( ca->chars_array[i]->isUnused() ) continue;
nPassed++;
if( _wcsicmp( name, ca->chars_array[i]->charName ) == 0 )
{
objectID = ca->chars_array[i]->objectID;
break;
}
if( nPassed >= count ) break;
}
ca->Unlock();
}
}
if( objectID == 0 )
{
// try NPCs
count = na->getCount();
nPassed = 0;
if( count > 0 )
{
na->Lock();
for( i=0; i<NpcArray::NPCA_MAX_NPCS; i++ )
{
if( na->npcs_array[i]->isUnused() ) continue;
nPassed++;
if( _wcsicmp( name, na->npcs_array[i]->charName ) == 0 )
{
objectID = na->npcs_array[i]->objectID;
break;
}
if( nPassed >= count ) break;
}
na->Unlock();
}
}
if( objectID == 0 ) return;
game_Action( objectID );
}
void IL2Client::game_TargetCancel()
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestTargetCanceld();
}
void IL2Client::game_Attack( unsigned int objectID )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_AttackRequest( objectID );
}
void IL2Client::game_autoSoulshot( unsigned int itemID, bool bEnable )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestAutoSoulshot( itemID, bEnable );
}
void IL2Client::game_buffCancel( unsigned int skillID )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_RequestDispel( skillID );
}
void IL2Client::game_sendPacketHex( const char *szHexStr )
{
L2Client *cl = (L2Client *)m_pcl;
cl->send_hackPacketHex( szHexStr );
}
int IL2Client::get_MapScale()
{
L2Client *cl = (L2Client *)m_pcl;
return cl->getScaleSliderPos();
}
void IL2Client::getMapShowParams( st_MapShowParams *st )
{
L2Client *cl = (L2Client *)m_pcl;
cl->getMapShowParams( st );
}
void IL2Client::set_last_NPC_HTML( const wchar_t *html, unsigned int objectID )
{
if( !html ) return;
if( html[0] == 0 ) return;
size_t memsize = wcslen( html ) * 2 + 2;
if( this->m_lastNPCHTML ) free( this->m_lastNPCHTML );
this->m_lastNPCHTML = NULL;
this->m_lastNPCHTML = (wchar_t *)malloc( memsize );
if( !this->m_lastNPCHTML ) return;
memset( this->m_lastNPCHTML, 0, memsize );
wcscpy( this->m_lastNPCHTML, html );
this->m_lastNPCHTMLoid = objectID;
if( objectID == 0 )
{
log_error( LOG_WARNING, "SE: set_last_NPC_HTML(): objectID is 0!\n" );
return;
}
}
wchar_t *IL2Client::get_last_NPC_HTML( unsigned int *pObjectID )
{
if( pObjectID ) (*pObjectID) = this->m_lastNPCHTMLoid;
return this->m_lastNPCHTML;
}
void IL2Client::clear_last_NPC_HTML()
{
m_lastNPCHTMLoid = 0;
if( m_lastNPCHTML )
{
free( m_lastNPCHTML );
m_lastNPCHTML = NULL;
}
}

108
l2ooghelper/IL2Client.h Normal file
View File

@@ -0,0 +1,108 @@
#ifndef IL2CLIENT
#define IL2CLIENT
// bot settings
#include "BotConfig.h"
// user state
#include "UserInfo_c.h"
#include "UserStorageMaxCount.h"
#include "UserInventory.h"
#include "UserSkills.h"
#include "UserEtcStatus.h"
#include "UserBuffs.h"
#include "UserParty.h"
// world state
#include "WorldObjectTree.h"
#include "CharArray.h"
#include "NpcArray.h"
#include "GIArray.h"
#include "ClanList.h"
// l2client window
#include "MapShowParams.h"
class IL2Client
{
public:
IL2Client( void *pvL2Client );
~IL2Client();
protected: // default constructor, copy constructor and operator= are closed
IL2Client() {}
IL2Client( const IL2Client& other ) { UNREFERENCED_PARAMETER(other); }
IL2Client& operator=( const IL2Client& other ) { UNREFERENCED_PARAMETER(other); }
public:
// get-fucntions
// botting
BotConfig *get_BotConfig();
bool isBotCombatEnabled() const;
void botCombatEnable( bool bEnable = true );
// state
int is_IN_GAME();
// user info
UserInfo *get_UserInfo();
UserStorageMaxCount *get_StorageMaxCount();
UserInventory *get_Inventory();
UserSkills *get_Skills();
UserEtcStatus *get_EtcStatus();
UserBuffs *get_Buffs();
UserParty *get_Party();
// world state
WorldObjectTree *get_WorldObjectTree();
CharArray *get_WorldChars();
NpcArray *get_WorldNpcs();
GIArray *get_WorldItems();
ClanList *get_WorldClans();
public:
// game actions
// party
void game_Party_Accept( bool bAccept );
void game_Party_InvitePlayer( const wchar_t *playerName, unsigned int partyLoot );
void game_Party_Leave();
void game_Party_KickPlayer( const wchar_t *playerName );
void game_Party_ChangeLeader( const wchar_t *playerName );
// chat
void game_Say( unsigned int channel, const wchar_t *text );
void game_SayPm( const wchar_t *text, const wchar_t *to );
void game_SendBypass( const wchar_t *bypass );
// move
void game_MoveBackwardToLocation( int xDst, int yDst, int zDst = 0x7FFFFFFF );
void game_MoveToDelta( int dx, int dy, int dz = 0 );
void game_SitStand();
void game_RunWalk();
// use skill, item
void game_SkillUse( unsigned int skillID, unsigned int ctrlPressed = 0, unsigned char shiftPressed = 0 );
int game_getSkillLevel( unsigned int skillID ); // 0 if no such skill
void game_UseItemByObjectId( unsigned int objectID );
void game_UseItemByItemId( unsigned int itemID );
unsigned long long int game_getItemCount( unsigned int itemID ); // 0 if no such item in inv
void game_DestroyItem( unsigned int objectID, long long int count = 1 );
void game_DropItem( unsigned int objectID, long long int count = 1, int x = 0, int y = 0, int z = 0 );
void game_CrystallizeItem( unsigned int objectID, long long int count = 1 );
void game_GiveItemToPet( unsigned int objectID, long long int count = 1 );
// attack, target
void game_Action( unsigned int objectID );
void game_TargetByName( const wchar_t *name );
void game_TargetCancel();
void game_Attack( unsigned int objectID = 0 );
void game_autoSoulshot( unsigned int itemID, bool bEnable = true );
// buff
void game_buffCancel( unsigned int skillID );
// packet hack
void game_sendPacketHex( const char *szHexStr );
public:
// for user interfaces that do not directly include L2Client
int get_MapScale();
void getMapShowParams( st_MapShowParams *st );
public: // talking to NPC support
void set_last_NPC_HTML( const wchar_t *html, unsigned int objectID );
wchar_t *get_last_NPC_HTML( unsigned int *pObjectID );
void clear_last_NPC_HTML();
protected:
void *m_pcl;
wchar_t *m_lastNPCHTML;
unsigned int m_lastNPCHTMLoid;
};
#endif

View File

@@ -0,0 +1,78 @@
#include "stdafx.h"
#include "InputStringDlg.h"
#include "Resource.h"
extern HINSTANCE g_hInst;
InputStringDlg::InputStringDlg()
{
title[0] = 0;
question[0] = 0;
text[0] = 0;
}
InputStringDlg::InputStringDlg( LPCTSTR ptitle, LPCTSTR pquestion, LPCTSTR ptext /*= NULL*/ )
{
title[0] = 0;
question[0] = 0;
text[0] = 0;
_tcscpy( title, ptitle );
_tcscpy( question, pquestion );
if( ptext ) _tcscpy( text, ptext );
}
InputStringDlg::~InputStringDlg()
{
title[0] = 0;
question[0] = 0;
text[0] = 0;
}
bool InputStringDlg::run( HWND hWndParent )
{
INT_PTR ret = DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_INPUTSTRING), hWndParent, DlgProc,
(LPARAM)this );
if( ret == IDCANCEL ) return false;
return true;
}
INT_PTR CALLBACK InputStringDlg::DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
InputStringDlg *pcls = (InputStringDlg *)lParam;
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)pcls );
SetWindowText( hDlg, pcls->title );
SetDlgItemText( hDlg, IDC_QUESTION, pcls->question );
SetDlgItemText( hDlg, IDC_EDIT1, pcls->text );
} break;
case WM_COMMAND:
{
InputStringDlg *pcls = (InputStringDlg *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
switch( LOWORD( wParam ) )
{
case IDCANCEL:
{
pcls->text[0] = 0;
EndDialog( hDlg, IDCANCEL );
} break;
case IDOK:
{
GetDlgItemText( hDlg, IDC_EDIT1, pcls->text, 255 );
EndDialog( hDlg, IDOK );
} break;
default: return FALSE; break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}
/*public:
TCHAR title[256];
TCHAR question[256];
TCHAR text[256];
};*/

View File

@@ -0,0 +1,19 @@
#ifndef H_DLG_INPUTSTRING
#define H_DLG_INPUTSTRING
class InputStringDlg
{
public:
InputStringDlg();
InputStringDlg( LPCTSTR ptitle, LPCTSTR pquestion, LPCTSTR ptext = NULL );
~InputStringDlg();
bool run( HWND hWndParent );
public:
TCHAR title[256];
TCHAR question[256];
TCHAR text[256];
protected:
static INT_PTR CALLBACK DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
};
#endif

1553
l2ooghelper/L2Client.cpp Normal file

File diff suppressed because it is too large Load Diff

448
l2ooghelper/L2Client.h Normal file
View File

@@ -0,0 +1,448 @@
#ifndef H_L2CLIENT
#define H_L2CLIENT
#include "Account.h"
#include "BotConfig.h"
#include "MessageBoxTimeout.h"
#include "MapShowParams.h"
// user state
#include "UserInfo_c.h"
#include "UserStorageMaxCount.h"
#include "UserInventory.h"
#include "UserSkills.h"
#include "UserEtcStatus.h"
#include "UserBuffs.h"
#include "UserParty.h"
// world state
#include "WorldObjectTree.h"
#include "CharArray.h"
#include "NpcArray.h"
#include "GIArray.h"
#include "ClanList.h"
#include "BuySellList.h"
// L2Client interface
#include "IL2Client.h"
// scripting
#include "ScriptEngine.h"
// non-modal persistent dialogs
#include "TradeP2PDlg.h"
#include "NpcHtmlMessageDlg.h"
// bot interprocess communications
#include "bot_interaction/BotIPC.h"
// AI
#include "L2ClientAI.h"
#define THREAD_SIGNAL_LOGOUT 1
#define THREAD_SIGNAL_DISCONNECT 2
#define THREAD_SIGNAL_FORCE_DISCONNECT 3
#define WMMY_UI_UPDATE (WM_USER+123) // wParam - update code, lParam - ext param
#define WMMY_UI_MESSAGEBOXTIMEOUTREPLY (WM_USER+124) // wParam: 0-no,1-yes; lParam - question type
#define WMMY_UI_BUYSELLDLGREPLY (WM_USER+126) // wParam: type (0-buylist, 1-selllist)
// lParam: resulting TradeItemsList to buy/sell (may be NULL!) must be freed
#define WMMY_UI_PRIVATESTOREDLGREPLY (WM_USER+127) // wParam: type (0-buy, 1-sell, 2-craft, 3-commoncraft)
// lParam: resulting TradeItemsList to buy/sell (may be NULL!) must be freed
class L2Client
{
public:
typedef enum eSTATE
{
STATE_OFFLINE = 0,
STATE_CONNECTING_LOGIN,
STATE_CONNECTED_LOGIN,
STATE_AUTHED_LOGIN,
STATE_CONNECTING_GAME,
STATE_CONNECTED_GAME,
STATE_AUTHED_GAME,
STATE_IN_GAME
} STATE;
static const int NUM_CHAT_TABS = 10;
typedef enum eCHAT_TAB_ID
{
CHAT_SYS = 0,
CHAT_DMG,
CHAT_ALL,
CHAT_TRADE,
CHAT_SHOUT,
CHAT_PARTY,
CHAT_CLAN,
CHAT_ALLY,
CHAT_HERO,
CHAT_WHISPER,
CHAT_LAST = CHAT_WHISPER
} CHAT_TAB_ID;
static const int NUM_INFO_TABS = 8;
typedef enum eINFO_TAB_ID
{
INFO_USER = 0,
INFO_INV,
INFO_SKILLS,
INFO_BUFFS,
INFO_PARTY,
INFO_MAP,
INFO_OTHER,
INFO_STATS
} INFO_TAB_ID;
typedef enum eUIUPDATECODE
{
UPDATE_USER = 1,
UPDATE_INV,
UPDATE_SKILLS,
UPDATE_SKILL_COOLTIME,
UPDATE_BUFFS,
UPDATE_BUFF_DURATION,
UPDATE_MAP_PLAYERS,
UPDATE_MAP_MOBS,
UPDATE_MAP_NPCS,
UPDATE_MAP_ITEMS,
UPDATE_PARTY,
UPDATE_PARTY_BUFFSDURATION,
UPDATE_USER_TARGET,
UPDATE_USER_CASTING
} UIUPDATECODE;
public:
L2Client();
~L2Client();
public:
void clear();
void clearUserAndWorldState();
public:
void setUnused() { bUsed = false; }
void setUsed() { bUsed = true; }
bool isUsed() const { if( bUsed ) return true; return false; }
bool isUnused() const { if( bUsed ) return false; return true; }
public:
void setAccount( const class Account *acc ) { if( acc ) account = (*acc); }
Account getAccount() const { return account; }
BotConfig getConfig() { return botcfg; }
void setBotConfig( const BotConfig &other ) { botcfg = other; }
public:
HWND createWindow( HWND hWndParent );
HWND getWindow() const { return hWnd; }
void showWindow();
void hideWindow();
void updateWindow();
void setTabId( int tabID ) { tab_id = tabID; }
int getTabId() const { return tab_id; }
void closeTab();
bool isThreadRunning() const { return (hThread != NULL); }
void postUpdateUI( UIUPDATECODE updateCode, LPARAM lParam = 0 );
int getScaleSliderPos();
void postUpdateMap();
void worldTick();
void getMapShowParams( st_MapShowParams *p );
void loadDefaultBotConfig();
void ensureRemoveSelfFromBotIPC();
public:
void bottingEnable( bool bEnable = true );
void bottingCombatEnable( bool bEnable = true );
L2_VERSION getL2Version() const;
public:
void addChatToTab( CHAT_TAB_ID chatTabId, wchar_t *message, wchar_t *from = NULL );
void addChatToTabFormat( CHAT_TAB_ID chatTabId, wchar_t *_Format, ... );
void addChatAnnouncement( wchar_t *message );
// do not directly call these
void addChatStringToTab_internal( CHAT_TAB_ID chatTabId, CHAT_TAB_ID origTabId, wchar_t *message, bool scroll = true );
static bool addChatStringToTab_internal_shouldAlsoAddToAll( CHAT_TAB_ID chatTabId );
static COLORREF addChatStringToTab_internal_getChatTabColor( CHAT_TAB_ID chatTabId );
protected:
void onButtonSystem();
void onButtonConfig();
void onButtonScript();
void onButtonActionTarget();
void onButtonAttackTarget();
void onButtonCancelTarget();
void onButtonSitStand();
void onButtonRunWalk();
void onButtonSay();
void onButtonActions();
bool handleSayCommand( LPWSTR text );
void onButtonDebug();
void OnUiUpdateUser( HWND hDlg );
void OnUiUpdateInv( HWND hDlg );
void OnUiUpdateSkills( HWND hDlg );
void OnUiUpdateBuffs( HWND hDlg );
void OnUiUpdateMapTab( HWND hDlg, int tabNo );
void OnUiUpdateParty( HWND hDlg );
void OnUiUpdateTarget( HWND hDlg );
void OnUiUpdateCasting( HWND hDlg );
void OnUiUpdateSkillCoolTimes();
void OnUiUpdateBuffsDuration();
void OnUiUpdatePartyBuffsDuration();
public:
void setState( L2Client::STATE newState );
L2Client::STATE getState() const { return state; }
public:
IL2Client *getInterface();
friend class IL2Client;
protected:
static INT_PTR CALLBACK L2ClientDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static void OnInitDialog( HWND hDlg, LPARAM lParam );
static void OnDestroy( HWND hDlg );
static void OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnNotify( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnPaint( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnMyUiUpdate( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnMyMessageBoxTimeoutReply( HWND hDlg, WPARAM wParam, LPARAM lParam );
//static void OnMyNpcHtmlMessageReply( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnMyBuySellDlgReply( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnMyPrivateStoreManageDlgReply( HWND hDlg, WPARAM wParam, LPARAM lParam );
public:
void handle_AskJoinParty( const wchar_t *requester, unsigned int itemDistribution );
//void handle_AskJoinPledge( const wchar_t *requester );
//void handle_AksJoinAlly( const wchar_t *requester );
void handle_BuyList( TradeItemsList *list );
void handle_SellList( TradeItemsList *list );
void handle_PrivateStoreManageListSell( TradeItemsList *list1, TradeItemsList *list2 );
void handle_PrivateStoreManageListBuy( TradeItemsList *list1, TradeItemsList *list2 );
void handle_RecipeShopManageList( TradeItemsList *list1, TradeItemsList *list2 );
void handle_PrivateStoreBuyList( TradeItemsList *list );
void handle_PrivateStoreSellList( TradeItemsList *list );
void handle_ConfirmDlg( wchar_t *question, unsigned int sm_ID, unsigned int requestId, unsigned int timeLimit, const wchar_t *text );
void game_MoveToDelta( int dx, int dy, int dz = 0 );
void send_Appearing();
void send_RequestGMList();
void send_RequestAnswerJoinParty( unsigned int accepted );
void send_RequestJoinParty( const wchar_t *target, unsigned int itemDistribution = 0 );
void send_RequestWithdrawalParty();
void send_RequestOustPartyMember( const wchar_t *playerName );
void send_RequestChangePartyLeader( const wchar_t *playerName );
void send_Say2( unsigned int chat_type, const wchar_t *text, const wchar_t *to );
void send_MoveBackwardToLocation( int xDst, int yDst, int zDst = 0x7FFFFFFF );
void send_RequestMagicSkillUse( unsigned int skillID, unsigned int ctrlPressed = 0, unsigned char shiftPressed = 0 );
void send_Action( unsigned int objectID, int x = 0, int y = 0, int z = 0, unsigned char useShift = 0 );
void send_RequestTargetCanceld();
void send_AttackRequest( unsigned int objectID = 0, int x = 0, int y = 0, int z = 0, unsigned char useShift = 0 );
void send_RequestUserCommand( unsigned int commandID );
void send_RequestAutoSoulshot( unsigned int itemID, bool enable );
void send_RequestActionUse( unsigned int actionID, unsigned int ctrlPressed = 0, unsigned char shiftPressed = 0 );
void send_UseItem( unsigned int objectID );
void send_RequestDestroyItem( unsigned int objectID, long long int count = 1 );
void send_RequestDropItem( unsigned int objectID, long long int count = 1, int x = 0, int y = 0, int z = 0 );
void send_RequestCrystallizeItem( unsigned int objectID, long long int count = 1 );
void send_RequestGiveItemToPet( unsigned int objectID, long long int count = 1 );
void send_RequestDispel( unsigned int skillID );
void send_RequestBypassToServer( const wchar_t *bypassStr );
void send_RequestLinkHtml( const wchar_t *link );
void send_ValidatePosition();
void send_RequestRestartPoint( unsigned int pointType = 0 );
void send_SendBypassBuildCmd( const wchar_t *cmd );
void send_RequestBuyItem( TradeItemsList *plist );
void send_RequestSellItem( TradeItemsList *plist );
void send_RequestEvaluate();
void send_RequestPrivateStoreQuitSell();
void send_RequestPrivateStoreQuitBuy();
void send_RequestRecipeShopManageQuit();
void send_SetPrivateStoreMsgBuy( const wchar_t *message );
void send_SetPrivateStoreMsgSell( const wchar_t *message );
void send_SetPrivateStoreWholeMsg( const wchar_t *message );
void send_RequestRecipeShopMessageSet( const wchar_t *message );
void send_SetPrivateStoreListSell( TradeItemsList *list );
void send_SetPrivateStoreListBuy( TradeItemsList *list );
void send_RequestRecipeShopListSet( TradeItemsList *list );
void send_RequestPrivateStoreBuy( TradeItemsList *list );
void send_RequestPrivateStoreSell( TradeItemsList *list );
void send_TradeRequest( unsigned int targetObjectId = 0 );
void send_AnswerTradeRequest( bool accept = true );
void send_AddTradeItem( unsigned int tradeID, unsigned int objectID, long long int count );
void send_TradeDone( int bConfirm );
void send_DlgAnswer( unsigned int sm_ID, int answer, unsigned int requestId );
void send_AuthLogin();
void send_Logout();
void send_RequestRestart();
void send_CharacterSelect( int iCharSlot );
void send_RequestGotoLobby();
void send_NewCharacter();
void send_CharacterDelete( int iCharSlot );
void send_CharacterRestore( int iCharSlot );
void send_CharacterCreate( const wchar_t *name, const L2Game_NewCharacterTemplate *tmpl,
int hairStyle, int hairColor, int face, int is_female );
void send_GameGuardReply( unsigned int r1, unsigned int r2, unsigned int r3, unsigned int r4 );
// hack function, do not use!
// input: string consisting of sequence of hex chars, representing packet, starting from packet type
// packet length will be prefixed automatically!
// example: 1F39A400109ACB00003D2BFFFFA9F3FFFF00 - 1F Action packet, without packet len
void send_hackPacketHex( const char *szHexStr );
protected:
void startClient();
void logoutClient();
void disconnectClient( bool force = false );
static void threadNetCleanup( class L2Client *pcls );
static DWORD WINAPI L2ClientThread( LPVOID lpParam );
static bool L2ClientThread_Login( class L2Client *pcls );
static bool L2ClientThread_Game( class L2Client *pcls );
static void L2ClientThread_Game_BotIPC( class L2Client *pcls );
protected: // packet handlers
static void ph_AbnormalStatusUpdate( class L2Client *pcls, L2GamePacket *p );
static void ph_AskJoinParty( class L2Client *pcls, L2GamePacket *p );
static void ph_AuthLoginFail( class L2Client *pcls, L2GamePacket *p );
static void ph_BuyList( class L2Client *pcls, L2GamePacket *p );
static void ph_ChangeMoveType( class L2Client *pcls, L2GamePacket *p );
static void ph_ChangeWaitType( class L2Client *pcls, L2GamePacket *p );
static void ph_CharCreateFail( class L2Client *pcls, L2GamePacket *p );
static void ph_CharCreateSuccess( class L2Client *pcls, L2GamePacket *p );
static void ph_CharDeleteFail( class L2Client *pcls, L2GamePacket *p );
static void ph_CharDeleteSuccess( class L2Client *pcls, L2GamePacket *p );
static void ph_CharInfo( class L2Client *pcls, L2GamePacket *p );
static void ph_CharSelected( class L2Client *pcls, L2GamePacket *p );
static void ph_CharSelectionInfo( class L2Client *pcls, L2GamePacket *p );
static void ph_CreatureSay( class L2Client *pcls, L2GamePacket *p );
static void ph_ConfirmDlg( class L2Client *pcls, L2GamePacket *p );
static void ph_DeleteObject( class L2Client *pcls, L2GamePacket *p );
static void ph_Die( class L2Client *pcls, L2GamePacket *p );
static void ph_DropItem( class L2Client *pcls, L2GamePacket *p );
static void ph_EtcStatusUpdate( class L2Client *pcls, L2GamePacket *p );
static void ph_ExNpcQuestHtmlMessage( class L2Client *pcls, L2GamePacket *p );
static void ph_ExSetPrivateStoreWholeMsg( class L2Client *pcls, L2GamePacket *p );
static void ph_ExStorageMaxCount( class L2Client *pcls, L2GamePacket *p );
static void ph_GameGuardQuery( class L2Client *pcls, L2GamePacket *p );
static void ph_GetItem( class L2Client *pcls, L2GamePacket *p );
static void ph_ItemList( class L2Client *pcls, L2GamePacket *p );
static void ph_InventoryUpdate( class L2Client *pcls, L2GamePacket *p );
static void ph_JoinParty( class L2Client *pcls, L2GamePacket *p );
static void ph_KeyPacket( class L2Client *pcls, L2GamePacket *p );
static void ph_MagicSkillCanceld( class L2Client *pcls, L2GamePacket *p );
static void ph_MagicSkillUse( class L2Client *pcls, L2GamePacket *p );
static void ph_MoveToLocation( class L2Client *pcls, L2GamePacket *p );
static void ph_MoveToPawn( class L2Client *pcls, L2GamePacket *p );
static void ph_NewCharacterSuccess( class L2Client *pcls, L2GamePacket *p );
static void ph_NpcHtmlMessage( class L2Client *pcls, L2GamePacket *p );
static void ph_NpcInfo( class L2Client *pcls, L2GamePacket *p );
static void ph_PartyMemberPosition( class L2Client *pcls, L2GamePacket *p );
static void ph_PartySmallWindowAdd( class L2Client *pcls, L2GamePacket *p );
static void ph_PartySmallWindowAll( class L2Client *pcls, L2GamePacket *p );
static void ph_PartySmallWindowDelete( class L2Client *pcls, L2GamePacket *p );
static void ph_PartySmallWindowDeleteAll( class L2Client *pcls, L2GamePacket *p );
static void ph_PartySmallWindowUpdate( class L2Client *pcls, L2GamePacket *p );
static void ph_PartySpelled( class L2Client *pcls, L2GamePacket *p );
static void ph_PledgeInfo( class L2Client *pcls, L2GamePacket *p );
static void ph_PrivateStoreListBuy( class L2Client *pcls, L2GamePacket *p );
static void ph_PrivateStoreListSell( class L2Client *pcls, L2GamePacket *p );
static void ph_PrivateStoreManageListBuy( class L2Client *pcls, L2GamePacket *p );
static void ph_PrivateStoreManageListSell( class L2Client *pcls, L2GamePacket *p );
static void ph_PrivateStoreMsgBuy( class L2Client *pcls, L2GamePacket *p );
static void ph_PrivateStoreMsgSell( class L2Client *pcls, L2GamePacket *p );
static void ph_RecipeShopManageList( class L2Client *pcls, L2GamePacket *p );
static void ph_RecipeShopMsg( class L2Client *pcls, L2GamePacket *p );
static void ph_Revive( class L2Client *pcls, L2GamePacket *p );
static void ph_SellList( class L2Client *pcls, L2GamePacket *p );
static void ph_SendTradeRequest( class L2Client *pcls, L2GamePacket *p );
static void ph_SetupGauge( class L2Client *pcls, L2GamePacket *p );
static void ph_ShortBuffStatusUpdate( class L2Client *pcls, L2GamePacket *p );
static void ph_SkillCoolTime( class L2Client *pcls, L2GamePacket *p );
static void ph_SkillList( class L2Client *pcls, L2GamePacket *p );
static void ph_SpawnItem( class L2Client *pcls, L2GamePacket *p );
static void ph_SSQInfo( class L2Client *pcls, L2GamePacket *p );
static void ph_StatusUpdate( class L2Client *pcls, L2GamePacket *p );
static void ph_StopMove( class L2Client *pcls, L2GamePacket *p );
static void ph_SystemMessage( class L2Client *pcls, L2GamePacket *p );
static void ph_TargetSelected( class L2Client *pcls, L2GamePacket *p );
static void ph_TargetUnselected( class L2Client *pcls, L2GamePacket *p );
static void ph_TradeDone( class L2Client *pcls, L2GamePacket *p );
static void ph_TradeOtherAdd( class L2Client *pcls, L2GamePacket *p );
static void ph_TradeOwnAdd( class L2Client *pcls, L2GamePacket *p );
static void ph_TradeStart( class L2Client *pcls, L2GamePacket *p );
static void ph_TeleportToLocation( class L2Client *pcls, L2GamePacket *p );
static void ph_UserInfo( class L2Client *pcls, L2GamePacket *p );
static void ph_ValidateLocation( class L2Client *pcls, L2GamePacket *p );
protected: // utils
static void log_packet( L2Client *pcls, bool fromServer, const unsigned char *p, unsigned int plen,
const char *hintStr = NULL, LOG_LEVEL logLevel = LOG_DEBUGDUMP );
bool pack_OpcodeDeObfuscate( unsigned char *bytes, unsigned int len );
bool pack_OpcodeObfuscate( unsigned char *bytes, unsigned int len );
bool pack_OpcodeDeObfuscate( L2GamePacket *p );
bool pack_OpcodeObfuscate( L2GamePacket *p );
// returns number of bytes sent
int sendPacket( L2GamePacket *pack, bool obfuscateAndXOREncode );
protected:
bool bUsed; // true if this account slot is in use
Account account; // account info - login/pass, server ip:port, proto ver, ...
BotConfig botcfg;
int tab_id; // tab number in main window :)
// child windows
HWND hWnd;
HWND hWndTabChat;
HWND hWndTabInfo;
HWND hWndProgressHP;
HWND hWndProgressMP;
HWND hWndProgressCP;
HWND hWndProgressWeight;
HWND hWndProgressTargetHP;
HWND hWndProgressExp;
HWND hWndMap;
HWND hWndSliderMapScale;
HWND hWndProgressCasting;
// map check buttons
st_MapShowParams mapShowParams;
// chat tab windows
int curTabChat;
HWND hWndTabChat_item[NUM_CHAT_TABS];
// info tab windows
int curTabInfo;
HWND hWndTabInfo_item[NUM_INFO_TABS];
// non-modal dialogs
TradeP2PDlg *tradep2pdlg;
NpcHtmlMessageDlg *npcHtmlDlg;
protected:
L2Client::STATE state;
SOCKET sock;
HANDLE hThread;
DWORD dwThreadId;
unsigned char login_sessionKey1[8];
unsigned char login_sessionKey2[8];
int login_selectedGsId;
char login_selectedGsIP[32];
int login_selectedGsPort;
long game_recvTimeoutMsec;
long game_sendTimeoutMsec;
bool game_logoutRequestSent;
bool game_XOR_enabled;
unsigned char game_key_send[16];
unsigned char game_key_recv[16];
unsigned int game_opcodeObfuscatorSeed;
L2PCodeObfuscator *game_pCodeObfuscator;
int threadSignal; // 0 - none, 1 - logout, 2 - disconnect
CRITICAL_SECTION cs_sendPacket;
protected:
//bool bEnableAutoFun;
//bool bEnableAutoCombat;
protected: // user info and state (inventory, skills, buffs, party, ...)
UserInfo usr;
UserStorageMaxCount storageMaxCount;
UserInventory inv;
UserSkills skills;
UserEtcStatus etcStatus;
UserBuffs buffs;
UserParty party;
protected: // world info and state (chars, npcs, mobs, items, clans)
WorldObjectTree world_tree;
CharArray world_chars;
NpcArray world_npcs;
GIArray world_ground_items;
ClanList world_clans;
protected: // scripting
ScriptEngine scripter; // user script VM
ScriptEngine sys_scripter; // internal script VM
char sys_main_ai_script_filename[256]; // internal script filename
int bot_enabled;
int bot_combat_enabled;
protected:
IL2Client *pInterface;
protected:
int botipc_index;
protected:
L2ClientAI *m_ai;
};
#endif

197
l2ooghelper/L2ClientAI.cpp Normal file
View File

@@ -0,0 +1,197 @@
#include "stdafx.h"
#include "Logger.h"
#include "L2ClientAI.h"
AI_INTENTION::AI_INTENTION()
{
m_type = INT_TYPE_NONE;
m_npcdlg_string[0] = 0;
}
AI_INTENTION::AI_INTENTION( const AI_INTENTION& other )
{
m_npcdlg_string[0] = 0;
operator=( other );
}
const AI_INTENTION& AI_INTENTION::operator=( const AI_INTENTION& other )
{
if( this == &other ) return (*this);
m_type = other.m_type;
m_x = other.m_x; m_y = other.m_y; m_z = other.m_z;
m_target_oid = other.m_target_oid;
wcsncpy( m_npcdlg_string, other.m_npcdlg_string, sizeof(m_npcdlg_string)/2 );
return (*this);
}
void AI_INTENTION::set_GOTO( int x, int y, int z )
{
m_type = INT_TYPE_GOTO;
m_x = x; m_y = y; m_z = z;
}
void AI_INTENTION::set_ATTACK( unsigned int target_oid )
{
m_type = INT_TYPE_ATTACK;
m_target_oid = target_oid;
}
void AI_INTENTION::set_NPC_TALK( unsigned int npc_oid, const wchar_t *dlg_str )
{
m_type = INT_TYPE_NPC_TALK;
m_target_oid = npc_oid;
wcsncpy( m_npcdlg_string, dlg_str, 255 ); m_npcdlg_string[255] = 0;
}
AiIntentionQueue::AiIntentionQueue()
{
m_q.clear();
}
AiIntentionQueue::~AiIntentionQueue()
{
m_q.clear();
}
void AiIntentionQueue::pushIntention( AI_INTENTION i )
{
m_q.push_back( i );
}
AI_INTENTION AiIntentionQueue::getIntention()
{
AI_INTENTION i = *m_q.begin();
m_q.pop_front();
return i;
}
bool AiIntentionQueue::hasIntentions() const
{
return m_q.size() > 0;
}
L2ClientAI::L2ClientAI( IL2Client *pinterfaceL2Client )
{
m_cl = pinterfaceL2Client;
m_last_think_time = GetTickCount() - THINK_DELAY - THINK_DELAY;
m_last_follow_time = m_last_think_time;
m_follow_enabled = false;
m_follow_oid = 0;
}
L2ClientAI::~L2ClientAI()
{
}
void L2ClientAI::think()
{
unsigned int t_now = (unsigned int)GetTickCount();
if( t_now - m_last_think_time < THINK_DELAY ) return;
m_last_think_time = t_now;
// check for follow
follow();
// check for intentions
if( !m_int_queue.hasIntentions() )
{
//log_error( LOG_USERAI, "L2ClientAI:think: no intentions" );
return;
}
AI_INTENTION i = m_int_queue.getIntention();
switch( i.getType() )
{
case INT_TYPE_NONE: break;
case INT_TYPE_GOTO: onIntentionGoto( i ); break;
case INT_TYPE_ATTACK: onIntentionAttack( i ); break;
case INT_TYPE_NPC_TALK: onIntentionNpcTalk( i ); break;
}
}
void L2ClientAI::setFollow( bool enable, unsigned int oid )
{
m_follow_enabled = enable;
m_follow_oid = oid;
}
void L2ClientAI::pushIntentionGoto( int x, int y, int z )
{
AI_INTENTION i;
i.set_GOTO( x, y, z );
m_int_queue.pushIntention( i );
}
void L2ClientAI::pushIntentionAttack( unsigned int target_oid )
{
AI_INTENTION i;
i.set_ATTACK( target_oid );
m_int_queue.pushIntention( i );
}
void L2ClientAI::pushIntentionNpcTalk( unsigned int npc_oid, const wchar_t *dlg_str )
{
AI_INTENTION i;
i.set_NPC_TALK( npc_oid, dlg_str );
m_int_queue.pushIntention( i );
}
void L2ClientAI::follow()
{
if( m_follow_enabled == false ) return;
UserInfo *user = m_cl->get_UserInfo();
CharArray *chars = m_cl->get_WorldChars();
int char_idx = chars->FindCharByObjectID( m_follow_oid );
if( char_idx >= 0 )
{
L2Player *target = chars->chars_array[char_idx];
// compare coordinates
int dx = target->x - user->x;
int dy = target->y - user->y;
int dz = target->z - user->z;
if( abs(dx) > 50 || abs(dy) > 50 || abs(dz) > 50 )
{
unsigned int t_now = (unsigned int)GetTickCount();
if( t_now - m_last_follow_time >= 1000 )
{
m_last_follow_time = t_now;
m_cl->game_MoveBackwardToLocation( target->x, target->y, target->z );
log_error( LOG_USERAI, "L2ClientAI:follow: following [%S] to (%d,%d,%d)\n", target->charName, target->x, target->y, target->z );
}
}
}
else // target not found in world
{
setFollow( false, 0 );
log_error( LOG_USERAI, "L2ClientAI:follow: target not found, cancel follow\n" );
}
}
void L2ClientAI::onIntentionGoto( AI_INTENTION& wish )
{
(void)wish;
}
void L2ClientAI::onIntentionAttack( AI_INTENTION& wish )
{
(void)wish;
}
void L2ClientAI::onIntentionNpcTalk( AI_INTENTION& wish )
{
(void)wish;
}

80
l2ooghelper/L2ClientAI.h Normal file
View File

@@ -0,0 +1,80 @@
#pragma once
#include "IL2Client.h"
enum AI_INTENTION_TYPE
{
INT_TYPE_NONE = 0,
INT_TYPE_GOTO,
INT_TYPE_ATTACK,
INT_TYPE_NPC_TALK
};
class AI_INTENTION
{
public:
AI_INTENTION();
AI_INTENTION( const AI_INTENTION& other );
const AI_INTENTION& operator=( const AI_INTENTION& other );
public:
AI_INTENTION_TYPE getType() const { return m_type; }
int getX() const { return m_x; }
int getY() const { return m_y; }
int getZ() const { return m_z; }
unsigned int getTargetOid() const { return m_target_oid; }
public:
void set_NONE() { m_type = INT_TYPE_NONE; }
void set_GOTO( int x, int y, int z );
void set_ATTACK( unsigned int target_oid );
void set_NPC_TALK( unsigned int npc_oid, const wchar_t *dlg_str );
protected:
AI_INTENTION_TYPE m_type;
int m_x;
int m_y;
int m_z;
unsigned int m_target_oid;
wchar_t m_npcdlg_string[256];
};
class AiIntentionQueue
{
public:
AiIntentionQueue();
~AiIntentionQueue();
public:
void pushIntention( AI_INTENTION i );
AI_INTENTION getIntention();
bool hasIntentions() const;
protected:
std::list<AI_INTENTION> m_q;
};
class L2ClientAI
{
public:
static const int THINK_DELAY = 500; // ms
public:
L2ClientAI( IL2Client *pinterfaceL2Client );
~L2ClientAI();
public:
void think();
void setFollow( bool enable, unsigned int oid );
public:
void pushIntentionGoto( int x, int y, int z );
void pushIntentionAttack( unsigned int target_oid );
void pushIntentionNpcTalk( unsigned int npc_oid, const wchar_t *dlg_str );
protected:
void follow();
void onIntentionGoto( AI_INTENTION& wish );
void onIntentionAttack( AI_INTENTION& wish );
void onIntentionNpcTalk( AI_INTENTION& wish );
protected:
IL2Client *m_cl;
AiIntentionQueue m_int_queue;
unsigned int m_last_think_time;
unsigned int m_last_follow_time;
bool m_follow_enabled;
unsigned int m_follow_oid;
};

View File

@@ -0,0 +1,22 @@
#include "stdafx.h"
#include "Resource.h"
#include "Logger.h"
#include "L2Client.h"
void L2Client::L2ClientThread_Game_BotIPC( class L2Client *pcls )
{
BOT_INFO bi;
BotIPC *ipc = BotIPC::getInstance();
ipc->getBotInfo( pcls->botipc_index, &bi );
if( bi.isSlave )
{
if( bi.followEnable )
{
pcls->m_ai->setFollow( true, bi.oidFollow );
}
else
{
pcls->m_ai->setFollow( false, 0 );
}
}
}

View File

@@ -0,0 +1,389 @@
#include "stdafx.h"
#include "Resource.h"
#include "Logger.h"
#include "MainWindow.h"
#include "L2Client.h"
#include "ChooseCharDlg.h"
extern HWND g_hWnd;
bool L2Client::L2ClientThread_Game( class L2Client *pcls )
{
// vars
bool was_error = false;
int rdyRead = 0;
int rdyWrite = 0;
unsigned char *packbuffer = NULL;
int r = -1;
long timerResolutionMsec = 250;
DWORD lastWorldTickTime = GetTickCount();
unsigned int plen = 0;
// packet objects
L2GamePacket *pack = NULL;
L2Game_ProtocolVersion *p_game_pv = NULL;
char szPacketName[256];
// memsets
memset( pcls->game_key_send, 0, sizeof(pcls->game_key_send) );
memset( pcls->game_key_recv, 0, sizeof(pcls->game_key_recv) );
memset( szPacketName, 0, sizeof(szPacketName) );
pcls->game_opcodeObfuscatorSeed = 0;
pcls->game_pCodeObfuscator = NULL;
pcls->game_logoutRequestSent = false;
// allocate recv packet buffer
packbuffer = (unsigned char *)malloc( 10240 ); // 10 kb;
if( !packbuffer )
{
log_error( LOG_ERROR, "Recv buffer malloc() failed!\n" );
pcls->threadNetCleanup( pcls );
pcls->addChatToTab( CHAT_SYS, L"Recv buffer malloc() failed!" );
return false;
}
// create socket
pcls->sock = L2PNet_TCPsocket_create( true );
if( pcls->sock == INVALID_SOCKET )
{
log_error( LOG_ERROR, "Game: sock crt fail!\n" );
pcls->threadNetCleanup( pcls );
pcls->addChatToTab( CHAT_SYS, L"Socket create failed!" );
return false;
}
// update net STATE, UI
pcls->setState( L2Client::STATE_CONNECTING_GAME );
log_error( LOG_DEBUG, "Game: connecting to %s:%d...\n",
pcls->login_selectedGsIP, pcls->login_selectedGsPort );
pcls->addChatToTabFormat( CHAT_SYS, L"Connecting to GS %S:%d...",
pcls->login_selectedGsIP, pcls->login_selectedGsPort );
// conenct
L2PNet_connect( pcls->sock, pcls->login_selectedGsIP, (unsigned short)pcls->login_selectedGsPort );
L2PNet_select( pcls->sock, L2PNET_SELECT_WRITE, 10000, &rdyRead, &rdyWrite );
if( !rdyWrite )
{
log_error( LOG_ERROR, "Game: connect failed!\n" );
pcls->threadNetCleanup( pcls );
pcls->addChatToTab( CHAT_SYS, L"Connect to GS failed!" );
return false;
}
// update net state, UI
pcls->botipc_index = -1; // no BotIPC
pcls->setState( L2Client::STATE_CONNECTED_GAME );
log_error( LOG_DEBUG, "Game: connected to GS %s:%d.\n",
pcls->login_selectedGsIP, pcls->login_selectedGsPort );
pcls->addChatToTabFormat( CHAT_SYS, L"Connected to game server %S:%d.",
pcls->login_selectedGsIP, pcls->login_selectedGsPort );
// create ProtocolVersion packet
p_game_pv = new L2Game_ProtocolVersion();
if( pcls->account.useDefaultProtocolVersion )
{
log_error( LOG_PACKETNAME, "Using default protocol version from config "
"for L2_VERSION %d\n", pcls->account.serverVersion );
switch( pcls->account.getL2Version() )
{
case L2_VERSION_T1: p_game_pv->createDefaultKamael(); break;
case L2_VERSION_T15: p_game_pv->createDefaultHellbound(); break;
case L2_VERSION_T2: p_game_pv->createDefaultGracia1(); break;
case L2_VERSION_T22: p_game_pv->createDefaultGracia2(); break;
case L2_VERSION_T23: p_game_pv->createDefaultGracia3(); break;
case L2_VERSION_T24: p_game_pv->createDefaultGracia4(); break;
default:
{
log_error( LOG_ERROR, "wrong serverVersion setting in config! "
"creating default Gracia Part 1!\n" );
p_game_pv->createDefaultGracia1();
pcls->addChatToTab( CHAT_SYS, L"Wrong serverVersion setting in config!" );
pcls->addChatToTab( CHAT_SYS, L"...Creating default protocolVersion Gracia Part 1!" );
} break;
}
}
else
{
log_error( LOG_PACKETNAME, "Creating manual protocolVersion %u\n",
pcls->account.protocolVersion );
p_game_pv->createDefaultGracia3( pcls->account.protocolVersion );
pcls->addChatToTabFormat( CHAT_SYS, L"Sending manual ProtocolVersion: %u",
pcls->account.protocolVersion );
}
// send ProtocolVersion
r = pcls->sendPacket( p_game_pv, false ); // false - do not obfuscate and XOR encode
// free packet mem
delete p_game_pv;
p_game_pv = NULL;
if( r <= 0 ) goto netErrorSend;
netRestartOK:
pcls->game_logoutRequestSent = false;
try
{
#pragma warning( push, 3 )
while( true )
#pragma warning( pop )
{
if( pcls->threadSignal != 0 )
{
if( pcls->threadSignal == THREAD_SIGNAL_FORCE_DISCONNECT )
{
pcls->send_Logout(); // send Logout, not needed, but...
break;
}
if( pcls->threadSignal == THREAD_SIGNAL_DISCONNECT )
{
if( pcls->game_logoutRequestSent == false )
{
pcls->send_Logout();
pcls->game_logoutRequestSent = true;
}
}
if( pcls->threadSignal == THREAD_SIGNAL_LOGOUT )
{
if( pcls->game_logoutRequestSent == false )
{
pcls->send_RequestRestart();
pcls->game_logoutRequestSent = true;
}
}
}
// process BotIPC events
if( pcls->botipc_index >= 0 ) L2ClientThread_Game_BotIPC( pcls );
// process AI tasks
if( pcls->m_ai ) pcls->m_ai->think();
// next deal with network packets
// check if we have to receive some packet
r = L2PNet_select( pcls->sock, L2PNET_SELECT_READ, timerResolutionMsec, &rdyRead, &rdyWrite );
DWORD curTick = GetTickCount();
if( curTick - lastWorldTickTime >= (unsigned)timerResolutionMsec )
{
lastWorldTickTime = curTick;
pcls->worldTick();
}
// select result
if( r == -1 ) break; // error?
if( r == 0 ) continue; // timeout
// receive packet!
r = L2PacketReceive_buffer( pcls->sock, pcls->game_recvTimeoutMsec, &plen, packbuffer );
if( r <= 0 ) goto netErrorRecv;
// decode XOR
if( pcls->game_XOR_enabled )
L2GamePacket::decodeXOR_buffer( packbuffer, plen, pcls->game_key_recv );
// deobfuscate opcode if enabled after XOR enc
//pcls->OpcodeDeObfuscate( packbuffer, plen );
// FIXED: de-obfuscation is not used for S->C packets!
unsigned char opcode1 = packbuffer[2];
unsigned short int opcode2 = ( ((unsigned short int)packbuffer[3]) |
(((unsigned short int)packbuffer[4]) << 8) );
unsigned short int opcode3 = ( ((unsigned short int)packbuffer[5]) |
(((unsigned short int)packbuffer[6]) << 8) );
L2Packets_GetL2PacketName( pcls->account.getL2Version(), true,
opcode1, opcode2, opcode3, szPacketName, 255 );
if( opcode1 != 0xFE ) log_error( LOG_PACKETNAME, "Server: %02X %s\n", opcode1, szPacketName );
else log_error( LOG_PACKETNAME, "Server: FE:%02X %s\n", opcode2, szPacketName );
// create packet object
pack = new L2GamePacket();
pack->setBytes( packbuffer, plen );
// dispatch packet to handlers
// packet parsing is based on opcodes, which may be the same in
// different connection states, so parsing is based on connection state
// same opcodes may be parsed differently in different states
switch( pcls->getState() )
{
// check for bad states
case L2Client::STATE_OFFLINE:
case L2Client::STATE_CONNECTING_LOGIN:
case L2Client::STATE_CONNECTED_LOGIN:
case L2Client::STATE_AUTHED_LOGIN:
case L2Client::STATE_CONNECTING_GAME:
break; // not used here
case L2Client::STATE_CONNECTED_GAME:
{
switch( opcode1 )
{
case 0x2E: pcls->ph_KeyPacket( pcls, pack ); break;
case 0x09: pcls->ph_CharSelectionInfo( pcls, pack ); break; // changes state to AUTHED_GAME
case 0x0A: pcls->ph_AuthLoginFail( pcls, pack ); break;
}
} break; /* STATE_CONNECTED_GAME */
case L2Client::STATE_AUTHED_GAME:
{
switch( opcode1 )
{
case 0x09: pcls->ph_CharSelectionInfo( pcls, pack ); break;
case 0x0B: pcls->ph_CharSelected( pcls, pack ); break; // changes state to IN_GAME
case 0x0D: pcls->ph_NewCharacterSuccess( pcls, pack ); break;
case 0x0F: pcls->ph_CharCreateSuccess( pcls, pack ); break;
case 0x10: pcls->ph_CharCreateFail( pcls, pack ); break;
case 0x1D: pcls->ph_CharDeleteSuccess( pcls, pack ); break;
case 0x1E: pcls->ph_CharDeleteFail( pcls, pack ); break;
case 0x73: pcls->ph_SSQInfo( pcls, pack ); break;
}
} break;
/* STATE_AUTHED_GAME */
case L2Client::STATE_IN_GAME:
{
switch( opcode1 )
{
case 0x00: pcls->ph_Die( pcls, pack ); break;
case 0x01: pcls->ph_Revive( pcls, pack ); break;
case 0x05: pcls->ph_SpawnItem( pcls, pack ); break;
case 0x06: pcls->ph_SellList( pcls, pack ); break;
case 0x07: pcls->ph_BuyList( pcls, pack ); break;
case 0x08: pcls->ph_DeleteObject( pcls, pack ); break;
case 0x0c: pcls->ph_NpcInfo( pcls, pack ); break;
case 0x11: pcls->ph_ItemList( pcls, pack ); break;
case 0x14: pcls->ph_TradeStart( pcls, pack ); break;
case 0x16: pcls->ph_DropItem( pcls, pack ); break;
case 0x17: pcls->ph_GetItem( pcls, pack ); break;
case 0x18: pcls->ph_StatusUpdate( pcls, pack ); break;
case 0x19: pcls->ph_NpcHtmlMessage( pcls, pack ); break;
case 0x1A: pcls->ph_TradeOwnAdd( pcls, pack ); break;
case 0x1B: pcls->ph_TradeOtherAdd( pcls, pack ); break;
case 0x1C: pcls->ph_TradeDone( pcls, pack ); break;
case 0x21: pcls->ph_InventoryUpdate( pcls, pack ); break;
case 0x22: pcls->ph_TeleportToLocation( pcls, pack ); break;
case 0x23: pcls->ph_TargetSelected( pcls, pack ); break;
case 0x24: pcls->ph_TargetUnselected( pcls, pack ); break;
case 0x28: pcls->ph_ChangeMoveType( pcls, pack ); break;
case 0x29: pcls->ph_ChangeWaitType( pcls, pack ); break;
case 0x2F: pcls->ph_MoveToLocation( pcls, pack ); break;
case 0x31: pcls->ph_CharInfo( pcls, pack ); break;
case 0x32: pcls->ph_UserInfo( pcls, pack ); break;
case 0x39: pcls->ph_AskJoinParty( pcls, pack ); break;
case 0x3a: pcls->ph_JoinParty( pcls, pack ); break;
case 0x47: pcls->ph_StopMove( pcls, pack ); break;
case 0x48: pcls->ph_MagicSkillUse( pcls, pack ); break;
case 0x49: pcls->ph_MagicSkillCanceld( pcls, pack ); break;
case 0x4a: pcls->ph_CreatureSay( pcls, pack ); break;
case 0x4E: pcls->ph_PartySmallWindowAll( pcls, pack ); break;
case 0x4F: pcls->ph_PartySmallWindowAdd( pcls, pack ); break;
case 0x50: pcls->ph_PartySmallWindowDeleteAll( pcls, pack ); break;
case 0x51: pcls->ph_PartySmallWindowDelete( pcls, pack ); break;
case 0x52: pcls->ph_PartySmallWindowUpdate( pcls, pack ); break;
case 0x5f: pcls->ph_SkillList( pcls, pack ); break;
case 0x62: pcls->ph_SystemMessage( pcls, pack ); break;
case 0x6B: pcls->ph_SetupGauge( pcls, pack ); break;
case 0x70: pcls->ph_SendTradeRequest( pcls, pack ); break;
case 0x71: // RestartResponse
{
pack->getPacketType(); // 0x71
int restartOK = pack->readD();
if( (restartOK == 0x01) && (pcls->threadSignal == THREAD_SIGNAL_LOGOUT) )
{
pcls->threadSignal = 0;
pcls->addChatToTab( CHAT_SYS, L"Restart OK" );
// remove bot from bot IPC
pcls->ensureRemoveSelfFromBotIPC();
goto netRestartOK;
}
if( restartOK == 0x00 )
{
log_error( LOG_USERAI, "RestartResponse: logout failed!\n" );
pcls->addChatToTab( CHAT_SYS, L"Logout failed!" );
}
} break;
case 0x72: pcls->ph_MoveToPawn( pcls, pack ); break;
// SSQInfo may be sent also when IN_GAME...
case 0x73: pcls->ph_SSQInfo( pcls, pack ); break;
case 0x74: pcls->ph_GameGuardQuery( pcls, pack ); break;
case 0x79: pcls->ph_ValidateLocation( pcls, pack ); break;
case 0x84: // LeaveWorld
{
if( pcls->threadSignal == THREAD_SIGNAL_DISCONNECT )
{
pcls->threadSignal = 0;
pcls->addChatToTab( CHAT_SYS, L"Disconnect OK" );
// remove bot from bot IPC
pcls->ensureRemoveSelfFromBotIPC();
goto netLeaveWorld;
}
} break;
case 0x85: pcls->ph_AbnormalStatusUpdate( pcls, pack ); break;
case 0x89: pcls->ph_PledgeInfo( pcls, pack ); break;
case 0xA0: pcls->ph_PrivateStoreManageListSell( pcls, pack ); break;
case 0xA1: pcls->ph_PrivateStoreListSell( pcls, pack ); break;
case 0xA2: pcls->ph_PrivateStoreMsgSell( pcls, pack ); break;
case 0xBA: pcls->ph_PartyMemberPosition( pcls, pack ); break;
case 0xBD: pcls->ph_PrivateStoreManageListBuy( pcls, pack ); break;
case 0xBE: pcls->ph_PrivateStoreListBuy( pcls, pack ); break;
case 0xBF: pcls->ph_PrivateStoreMsgBuy( pcls, pack ); break;
case 0xC7: pcls->ph_SkillCoolTime( pcls, pack ); break;
case 0xDE: pcls->ph_RecipeShopManageList( pcls, pack ); break;
case 0xE1: pcls->ph_RecipeShopMsg( pcls, pack ); break;
case 0xF3: pcls->ph_ConfirmDlg( pcls, pack ); break;
case 0xF4: pcls->ph_PartySpelled( pcls, pack ); break;
case 0xF9: pcls->ph_EtcStatusUpdate( pcls, pack ); break;
case 0xFA: pcls->ph_ShortBuffStatusUpdate( pcls, pack ); break;
case 0xFE:
{
switch( opcode2 )
{
case 0x002f: pcls->ph_ExStorageMaxCount( pcls, pack ); break;
case 0x0080: pcls->ph_ExSetPrivateStoreWholeMsg( pcls, pack ); break;
case 0x008D: pcls->ph_ExNpcQuestHtmlMessage( pcls, pack ); break;
}
} break;
}
} break;
/* STATE_IN_GAME */
} // switch state
// delete packet object
delete pack;
pack = NULL;
} // while( 1 )
} // try
catch( L2P_Exception& e )
{
log_error( LOG_ERROR, "L2ClientThread_Game: L2P_Exception: %s\n", e.what() );
}
catch( std::exception& e )
{
log_error( LOG_ERROR, "L2ClientThread_Game: std::exception: %s\n", e.what() );
}
netLeaveWorld:
//
was_error = false;
goto normalEnd;
// error handlers
netErrorRecv:
was_error = true;
log_error( LOG_ERROR, "L2ClientThread: recv failed; some network error?\n" );
pcls->addChatToTab( CHAT_SYS, L"Network error! (recv)" );
goto normalEnd;
netErrorSend:
was_error = true;
log_error( LOG_ERROR, "L2ClientThread: send failed; some network error?\n" );
pcls->addChatToTab( CHAT_SYS, L"Network error! (send)" );
goto normalEnd;
normalEnd:
if( pcls->game_pCodeObfuscator ) delete pcls->game_pCodeObfuscator;
pcls->game_pCodeObfuscator = NULL;
pcls->addChatToTab( CHAT_SYS, L"Disconnected." );
free( packbuffer );
packbuffer = NULL;
pcls->threadNetCleanup( pcls );
if( was_error ) return false;
return true;
}

View File

@@ -0,0 +1,443 @@
#include "stdafx.h"
#include "Resource.h"
#include "Logger.h"
#include "MainWindow.h"
#include "L2Client.h"
#include "ChooseServerDlg.h"
extern HINSTANCE g_hInst;
extern HWND g_hWnd;
bool L2Client::L2ClientThread_Login( class L2Client *pcls )
{
bool was_error = false;
int i = 0;
int rdyRead = 0, rdyWrite = 0;
unsigned char *packbuffer = NULL;
int r = -1;
long recvTimeoutMsec = 5000;
long sendTimeoutMsec = 5000;
unsigned int plen = 0;
unsigned char ptype = 0;
pcls->setState( L2Client::STATE_OFFLINE );
pcls->sock = INVALID_SOCKET;
pcls->sock = L2PNet_TCPsocket_create( true );
if( pcls->sock == INVALID_SOCKET )
{
log_error( LOG_ERROR, "L2ClientThread: socket crt failed!\n" );
pcls->threadNetCleanup( pcls );
return false;
}
pcls->setState( L2Client::STATE_CONNECTING_LOGIN );
pcls->addChatToTabFormat( L2Client::CHAT_SYS, L"Connecting to login %S:%d...",
pcls->account.loginServerIP, pcls->account.loginServerPort );
L2PNet_connect( pcls->sock, pcls->account.loginServerIP,
(unsigned short)pcls->account.loginServerPort );
L2PNet_select( pcls->sock, L2PNET_SELECT_WRITE, 10000, &rdyRead, &rdyWrite );
if( !rdyWrite )
{
log_error( LOG_ERROR, "L2ClientThread: login connect failed!\n" );
pcls->threadNetCleanup( pcls );
pcls->addChatToTab( CHAT_SYS, L"Connect to login failed!" );
return false;
}
packbuffer = (unsigned char *)malloc( 10240 );
if( !packbuffer )
{
log_error( LOG_ERROR, "L2ClientThread: malloc() packbuffer failed!\n" );
pcls->threadNetCleanup( pcls );
return false;
}
pcls->addChatToTab( L2Client::CHAT_SYS, L"Connected to login." );
// TODO: Login server session vars
// login server session vars
unsigned char ls_sessionID[4] = {0,0,0,0};
unsigned int ls_sessionIDUInt = 0;
unsigned int ls_protoVer = 0;
unsigned char ls_RSA_pubKeyMod[128];
unsigned char ls_ggShit[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
unsigned char ls_newBFKey[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
unsigned int ls_ggAuthResponse = 0;
unsigned char ls_sessionKey1[8] = {0,0,0,0, 0,0,0,0};
unsigned char ls_sessionKey2[8] = {0,0,0,0, 0,0,0,0};
unsigned char ls_nGameServersCount = 0;
unsigned char ls_lastServerID = 0;
int ls_chosenGameServer = -1;
// login server session vars memset
memset( ls_RSA_pubKeyMod, 0, sizeof(ls_RSA_pubKeyMod) );
memset( pcls->login_sessionKey1, 0, sizeof(pcls->login_sessionKey1) );
memset( pcls->login_sessionKey2, 0, sizeof(pcls->login_sessionKey1) );
pcls->login_selectedGsId = 0;
memset( pcls->login_selectedGsIP, 0, sizeof(pcls->login_selectedGsIP) );
pcls->login_selectedGsPort = 0;
const int MAX_GAMESERVERS = 32;
L2GameServerInfo ls_gameservers[MAX_GAMESERVERS];
memset( ls_gameservers, 0, sizeof(ls_gameservers) );
// packet objects
L2LoginPacket *pack = NULL;
L2Login_Init *p_init = NULL;
L2Login_RequestGGAuth *p_rgga = NULL;
L2Login_GGAuthResponse *p_ggar = NULL;
L2Login_RequestAuthLogin *p_ral = NULL;
L2Login_LoginOK *p_lok = NULL;
L2Login_LoginFail *p_lfail = NULL;
L2Login_AccountKicked *p_acckick = NULL;
L2Login_RequestServerList *p_rsl = NULL;
L2Login_ServerList *p_sl = NULL;
L2Login_RequestServerLogin *p_rgsl = NULL;
L2Login_PlayOK *p_pok = NULL;
L2Login_PlayFail *p_pfail = NULL;
// receive Init
r = L2PacketReceive_buffer( pcls->sock, recvTimeoutMsec, &plen, packbuffer );
if( r <= 0 ) goto netErrorRecv;
if( plen != 186 )
{
log_error( LOG_ERROR, "L2ClientThread: recv Init: received %d bytes instead of %d! Maybe wrong loginserver!\n",
plen, 186 );
goto netErrorRecv;
}
p_init = new L2Login_Init();
p_init->setBytes( packbuffer, plen );
if( p_init->decodeBlowfish( true ) )
{
if( p_init->decodeXOR() )
{
p_init->read_SessionID( ls_sessionID );
memcpy( &ls_sessionIDUInt, ls_sessionID, sizeof(ls_sessionID) );
ls_protoVer = p_init->read_ProtoVer();
p_init->read_RSA_pubKeyMod( ls_RSA_pubKeyMod );
p_init->read_GGShit( ls_ggShit );
p_init->read_DynamicBFKey( ls_newBFKey );
}
else log_error( LOG_ERROR, "L2ClientThread: XOR decode failed\n" );
}
else log_error( LOG_ERROR, "L2ClientThread: BF decode failed\n" );
delete p_init;
p_init = NULL;
// reply RequestGGAuth
p_rgga = new L2Login_RequestGGAuth();
memcpy( p_rgga->sessionId, ls_sessionID, 4 );
p_rgga->create();
p_rgga->padPacketTo8ByteLen();
p_rgga->appendChecksum( true );
p_rgga->appendMore8Bytes();
p_rgga->setDynamicBFKey( ls_newBFKey, 16 );
p_rgga->encodeBlowfish( false );
r = L2PacketSend2( p_rgga->getBytesPtr(), pcls->sock, sendTimeoutMsec, &plen );
delete p_rgga;
p_rgga = NULL;
if( r == -1 ) goto netErrorSend;
// recv GGAuthResponse
r = L2PacketReceive_buffer( pcls->sock, recvTimeoutMsec, &plen, packbuffer );
if( r <= 0 ) goto netErrorRecv;
p_ggar = new L2Login_GGAuthResponse();
p_ggar->setBytes( packbuffer, plen );
p_ggar->setDynamicBFKey( ls_newBFKey, 16 );
p_ggar->decodeBlowfish( false );
ptype = p_ggar->getPacketType();
if( ptype != 0x0B )
log_error( LOG_WARNING, "L2ClientThread: login: Unknown GGAuthResponse code 0x%02X!!!!\n",
(unsigned int)ptype );
else
log_error( LOG_OK, "L2ClientThread: login: GGAuthResponse: bypass GameGuard authorization...\n" );
ls_ggAuthResponse = p_ggar->read_Response();
if( ls_ggAuthResponse != ls_sessionIDUInt )
{
log_error( LOG_WARNING, "L2ClientThread: login: sessionID != ggAuthResponse (%04X != %04X)\n",
ls_sessionIDUInt, ls_ggAuthResponse );
}
else
{
log_error( LOG_DEBUG, "L2ClientThread: login: sessionID == ggAuthResponse, good\n" );
pcls->addChatToTab( L2Client::CHAT_SYS, L"lol gameguard :)" );
}
delete p_ggar;
p_ggar = NULL;
// convert charset
char al2login[32], al2pass[32];
memset( al2login, 0, sizeof(al2login) );
memset( al2pass, 0, sizeof(al2pass) );
WideCharToMultiByte( CP_ACP, 0, pcls->account.login, -1, al2login, 31, NULL, NULL );
WideCharToMultiByte( CP_ACP, 0, pcls->account.pass, -1, al2pass, 31, NULL, NULL );
log_error( LOG_DEBUG, "L2ClientThread: login.. [%s] [%s]\n", al2login, al2pass );
L2Login_Init::unscramble_RSA_PubKeyMod( ls_RSA_pubKeyMod );
// response with RequestAuthLogin
p_ral = new L2Login_RequestAuthLogin();
p_ral->create( al2login, al2pass, ls_ggAuthResponse, ls_RSA_pubKeyMod );
p_ral->padPacketTo8ByteLen();
p_ral->appendChecksum( true );
p_ral->appendMore8Bytes();
p_ral->setDynamicBFKey( ls_newBFKey, 16 );
p_ral->encodeBlowfish( false );
r = L2PacketSend2( p_ral->getBytesPtr(), pcls->sock, sendTimeoutMsec, &plen );
delete p_ral;
p_ral = NULL;
if( r == -1 ) goto netErrorSend;
// recv response to RequestAuthLogin
// it will be LoginOK or LoginFail
r = L2PacketReceive_buffer( pcls->sock, recvTimeoutMsec, &plen, packbuffer );
if( r <= 0 ) goto netErrorRecv;
pack = new L2LoginPacket( packbuffer, plen );
pack->setDynamicBFKey( ls_newBFKey, 16 );
pack->decodeBlowfish( false );
ptype = pack->getPacketType();
log_error( LOG_DEBUGDUMP, "L2ClientThread: response to RequestAuthLogin is 0x%02X\n", ptype );
if( ptype == 0x03 ) // login ok
{
log_error( LOG_DEBUG, "L2ClientThread: Login OK\n" );
p_lok = new L2Login_LoginOK( pack->getBytesPtr(), pack->getPacketSize() );
p_lok->getPacketType();
p_lok->read_sessionKey1( ls_sessionKey1 );
delete p_lok;
p_lok = NULL;
pcls->addChatToTab( L2Client::CHAT_SYS, L"Login OK" );
pcls->setState( STATE_AUTHED_LOGIN );
}
else if( ptype == 0x01 )
{
p_lfail = new L2Login_LoginFail( pack->getBytesPtr(), pack->getPacketSize() );
p_lfail->getPacketType();
unsigned int reason = p_lfail->read_reason();
log_error( LOG_ERROR, "L2ClientThread: Login failed: 0x%02X\n", reason );
wchar_t strReason[64] = {0};
switch( reason )
{
case L2Login_LoginFail::REASON_SYSTEM_ERROR : wcscpy( strReason, L"REASON_SYSTEM_ERROR" ); break;
case L2Login_LoginFail::REASON_PASS_WRONG : wcscpy( strReason, L"REASON_PASS_WRONG" ); break;
case L2Login_LoginFail::REASON_USER_OR_PASS_WRONG : wcscpy( strReason, L"REASON_USER_OR_PASS_WRONG" ); break;
case L2Login_LoginFail::REASON_ACCESS_FAILED : wcscpy( strReason, L"REASON_ACCESS_FAILED" ); break;
case L2Login_LoginFail::REASON_ACCOUNT_IN_USE : wcscpy( strReason, L"REASON_ACCOUNT_IN_USE" ); break;
case L2Login_LoginFail::REASON_SERVER_OVERLOADED : wcscpy( strReason, L"REASON_SERVER_OVERLOADED" ); break;
case L2Login_LoginFail::REASON_SERVER_MAINTENANCE : wcscpy( strReason, L"REASON_SERVER_MAINTENANCE" ); break;
case L2Login_LoginFail::REASON_TEMP_PASS_EXPIRED : wcscpy( strReason, L"REASON_TEMP_PASS_EXPIRED" ); break;
case L2Login_LoginFail::REASON_DUAL_BOX : wcscpy( strReason, L"REASON_DUAL_BOX" ); break;
default : wcscpy( strReason, L"REASON_UNKNOWN" ); break;
}
wchar_t mes[128] = {0};
wsprintfW( mes, L"Login FAILED! Reason: [%s]", strReason );
pcls->addChatToTab( L2Client::CHAT_SYS, mes );
delete p_lfail;
p_lfail = NULL;
delete pack;
pack = NULL;
goto netErrorRecv;
}
else if( ptype == 0x02 )
{
p_acckick = new L2Login_AccountKicked( pack->getBytesPtr(), pack->getPacketSize() );
p_acckick->getPacketType();
unsigned int reason = p_acckick->read_reason();
log_error( LOG_ERROR, "L2ClientThread: Login failed: AccountKicked: 0x%02X\n", reason );
wchar_t strReason[64] = {0};
switch( reason )
{
case L2Login_AccountKicked::REASON_DATA_STEALER : wcscpy( strReason, L"REASON_DATA_STEALER" ); break;
case L2Login_AccountKicked::REASON_GENERIC_VIOLATION : wcscpy( strReason, L"REASON_GENERIC_VIOLATION" ); break;
case L2Login_AccountKicked::REASON_7_DAYS_SUSPENDED : wcscpy( strReason, L"REASON_7_DAYS_SUSPENDED" ); break;
case L2Login_AccountKicked::REASON_PERMANENTLY_BANNED : wcscpy( strReason, L"REASON_PERMANENTLY_BANNED" ); break;
default : wcscpy( strReason, L"REASON_UNKNOWN" ); break;
}
wchar_t mes[128] = {0};
wsprintfW( mes, L"Login FAILED! Reason: [%s]", strReason );
pcls->addChatToTab( L2Client::CHAT_SYS, mes );
delete p_acckick;
p_acckick = NULL;
delete pack;
pack = NULL;
goto netErrorRecv;
}
else
{
wchar_t mes[128] = {0};
wsprintfW( mes, L"Login failed: Unknown response: 0x%02X\n", ptype );
pcls->addChatToTab( L2Client::CHAT_SYS, mes );
log_error( LOG_ERROR, "L2ClientThread: Login failed: Unknown response: 0x%02X\n", ptype );
delete pack;
pack = NULL;
goto netErrorRecv;
}
delete pack;
pack = NULL;
// request server list
p_rsl = new L2Login_RequestServerList();
p_rsl->create( ls_sessionKey1 );
p_rsl->padPacketTo8ByteLen();
p_rsl->appendChecksum( true );
p_rsl->appendMore8Bytes();
p_rsl->setDynamicBFKey( ls_newBFKey, 16 );
p_rsl->encodeBlowfish( false );
r = L2PacketSend2( p_rsl->getBytesPtr(), pcls->sock, sendTimeoutMsec, &plen );
delete p_rsl;
p_rsl = NULL;
if( r == -1 ) goto netErrorSend;
// receive server list
r = L2PacketReceive_buffer( pcls->sock, recvTimeoutMsec, &plen, packbuffer );
if( r <= 0 ) goto netErrorRecv;
p_sl = new L2Login_ServerList( packbuffer, plen );
p_sl->setDynamicBFKey( ls_newBFKey, 16 );
p_sl->decodeBlowfish( false );
p_sl->read_header( &ls_nGameServersCount, &ls_lastServerID );
for( i=0; i<ls_nGameServersCount; i++ )
{
p_sl->read_next_GS_Info( &ls_gameservers[i] );
log_error( LOG_DEBUGDUMP, "GS #%d: ", (int)ls_gameservers[i].gsID );
log_error_np( LOG_DEBUGDUMP, "Addr: %d.%d.%d.%d : %d; ",
(int)ls_gameservers[i].gsIP[0], (int)ls_gameservers[i].gsIP[1],
(int)ls_gameservers[i].gsIP[2], (int)ls_gameservers[i].gsIP[3],
(int)ls_gameservers[i].gsPort );
log_error_np( LOG_DEBUGDUMP, "Online: %d / %d\n",
(int)ls_gameservers[i].gsPlayersOnline, (int)ls_gameservers[i].gsPlayersMax );
}
delete p_sl;
p_sl = NULL;
pcls->addChatToTab( L2Client::CHAT_SYS, L"Received ServerList" );
// now we must choose server
// in manual mode, run dialog
// in auto mode, use accoutn setting
if( pcls->account.gameserverSelectManual )
{
int sel_idx = ChooseServer( g_hWnd, ls_gameservers, ls_nGameServersCount );
if( sel_idx == -1 ) goto normalEnd;
ls_chosenGameServer = ls_gameservers[ sel_idx ].gsID;
log_error( LOG_DEBUG, "L2ClientThread: login: manual select game server idx[%d]: id = %d\n",
sel_idx, ls_chosenGameServer );
sprintf( pcls->login_selectedGsIP, "%d.%d.%d.%d",
ls_gameservers[ sel_idx ].gsIP[0], ls_gameservers[ sel_idx ].gsIP[1],
ls_gameservers[ sel_idx ].gsIP[2], ls_gameservers[ sel_idx ].gsIP[3] );
pcls->login_selectedGsPort = (int)ls_gameservers[ sel_idx ].gsPort;
}
else
{
ls_chosenGameServer = pcls->account.gameserverID;
log_error( LOG_DEBUG, "L2ClientThread: login: auto select game server id %d\n",
ls_chosenGameServer );
pcls->login_selectedGsId = ls_chosenGameServer;
int idx = -1;
for( i=0; i<ls_nGameServersCount; i++ )
{
if( ls_gameservers[i].gsID == ls_chosenGameServer ) idx = i;
}
if( idx >= 0 )
{
sprintf( pcls->login_selectedGsIP, "%d.%d.%d.%d",
ls_gameservers[ idx ].gsIP[0], ls_gameservers[ idx ].gsIP[1],
ls_gameservers[ idx ].gsIP[2], ls_gameservers[ idx ].gsIP[3] );
pcls->login_selectedGsPort = (int)ls_gameservers[ idx ].gsPort;
}
}
// request server login
p_rgsl = new L2Login_RequestServerLogin();
p_rgsl->create( ls_sessionKey1, (unsigned char)(ls_chosenGameServer & 0x000000ff) );
p_rgsl->padPacketTo8ByteLen();
p_rgsl->appendChecksum( true );
p_rgsl->appendMore8Bytes();
p_rgsl->setDynamicBFKey( ls_newBFKey, 16 );
p_rgsl->encodeBlowfish( false );
r = L2PacketSend2( p_rgsl->getBytesPtr(), pcls->sock, sendTimeoutMsec, &plen );
delete p_rgsl;
p_rgsl = NULL;
if( r == -1 ) goto netErrorSend;
// recv PalyOK / PlayFail
r = L2PacketReceive_buffer( pcls->sock, recvTimeoutMsec, &plen, packbuffer );
if( r <= 0 ) goto netErrorRecv;
pack = new L2LoginPacket( packbuffer, plen );
pack->setDynamicBFKey( ls_newBFKey, 16 );
pack->decodeBlowfish( false );
ptype = pack->getPacketType();
if( ptype == 0x07 )
{
log_error( LOG_DEBUG, "L2ClientThread: login: PlayOK\n" );
pcls->addChatToTab( L2Client::CHAT_SYS, L"Play OK" );
p_pok = new L2Login_PlayOK( pack->getBytesPtr(), pack->getPacketSize() );
p_pok->getPacketType();
p_pok->read_sessionKey2( ls_sessionKey2 );
delete p_pok;
p_pok = NULL;
}
else if( ptype == 0x06 )
{
p_pfail = new L2Login_PlayFail( pack->getBytesPtr(), pack->getPacketSize() );
p_pfail->getPacketType();
unsigned int reason = (unsigned int)p_pfail->read_reason();
log_error( LOG_ERROR, "L2ClientThread: login: PlayFail: 0x%02X\n", reason );
wchar_t msg[128];
wchar_t strReason[128] = {0};
switch( reason )
{
case L2Login_PlayFail::REASON_SYSTEM_ERROR : wcscpy( strReason, L"REASON_SYSTEM_ERROR" ); break;
case L2Login_PlayFail::REASON_USER_OR_PASS_WRONG : wcscpy( strReason, L"REASON_USER_OR_PASS_WRONG" ); break;
case L2Login_PlayFail::REASON3 : wcscpy( strReason, L"REASON3" ); break;
case L2Login_PlayFail::REASON_ACCESS_FAILED : wcscpy( strReason, L"REASON_ACCESS_FAILED" ); break;
case L2Login_PlayFail::REASON_TOO_MANY_PLAYERS : wcscpy( strReason, L"REASON_TOO_MANY_PLAYERS" ); break;
default: wcscpy( strReason, L"REASON_UNKNOWN" ); break;
}
wsprintfW( msg, L"PlayFail: %s", strReason );
pcls->addChatToTab( L2Client::CHAT_SYS, msg );
delete p_pfail;
p_pfail = NULL;
delete pack;
pack = NULL;
goto netErrorRecv;
}
else
{
log_error( LOG_DEBUG, "L2ClientThread: login: unknown response 0x%02X to RequestServerLogin\n",
(int)ptype );
wchar_t msg[128];
wsprintfW( msg, L"Unknown response 0x%02X to RequestServerLogin\n", (int)ptype );
pcls->addChatToTab( L2Client::CHAT_SYS, msg );
delete pack;
pack = NULL;
goto netErrorRecv;
}
delete pack;
pack = NULL;
L2PNet_shutdown( pcls->sock );
L2PNet_closesocket( pcls->sock );
pcls->sock = INVALID_SOCKET;
// save session vars
memcpy( pcls->login_sessionKey1, ls_sessionKey1, sizeof(ls_sessionKey1) );
memcpy( pcls->login_sessionKey2, ls_sessionKey2, sizeof(ls_sessionKey2) );
was_error = false;
goto normalEnd;
// error handlers
netErrorRecv:
was_error = true;
log_error( LOG_ERROR, "L2ClientThread: recv failed; some network error?\n" );
pcls->addChatToTab( CHAT_SYS, L"Network error! (recv)" );
goto normalEnd;
netErrorSend:
was_error = true;
log_error( LOG_ERROR, "L2ClientThread: send failed; some network error?\n" );
pcls->addChatToTab( CHAT_SYS, L"Network error! (send)" );
normalEnd:
free( packbuffer );
packbuffer = NULL;
pcls->threadNetCleanup( pcls );
pcls->addChatToTab( CHAT_SYS, L"Login connection closed." );
if( was_error ) return false;
if( ls_chosenGameServer == -1 ) return false;
return true;
}

View File

@@ -0,0 +1,97 @@
#include "stdafx.h"
#include "logger.h"
#include "L2Client.h"
int L2Client::sendPacket( L2GamePacket *pack, bool obfuscateAndXOREncode )
{
// this function can be used only during GS connection
if( (this->state != STATE_IN_GAME) &&
(this->state != STATE_AUTHED_GAME) &&
(this->state != STATE_CONNECTING_GAME) &&
(this->state != STATE_CONNECTED_GAME) )
{
#ifdef _DEBUG
log_error( LOG_ERROR, "L2Client::sendPacket(): ERROR: function used "
"not for GS connection! (state = %d)\n", (int)(this->state) );
#endif
return 0;
}
// check socket
if( this->sock == INVALID_SOCKET )
{
#ifdef _DEBUG
log_error( LOG_ERROR, "L2Client::sendPacket(): sock == INVALID_SOCKET!\n" );
#endif
return false;
}
//
unsigned int nBytesSent = 0;
if( obfuscateAndXOREncode )
{
this->pack_OpcodeObfuscate( pack );
if( game_XOR_enabled ) pack->encodeXOR( this->game_key_send );
}
EnterCriticalSection( &(this->cs_sendPacket) );
int r = L2PacketSend( this->sock, pack, this->game_sendTimeoutMsec, &nBytesSent );
LeaveCriticalSection( &(this->cs_sendPacket) );
#ifdef _DEBUG
if( r <= 0 )
{
log_error( LOG_ERROR, "L2Client::sendPacket(): ERROR return: %d (sent %u bytes)\n",
r, nBytesSent );
}
#endif
return r;
}
bool L2Client::pack_OpcodeDeObfuscate( unsigned char *bytes, unsigned int len )
{
if( !game_pCodeObfuscator ) return false;
if( len < 3 ) return false;
// gracia final does not use opcode obfuscation for S->C packets
if( this->account.getL2Version() == L2_VERSION_T23 ) return false; // ? sure?
int ret = 0;
try
{
game_pCodeObfuscator->decodeIDs( bytes );
}
catch( L2P_Exception& e )
{
log_error( LOG_ERROR, "OpcodeDeObfuscate: L2P_Exception: %s\n", e.what() );
}
if( ret < 0 )
log_error( LOG_WARNING, "L2Client: opcode deobfuscation failed: error code: %d\n", ret );
return (ret > 0);
}
bool L2Client::pack_OpcodeObfuscate( unsigned char *bytes, unsigned int len )
{
if( !game_pCodeObfuscator ) return false;
if( len < 3 ) return false;
int ret = 0;
try
{
game_pCodeObfuscator->encodeIDs( bytes );
}
catch( L2P_Exception& e )
{
log_error( LOG_ERROR, "OpcodeObfuscate: L2P_Exception: %s\n", e.what() );
}
if( ret < 0 )
log_error( LOG_WARNING, "L2Client: opcode obfuscation failed: error code: %d\n", ret );
return (ret > 0);
}
bool L2Client::pack_OpcodeDeObfuscate( L2GamePacket *p )
{
if( !game_pCodeObfuscator ) return false;
if( !p ) return false;
return pack_OpcodeDeObfuscate( (unsigned char *)p->getBytesPtr(), p->getPacketSize() );
}
bool L2Client::pack_OpcodeObfuscate( L2GamePacket *p )
{
if( !game_pCodeObfuscator ) return false;
if( !p ) return false;
return pack_OpcodeObfuscate( (unsigned char *)p->getBytesPtr(), p->getPacketSize() );
}

View File

@@ -0,0 +1,205 @@
#include "stdafx.h"
#include "Resource.h"
#include "Logger.h"
#include "MainWindow.h"
#include "L2Client.h"
#include "SEH_global.h"
void L2Client::startClient()
{
if( isThreadRunning() )
{
MessageBox( hWnd, TEXT("<EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("O_o"), MB_ICONWARNING );
return;
}
hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))L2ClientThread, (void *)this,
0, (unsigned int *)&dwThreadId );
if( !hThread )
{
dwThreadId = 0;
MessageBox( hWnd, TEXT("_beginthreadex() failed!"),
TEXT("Cannot start thread!"), MB_ICONSTOP );
}
}
void L2Client::logoutClient()
{
if( !isThreadRunning() )
{
MessageBox( hWnd, TEXT("<EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("O_o"), MB_ICONWARNING );
return;
}
this->game_logoutRequestSent = false;
this->threadSignal = THREAD_SIGNAL_LOGOUT;
}
void L2Client::disconnectClient( bool force )
{
if( !isThreadRunning() )
{
//MessageBox( hWnd, TEXT("<22><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("O_o"), MB_ICONWARNING );
return;
}
this->game_logoutRequestSent = false;
if( !force ) this->threadSignal = THREAD_SIGNAL_DISCONNECT;
if( force ) this->threadSignal = THREAD_SIGNAL_FORCE_DISCONNECT;
}
void L2Client::threadNetCleanup( class L2Client *pcls )
{
if( pcls->sock != INVALID_SOCKET )
{
L2PNet_shutdown( pcls->sock );
L2PNet_closesocket( pcls->sock );
}
//CloseHandle( pcls->hThread );
//pcls->hThread = NULL;
//pcls->dwThreadId = 0;
pcls->sock = INVALID_SOCKET;
pcls->setState( STATE_OFFLINE );
pcls->threadSignal = 0;
// check Bot IPC
// remove bot from bot IPC
pcls->ensureRemoveSelfFromBotIPC();
}
DWORD WINAPI L2Client::L2ClientThread( LPVOID lpParam )
{
#ifdef USE_SEH
#ifdef _MSC_VER
__try { // start exception handler
#endif
#endif
class L2Client *pcls = (class L2Client *)lpParam;
pcls->threadSignal = 0;
bool ret = L2Client::L2ClientThread_Login( pcls );
if( ret )
{
L2Client::L2ClientThread_Game( pcls );
}
pcls->clearUserAndWorldState();
// mark thread as not running
CloseHandle( pcls->hThread );
pcls->hThread = NULL;
pcls->dwThreadId = 0;
#ifdef USE_SEH
#ifdef _MSC_VER // exception handler
}
__except( L2ClientThreadExceptonHandler( GetExceptionInformation() ) )
{
log_error( LOG_ERROR, "__except: Exception in L2ClientThread thread...\n" );
ErrorLogger_FlushLogFile();
}
#endif
#endif
return 0;
}
void L2Client::log_packet( L2Client *pcls, bool fromServer,
const unsigned char *p, unsigned int plen, const char *hintStr, LOG_LEVEL logLevel )
{
if( !p || (plen<3) ) return;
unsigned char opcode1 = p[2];
unsigned short opcode2 = p[3] | ( ((unsigned short)p[4])<<8 );
unsigned short opcode3 = p[5] | ( ((unsigned short)p[6])<<8 );
char pname[256] = {0};
LOG_LEVEL ll = logLevel;
if( fromServer ) log_error( ll, "Server: " );
else log_error( ll, "Client: " );
L2_VERSION l2_version = pcls->account.getL2Version();
L2Packets_GetL2PacketName( l2_version, fromServer, opcode1, opcode2, opcode3, pname, 127 );
log_error_np( ll, "%02X %s: len %u\n", opcode1, pname, plen );
log_error_np( ll, "%02X %02X\n", p[0], p[1] );
log_error_np( ll, "%02X\n", p[2] );
if( !hintStr )
{
unsigned int i;
unsigned int il = 0; // number of char in line
for( i=3; i<plen; i++ )
{
log_error_np( ll, "%02X ", p[i] );
il++;
// space every 4 chars
if( il % 4 == 0 ) log_error_np( ll, " " );
if( il == 16 )
{
for( il=(i-16); il<=i; il++ )
{
char ch = p[il];
bool bd = false;
if( (ch>='0') && (ch<='9') ) bd = true;
if( (ch>='A') && (ch<='Z') ) bd = true;
if( (ch>='a') && (ch<='z') ) bd = true;
//if( (ch>='<27>') && (ch<='<27>') ) bd = true;
//if( (ch>='<27>') && (ch<='<27>') ) bd = true;
if( (ch=='!') || (ch==',') || (ch=='.') || (ch=='\'') || (ch=='\"')
|| (ch==':') || (ch=='(') || (ch==')') ) bd = true;
if( bd ) log_error_np( ll, "%c", ch );
else log_error_np( ll, " " );
}
log_error_np( ll, "\n" );
il = 0;
}
}
/*if( il < 16 )
{
for( i=il; i<=16; i++ ) log_error_np( ll, " " );
}*/
}
else
{
char *phint = (char *)hintStr;
unsigned int i = 3;
while( (*phint) )
{
switch( (*phint) )
{
case 'c':
{
log_error( ll, "c: %c\n", p[i] );
i++;
} break;
case 'h':
{
log_error( ll, "h: %hd\n", *((unsigned short *)(p+i)) );
i += 2;
} break;
case 'd':
{
log_error( ll, "d: %d\n", *((int *)(p+i)) );
i += 4;
} break;
case 'u':
{
log_error( ll, "u: %u\n", *((unsigned int *)(p+i)) );
i += 4;
} break;
case 'x':
{
log_error( ll, "x: %x\n", *((unsigned int *)(p+i)) );
i += 4;
} break;
case 'f':
{
log_error( ll, "f: %0.6f\n", *((double *)(p+i)) );
i += 8;
} break;
case 'S':
{
log_error( ll, "S: %S\n", ((wchar_t *)(p+i)) );
i += wcslen( (wchar_t *)(p+i) )*2 + 2;
} break;
}
phint++;
}
}
log_error_np( ll, "\n" );
}

View File

@@ -0,0 +1,63 @@
#include "stdafx.h"
#include "Resource.h"
#include "logger.h"
#include "L2Client.h"
void L2Client::worldTick()
{
static int countCalled = 0;
unsigned int i = 0;
unsigned int nProcessed = 0;
unsigned int curTick = GetTickCount();
// user
usr.processMoveTick();
// send ValidatePosition?
countCalled++;
if( usr.isMoving() )
{
if( countCalled % 8 == 0 ) // every 8th worldTick() function call (once in 2 sec)
{
//log_error( LOG_OK, "Validating position: %d, %d, %d, %d\n", usr.x, usr.y, usr.z, usr.heading );
send_ValidatePosition();
}
}
// current casting progress is calculated and updated here
skills.processCasting( curTick );
postUpdateUI( UPDATE_USER_CASTING );
// npc
if( world_npcs.getCount() > 0 )
{
nProcessed = 0;
for( i=0; i<world_npcs.getCount(); i++ )
{
if( world_npcs.npcs_array[i]->isUnused() ) continue;
world_npcs.npcs_array[i]->processMoveTick();
nProcessed++;
if( nProcessed >= world_npcs.getCount() ) break;
}
}
// pc
if( world_chars.GetCount() > 0 )
{
nProcessed = 0;
for( i=0; i<world_chars.GetCount(); i++ )
{
if( world_chars.chars_array[i]->isUnused() ) continue;
world_chars.chars_array[i]->processMoveTick();
nProcessed++;
if( nProcessed >= world_chars.GetCount() ) break;
}
}
// update skills reuse timers
skills.processCoolTimes( curTick );
OnUiUpdateSkillCoolTimes();
// update user buffs times
buffs.process_BuffTick( curTick );
OnUiUpdateBuffsDuration();
// update party buffs times
party.process_BuffTick( curTick );
//OnUiUpdatePartyBuffsDuration();
// no really need to update party buffs duration - UI does not display duration, only skill names
// post user interface updates
postUpdateMap();
}

195
l2ooghelper/Logger.cpp Normal file
View File

@@ -0,0 +1,195 @@
#include "stdafx.h"
#include "Logger.h"
// global ErrorLogger vars
bool g_error_logger_enabled;
bool g_error_logger_enabled_console;
FILE *g_error_logger_file;
bool g_error_logger_auto_prepend;
CRITICAL_SECTION g_error_logger_cs;
HANDLE g_error_logger_stdout;
// strings
char g_error_logger_strtype_unknown[16];
char g_error_logger_strtype[LOG_LEVELS][16];
//
LOG_LEVEL g_errorLogger_WarnMessageLevel;
void ErrorLogger_InitStrings()
{
strcpy( g_error_logger_strtype_unknown, "[??] " );
strcpy( g_error_logger_strtype[LOG_OK], "[++] " );
strcpy( g_error_logger_strtype[LOG_ERROR], "[--] " );
strcpy( g_error_logger_strtype[LOG_WARNING], "[WARN] " );
strcpy( g_error_logger_strtype[LOG_USERAI], "[AI] " );
strcpy( g_error_logger_strtype[LOG_PACKETNAME], "[PACK] " );
strcpy( g_error_logger_strtype[LOG_DEBUG], "[DBG] " );
strcpy( g_error_logger_strtype[LOG_DEBUGDUMP], "[DUMP] " );
}
void ErrorLogger_Init()
{
g_error_logger_enabled = false;
g_error_logger_enabled_console = false;
g_error_logger_file = stdout;
g_error_logger_auto_prepend = false;
g_error_logger_stdout = INVALID_HANDLE_VALUE;
g_errorLogger_WarnMessageLevel = LOG_DEBUG;
InitializeCriticalSection( &g_error_logger_cs );
ErrorLogger_InitStrings();
}
void ErrorLogger_Enable( bool bEnable )
{
g_error_logger_enabled = bEnable;
}
void ErrorLogger_SetWarnMessageLevel( LOG_LEVEL level )
{
g_errorLogger_WarnMessageLevel = level;
}
void ErrorLogger_EnableLoggingToConsole( bool bEnable )
{
EnterCriticalSection( &g_error_logger_cs );
if( bEnable )
{
if( g_error_logger_enabled_console == false ) AllocConsole();
g_error_logger_stdout = GetStdHandle( STD_OUTPUT_HANDLE );
}
else
{
g_error_logger_stdout = INVALID_HANDLE_VALUE;
if( g_error_logger_enabled_console == true ) FreeConsole();
}
g_error_logger_enabled_console = bEnable;
LeaveCriticalSection( &g_error_logger_cs );
}
void ErrorLogger_SetLogFile( FILE *f )
{
EnterCriticalSection( &g_error_logger_cs );
if( !f ) g_error_logger_file = stdout; else g_error_logger_file = f;
LeaveCriticalSection( &g_error_logger_cs );
}
FILE *ErrorLogger_GetLogFile()
{
return g_error_logger_file;
}
void ErrorLogger_FlushLogFile()
{
EnterCriticalSection( &g_error_logger_cs );
if( g_error_logger_file ) fflush( g_error_logger_file );
LeaveCriticalSection( &g_error_logger_cs );
}
void ErrorLogger_SetAutoPrependErrorType( bool bPrepend )
{
g_error_logger_auto_prepend = bPrepend;
}
int log_error( LOG_LEVEL logLevel, const char *_Format, ... )
{
if( !g_error_logger_enabled ) return 0;
int ret = 0;
if( (logLevel < 0) || (!_Format) ) return 0;
if( logLevel > g_errorLogger_WarnMessageLevel ) return 0;
EnterCriticalSection( &g_error_logger_cs );
va_list l;
va_start( l, _Format );
if( g_error_logger_auto_prepend )
{
char *szPrepend = g_error_logger_strtype_unknown;
if( (logLevel >= LOG_OK) && (logLevel <= LOGLEVEL_LAST) )
szPrepend = g_error_logger_strtype[logLevel];
fprintf( g_error_logger_file, "%s", szPrepend );
// also write to console, if enabled
if( g_error_logger_enabled_console )
{
DWORD numWritten = 0;
WriteConsoleA( g_error_logger_stdout, szPrepend, (DWORD)strlen(szPrepend), &numWritten, NULL );
}
}
ret = vfprintf( g_error_logger_file, _Format, l );
// also write to console, if enabled
if( g_error_logger_enabled_console )
{
char *cbuffer = (char *)malloc( 20480 ); // 20 Kb >_<
if( cbuffer )
{
va_list l2;
va_start( l2, _Format );
vsprintf( cbuffer, _Format, l2 );
DWORD numWritten = 0;
WriteConsoleA( g_error_logger_stdout, cbuffer, (DWORD)strlen(cbuffer), &numWritten, NULL );
free( cbuffer );
}
}
LeaveCriticalSection( &g_error_logger_cs );
return ret;
}
// forces NO prepend even if set to
int log_error_np( LOG_LEVEL logLevel, const char *_Format, ... )
{
if( !g_error_logger_enabled ) return 0;
int ret = 0;
if( (logLevel < 0) || (!_Format) ) return 0;
if( logLevel > g_errorLogger_WarnMessageLevel ) return 0;
EnterCriticalSection( &g_error_logger_cs );
va_list l;
va_start( l, _Format );
// no prepend, just vfprintf
ret = vfprintf( g_error_logger_file, _Format, l );
// also write to console, if enabled?
if( g_error_logger_enabled_console )
{
char *cbuffer = (char *)malloc( 20480 );
if( cbuffer )
{
va_list l2;
va_start( l2, _Format );
vsprintf( cbuffer, _Format, l2 );
DWORD numWritten = 0;
WriteConsoleA( g_error_logger_stdout, cbuffer, (DWORD)strlen(cbuffer), &numWritten, NULL );
free( cbuffer );
}
}
LeaveCriticalSection( &g_error_logger_cs );
return ret;
}
//int log_console( LOG_LEVEL logLevel, const char *_Format, ... )
//{
// if( !g_error_logger_enabled_console ) return 0;
//}
//
//int log_console_np( LOG_LEVEL logLevel, const char *_Format, ... )
//{
// if( !g_error_logger_enabled_console ) return 0;
//}
void ErrorLogger_FormatLastError( char *msg, size_t nMaxCount, DWORD error_code )
{
FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error_code, 0, msg, nMaxCount, NULL );
}
void ErrorLogger_LogLastError( char *comment, DWORD error_code )
{
char errbuf[512];
errbuf[0] = 0;
ErrorLogger_FormatLastError( errbuf, 511, error_code );
errbuf[511] = 0;
size_t ll = strlen( errbuf );
if( ll > 0 )
{
if( errbuf[ll-1] == '\n' || errbuf[ll-1] == '\r' ) errbuf[ll-1] = 0;
if( ll > 1 )
{
if( errbuf[ll-2] == '\n' || errbuf[ll-2] == '\r' ) errbuf[ll-2] = 0;
}
}
log_error( LOG_ERROR, "%s: error code: %u (%s)\n", comment, (unsigned int)error_code, errbuf );
}

37
l2ooghelper/Logger.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef FL_ERRORLOGGER_H_
#define FL_ERRORLOGGER_H_
typedef enum eLOG_LEVEL
{
LOG_OK = 0,
LOG_ERROR, // 1
LOG_WARNING, // 2
LOG_USERAI, // 3
LOG_PACKETNAME, // 4
LOG_DEBUG, // 5
LOG_DEBUGDUMP, // 6
LOGLEVEL_LAST = LOG_DEBUGDUMP
} LOG_LEVEL;
#define LOG_LEVELS 7
void ErrorLogger_Init();
void ErrorLogger_Enable( bool bEnable );
void ErrorLogger_EnableLoggingToConsole( bool bEnable );
void ErrorLogger_SetLogFile( FILE *f );
FILE *ErrorLogger_GetLogFile();
void ErrorLogger_FlushLogFile();
void ErrorLogger_SetWarnMessageLevel( LOG_LEVEL level );
void ErrorLogger_SetAutoPrependErrorType( bool bPrepend );
int log_error( LOG_LEVEL logLevel, const char *_Format, ... );
int log_error_np( LOG_LEVEL logLevel, const char *_Format, ... ); // forces NO prepend even if set to
//int log_console( LOG_LEVEL logLevel, const char *_Format, ... );
//int log_console_np( LOG_LEVEL logLevel, const char *_Format, ... );
void ErrorLogger_FormatLastError( char *msg, size_t nMaxCount, DWORD error_code );
void ErrorLogger_LogLastError( char *comment, DWORD error_code );
#endif /*FL_ERRORLOGGER_H_*/

381
l2ooghelper/MainWindow.cpp Normal file
View File

@@ -0,0 +1,381 @@
#include "stdafx.h"
#include "Resource.h"
#include "AccountDlg.h"
#include "Tabs.h"
#include "MainWindow.h"
#include "ScriptEngine.h"
#include "GlobalMapImages.h"
#include "DBLayer.h"
#include "SEH_global.h"
#include "HWID.h"
#include "bot_interaction/BotIPC.h"
#ifdef _DEBUG
#include "Logger.h"
#endif
#define MAX_LOADSTRING 256
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
HINSTANCE g_hInst; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HWND g_hWnd; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
HWND g_hWndTab; // TabControl <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TCHAR szTitle[MAX_LOADSTRING]; // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
TCHAR szWindowClass[MAX_LOADSTRING]; // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
GlobalMapImages g_mapImg; // <20><><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>:
ATOM MyRegisterClass( HINSTANCE hInstance );
BOOL InitInstance( HINSTANCE, int );
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
INT_PTR CALLBACK About( HWND, UINT, WPARAM, LPARAM );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
LRESULT OnCreate();
LRESULT OnClose();
LRESULT OnDestroy();
LRESULT OnCommand( WPARAM wParam, LPARAM lParam );
LRESULT OnNotify( WPARAM wParam, LPARAM lParam );
LRESULT OnPaint();
LRESULT OnSize( WPARAM wParam, LPARAM lParam );
int APIENTRY _tWinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow )
{
UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
MSG msg;
HACCEL hAccelTable;
//
#ifdef _DEBUG
FILE *error_logger_file = fopen( "L2OOGHelper.log", "wt" );
ErrorLogger_Init();
ErrorLogger_SetWarnMessageLevel( LOG_DEBUG );
ErrorLogger_SetAutoPrependErrorType( true );
ErrorLogger_Enable( true );
ErrorLogger_SetLogFile( error_logger_file );
log_error( LOG_OK, "L2OOGHelper: Debug build start\n" );
#endif // _DEBUG
// init Comctl32.dll
InitCommonControls();
#ifdef USE_SEH
// set default error mode and global exception handler
SetErrorMode(0); // Use the system default, which is to display all error dialog boxes.
SetUnhandledExceptionFilter( GlobalUnhandledExceptionFilter );
#ifdef _DEBUG
SEH_loadMap();
#endif
#endif // USE_SEH
#ifdef CHAT_USE_RICHEDIT // <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Riched20.dll (<28><><EFBFBD> RichEdit <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
HINSTANCE hInstDllRichEdit = LoadLibrary( TEXT("Riched20") );
if( !hInstDllRichEdit )
{
#ifdef _DEBUG
log_error( LOG_ERROR, "_tWinMain: cannot load Riched20.dll!" );
#endif
MessageBox( NULL, TEXT("RichEdit control class DLL cannot be loaded\n")
TEXT("(Riched20.dll not found)"),
TEXT("L2OogHelper: FATAL ERROR"), MB_ICONSTOP );
return -1;
}
#ifdef _DEBUG
log_error( LOG_DEBUG, "_tWinMain: Riched20.dll loaded OK\n" );
#endif
#endif // CHAT_USE_RICHEDIT
// verify HWID
if( !verifyHWID() ) return 0;
if( !verifyTimeLimit() ) return 0;
// init WinSock
WSADATA wsadata;
WSAStartup( MAKEWORD(2,0), &wsadata );
// init L2Packets
L2PNet_InitDefault();
L2PacketNames_Init();
L2Data_init();
L2Data_SM_init();
// init caching database layer (based on L2Packets L2Data_*)
DBLayer_init();
// init global map images maps directory
char aCurDir[256] = {0};
GetCurrentDirectoryA( 255, aCurDir );
strcat( aCurDir, "\\maps" );
g_mapImg.setMapsDir( aCurDir );
// init recipe data
L2Data_InitRecipes();
// init Bot interprocess communications
BotIPC::getInstance();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
LoadString( hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING );
LoadString( hInstance, IDC_L2OOGHELPER, szWindowClass, MAX_LOADSTRING );
MyRegisterClass( hInstance );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
if( !InitInstance( hInstance, nCmdShow ) )
{
return FALSE;
}
hAccelTable = LoadAccelerators( hInstance, MAKEINTRESOURCE(IDC_L2OOGHELPER) );
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
while( GetMessage( &msg, NULL, 0, 0) )
{
if( !TranslateAccelerator( msg.hwnd, hAccelTable, &msg ) )
{
//if( !IsDialogMessage( msg.hwnd, &msg ) ) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>, <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
//{
TranslateMessage( &msg );
DispatchMessage( &msg );
//}
}
}
BotIPC::getInstance()->delAllMyProcessBots(); // safe cleanup
BotIPC::freeInstance();
L2Data_SM_free();
DBLayer_free();
WSACleanup();
g_mapImg.unloadAllSquares();
if( g_mapImg.getLoadedCount() > 0 )
{
MessageBox( NULL, TEXT("GlobalMapImages: not all images are unloaded!"),
TEXT("Warning! Potential memory leaks!"), MB_ICONWARNING );
}
#ifdef _DEBUG
log_error( LOG_OK, "Closing log; last message... Bye!\n" );
ErrorLogger_SetLogFile( stdout );
ErrorLogger_Enable( false );
if( error_logger_file ) fclose( error_logger_file );
error_logger_file = NULL;
#endif
return (int)msg.wParam;
}
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: MyRegisterClass()
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
//
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Win32, <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> RegisterClassEx'
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> Windows 95. <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD>,
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
// <20> <20><><EFBFBD><EFBFBD>.
//
ATOM MyRegisterClass( HINSTANCE hInstance )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_OWNDC; // | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon( hInstance, MAKEINTRESOURCE(IDI_L2OOGHELPER) );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = (HBRUSH)( COLOR_WINDOW + 1 );
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_L2OOGHELPER);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon( wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL) );
return RegisterClassEx( &wcex );
}
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: InitInstance(HINSTANCE, int)
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>.
//
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
//
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20> <20><><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
//
BOOL InitInstance( HINSTANCE hInstance, int nCmdShow )
{
HWND hWnd;
g_hInst = hInstance; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
hWnd = CreateWindow( szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, 960 /*CW_USEDEFAULT*/, 695, NULL, NULL, hInstance, NULL );
if( !hWnd ) return FALSE;
ShowWindow( hWnd, nCmdShow );
UpdateWindow( hWnd );
return TRUE;
}
LRESULT OnCreate()
{
RECT r;
GetClientRect( g_hWnd, &r );
// init common controls :)
INITCOMMONCONTROLSEX icex;
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_TAB_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TREEVIEW_CLASSES |
ICC_BAR_CLASSES | ICC_STANDARD_CLASSES | ICC_PROGRESS_CLASS;
InitCommonControlsEx( &icex );
// create tab control
g_hWndTab = CreateWindowEx( 0, WC_TABCONTROL, NULL,
WS_CHILD | WS_VISIBLE | TCS_MULTILINE | TCS_TABS,
0, 0, r.right - r.left, r.bottom - r.top, g_hWnd, NULL, g_hInst, NULL );
//
Tabs_Init();
return 0;
}
LRESULT OnClose()
{
return 0;
}
LRESULT OnDestroy()
{
PostQuitMessage( 0 );
return 0;
}
LRESULT OnCommand( WPARAM wParam, LPARAM lParam )
{
int wmId, wmEvent;
wmId = LOWORD( wParam );
wmEvent = HIWORD( wParam );
switch( wmId )
{
case IDM_ABOUT:
DialogBox( g_hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), g_hWnd, About );
break;
case IDM_EXIT:
PostMessage( g_hWnd, WM_CLOSE, 0, 0 );
break;
case IDM_LINEAGE_ADD_ACC:
{
AccountDlg *dlg = new AccountDlg();
if( dlg->run( g_hWnd ) )
{
Account acc = dlg->getAccount();
Tabs_AddAccount( &acc );
}
delete dlg;
} break;
#ifdef _DEBUG
case ID_DEBUG_ENABLECON: ErrorLogger_EnableLoggingToConsole( true ); break;
case ID_DEBUG_DISABLECON: ErrorLogger_EnableLoggingToConsole( false ); break;
case ID_LOGLEVEL_OK: ErrorLogger_SetWarnMessageLevel( LOG_OK ); break;
case ID_LOGLEVEL_ERROR: ErrorLogger_SetWarnMessageLevel( LOG_ERROR ); break;
case ID_LOGLEVEL_WARN: ErrorLogger_SetWarnMessageLevel( LOG_WARNING ); break;
case ID_LOGLEVEL_USERAI: ErrorLogger_SetWarnMessageLevel( LOG_USERAI ); break;
case ID_LOGLEVEL_PACKETNAME: ErrorLogger_SetWarnMessageLevel( LOG_PACKETNAME ); break;
case ID_LOGLEVEL_DEBUG: ErrorLogger_SetWarnMessageLevel( LOG_DEBUG ); break;
case ID_LOGLEVEL_DEBUGDUMP: ErrorLogger_SetWarnMessageLevel( LOG_DEBUGDUMP ); break;
/*case ID_DEBUG_RUNTESTSCRIPT:
{
ScriptEngine se;
se.init();
se.startScript( "test.lua" );
se.deinit();
} break;*/
#endif
default:
return DefWindowProc( g_hWnd, WM_COMMAND, wParam, lParam );
}
return 0;
}
LRESULT OnNotify( WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(wParam);
LPNMHDR lpnmhdr = (LPNMHDR)lParam;
switch( lpnmhdr->code )
{
case TCN_SELCHANGING: Tabs_OnSelChanging( lpnmhdr ); break;
case TCN_SELCHANGE: Tabs_OnSelChange( lpnmhdr ); break;
}
return 0;
}
LRESULT OnPaint()
{
//RECT wr;
//GetWindowRect( hWnd, &wr );
//TCHAR tstr[256];
//wsprintf( tstr, TEXT("%d x %d"), wr.right - wr.left, wr.bottom - wr.top );
PAINTSTRUCT ps;
HDC hdc;
hdc = BeginPaint( g_hWnd, &ps );
// TODO: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
//TextOut( hdc, 0, 0, tstr, lstrlen(tstr) );
EndPaint( g_hWnd, &ps );
Tabs_OnPaint();
return 0;
}
LRESULT OnSize( WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(wParam);
/*lParam:
The low-order word of lParam specifies the new width of the client area.
The high-order word of lParam specifies the new height of the client area.*/
int w = LOWORD( lParam );
int h = HIWORD( lParam );
// resize tab
MoveWindow( g_hWndTab, 0, 0, w, h, TRUE );
return 0;
}
LRESULT OnMyDeleteTab( LPARAM lParam )
{
Tabs_DeleteTab( (int)lParam );
return 0;
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_CREATE:
{
g_hWnd = hWnd;
return OnCreate();
} break;
case WM_COMMAND: return OnCommand( wParam, lParam ); break;
case WM_PAINT: return OnPaint(); break;
case WM_DESTROY: return OnDestroy(); break;
case WM_SIZE: return OnSize( wParam, lParam ); break;
case WM_NOTIFY: return OnNotify( wParam, lParam ); break;
case WMMY_DELETETAB: return OnMyDeleteTab( lParam ); break;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD> "<22> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>".
INT_PTR CALLBACK About( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(lParam);
switch( message )
{
case WM_INITDIALOG: return (INT_PTR)TRUE;
case WM_COMMAND:
if( LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL )
{
EndDialog( hDlg, LOWORD(wParam) );
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}

6
l2ooghelper/MainWindow.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef H_MAINWINDOW
#define H_MAINWINDOW
#define WMMY_DELETETAB (WM_USER+1) // lparam is tab_id
#endif

View File

@@ -0,0 +1,320 @@
#include "stdafx.h"
#include "Resource.h"
#include "windowUtils.h"
#include "logger.h"
#include "DBLayer.h"
//
#include "CharArray.h"
#include "NpcArray.h"
#include "GIArray.h"
#include "IL2Client.h"
extern HINSTANCE g_hInst;
INT_PTR CALLBACK MapItemsTabDlg_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
HWND MapItemsTabDlg_Create( HWND hWndParent, IL2Client *pcl )
{
HWND hDlg = CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_MAPINFO),
hWndParent, MapItemsTabDlg_Proc, (LPARAM)pcl );
return hDlg;
}
#define MAP_TABS 4
typedef struct stMapTab
{
int nTabs;
HWND hwndLV[MAP_TABS];
IL2Client *cl;
} MapTab;
void MapItem_updatePlayers( HWND hDlg, LPARAM lParam );
void MapItem_updateNpcs( HWND hDlg, LPARAM lParam, bool mobs );
void MapItem_updateItems( HWND hDlg, LPARAM lParam );
INT_PTR CALLBACK MapItemsTabDlg_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
IL2Client *pcl = (IL2Client *)lParam;
//
MapTab *st = (MapTab *)malloc( sizeof(MapTab) );
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)st );
st->nTabs = MAP_TABS;
st->cl = pcl;
//
HWND hWndTab = GetDlgItem( hDlg, IDC_TAB2 );
WUTab_InsertItem( hWndTab, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 0 );
WUTab_InsertItem( hWndTab, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 1 );
WUTab_InsertItem( hWndTab, TEXT("<EFBFBD><EFBFBD><EFBFBD>"), 2 );
WUTab_InsertItem( hWndTab, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 3 );
//
RECT rc;
GetClientRect( hWndTab, &rc );
// players
HWND hwndLV = CreateWindowEx( WS_EX_CLIENTEDGE,
WC_LISTVIEW, NULL,
WS_VSCROLL | WS_CHILD | WS_VISIBLE |
LVS_REPORT | LVS_SORTASCENDING | LVS_SINGLESEL | LVS_SHOWSELALWAYS,
2, 24, rc.right - rc.left - 5, rc.bottom - rc.top - 30,
hWndTab, (HMENU)100, g_hInst, NULL );
st->hwndLV[0] = hwndLV;
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD>"), 100, 0 );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 100, 1 );
WULV_InsertColumn( hwndLV, TEXT("dz"), 50, 2 );
WULV_InsertColumn( hwndLV, TEXT("war"), 50, 3 );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 100, 4 );
// mobs
hwndLV = CreateWindowEx( WS_EX_CLIENTEDGE,
WC_LISTVIEW, NULL,
WS_VSCROLL | WS_CHILD | /*WS_VISIBLE |*/
LVS_REPORT | LVS_SORTASCENDING | LVS_SINGLESEL | LVS_SHOWSELALWAYS,
2, 24, rc.right - rc.left - 5, rc.bottom - rc.top - 30,
hWndTab, (HMENU)101, g_hInst, NULL );
st->hwndLV[1] = hwndLV;
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD>"), 100, 0 );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 80, 1 );
WULV_InsertColumn( hwndLV, TEXT("npcID"), 50, 2 );
WULV_InsertColumn( hwndLV, TEXT("dz"), 50, 3 );
// NPC
hwndLV = CreateWindowEx( WS_EX_CLIENTEDGE,
WC_LISTVIEW, NULL,
WS_VSCROLL | WS_CHILD | /*WS_VISIBLE |*/
LVS_REPORT | LVS_SORTASCENDING | LVS_SINGLESEL | LVS_SHOWSELALWAYS,
2, 24, rc.right - rc.left - 5, rc.bottom - rc.top - 30,
hWndTab, (HMENU)102, g_hInst, NULL );
st->hwndLV[2] = hwndLV;
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD>"), 130, 0 );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 80, 1 );
WULV_InsertColumn( hwndLV, TEXT("npcID"), 50, 2 );
WULV_InsertColumn( hwndLV, TEXT("dz"), 50, 3 );
// Items
hwndLV = CreateWindowEx( WS_EX_CLIENTEDGE,
WC_LISTVIEW, NULL,
WS_VSCROLL | WS_CHILD | /*WS_VISIBLE |*/
LVS_REPORT | LVS_SORTASCENDING | LVS_SINGLESEL | LVS_SHOWSELALWAYS,
2, 24, rc.right - rc.left - 5, rc.bottom - rc.top - 30,
hWndTab, (HMENU)103, g_hInst, NULL );
st->hwndLV[3] = hwndLV;
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), 130, 0 );
WULV_InsertColumn( hwndLV, TEXT("itemID"), 50, 1 );
WULV_InsertColumn( hwndLV, TEXT("<EFBFBD><EFBFBD><EFBFBD>-<2D><>"), 50, 2 );
} break;
case WM_DESTROY:
{
MapTab *st = (MapTab *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( st ) free( st );
SetWindowLongPtr( hDlg, GWLP_USERDATA, 0 );
} break;
case WM_NOTIFY:
{
LPNMHDR phdr = (LPNMHDR)lParam;
HWND hWndTab = GetDlgItem( hDlg, IDC_TAB2 );
MapTab *st = (MapTab *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( phdr->hwndFrom == hWndTab )
{
int cur_sel = TabCtrl_GetCurSel( hWndTab );
switch( phdr->code )
{
case TCN_SELCHANGING:
{
if( (cur_sel >= 0) && (cur_sel < st->nTabs) ) ShowWindow( st->hwndLV[cur_sel], SW_HIDE );
} break;
case TCN_SELCHANGE:
{
if( (cur_sel >= 0) && (cur_sel < st->nTabs) ) ShowWindow( st->hwndLV[cur_sel], SW_SHOW );
} break;
}
}
if( phdr->code == NM_DBLCLK )
{
LPNMITEMACTIVATE lpnmitemactivate = (LPNMITEMACTIVATE)lParam;
int i;
for( i=0; i<st->nTabs; i++ )
{
if( phdr->hwndFrom == st->hwndLV[i] )
{
unsigned int objectID = (unsigned int)WULV_GetItemLPARAM( st->hwndLV[i], lpnmitemactivate->iItem );
if( objectID > 0 )
{
//log_error( LOG_OK, "Map LV action to oid %u\n", objectID );
st->cl->game_Action( objectID );
}
}
}
}
} break;
case WM_USER:
{
int tabId = (int)wParam;
log_error( LOG_DEBUG, "MapItemsTabDlgProc(): update tab %d\n", tabId );
switch( tabId )
{
case 0: MapItem_updatePlayers( hDlg, lParam ); break;
case 1: MapItem_updateNpcs( hDlg, lParam, true ); break;
case 2: MapItem_updateNpcs( hDlg, lParam, false ); break;
case 3: MapItem_updateItems( hDlg, lParam ); break;
}
} break;
default: return FALSE; break;
}
return TRUE;
}
void MapItem_updatePlayers( HWND hDlg, LPARAM lParam )
{
MapTab *st = (MapTab *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !st ) return;
IL2Client *pcl = (IL2Client *)lParam;
if( !pcl ) return;
CharArray *ca = pcl->get_WorldChars();
ClanList *cl = pcl->get_WorldClans();
UserInfo *usr = pcl->get_UserInfo();
// Lock !!!
ca->Lock();
cl->Lock();
///
HWND hwndLV = st->hwndLV[0];
ListView_DeleteAllItems( hwndLV );
int i;
int added_item;
TCHAR text[256] = {0};
int dz;
unsigned int nDisplayed = 0;
for( i=0; i<CharArray::CHARARRAY_MAX_CHARS; i++ )
{
if( ca->chars_array[i]->isUnused() ) continue;
nDisplayed++;
added_item = WULV_InsertItem( hwndLV, ca->chars_array[i]->charName, 0, ca->chars_array[i]->objectID );
// class
if( ca->chars_array[i]->classID != ca->chars_array[i]->baseClassID )
{
wsprintf( text, TEXT("%S / %S"),
L2Data_getClass( ca->chars_array[i]->classID ),
L2Data_getClass( ca->chars_array[i]->baseClassID ) );
}
else
{
wsprintf( text, TEXT("%S"), L2Data_getClass( ca->chars_array[i]->classID ) );
}
WULV_SetItem( hwndLV, text, added_item, 1 );
// dz
dz = usr->z - ca->chars_array[i]->z;
wsprintf( text, TEXT("%d"), dz );
WULV_SetItem( hwndLV, text, added_item, 2 );
// war state
text[0] = 0;
switch( ca->chars_array[i]->relation )
{
case L2Player::RELATION_1SIDED_WAR: lstrcpy( text, TEXT("<") ); break;
case L2Player::RELATION_MUTUAL_WAR: lstrcpy( text, TEXT("<>") ); break;
}
WULV_SetItem( hwndLV, text, added_item, 3 );
// clan
if( ca->chars_array[i]->clanID )
cl->GetClanNameByID( ca->chars_array[i]->clanID, text );
WULV_SetItem( hwndLV, text, added_item, 4 );
//
if( nDisplayed >= ca->GetCount() ) break;
}
// Unlock!!!
ca->Unlock();
cl->Unlock();
}
void MapItem_updateNpcs( HWND hDlg, LPARAM lParam, bool mobs )
{
MapTab *st = (MapTab *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !st ) return;
IL2Client *pcl = (IL2Client *)lParam;
if( !pcl ) return;
NpcArray *na = pcl->get_WorldNpcs();
UserInfo *usr = pcl->get_UserInfo();
//
na->Lock();
//
HWND hwndLV = st->hwndLV[1];
if( !mobs ) hwndLV = st->hwndLV[2];
ListView_DeleteAllItems( hwndLV );
int i;
int added_item;
TCHAR text[256] = {0};
wchar_t npcName[256] = {0}, npcTitle[256] = {0};
int dz;
unsigned int nDisplayed = 0;
for( i=0; i<NpcArray::NPCA_MAX_NPCS; i++ )
{
if( na->npcs_array[i]->isUnused() ) continue;
nDisplayed++; // not really displayed, but passed index in array
if( mobs && !na->npcs_array[i]->isAttackable ) continue;
if( !mobs && na->npcs_array[i]->isAttackable ) continue;
npcName[0] = 0, npcTitle[0] = 0;
text[0] = 0;
// mob name, title, npcID, dz
// name
if( na->npcs_array[i]->charName[0] == 0 )
{
DBLayer_getNpcNameTitle( na->npcs_array[i]->templateID, npcName, 256, npcTitle, 256 );
na->npcs_array[i]->setName( npcName );
}
added_item = WULV_InsertItem( hwndLV, na->npcs_array[i]->charName, 0, na->npcs_array[i]->objectID );
// title
if( na->npcs_array[i]->charTitle[0] == 0 )
if( npcTitle[0] != 0 ) na->npcs_array[i]->setTitle( npcTitle );
WULV_SetItem( hwndLV, na->npcs_array[i]->charTitle, added_item, 1 );
// npcID
wsprintf( text, TEXT("%u"), na->npcs_array[i]->templateID );
WULV_SetItem( hwndLV, text, added_item, 2 );
// dz
dz = usr->z - na->npcs_array[i]->z;
wsprintf( text, TEXT("%d"), dz );
WULV_SetItem( hwndLV, text, added_item, 3 );
//
if( nDisplayed >= na->getCount() ) break;
}
na->Unlock();
}
void MapItem_updateItems( HWND hDlg, LPARAM lParam )
{
MapTab *st = (MapTab *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !st ) return;
IL2Client *pcl = (IL2Client *)lParam;
if( !pcl ) return;
GIArray *ga = pcl->get_WorldItems();
// lock
ga->Lock();
//
HWND hwndLV = st->hwndLV[3];
ListView_DeleteAllItems( hwndLV );
int i;
int added_item;
TCHAR text[256] = {0};
unsigned int nDisplayed = 0;
for( i=0; i<GIArray::GA_MAX_ITEMS; i++ )
{
if( ga->gi_array[i]->isUnused() ) continue;
nDisplayed++; // not really displayed, but passed index in array
text[0] = 0;
// item name, itemID, count
// item name
DBLayer_getItemName( ga->gi_array[i]->itemID, text, 255 );
added_item = WULV_InsertItem( hwndLV, text, 0, ga->gi_array[i]->objectID );
// itemID
wsprintf( text, TEXT("%u"), ga->gi_array[i]->itemID );
WULV_SetItem( hwndLV, text, added_item, 1 );
// count
wsprintf( text, TEXT("%d"), ga->gi_array[i]->count );
WULV_SetItem( hwndLV, text, added_item, 2 );
//
if( nDisplayed >= ga->getCount() ) break;
}
ga->Unlock();
}

View File

@@ -0,0 +1,6 @@
#ifndef H_MAPITEMSTABDLG
#define H_MAPITEMSTABDLG
HWND MapItemsTabDlg_Create( HWND hWndParent, IL2Client *pcl );
#endif

View File

@@ -0,0 +1,18 @@
#include "stdafx.h"
#include "MapShowParams.h"
void st_MapShowParams::init()
{
// map checks
zrange = 5000;
mobs = 0;
npcs = 0;
pcs = 1;
items = 0;
vectors = 1;
fightrange = 0;
realmap = 0;
sellshop = 0;
craftshop = 0;
buyshop = 0;
}

View File

@@ -0,0 +1,23 @@
#ifndef H_MAPSHOWPARAMS
#define H_MAPSHOWPARAMS
class st_MapShowParams
{
public:
void init();
public:
// map checks
int zrange;
int mobs;
int npcs;
int pcs;
int items;
int vectors;
int fightrange;
int realmap;
int sellshop;
int craftshop;
int buyshop;
};
#endif

745
l2ooghelper/MapWnd.cpp Normal file
View File

@@ -0,0 +1,745 @@
#include "stdafx.h"
#include "Resource.h"
#include "IL2Client.h"
#include "MapWnd.h"
#include "GlobalMapImages.h"
#include "logger.h"
#include "DBLayer.h"
extern GlobalMapImages g_mapImg;
WNDPROC OriginalMapStaticProc = NULL;
LRESULT CALLBACK NewMapStaticProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
//const int MapWindowBrushes = 1;
const int MapWindowPens = 8;
const int MapWindowFonts = 1;
struct MapWindowStruct
{
IL2Client *pcl; // L2Client interface
HDC hdcc; // compatible DC
HBITMAP hbm; // compatible bitmap
// gdi
HPEN pens[MapWindowPens];
HFONT fonts[MapWindowFonts];
// map image
HDC hdcImage; // NULL if not loaded
int geo_x;
int geo_y;
int geo_img_w;
int geo_img_h;
};
void Map_struct_create( MapWindowStruct *st )
{
HPEN hpenMob = CreatePen( PS_SOLID, 1, RGB(255,0,0) );
HPEN hpenParty = CreatePen( PS_SOLID, 1, RGB(0,255,0) );
HPEN hpenPc = CreatePen( PS_SOLID, 1, RGB(0,0,255) );
HPEN hpenNpc = CreatePen( PS_SOLID, 1, RGB(255,255,0) );
HPEN hpenMoveVector = CreatePen( PS_SOLID, 1, RGB(60,60,60) );
HPEN hpenItem = CreatePen( PS_SOLID, 1, RGB(255,128,64) );
HPEN hpenTarget = CreatePen( PS_SOLID, 1, RGB(255,0,255) );
HPEN hpenDeadMob = CreatePen( PS_SOLID, 1, RGB(128,128,128) );
//
st->pens[0] = hpenMob;
st->pens[1] = hpenParty;
st->pens[2] = hpenPc;
st->pens[3] = hpenNpc;
st->pens[4] = hpenMoveVector;
st->pens[5] = hpenItem;
st->pens[6] = hpenTarget;
st->pens[7] = hpenDeadMob;
//
//st->fonts[0] = CreateFont( 11, 5, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET,
st->fonts[0] = CreateFont( 14, 5, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
/*DEFAULT_QUALITY,*/ ANTIALIASED_QUALITY,
FF_DONTCARE, TEXT("Arial") );
// map image
st->hdcImage = NULL;
st->geo_x = 0;
st->geo_y = 0;
st->geo_img_w = 0;
st->geo_img_h = 0;
}
void Map_struct_delete( MapWindowStruct *st )
{
int i;
for( i=0; i<MapWindowPens; i++ ) DeleteObject( st->pens[i] );
for( i=0; i<MapWindowFonts; i++ ) DeleteObject( st->fonts[i] );
DeleteDC( st->hdcc );
DeleteObject( (HGDIOBJ)st->hbm );
// map image
st->hdcImage = NULL;
// free all struct mem
HeapFree( GetProcessHeap(), 0, st );
}
void Map_struct_check_geo_square_and_preload_image( MapWindowStruct *st, int usr_x, int usr_y );
void SubclassMapWindowProc( HWND hWnd, IL2Client *pcl )
{
if( OriginalMapStaticProc == NULL )
{
OriginalMapStaticProc = (WNDPROC)(LPVOID)GetWindowLongPtr( hWnd, GWLP_WNDPROC );
//log_error( LOG_OK, "SubclassMapWindowProc: saved old, userdata: 0x%08X\n", GetWindowLongPtr( hWnd, GWLP_USERDATA ) );
}
//
RECT rc;
GetClientRect( hWnd, &rc );
//
MapWindowStruct *st = (MapWindowStruct *)HeapAlloc( GetProcessHeap(), 0, sizeof(MapWindowStruct) );
st->pcl = pcl;
st->hdcc = NULL;
st->hbm = NULL;
Map_struct_create( st );
//
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)st );
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR)(LPVOID)NewMapStaticProc );
}
void NewMapStatic_OnPaint( HWND hWnd );
void NewMapStatic_OnMouseMove( HWND hWnd, WPARAM wParam, LPARAM lParam );
void NewMapStatic_OnLButtonUp( HWND hWnd, WPARAM wParam, LPARAM lParam );
void NewMapStatic_ReloadImage( HWND hWnd );
LRESULT CALLBACK NewMapStaticProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT ret = 0;
switch( uMsg )
{
case WM_PAINT: NewMapStatic_OnPaint( hWnd ); break;
case WM_LBUTTONDOWN: NewMapStatic_OnLButtonUp( hWnd, wParam, lParam ); break;
case WM_DESTROY:
{
MapWindowStruct *st = (MapWindowStruct *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
Map_struct_delete( st );
ret = CallWindowProc( OriginalMapStaticProc, hWnd, uMsg, wParam, lParam );
} break;
case WM_USER: NewMapStatic_ReloadImage( hWnd ); break;
default: ret = CallWindowProc( OriginalMapStaticProc, hWnd, uMsg, wParam, lParam ); break;
}
return ret;
}
void NewMapStatic_OnPaint( HWND hWnd )
{
//log_error_np( LOG_OK, "WM_PAINT\n" );
//
RECT rc;
GetClientRect( hWnd, &rc );
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
int cx = w/2;
int cy = h/2;
int min_size = h;
if( w < min_size ) min_size = w;
MapWindowStruct *st = (MapWindowStruct *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
// init hdc?
if( st->hdcc == NULL )
{
HDC hdc = GetDC( hWnd ); // get window hdc
st->hdcc = CreateCompatibleDC( hdc );
st->hbm = CreateCompatibleBitmap( hdc, w, h );
SelectObject( st->hdcc, (HGDIOBJ)st->hbm );
SelectObject( st->hdcc, GetStockObject( WHITE_PEN ) );
SelectObject( st->hdcc, GetStockObject( BLACK_BRUSH ) );
SelectObject( st->hdcc, st->fonts[0] );
SetStretchBltMode( st->hdcc, HALFTONE ); // TODO: check StretchBlt mode
// release window hdc
ReleaseDC( hWnd, hdc );
//log_error( LOG_OK, "NewMapStaticProc(): init %d x %d\n", w, h );
st->hdcImage = NULL;
}
// init
const int map_text_h = 13;
const double max_range = 20000.0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// scale - <20>-<2D><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>2, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" <20> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double scale = max_range * (double)st->pcl->get_MapScale() / 100.0;
// scale_k <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20>2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD>
double scale_k = scale / (double)min_size;
unsigned int nDisplayed = 0;
unsigned int i;
int map_dx = 0, map_dy = 0, map_dz = 0;
UserInfo *pusr = st->pcl->get_UserInfo();
int usr_x = pusr->x;
int usr_y = pusr->y;
int usr_z = pusr->z;
int usr_xDst = pusr->xDst;
int usr_yDst = pusr->yDst;
int screen_dx = 0, screen_dy = 0;
int draw_x = 0, draw_y = 0;
int sq_w = 4;
// map show text params
st_MapShowParams map_show;
st->pcl->getMapShowParams( &map_show );
//
// all drawing below
//
// save old gdi objects
//HBRUSH oldBrush = (HBRUSH)SelectObject( st->hdcc, GetStockObject( NULL_BRUSH ) );
//HPEN oldPen = (HPEN)SelectObject( st->hdcc, GetStockObject( WHITE_PEN ) );
//HFONT oldFont = (HFONT)SelectObject( st->hdcc, GetStockObject( ANSI_VAR_FONT ) );
//
SelectObject( st->hdcc, GetStockObject( BLACK_PEN ) );
SelectObject( st->hdcc, GetStockObject( BLACK_BRUSH ) );
SetBkMode( st->hdcc, TRANSPARENT );
SetTextColor( st->hdcc, RGB(255,255,255) );
// map background:
Rectangle( st->hdcc, 0, 0, w, h ); // black rect
// if map show enabled, show
if( map_show.realmap ) // real map
{
Map_struct_check_geo_square_and_preload_image( st, usr_x, usr_y );
if( st->hdcImage && (st->geo_x>0) && (st->geo_y>0) )
{
// preloaded into surface, BitBlt/StretchBlt
// scale - <20>-<2D><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>2, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" <20> <20><><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// 33333 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// geoimg_scale - <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20>2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double geoimg_scale = ((double)GlobalMapImages::GEO_BOX_L2_SIZE) / ((double)st->geo_img_w);
// screen_geoimg_w - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>) <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>).
// <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int screen_geoimg_w = (int)( (scale / geoimg_scale) + 0.5 );
int geo_square_l2_x = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20>2 <20><><EFBFBD><EFBFBD>
int geo_square_l2_y = 0;
GlobalMapImages::GetGeoSquareStartL2Coords( st->geo_x, st->geo_y, &geo_square_l2_x, &geo_square_l2_y );
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20>2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int geo_square_l2_user_dx = usr_x - geo_square_l2_x;
int geo_square_l2_user_dy = usr_y - geo_square_l2_y;
int geoimg_offset_x = (int)( ((double)geo_square_l2_user_dx - scale/2 ) / geoimg_scale + 0.5 );
int geoimg_offset_y = (int)( ((double)geo_square_l2_user_dy - scale/2 ) / geoimg_scale + 0.5 );
//
StretchBlt( st->hdcc,
0, 0, min_size, min_size,
st->hdcImage,
geoimg_offset_x, geoimg_offset_y, screen_geoimg_w, screen_geoimg_w,
SRCCOPY );
}
}
//
// display all npcs
//
unsigned int count = 0;
NpcArray *pnpcs = st->pcl->get_WorldNpcs();
if( pnpcs->getCount() > 0 )
{
SelectObject( st->hdcc, st->pens[3] );
nDisplayed = 0;
pnpcs->Lock();
count = pnpcs->getCount();
for( i=0; i<NpcArray::NPCA_MAX_NPCS; i++ )
{
if( pnpcs->npcs_array[i]->isUnused() ) continue;
nDisplayed++;
//
map_dx = pnpcs->npcs_array[i]->x - usr_x;
map_dy = pnpcs->npcs_array[i]->y - usr_y;
map_dz = pnpcs->npcs_array[i]->z - usr_z;
if( abs( map_dz ) >= map_show.zrange )
{
log_error( LOG_DEBUG, "Denied display npc [%S] because map_dz is %d (zrange %d)\n",
pnpcs->npcs_array[i]->charName, map_dz, map_show.zrange );
continue; // not fit in zrange
}
//
screen_dx = (int)( (double)map_dx / scale_k );
screen_dy = (int)( (double)map_dy / scale_k );
//
SelectObject( st->hdcc, st->pens[3] ); // npc pen
if( pnpcs->npcs_array[i]->isAttackable ) SelectObject( st->hdcc, st->pens[0] ); // mob pen
if( pnpcs->npcs_array[i]->isAlikeDead ) SelectObject( st->hdcc, st->pens[7] ); // dead pen
if( pnpcs->npcs_array[i]->objectID == pusr->targetObjectID ) SelectObject( st->hdcc, st->pens[6] ); // target pen
draw_x = cx + screen_dx;
draw_y = cy + screen_dy;
Rectangle( st->hdcc, draw_x - 1, draw_y - 1, draw_x + sq_w, draw_y + sq_w );
// vector?
if( map_show.vectors )
{
if( pnpcs->npcs_array[i]->isMoving() )
{
int map_vector_dx = pnpcs->npcs_array[i]->xDst - pnpcs->npcs_array[i]->x;
int map_vector_dy = pnpcs->npcs_array[i]->yDst - pnpcs->npcs_array[i]->y;
int screen_vector_dx = (int)( (double)map_vector_dx / scale_k );
int screen_vector_dy = (int)( (double)map_vector_dy / scale_k );
SelectObject( st->hdcc, st->pens[4] );
MoveToEx( st->hdcc, draw_x+1, draw_y+1, NULL );
LineTo( st->hdcc, draw_x+1+screen_vector_dx, draw_y+1+screen_vector_dy );
}
}
// npc name?
bool show_text = false;
if( (pnpcs->npcs_array[i]->isAttackable) && map_show.mobs ) show_text = true;
if( (!pnpcs->npcs_array[i]->isAttackable) && map_show.npcs ) show_text = true;
if( show_text )
{
wchar_t *text = pnpcs->npcs_array[i]->charName;
//TextOutW( st->hdcc, draw_x, draw_y, text, wcslen( text ) );
rc.left = draw_x - 100;
rc.right = draw_x + 100;
rc.bottom = draw_y;
rc.top = rc.bottom - map_text_h;
DrawText( st->hdcc, text, wcslen(text), &rc, DT_CENTER | DT_VCENTER );
}
//
if( nDisplayed >= count ) break;
}
pnpcs->Unlock();
}
//
// display all items
//
GIArray *pitems = st->pcl->get_WorldItems();
if( pitems->getCount() > 0 )
{
nDisplayed = 0;
SelectObject( st->hdcc, st->pens[5] );
pitems->Lock();
count = pitems->getCount();
for( i=0; i<GIArray::GA_MAX_ITEMS; i++ )
{
if( pitems->gi_array[i]->isUnused() ) continue;
nDisplayed++;
//
map_dx = pitems->gi_array[i]->x - usr_x;
map_dy = pitems->gi_array[i]->y - usr_y;
map_dz = pitems->gi_array[i]->z - usr_z;
if( abs( map_dz ) >= map_show.zrange ) continue; // not fit in zrange
//
screen_dx = (int)( (double)map_dx / scale_k );
screen_dy = (int)( (double)map_dy / scale_k );
//
draw_x = cx + screen_dx;
draw_y = cy + screen_dy;
Rectangle( st->hdcc, draw_x - 1, draw_y - 1, draw_x + sq_w, draw_y + sq_w );
// show name?
if( map_show.items )
{
wchar_t text[256] = {0};
// itemName is no longer part og GroundItem
//if( pitems->gi_array[i]->itemName[0] )
// MultiByteToWideChar( CP_ACP, 0, pitems->gi_array[i]->itemName, -1, text, 255 );
// use cached DB layer instead
DBLayer_getItemName( pitems->gi_array[i]->itemID, text, 255 );
if( text[0] )
{
rc.left = draw_x - 100;
rc.right = draw_x + 100;
rc.bottom = draw_y;
rc.top = rc.bottom - map_text_h;
DrawText( st->hdcc, text, wcslen(text), &rc, DT_CENTER | DT_VCENTER );
}
}
//
if( nDisplayed >= count ) break;
}
pitems->Unlock();
}
//
//
// display all players
//
UserParty *pparty = st->pcl->get_Party();
CharArray *pchars = st->pcl->get_WorldChars();
if( pchars->GetCount() > 0 )
{
nDisplayed = 0;
SelectObject( st->hdcc, st->pens[2] ); // pc
pchars->Lock();
count = pchars->GetCount();
for( i=0; i<CharArray::CHARARRAY_MAX_CHARS; i++ )
{
if( pchars->chars_array[i]->isUnused() ) continue;
nDisplayed++;
//
map_dx = pchars->chars_array[i]->x - usr_x;
map_dy = pchars->chars_array[i]->y - usr_y;
map_dz = pchars->chars_array[i]->z - usr_z;
if( abs( map_dz ) >= map_show.zrange ) continue; // not fit in zrange
//
screen_dx = (int)( (double)map_dx / scale_k );
screen_dy = (int)( (double)map_dy / scale_k );
//
draw_x = cx + screen_dx;
draw_y = cy + screen_dy;
SelectObject( st->hdcc, st->pens[2] ); // always select pc pen beore draw
if( pparty->isInParty( pchars->chars_array[i]->objectID, NULL ) ) SelectObject( st->hdcc, st->pens[1] ); // party
if( pchars->chars_array[i]->objectID == pusr->targetObjectID ) SelectObject( st->hdcc, st->pens[6] ); // target
Rectangle( st->hdcc, draw_x - 1, draw_y - 1, draw_x + sq_w, draw_y + sq_w );
// vector?
if( map_show.vectors )
{
if( pchars->chars_array[i]->isMoving() )
{
int map_vector_dx = pchars->chars_array[i]->xDst - pchars->chars_array[i]->x;
int map_vector_dy = pchars->chars_array[i]->yDst - pchars->chars_array[i]->y;
int screen_vector_dx = (int)( (double)map_vector_dx / scale_k );
int screen_vector_dy = (int)( (double)map_vector_dy / scale_k );
SelectObject( st->hdcc, st->pens[4] );
MoveToEx( st->hdcc, draw_x+1, draw_y+1, NULL );
LineTo( st->hdcc, draw_x+1+screen_vector_dx, draw_y+1+screen_vector_dy );
}
}
// show name?
if( map_show.pcs || (pchars->chars_array[i]->privateStoreType > 0) )
{
wchar_t *text = pchars->chars_array[i]->charName;
//TextOutW( st->hdcc, draw_x, draw_y, text, wcslen( text ) );
rc.left = draw_x - 100;
rc.right = draw_x + 100;
rc.bottom = draw_y;
rc.top = rc.bottom - map_text_h;
if( map_show.pcs ) DrawText( st->hdcc, text, wcslen(text), &rc, DT_CENTER | DT_VCENTER );
if( pchars->chars_array[i]->privateStoreType > 0 )
{
wchar_t *storemsg = NULL;
COLORREF textColor = RGB(255,255,255);
switch( pchars->chars_array[i]->privateStoreType )
{
case L2Player::PRIVATE_STORE_BUY:
{
if( map_show.buyshop )
{
storemsg = pchars->chars_array[i]->privateStoreMsgBuy;
textColor = RGB(255,255,151);
}
} break;
case L2Player::PRIVATE_STORE_SELL:
{
if( map_show.sellshop )
{
storemsg = pchars->chars_array[i]->privateStoreMsgSell;
textColor = RGB(255,108,255);
}
} break;
case L2Player::PRIVATE_STORE_CRAFT:
{
if( map_show.craftshop )
{
storemsg = pchars->chars_array[i]->privateStoreMsgRecipe;
textColor = RGB(250,204,46);
}
} break;
case L2Player::PRIVATE_STORE_PACKAGESALE:
{
if( map_show.sellshop )
{
storemsg = pchars->chars_array[i]->privateStoreMsgSell;
textColor = RGB(253,80,43);
}
} break;
}
if( storemsg )
{
rc.top -= (map_text_h+1);
rc.bottom -= (map_text_h+1);
SetTextColor( st->hdcc, textColor );
DrawText( st->hdcc, storemsg, wcslen(storemsg), &rc, DT_CENTER | DT_VCENTER );
SetTextColor( st->hdcc, RGB(255,255,255) );
}
} // privateStoreType > 0
} // show_pcs
//
if( nDisplayed >= count ) break;
}
pchars->Unlock();
}
//
// display self in center
//
SelectObject( st->hdcc, GetStockObject( WHITE_PEN ) );
Rectangle( st->hdcc, cx-1, cy-1, cx+sq_w, cy+sq_w );
// user name?
if( map_show.pcs || (pusr->privateStoreType > 0) )
{
wchar_t *text = pusr->charName;
rc.left = cx - 100;
rc.right = cx + 100;
rc.bottom = cy;
rc.top = rc.bottom - map_text_h;
if( map_show.pcs ) DrawText( st->hdcc, text, wcslen(text), &rc, DT_CENTER | DT_VCENTER );
// self shop message?
if( pusr->privateStoreType > 0 )
{
wchar_t *storemsg = NULL;
COLORREF textColor = RGB(255,255,255);
switch( pusr->privateStoreType )
{
case L2Player::PRIVATE_STORE_BUY:
{
if( map_show.buyshop )
{
storemsg = pusr->privateStoreMsgBuy;
textColor = RGB(255,255,151);
}
} break;
case L2Player::PRIVATE_STORE_SELL:
{
if( map_show.sellshop )
{
storemsg = pusr->privateStoreMsgSell;
textColor = RGB(255,108,255);
}
} break;
case L2Player::PRIVATE_STORE_CRAFT:
{
if( map_show.craftshop )
{
storemsg = pusr->privateStoreMsgRecipe;
textColor = RGB(250,204,46);
}
} break;
case L2Player::PRIVATE_STORE_PACKAGESALE:
{
if( map_show.sellshop )
{
storemsg = pusr->privateStoreMsgSell;
textColor = RGB(253,80,43);
}
} break;
}
if( storemsg )
{
rc.top -= (map_text_h+1);
rc.bottom -= (map_text_h+1);
SetTextColor( st->hdcc, textColor );
DrawText( st->hdcc, storemsg, wcslen(storemsg), &rc, DT_CENTER | DT_VCENTER );
SetTextColor( st->hdcc, RGB(255,255,255) );
}
} // privateStoreType > 0
} // show_pcs
// user move vector?
if( map_show.vectors )
{
if( pusr->isMoving() )
{
int map_vector_dx = usr_xDst - usr_x;
int map_vector_dy = usr_yDst - usr_y;
int screen_vector_dx = (int)( (double)map_vector_dx / scale_k );
int screen_vector_dy = (int)( (double)map_vector_dy / scale_k );
SelectObject( st->hdcc, st->pens[4] );
MoveToEx( st->hdcc, cx+1, cy+1, NULL );
LineTo( st->hdcc, cx+1+screen_vector_dx, cy+1+screen_vector_dy );
}
}
// select old GDI objects
//SelectObject( st->hdcc, oldPen );
//SelectObject( st->hdcc, oldBrush );
// copy surface
//PAINTSTRUCT ps;
//HDC hdc = BeginPaint( hWnd, &ps );
HDC hdc = GetDC( hWnd );
BitBlt( hdc, 0, 0, w, h, st->hdcc, 0, 0, SRCCOPY );
//EndPaint( hWnd, &ps );
ReleaseDC( hWnd, hdc );
ValidateRect( hWnd, NULL );
}
bool Map_isInTargetRect( int mx, int my, int object_x, int object_y )
{
const int d = 40;
int l = mx - d/4;
int r = mx + d;
int t = my - d/4;
int b = my + d;
if( (object_x>=l) && (object_x<=r) && (object_y>=t) && (object_y<=b) ) return true;
return false;
}
void NewMapStatic_OnLButtonUp( HWND hWnd, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(wParam);
//log_error_np( LOG_OK, "WM_LBUTTONUP\n" );
// message params
int mx = GET_X_LPARAM(lParam);
int my = GET_Y_LPARAM(lParam);
// window dimensions
RECT rc;
GetClientRect( hWnd, &rc );
int w = rc.right - rc.left;
int h = rc.bottom - rc.top;
int cx = w/2;
int cy = h/2;
int min_size = h;
if( w < min_size ) min_size = w;
MapWindowStruct *st = (MapWindowStruct *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
// init default scale state
const double max_range = 20000.0;
double scale = max_range * (double)st->pcl->get_MapScale() / 100.0;
double scale_k = scale / (double)min_size;
unsigned int nPassed = 0;
unsigned int i = 0;
unsigned int count;
int map_dx = 0, map_dy = 0; // map_dz = 0;
UserInfo *pusr = st->pcl->get_UserInfo();
int usr_x = pusr->x;
int usr_y = pusr->y;
int usr_z = pusr->z;
//int usr_xDst = pusr->xDst;
//int usr_yDst = pusr->yDst;
int screen_dx = 0, screen_dy = 0;
//int draw_x = 0, draw_y = 0;
//int sq_w = 4;
// map show text params
st_MapShowParams map_show;
st->pcl->getMapShowParams( &map_show );
//
// user clicked mouse in coords mx, my relative to 0,0 of window client area
// but we know only user's L2 map coords
// to get real L2 map coords of user click, we must calc click delta from user coords
//
screen_dx = mx - cx; // if mx > cx, user moves east
screen_dy = my - cy; // if my > cy, user moves south
map_dx = (int)( screen_dx * scale_k );
map_dy = (int)( screen_dy * scale_k );
int map_x = usr_x + map_dx;
int map_y = usr_y + map_dy;
//log_error( LOG_OK, "m(%d,%d) screen(%d,%d) map(%d,%d)\n", mx, my, screen_dx, screen_dy, map_dx, map_dy );
// maybe target self?
if( (screen_dx>-5) && (screen_dx<5) && (screen_dy>-5) && (screen_dy<5) )
{
st->pcl->game_Action( pusr->objectID );
return;
}
// first try to target players
nPassed = 0;
CharArray *ca = st->pcl->get_WorldChars();
count = ca->GetCount();
ca->Lock();
for( i=0; i<count; i++ )
{
if( ca->chars_array[i]->isUnused() ) continue;
nPassed++;
// Z-range limit (if this char is not be displayed on map, it cannot be targeted)
if( abs( ca->chars_array[i]->z - usr_z ) > map_show.zrange ) continue;
// hit target coords?
if( Map_isInTargetRect( map_x, map_y, ca->chars_array[i]->x, ca->chars_array[i]->y ) )
{
ca->Unlock();
st->pcl->game_Action( ca->chars_array[i]->objectID );
return;
}
if( nPassed >= count ) break;
}
ca->Unlock();
ca = NULL;
// if we here, PC not targeted
// try to target NPC / mob
nPassed = 0;
NpcArray *na = st->pcl->get_WorldNpcs();
count = na->getCount();
na->Lock();
for( i=0; i<count; i++ )
{
if( na->npcs_array[i]->isUnused() ) continue;
nPassed++;
// Z-range limit (if this npc is not be displayed on map, it cannot be targeted)
if( abs( na->npcs_array[i]->z - usr_z ) > map_show.zrange ) continue;
// hit target coords?
if( Map_isInTargetRect( map_x, map_y, na->npcs_array[i]->x, na->npcs_array[i]->y ) )
{
na->Unlock();
st->pcl->game_Action( na->npcs_array[i]->objectID );
return;
}
if( nPassed >= count ) break;
}
na->Unlock();
na = NULL;
// if we here, no PC/NPC/Mob targeted :(
// maybe try to pick up item?
nPassed = 0;
GIArray *ga = st->pcl->get_WorldItems();
count = ga->getCount();
ga->Lock();
for( i=0; i<count; i++ )
{
if( ga->gi_array[i]->isUnused() ) continue;
nPassed++;
// Z-range limit (if this char is not be displayed on map, it cannot be targeted)
if( abs( ga->gi_array[i]->z - usr_z ) > map_show.zrange ) continue;
// hit target coords?
if( Map_isInTargetRect( map_x, map_y, ga->gi_array[i]->x, ga->gi_array[i]->y ) )
{
ga->Unlock();
st->pcl->game_Action( ga->gi_array[i]->objectID );
return;
}
if( nPassed >= count ) break;
}
ga->Unlock();
ga = NULL;
// nothing targeted, move ? :)
st->pcl->game_MoveToDelta( map_dx, map_dy );
}
void Map_struct_check_geo_square_and_preload_image( MapWindowStruct *st, int usr_x, int usr_y )
{
int cur_geo_x = 0, cur_geo_y = 0;
GlobalMapImages::GetGeoMapSquareXYByL2Coords( usr_x, usr_y, &cur_geo_x, &cur_geo_y );
if( (st->geo_x != cur_geo_x) || (st->geo_y != cur_geo_y) )
{
//
log_error_np( LOG_OK, "Geo: square changed: %d,%d -> %d,%d\n",
st->geo_x, st->geo_y, cur_geo_x, cur_geo_y );
// geodata square changed! change coords
st->geo_x = cur_geo_x;
st->geo_y = cur_geo_y;
// NULL current vars
st->hdcImage = NULL;
st->geo_img_w = 0;
st->geo_img_h = 0;
// load new
g_mapImg.preloadSquare( cur_geo_x, cur_geo_y );
if( g_mapImg.isSquareLoaded( cur_geo_x, cur_geo_y ) )
{
st->hdcImage = g_mapImg.getSquareHDC( cur_geo_x, cur_geo_y );
g_mapImg.getSquareWH( cur_geo_x, cur_geo_y, st->geo_img_w, st->geo_img_h );
log_error_np( LOG_OK, "Geo: preloaded geo square [%d_%d] img size [%d x %d]\n",
cur_geo_x, cur_geo_y, st->geo_img_w, st->geo_img_h );
}
else
{
log_error( LOG_WARNING, "Geo: cannot preload geo square [%d_%d]\n", cur_geo_x, cur_geo_y );
/*char aCurDir[256];
GetCurrentDirectoryA( 200, aCurDir );
log_error( LOG_WARNING, "Geo: curDir [%s]\n", aCurDir );*/
}
}
}
void NewMapStatic_ReloadImage( HWND hWnd )
{
MapWindowStruct *st = (MapWindowStruct *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
// reload
log_error_np( LOG_OK, "MapWindow: reload square: %d,%d\n", st->geo_x, st->geo_y );
// NULL current vars
st->hdcImage = NULL;
st->geo_img_w = 0;
st->geo_img_h = 0;
// load new
g_mapImg.preloadSquare( st->geo_x, st->geo_y );
if( g_mapImg.isSquareLoaded( st->geo_x, st->geo_y ) )
{
st->hdcImage = g_mapImg.getSquareHDC( st->geo_x, st->geo_y );
g_mapImg.getSquareWH( st->geo_x, st->geo_y, st->geo_img_w, st->geo_img_h );
log_error_np( LOG_OK, "MapWindow: reloaded geo square [%d_%d] img size [%d x %d]\n",
st->geo_x, st->geo_y, st->geo_img_w, st->geo_img_h );
}
else
{
log_error( LOG_WARNING, "MapWindow: cannot reload geo square [%d_%d]\n", st->geo_x, st->geo_y );
}
}

7
l2ooghelper/MapWnd.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef H_MAPWND
#define H_MAPWND
#include "IL2Client.h"
void SubclassMapWindowProc( HWND hWnd, IL2Client *pcl );
#endif

View File

@@ -0,0 +1,188 @@
#include "stdafx.h"
#include "Resource.h"
#include "MessageBoxTimeout.h"
#include "logger.h"
#include "L2Client.h"
extern HINSTANCE g_hInst;
extern HWND g_hWnd;
#define USE_MODELESS
MessageBoxTimeout::MessageBoxTimeout(
HWND hWndNotify, UINT uMessage, int type,
LPTSTR szQuestiion, int timeoutSec )
{
m_hWndNotify = hWndNotify;
m_uNotifyMesasage = uMessage;
m_type = type;
m_question[0] = 0;
if( szQuestiion ) lstrcpy( m_question, szQuestiion );
m_timeout = timeoutSec;
m_curChar[0] = 0;
m_requestId = 0;
m_sm_ID = 0;
m_pvL2Client = NULL;
}
MessageBoxTimeout::~MessageBoxTimeout()
{
//log_error( LOG_OK, "MessageBoxTimeout::~MessageBoxTimeout()\n" );
}
void MessageBoxTimeout::run( const wchar_t *curCharName )
{
wcscpy( m_curChar, curCharName );
// thread
DWORD dwTID = 0;
HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))MBTimeout_Thread, (void *)this,
0, (unsigned int *)&dwTID );
if( hThread ) CloseHandle( hThread );
}
void MessageBoxTimeout::runConfirmDlg( const wchar_t *curCharName,
unsigned int requestId, unsigned int sm_ID,
void *pvActionL2Client )
{
wcscpy( m_curChar, curCharName );
m_requestId = requestId;
m_sm_ID = sm_ID;
m_pvL2Client = pvActionL2Client;
// thread
DWORD dwTID = 0;
HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))MBTimeout_Thread, (void *)this,
0, (unsigned int *)&dwTID );
if( hThread ) CloseHandle( hThread );
}
DWORD WINAPI MessageBoxTimeout::MBTimeout_Thread( LPVOID lpParam )
{
class MessageBoxTimeout *mb = (MessageBoxTimeout *)lpParam;
#ifndef USE_MODELESS
DialogBoxParam( g_hInst, MAKEINTRESOURCE(IDD_MBTIMEOUT), g_hWnd,
MBTimeout_DlgProc, (LPARAM)mb );
#else
HWND hDlg = CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_MBTIMEOUT),
g_hWnd, MBTimeout_DlgProc, (LPARAM)mb );
ShowWindow( hDlg, SW_SHOW );
MSG msg;
//while( GetMessage( &msg, hDlg, 0, 0 ) )
while( GetMessage( &msg, NULL, 0, 0 ) )
{
if( !IsDialogMessage( hDlg, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
//log_error( LOG_OK, "MBTimeout_Thread(): ended window loop\n" );
DestroyWindow( hDlg );
#endif
return 0;
}
INT_PTR CALLBACK MessageBoxTimeout::MBTimeout_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
OnInitDialog( hDlg, lParam );
} break;
case WM_COMMAND: OnCommand( hDlg, wParam, lParam ); break;
case WM_DESTROY: { OnDestroy( hDlg ); return FALSE; } break;
case WM_TIMER: OnTimer( hDlg, wParam ); break;
default: return FALSE; break;
}
return TRUE;
}
void MessageBoxTimeout::OnInitDialog( HWND hDlg, LPARAM lParam )
{
//log_error( LOG_OK, "MessageBoxTimeout::OnInitDialog()\n" );
MessageBoxTimeout *pcls = (MessageBoxTimeout *)lParam;
wchar_t text[256] = {0};
wsprintfW( text, L"%s - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>", pcls->m_curChar );
SetWindowTextW( hDlg, text );
SetDlgItemText( hDlg, IDC_ST_Q, pcls->m_question );
HWND hWndProgress = GetDlgItem( hDlg, IDC_PROGRESS1 );
SendMessage( hWndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, pcls->m_timeout) );
SendMessage( hWndProgress, PBM_SETPOS, pcls->m_timeout, 0 );
SendMessage( hWndProgress, PBM_SETSTEP, (WPARAM)-1, 0 );
if( pcls->m_timeout > 0 )
{
SetTimer( hDlg, 1, 1000, NULL );
}
}
void MessageBoxTimeout::OnDestroy( HWND hDlg )
{
//log_error( LOG_OK, "MessageBoxTimeout::OnDestroy()\n" );
KillTimer( hDlg, 1 );
MessageBoxTimeout *pcls = (MessageBoxTimeout *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
delete pcls;
}
void MessageBoxTimeout::OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(lParam);
MessageBoxTimeout *pcls = (MessageBoxTimeout *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
switch( LOWORD( wParam ) )
{
case IDOK:
{
if( pcls->m_type < MessageBoxTimeout::TYPE_CONFIRMDLG )
{
PostMessage( pcls->m_hWndNotify, pcls->m_uNotifyMesasage, TRUE, (pcls->m_type) );
}
if( pcls->m_type == MessageBoxTimeout::TYPE_CONFIRMDLG )
{
L2Client *pcl = (L2Client *)pcls->m_pvL2Client;
if( pcl ) pcl->send_DlgAnswer( pcls->m_sm_ID, 1, pcls->m_requestId );
}
#ifdef USE_MODELESS
PostMessage( hDlg, WM_QUIT, 0, 0 );
//PostQuitMessage( 0 );
//DestroyWindow( hDlg );
#else
EndDialog( hDlg, IDOK );
#endif
} break;
case IDCANCEL:
{
if( pcls->m_type < MessageBoxTimeout::TYPE_CONFIRMDLG )
{
PostMessage( pcls->m_hWndNotify, pcls->m_uNotifyMesasage, FALSE, (pcls->m_type) );
}
if( pcls->m_type == MessageBoxTimeout::TYPE_CONFIRMDLG )
{
L2Client *pcl = (L2Client *)pcls->m_pvL2Client;
if( pcl ) pcl->send_DlgAnswer( pcls->m_sm_ID, 0, pcls->m_requestId );
}
#ifdef USE_MODELESS
PostMessage( hDlg, WM_QUIT, 0, 0 );
//DestroyWindow( hDlg );
#else
EndDialog( hDlg, IDCANCEL );
#endif
} break;
}
}
void MessageBoxTimeout::OnTimer( HWND hDlg, WPARAM wParam )
{
switch( wParam )
{
case 1:
{
HWND hWndProgress = GetDlgItem( hDlg, IDC_PROGRESS1 );
SendMessage( hWndProgress, PBM_STEPIT, 0, 0 );
int pos = (int)SendMessage( hWndProgress, PBM_GETPOS, 0, 0 );
//log_error( LOG_OK, "OnTimer(): pos = %d\n", pos );
if( pos <= 0 ) PostMessage( hDlg, WM_COMMAND, IDCANCEL, 0 );
} break;
}
}

View File

@@ -0,0 +1,40 @@
#ifndef H_MESSAGEBOX_TIMEOUT
#define H_MESSAGEBOX_TIMEOUT
class MessageBoxTimeout
{
public:
static const int TYPE_PARTY = 0;
static const int TYPE_CLAN = 1;
static const int TYPE_FRIEND = 2;
static const int TYPE_ALLY = 3;
static const int TYPE_TRADEREQUEST = 4;
static const int TYPE_CONFIRMDLG = 10;
public:
MessageBoxTimeout( HWND hWndNotify, UINT uMessage, int type, LPTSTR szQuestiion,
int timeoutSec = 0 );
~MessageBoxTimeout();
void run( const wchar_t *curCharName );
void runConfirmDlg( const wchar_t *curCharName,
unsigned int requestId, unsigned int sm_ID,
void *pvActionL2Client );
protected:
HWND m_hWndNotify;
UINT m_uNotifyMesasage;
int m_type;
TCHAR m_question[8192];
int m_timeout;
wchar_t m_curChar[256];
unsigned int m_requestId;
unsigned int m_sm_ID;
void *m_pvL2Client;
protected:
static DWORD WINAPI MBTimeout_Thread( LPVOID lpParam );
static INT_PTR CALLBACK MBTimeout_DlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static void OnInitDialog( HWND hDlg, LPARAM lParam );
static void OnDestroy( HWND hDlg );
static void OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnTimer( HWND hDlg, WPARAM wParam );
};
#endif

225
l2ooghelper/NpcArray.cpp Normal file
View File

@@ -0,0 +1,225 @@
#include "stdafx.h"
#include "Logger.h"
#include "NpcArray.h"
void NpcArray::Init()
{
npcArray_updateHWND = NULL;
npcArray_updateMSG = 0;
npcArray_count = 0;
InitializeCriticalSection( &cs_npcs_array );
int i;
for( i=0; i<NPCA_MAX_NPCS; i++ ) npcs_array[i] = new L2Npc();
}
void NpcArray::Free()
{
Lock();
int i;
for( i=0; i<NPCA_MAX_NPCS; i++ )
{
if( npcs_array[i] != NULL )
{
delete npcs_array[i];
npcs_array[i] = NULL;
}
}
npcArray_count = 0;
Unlock();
DeleteCriticalSection( &cs_npcs_array );
}
int NpcArray::AddNpcInfo( L2Npc *pNpcInfo )
{
Lock();
// Add new npc info
int idx = FindFreeIndex();
if( idx == -1 )
{
Unlock();
return -1;
}
if( !npcs_array[idx] ) npcs_array[idx] = new L2Npc();
if( !npcs_array[idx] )
{
Unlock();
return -1;
}
memcpy( npcs_array[idx], pNpcInfo, sizeof(class L2Npc) );
npcArray_count++;
Unlock();
PostUpdateMessage();
//log_error( LOG_OK, "NpcArray: Added new[%d]: [%S] [%S] (%d,%d,%d) tpml %u, oid %u\n",
// idx,
// name, title, x,y,z, templateID, objectID );
return idx;
}
void NpcArray::UpdateNpcInfo( int idx, L2Npc *pNpcInfo )
{
Lock();
// update info on existing NPC
if( !npcs_array[idx] )
{
log_error( LOG_ERROR, "NpcArray_UpdateNpcInfo(): idx[%d] is free!\n", idx );
// try to allocate!
npcs_array[idx] = new L2Npc();
if( !npcs_array[idx] )
{
Unlock();
return;
}
}
if( npcs_array[idx]->isUnused() ) log_error( LOG_ERROR, "NpcArray_UpdateNpcInfo(): idx[%d] is unused!\n", idx );
// save old move vectors (since by default unused NpcInfo is not moving)
int xDst = npcs_array[idx]->xDst;
int yDst = npcs_array[idx]->yDst;
int zDst = npcs_array[idx]->zDst;
//
memcpy( npcs_array[idx], pNpcInfo, sizeof(class L2Npc) );
// restore old move vectors (since by default unused NpcInfo is not moving)
npcs_array[idx]->xDst = xDst;
npcs_array[idx]->yDst = yDst;
npcs_array[idx]->zDst = zDst;
//
Unlock();
PostUpdateMessage();
//log_error( LOG_OK, "NpcArray: Updated[%d]: [%S] [%S] (%d,%d,%d) tpml %u, oid %u\n",
// idx,
// name, title, x,y,z, templateID, objectID );
}
/*void NpcArray::DelNPC( unsigned int objectID )
{
Lock();
int idx = FindNPCByObjectID( objectID );
if( idx == -1 )
{
Unlock();
return;
}
if( npcs_array[idx] )
{
npcs_array[idx]->setUnused();
}
//log_error( LOG_OK, "NpcArray: deleted " );
Unlock();
}*/
void NpcArray::DelNPCByArrayIdx( int idx )
{
if( idx<0 || (idx>=NPCA_MAX_NPCS) ) return;
Lock();
if( npcs_array[idx] )
{
npcs_array[idx]->setUnused();
npcArray_count--;
//log_error( LOG_OK, "NpcArray: deleted npc %u from index OK\n", objectID, idx );
}
Unlock();
PostUpdateMessage();
}
void NpcArray::DeleteAll()
{
Lock();
int i;
for( i=0; i<NPCA_MAX_NPCS; i++ )
{
npcs_array[i]->setUnused();
}
npcArray_count = 0;
Unlock();
PostUpdateMessage();
}
void NpcArray::Lock()
{
EnterCriticalSection( &cs_npcs_array );
}
void NpcArray::Unlock()
{
LeaveCriticalSection( &cs_npcs_array );
}
int NpcArray::FindNPCByObjectID( unsigned int objectID )
{
int ret = -1;
int i;
Lock();
for( i=0; i<NPCA_MAX_NPCS; i++ )
{
if( npcs_array[i] == NULL ) continue;
if( npcs_array[i]->objectID == objectID )
{
ret = i;
break;
}
}
Unlock();
return ret;
}
int NpcArray::FindFreeIndex()
{
int i;
Lock();
for( i=0; i<NPCA_MAX_NPCS; i++ )
{
if( npcs_array[i] == NULL )
{
npcs_array[i] = new L2Npc(); // allocate new
npcs_array[i]->setUnused(); // and set as unused
Unlock();
return i;
}
if( npcs_array[i]->isUnused() )
{
Unlock();
return i;
}
}
Unlock();
log_error( LOG_ERROR, "NpcArray_FindFreeIndex(): canot find free index, limit is %d!\n", NPCA_MAX_NPCS );
return -1;
}
void NpcArray::SetUpdateCommand( HWND hWnd, UINT uMsg )
{
npcArray_updateHWND = hWnd;
npcArray_updateMSG = uMsg;
}
void NpcArray::PostUpdateMessage()
{
if( !npcArray_updateHWND ) return;
if( npcArray_updateMSG < WM_USER ) return;
PostMessage( npcArray_updateHWND, npcArray_updateMSG, 0, 0 );
}
void NpcArray::DisplayToConsole()
{
int i = 0;
unsigned int nDisplayed = 0;
log_error( LOG_USERAI, "=== NPCs: %d ===\n", npcArray_count );
if( npcArray_count > 0 )
{
Lock();
for( i=0; i<NPCA_MAX_NPCS; i++ )
{
if( npcs_array[i]->isUnused() )
log_error( LOG_USERAI, "NPC: %2d: <unused>\n", i );
else
{
log_error( LOG_USERAI, "NPC: %2d: %u [%S] [%S]\n", i,
npcs_array[i]->templateID,
npcs_array[i]->charName, npcs_array[i]->charTitle );
nDisplayed++;
}
if( nDisplayed >= npcArray_count ) break;
}
Unlock();
}
log_error( LOG_USERAI, "=== NPCs End ===\n" );
}

40
l2ooghelper/NpcArray.h Normal file
View File

@@ -0,0 +1,40 @@
#ifndef H_NPC_ARRAY
#define H_NPC_ARRAY
class NpcArray
{
public:
NpcArray() { Init(); }
~NpcArray() { Free(); }
public:
static const int NPCA_MAX_NPCS = 512;
L2Npc *npcs_array[NPCA_MAX_NPCS];
public:
void Init();
void Free();
public:
int AddNpcInfo( L2Npc *pNpcInfo );
void UpdateNpcInfo( int idx, L2Npc *pNpcInfo );
//void DelNPC( unsigned int objectID );
void DelNPCByArrayIdx( int idx );
void DeleteAll();
public:
void Lock();
void Unlock();
public:
int FindNPCByObjectID( unsigned int objectID );
int FindFreeIndex();
public:
void SetUpdateCommand( HWND hWnd, UINT uMsg );
unsigned int getCount() const { return npcArray_count; }
void DisplayToConsole();
protected:
void PostUpdateMessage();
protected:
unsigned int npcArray_count;
CRITICAL_SECTION cs_npcs_array;
HWND npcArray_updateHWND;
UINT npcArray_updateMSG;
};
#endif

View File

@@ -0,0 +1,422 @@
#include "stdafx.h"
#include "Resource.h"
#include "Logger.h"
#include "NpcHtmlMessageDlg.h"
#include "L2Client.h"
extern HINSTANCE g_hInst;
NpcHtmlMessageDlg::NpcHtmlMessageDlg( void *pvL2Client )
{
m_hDlg = m_hWndParent = NULL;
m_html = NULL;
m_itemID = m_questID = 0;
m_npc = NULL;
m_pvL2Client = pvL2Client;
// childs
m_hWndHtml = m_hWndCombo = m_hWndBypassText = NULL;
}
NpcHtmlMessageDlg::~NpcHtmlMessageDlg()
{
destroyDialog();
if( m_html )
{
free( m_html );
m_html = NULL;
}
}
bool NpcHtmlMessageDlg::createDialog( HWND hWndParent )
{
m_hWndParent = hWndParent;
m_hDlg = CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_NPCHTML), hWndParent,
NpcHtmlMessageDlgProc, (LPARAM)this );
if( m_hDlg ) return true;
// error
m_hWndParent = NULL;
return false;
}
void NpcHtmlMessageDlg::destroyDialog()
{
if( m_hDlg )
{
DestroyWindow( m_hDlg );
m_hDlg = NULL;
}
}
void NpcHtmlMessageDlg::showWindow( bool bShow )
{
if( m_hDlg )
{
if( bShow ) ShowWindow( m_hDlg, SW_SHOWNORMAL );
else ShowWindow( m_hDlg, SW_HIDE );
}
}
void NpcHtmlMessageDlg::displayNPCHTML( const TCHAR *html, L2Npc *pNpc,
unsigned int itemID, unsigned int questID )
{
if( !html ) return;
//
m_itemID = itemID;
m_questID = questID;
m_npc = pNpc;
if( m_html ) free( m_html );
m_html = _tcsdup( html );
//
NpcHtmlMessageDlg::wnd_initHtml( m_hDlg );
showWindow( true );
}
class NpcHtmlLink
{
public:
NpcHtmlLink() { text[0] = 0; bypass[0] = 0; next = NULL; }
~NpcHtmlLink() { if( next ) delete next; }
public:
wchar_t text[128];
wchar_t bypass[128];
NpcHtmlLink *next;
};
class NpcHtmlInfo
{
public:
NpcHtmlInfo()
{
html = NULL;
head = NULL;
}
~NpcHtmlInfo()
{
if( html ) free( html );
html = NULL;
if( head ) delete head;
head = NULL;
}
public:
wchar_t *html;
NpcHtmlLink *head;
};
void process_bypass( NpcHtmlInfo *info, wchar_t *tagHeader, wchar_t *tagTextStart )
{
// a action="bypass -h npc_268437990_Quest 1106_teleport_to_fantasy_isle" msg="811;Fantasy Island"
//log_error( LOG_OK, "[%S] [%S]\n", tagHeader, tagTextStart );
wchar_t bypass[128] = {0};
wchar_t *pbypass = bypass;
wchar_t text[128] = {0};
wchar_t *ptext = text;
wchar_t *w = wcschr( tagHeader, L'\"' );
if( !w ) return;
w++;
while( (*w) != L'\"' ) { (*pbypass) = (*w); pbypass++, w++; }
(*pbypass) = 0;
w = tagTextStart;
while( (*w) != L'<' ) { (*ptext) = (*w); ptext++, w++; }
(*ptext) = 0;
//
NpcHtmlLink *adding = new NpcHtmlLink();
wcscpy( adding->bypass, bypass );
wcscpy( adding->text, text );
adding->next = NULL;
//
if( !info->head ) info->head = adding;
else
{
NpcHtmlLink *cur = info->head;
while( cur->next ) cur = cur->next;
cur->next = adding;
}
}
NpcHtmlInfo *parse_NpcHtml( wchar_t *html )
{
if( !html ) return NULL;
NpcHtmlInfo *info = new NpcHtmlInfo();
//
info->html = (wchar_t *)malloc( 20480 );
if( !info->html ) { delete info; return NULL; }
info->html[0] = 0;
//
wchar_t *phtml = html;
wchar_t *pinfohtml = info->html;
wchar_t curChar = phtml[0];
wchar_t tagHeader[256] = {0};
wchar_t *ptagHeader = tagHeader;
bool in_tag = false;
//
const int maxCharsInLine = 40;
int curCharsInLine = 0;
bool break_next_space = false;
//
while( curChar )
{
curChar = (*phtml);
if( curChar == L'<' )
{
in_tag = true;
phtml++;
tagHeader[0] = (*phtml);
ptagHeader = tagHeader;
ptagHeader++;
phtml++;
}
else if( curChar == L'>' )
{
(*ptagHeader) = 0;
in_tag = false;
phtml++;
// parse passed tag
if( (_wcsicmp( tagHeader, L"br" ) == 0) || (_wcsicmp( tagHeader, L"br1" ) == 0) )
{
(*pinfohtml) = L'\r';
pinfohtml++;
(*pinfohtml) = L'\n';
pinfohtml++;
(*pinfohtml) = 0;
curCharsInLine = 0;
break_next_space = false;
}
else if( (wcsstr( tagHeader, L"a " ) == tagHeader) || (wcsstr( tagHeader, L"A " ) == tagHeader) )
{
process_bypass( info, tagHeader, phtml );
}
}
else if( (curChar == L'\r') || (curChar == L'\n') || (curChar == L' ') || (curChar == L'\t') )
{
if( break_next_space ) // insert line break
{
(*pinfohtml) = L'\r';
pinfohtml++;
(*pinfohtml) = L'\n';
pinfohtml++;
(*pinfohtml) = 0;
curCharsInLine = 0; // new line started
break_next_space = false; // we should not break at next whitespace )
}
// append space instead of \r, \n, \t
else if( curChar == L' ' )
{
if( in_tag )
{
(*ptagHeader) = L' ';
ptagHeader++;
(*ptagHeader) = 0;
}
else
{
(*pinfohtml) = L' ';
pinfohtml++;
}
}
phtml++;
}
else
{
if( !in_tag )
{
if( curChar != L'\n' && curChar != L'\r' )
{
(*pinfohtml) = curChar;
pinfohtml++;
(*pinfohtml) = 0;
//
curCharsInLine++;
if( curCharsInLine >= maxCharsInLine ) break_next_space = true;
}
}
else
{
(*ptagHeader) = curChar;
ptagHeader++;
(*ptagHeader) = 0;
}
phtml++;
}
}
//
return info;
}
struct NpcHtmlDlgSt
{
NpcHtmlMessageDlg *cls;
NpcHtmlInfo *htmlInfo;
};
INT_PTR CALLBACK NpcHtmlMessageDlg::NpcHtmlMessageDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
// get ptr to class
NpcHtmlMessageDlg *cls = (NpcHtmlMessageDlg *)lParam;
// save all info as window user data
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)malloc( sizeof(NpcHtmlDlgSt) );
st->cls = cls; // pointer to class
st->htmlInfo = NULL; // no html and links at this time
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)st );
// get children
cls->m_hWndHtml = GetDlgItem( hDlg, IDC_EDIT1 );
cls->m_hWndCombo = GetDlgItem( hDlg, IDC_COMBO1 );
cls->m_hWndBypassText = GetDlgItem( hDlg, IDC_EDIT2 );
} break;
case WM_COMMAND:
{
switch( LOWORD( wParam ) )
{
case IDCANCEL: NpcHtmlMessageDlg::wnd_onCancel( hDlg ); break;
case IDOK: NpcHtmlMessageDlg::wnd_onOK( hDlg ); break;
case IDC_COMBO1:
{
int code = HIWORD(wParam);
if( code == CBN_SELCHANGE ) NpcHtmlMessageDlg::wnd_onCombo1SelChange( hDlg );
} break;
}
return FALSE; // message was not processed
} break;
case WM_DESTROY: NpcHtmlMessageDlg::wnd_onDestroy( hDlg ); break;
case WM_KEYDOWN:
{
log_error( LOG_ERROR, "NpcHtmlMessageDlgProc(): WM_KEYDOWN\n" );
} break;
default: return FALSE; break;
}
return TRUE; // message was processed
}
void NpcHtmlMessageDlg::wnd_initHtml( HWND hDlg )
{
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !st ) return;
// set dlg title
if( st->cls->m_npc )
{
TCHAR title[512] = {0};
wsprintf( title, TEXT("%s (%s)"), st->cls->m_npc->charName, st->cls->m_npc->charTitle );
SetWindowText( hDlg, title );
}
else SetWindowText( hDlg, TEXT("NpcHtmlMessage") );
// clear prev. html
SetWindowText( st->cls->m_hWndHtml, TEXT("no text") );
if( st->htmlInfo )
{
delete st->htmlInfo;
st->htmlInfo = NULL;
}
// parse and set html
NpcHtmlInfo *htmlInfo = parse_NpcHtml( st->cls->m_html );
st->htmlInfo = htmlInfo; // pointer to html info...
if( st->htmlInfo )
SetDlgItemText( hDlg, IDC_EDIT1, st->htmlInfo->html );
// init combobox
ComboBox_ResetContent( st->cls->m_hWndCombo );
if( st->htmlInfo )
{
NpcHtmlLink *cur = st->htmlInfo->head;
while( cur )
{
ComboBox_AddString( st->cls->m_hWndCombo, cur->text );
cur = cur->next;
}
}
// init bypass text
SetWindowText( st->cls->m_hWndBypassText, TEXT("") );
}
void NpcHtmlMessageDlg::wnd_onCancel( HWND hDlg )
{
ShowWindow( hDlg, SW_HIDE );
}
void NpcHtmlMessageDlg::wnd_onOK( HWND hDlg )
{
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !st ) return;
// save selection and post message to notify window
int cur_sel = ComboBox_GetCurSel( st->cls->m_hWndCombo );
if( cur_sel == -1 ) return;
//
ShowWindow( hDlg, SW_HIDE );
//
int nPassed = 0;
NpcHtmlLink *cur = st->htmlInfo->head;
while( cur )
{
if( nPassed == cur_sel )
{
if( cur->bypass )
{
// send request bypass to server
class L2Client *pcl = (L2Client *)st->cls->m_pvL2Client;
if( wcsstr( cur->bypass, L"bypass -h " ) )
{
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> "bypass -h " <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pcl->send_RequestBypassToServer( cur->bypass + 10 /*wcslen( L"bypass -h " )*/ );
}
else if( wcsstr( cur->bypass, L"link " ) )
{
// <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> "link " <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pcl->send_RequestLinkHtml( cur->bypass + 5 /*wcslen( L"link " )*/ );
}
else
{
log_error( LOG_ERROR, "Possibly wrong bypass in HTML from server!\n[%S]\n", cur->bypass );
}
}
break;
}
else
{
cur = cur->next;
nPassed++;
}
}
}
void NpcHtmlMessageDlg::wnd_onCombo1SelChange( HWND hDlg )
{
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !st ) return;
int cur_sel = ComboBox_GetCurSel( st->cls->m_hWndCombo );
if( cur_sel == -1 ) return;
//
if( !st->htmlInfo ) return;
int nPassed = 0;
NpcHtmlLink *cur = st->htmlInfo->head;
while( cur )
{
if( nPassed == cur_sel )
{
SetWindowText( st->cls->m_hWndBypassText, cur->bypass );
break;
}
else
{
cur = cur->next;
nPassed++;
}
}
}
void NpcHtmlMessageDlg::wnd_onDestroy( HWND hDlg )
{
NpcHtmlDlgSt *st = (NpcHtmlDlgSt *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
if( !st ) return;
delete st->htmlInfo;
st->htmlInfo = NULL;
free( st );
SetWindowLongPtr( hDlg, GWLP_USERDATA, 0 );
}

View File

@@ -0,0 +1,39 @@
#ifndef H_NPC_HTML_MESSAGE_DLG
#define H_NPC_HTML_MESSAGE_DLG
class NpcHtmlMessageDlg
{
public:
NpcHtmlMessageDlg( void *pvL2Client );
~NpcHtmlMessageDlg();
public:
bool createDialog( HWND hWndParent );
void destroyDialog();
void showWindow( bool bShow );
void displayNPCHTML( const TCHAR *html, L2Npc *pNpc,
unsigned int itemID = 0, unsigned int questID = 0 );
protected:
HWND m_hDlg;
HWND m_hWndParent;
TCHAR *m_html;
unsigned int m_itemID;
unsigned int m_questID;
L2Npc *m_npc;
void *m_pvL2Client;
// child windows
HWND m_hWndHtml;
HWND m_hWndCombo;
HWND m_hWndBypassText;
protected:
static INT_PTR CALLBACK NpcHtmlMessageDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static void wnd_initHtml( HWND hDlg );
static void wnd_onCancel( HWND hDlg );
static void wnd_onOK( HWND hDlg );
static void wnd_onCombo1SelChange( HWND hDlg );
static void wnd_onDestroy( HWND hDlg );
};
#endif

View File

@@ -0,0 +1,339 @@
#include "stdafx.h"
#if 0
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "PngJpegImage.h"
PngJpegImage::PngJpegImage() { initnull(); }
PngJpegImage::~PngJpegImage() { freeself(); }
bool PngJpegImage::readFile_PNG( const char *fileName )
{
if( !fileName ) return FALSE;
// try to open file 1st
FILE *fp = fopen( fileName, "rb" );
if( !fp )
{
SetLastError( ERROR_FILE_NOT_FOUND );
return FALSE;
}
// check is it png?
fread( b_header, 1, number, fp );
int is_png = !png_sig_cmp( b_header, 0, number );
if( !is_png )
{
SetLastError( ERROR_INVALID_DATA );
fclose( fp );
return FALSE;
}
memset( m_filename, 0, sizeof(m_filename) );
strncpy( m_filename, fileName, sizeof(m_filename)-1 );
// now free possible previous data
freeself();
// and read new file
// allocate libPNG structs
png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
if( !png_ptr )
{
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
png_ptr = NULL;
fclose( fp );
return FALSE;
}
info_ptr = png_create_info_struct( png_ptr );
if( !info_ptr )
{
png_destroy_read_struct( &png_ptr, (png_infopp)NULL, (png_infopp)NULL );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
png_ptr = NULL;
info_ptr = NULL;
fclose( fp );
return FALSE;
}
png_init_io( png_ptr, fp );
png_set_sig_bytes( png_ptr, number );
png_read_info( png_ptr, info_ptr );
width = png_get_image_width( png_ptr, info_ptr );
height = png_get_image_height( png_ptr, info_ptr );
bit_depth = png_get_bit_depth( png_ptr, info_ptr );
rowbytes = png_get_rowbytes( png_ptr, info_ptr );
channels = png_get_channels( png_ptr, info_ptr );
color_type = png_get_color_type( png_ptr, info_ptr );
/** // color types. Note that not all combinations are legal
#define PNG_COLOR_TYPE_GRAY 0
#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
// aliases
#define PNG_COLOR_TYPE_RGBA PNG_COLOR_TYPE_RGB_ALPHA
#define PNG_COLOR_TYPE_GA PNG_COLOR_TYPE_GRAY_ALPHA **/
// allocate space for image data
row_pointers = (unsigned char **)png_malloc( png_ptr, height*sizeof(png_bytep) );
if( !row_pointers )
{
png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
png_ptr = NULL;
info_ptr = NULL;
fclose( fp );
return FALSE;
}
int i = 0;
for( i=0; i<height; i++ )
{
row_pointers[i] = (unsigned char *)png_malloc( png_ptr, rowbytes );
if( !row_pointers[i] )
{
png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
png_ptr = NULL;
info_ptr = NULL;
fclose( fp );
return false;
}
}
png_read_image( png_ptr, row_pointers );
png_read_end( png_ptr, info_ptr );
// we no longer need all libPNG stuff, we just need image data row_pointers // REALLY DON'T NEED??
//png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
//png_ptr = NULL;
//info_ptr = NULL;
fclose( fp );
fp = NULL;
image_is_png = 1;
image_is_jpeg = 0;
return true;
}
bool PngJpegImage::readFile_JPEG( const char *fileName )
{
if( !fileName ) return false;
// try to open file 1st
FILE *fp = fopen( fileName, "rb" );
if( !fp )
{
SetLastError( ERROR_FILE_NOT_FOUND );
return false;
}
// init libjpeg decompressor
jpeg_cinfo.err = jpeg_std_error( &jpeg_err );
jpeg_create_decompress( &jpeg_cinfo );
// set file as data source
jpeg_stdio_src( &jpeg_cinfo, fp );
// read image header
jpeg_read_header( &jpeg_cinfo, TRUE );
width = jpeg_cinfo.image_width;
height = jpeg_cinfo.image_height;
bit_depth = 8 * jpeg_cinfo.num_components;
color_type = jpeg_cinfo.jpeg_color_space;
rowbytes = width * jpeg_cinfo.num_components * 8;
//printf( "JPEG: %d x %d @ %d (color space: %d)\n", width, height, bit_depth, color_type );
/* Known color spaces. */
//typedef enum {
// JCS_UNKNOWN, /* error/unspecified */
// JCS_GRAYSCALE, /* monochrome */
// JCS_RGB, /* red/green/blue */
// JCS_YCbCr, /* Y/Cb/Cr (also known as YUV) */
// JCS_CMYK, /* C/M/Y/K */
// JCS_YCCK /* Y/Cb/Cr/K */
//} J_COLOR_SPACE; */
// we do not set any transforms, so output parameters are like in original image
// allocate row pointers array
row_pointers = (unsigned char **)malloc( height * sizeof(void *) );
if( !row_pointers )
{
jpeg_abort( (j_common_ptr)&jpeg_cinfo );
jpeg_destroy_decompress( &jpeg_cinfo );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
return false;
}
// allocate each row
int i = 0;
for( i=0; i<height; i++ )
{
row_pointers[i] = (unsigned char *)malloc( rowbytes );
if( !row_pointers[i] )
{
jpeg_abort( (j_common_ptr)&jpeg_cinfo );
jpeg_destroy_decompress( &jpeg_cinfo );
SetLastError( ERROR_NOT_ENOUGH_MEMORY );
free( row_pointers );
return false;
}
}
// start
jpeg_start_decompress( &jpeg_cinfo );
//dummy array
unsigned char *one_row = (unsigned char *)malloc( rowbytes );
unsigned char **dummy_array_of_one_row = &one_row;
/*JSAMPARRAY unsigned char **
JSAMPROW unsigned char *
JSAMPLE unsigned char*/
i = 0;
int iread = 0;
while( jpeg_cinfo.output_scanline < jpeg_cinfo.output_height )
{
//jpeg_read_scanlines( &jpeg_cinfo, (JSAMPARRAY)row_pointers, height );
//jpeg_read_scanlines( &jpeg_cinfo, (JSAMPARRAY)row_pointers[jpeg_cinfo.output_scanline], 1 );
iread = jpeg_read_scanlines( &jpeg_cinfo, (JSAMPARRAY)dummy_array_of_one_row, 1 );
//printf( "read: %d (i = %d)\n", iread, i );
memcpy( row_pointers[i], one_row, rowbytes );
i++;
}
free( one_row ); one_row = NULL;
// end decompress free libjpeg's mem
jpeg_finish_decompress( &jpeg_cinfo );
jpeg_destroy_decompress( &jpeg_cinfo );
fclose( fp );
image_is_jpeg = 1;
image_is_png = 0;
return true;
}
bool PngJpegImage::freeImage() { freeself(); return TRUE; }
bool PngJpegImage::displayOn( HDC hdc, int x0, int y0 )
{
if( !row_pointers ) return FALSE;
if( height < 1 ) return FALSE;
if( width < 1 ) return FALSE;
int i, j;
unsigned char **p = row_pointers;
COLORREF crColor = 0; // pixel color in RGB mode
unsigned char alpha = 0; // alpha channel ;) only for RGBA color mode // not used ><
// TODO: other color types or set translations while reading
for( i=0; i<height; i++ )
{
for( j=0; j<width; j++ )
{
if( image_is_png )
{
if( (bit_depth == 8) && (channels == 3) && (color_type == PNG_COLOR_TYPE_RGB) )
crColor = RGB( p[i][j*3 + 0], p[i][j*3 + 1], p[i][j*3 + 2] );
if( (bit_depth == 8) && (channels == 4) && (color_type == PNG_COLOR_TYPE_RGBA) )
{
crColor = RGB( p[i][j*4 + 0], p[i][j*4 + 1], p[i][j*4 + 2] );
alpha = p[i][j*4 + 3]; // alpha channel ;) only for RGBA color mode // not used ><
}
}
else if( image_is_jpeg )
{
if( jpeg_cinfo.out_color_space == JCS_RGB )
{
crColor = RGB( p[i][j*3], p[i][j*3+1], p[i][j*3+2] );
}
}
SetPixel( hdc, x0+j, y0+i, crColor );
}
}
return TRUE;
}
bool PngJpegImage::getParams( int *w, int *h, int *bpp, int *ch ) const
{
if( w ) *w = width;
if( h ) *h = height;
if( bpp ) *bpp = bit_depth;
if( ch ) *ch = channels;
//if( ctype ) *ctype = color_type;
return TRUE;
}
bool PngJpegImage::getFileName( char *out, size_t cchMax ) const
{
if( !out || (cchMax < 1) ) return FALSE;
strncpy( out, m_filename, cchMax );
return TRUE;
}
void PngJpegImage::initnull()
{
number = 6;
memset( b_header, 0, sizeof(b_header) );
m_filename[0] = 0;
png_ptr = NULL;
info_ptr = NULL;
width = height = bit_depth = rowbytes = channels = 0;
// image data
row_pointers = NULL;
//
image_is_png = image_is_jpeg = 0;
}
void PngJpegImage::freeself()
{
if( image_is_png )
{
int i = 0;
if( row_pointers )
{
for( i=0; i<height; i++ )
{
if( row_pointers[i] )
{
png_free( png_ptr, row_pointers[i] );
}
}
png_free( png_ptr, row_pointers );
#ifdef _DEBUG_LOG
log_error( LOG_DEBUG, "png.freeself() freed row_pointers\n" );
#endif
}
if( png_ptr && info_ptr )
{
png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
#ifdef _DEBUG_LOG
log_error( LOG_DEBUG, "png.freeself() freed read_struct 0x%p, 0x%p\n", png_ptr, info_ptr );
#endif
}
} // image_is_png
else if( image_is_jpeg )
{
int i = 0;
if( row_pointers )
{
for( i=0; i<height; i++ )
{
if( row_pointers[i] ) free( row_pointers[i] );
}
free( row_pointers );
#ifdef _DEBUG_LOG
log_error( LOG_DEBUG, "jpeg.freeself() freed row_pointers\n" );
#endif
}
}
initnull();
}

View File

@@ -0,0 +1,43 @@
#ifndef H_PNGIMAGE
#define H_PNGIMAGE
class PngJpegImage
{
public:
PngJpegImage();
PngJpegImage( const char *fileName );
~PngJpegImage();
bool readFile_PNG( const char *fileName );
bool readFile_JPEG( const char *fileName );
bool freeImage();
bool displayOn( HDC hdc, int x0, int y0 );
bool getParams( int *w, int *h, int *bpp, int *ch ) const;
bool getFileName( char *out, size_t cchMax ) const;
protected:
void initnull();
void freeself();
protected:
int number;
unsigned char b_header[12];
char m_filename[512];
// lib PNG
png_structp png_ptr;
png_infop info_ptr;
// info
int width;
int height;
int bit_depth;
int rowbytes;
int channels;
int color_type; // depends on image type - png or jpeg have own constants :(
// image data
unsigned char **row_pointers;
// lib JPEG
jpeg_decompress_struct jpeg_cinfo;
jpeg_error_mgr jpeg_err;
// image type
int image_is_png;
int image_is_jpeg;
};
#endif

View File

@@ -0,0 +1,19 @@
set out=..\..\out\dist_L2OOGHelper
rem Copy EXE
echo Copy %1.exe...
copy /y %2\%1.exe %2\%out% > NUL
rem Copy PDB
echo Copy %1.pdb...
copy /y %2\%1.pdb %2\%out% > NUL
rem Copy scripts...
echo Copy scripts...
copy /y l2ooghelper\scripts\*.lua %2\%out%\scripts > NUL
copy /y l2ooghelper\scripts\*.luac %2\%out%\scripts > NUL
copy /y l2ooghelper\scripts\*.html %2\%out%\scripts > NUL
copy /y l2ooghelper\sys_scripts\*.lua %2\%out%\sys_scripts > NUL
copy /y l2ooghelper\sys_scripts\*.luac %2\%out%\sys_scripts > NUL
echo Results copied to dist directory [%out%]

View File

@@ -0,0 +1,403 @@
#include "stdafx.h"
#include "Resource.h"
#include "PrivateStoreDlg.h"
#include "logger.h"
#include "windowUtils.h"
#include "InputStringDlg.h"
#include "RecipeData.h"
#include "DBLayer.h"
extern HINSTANCE g_hInst;
extern HWND g_hWnd;
PrivateStoreManageDlg::PrivateStoreManageDlg( HWND hWndNotify, UINT uMessage, int type, TradeItemsList *list1, TradeItemsList *list2 )
{
m_hWndNotify = hWndNotify;
m_uNotifyMesasage = uMessage;
m_type = type;
m_list1 = list1;
m_list2 = list2;
}
PrivateStoreManageDlg::~PrivateStoreManageDlg()
{
delete m_list1;
m_list1 = NULL;
m_list2 = NULL; // this list is deleted by L2Client reply message receiver
//log_error( LOG_OK, "PrivateStoreManageDlg::~PrivateStoreManageDlg()\n" );
}
void PrivateStoreManageDlg::run()
{
DWORD dwTID = 0;
HANDLE hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))Dlg_Thread, (void *)this,
0, (unsigned int *)&dwTID );
if( hThread ) CloseHandle( hThread );
}
DWORD WINAPI PrivateStoreManageDlg::Dlg_Thread( LPVOID lpParam )
{
class PrivateStoreManageDlg *pcls = (PrivateStoreManageDlg *)lpParam;
HWND hDlg = CreateDialogParam( g_hInst, MAKEINTRESOURCE(IDD_PRIVATETRADEITEMS),
g_hWnd, Dlg_Proc, (LPARAM)pcls );
ShowWindow( hDlg, SW_SHOW );
MSG msg;
while( GetMessage( &msg, NULL, 0, 0 ) )
{
if( !IsDialogMessage( hDlg, &msg ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
//log_error( LOG_OK, "PrivateStoreManageDlg::Dlg_Thread(): ended window loop\n" );
DestroyWindow( hDlg );
return 0;
}
INT_PTR CALLBACK PrivateStoreManageDlg::Dlg_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch( uMsg )
{
case WM_INITDIALOG:
{
SetWindowLongPtr( hDlg, GWLP_USERDATA, (LONG_PTR)lParam );
OnInitDialog( hDlg, lParam );
} break;
case WM_COMMAND: OnCommand( hDlg, wParam, lParam ); break;
case WM_NOTIFY: OnNotify( hDlg, wParam, lParam ); break;
case WM_DESTROY: { OnDestroy( hDlg ); return FALSE; } break;
default: return FALSE; break;
}
return TRUE;
}
void PrivateStoreManageDlg::FillListViews( HWND hDlg, PrivateStoreManageDlg *pcls )
{
long long int downAdena = 0;
HWND hwndLV = NULL;
int i = 0;
// up LV
hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
ListView_DeleteAllItems( hwndLV );
for( i=0; i<pcls->m_list1->itemCount; i++ )
{
TradeItem it;
it = pcls->m_list1->item[i];
wchar_t wstr[256] = {0};
// get item name
if( (pcls->m_type == TYPE_BUY) || (pcls->m_type == TYPE_SELL) )
{
DBLayer_getItemName( it.itemID, wstr, 255 );
}
else if( (pcls->m_type == TYPE_CRAFT) || (pcls->m_type == TYPE_COMMONCRAFT) )
{
int iid = 0;
L2Data_RecipeInfo recInfo;
if( L2Data_GetRecipeInfoForRecID( it.itemID, &recInfo ) ) iid = recInfo.rec_itemID;
DBLayer_getItemName( iid, wstr, 255 );
}
int added_iid = 0;
if( it.enchantLevel == 0 )
{
added_iid = WULV_InsertItem( hwndLV, wstr, 0, i ); // lParam is just index
}
else
{
wchar_t descr[256] = {0};
swprintf( descr, 255, L"+%d %s", it.enchantLevel, wstr );
added_iid = WULV_InsertItem( hwndLV, descr, 0, i ); // lParam is just index
}
if( added_iid == -1 ) continue;
wsprintfW( wstr, L"%I64d", it.price );
WULV_SetItem( hwndLV, wstr, added_iid, 1 );
wsprintfW( wstr, L"%I64d", it.storePrice );
WULV_SetItem( hwndLV, wstr, added_iid, 2 );
wsprintfW( wstr, L"%I64d", it.count );
WULV_SetItem( hwndLV, wstr, added_iid, 3 );
wsprintfW( wstr, L"%u", it.itemID );
WULV_SetItem( hwndLV, wstr, added_iid, 4 );
wsprintfW( wstr, L"%u", it.objectID );
WULV_SetItem( hwndLV, wstr, added_iid, 5 );
}
// down LV
hwndLV = GetDlgItem( hDlg, IDC_LIST2 );
ListView_DeleteAllItems( hwndLV );
for( i=0; i<pcls->m_list2->itemCount; i++ )
{
TradeItem it;
it = pcls->m_list2->item[i];
wchar_t wstr[256] = {0};
// get item name
if( (pcls->m_type == TYPE_BUY) || (pcls->m_type == TYPE_SELL) )
{
DBLayer_getItemName( it.itemID, wstr, 256 );
}
else if( (pcls->m_type == TYPE_CRAFT) || (pcls->m_type == TYPE_COMMONCRAFT) )
{
int iid = 0;
L2Data_RecipeInfo recInfo;
if( L2Data_GetRecipeInfoForRecID( it.itemID, &recInfo ) ) iid = recInfo.rec_itemID;
DBLayer_getItemName( iid, wstr, 256 );
}
int added_iid = 0;
if( it.enchantLevel == 0 )
{
added_iid = WULV_InsertItem( hwndLV, wstr, 0, i ); // lParam is just index
}
else
{
wchar_t descr[256] = {0};
swprintf( descr, 255, L"+%d %s", it.enchantLevel, wstr );
added_iid = WULV_InsertItem( hwndLV, descr, 0, i ); // lParam is just index
}
if( added_iid == -1 ) continue;
wsprintfW( wstr, L"%I64d", it.price );
WULV_SetItem( hwndLV, wstr, added_iid, 1 );
wsprintfW( wstr, L"%I64d", it.storePrice );
WULV_SetItem( hwndLV, wstr, added_iid, 2 );
wsprintfW( wstr, L"%I64d", it.count );
WULV_SetItem( hwndLV, wstr, added_iid, 3 );
wsprintfW( wstr, L"%u", it.itemID );
WULV_SetItem( hwndLV, wstr, added_iid, 4 );
wsprintfW( wstr, L"%u", it.objectID );
WULV_SetItem( hwndLV, wstr, added_iid, 5 );
//
downAdena += (it.count * it.price);
}
// update adena counters
WU_SetDlgItemInt64( hDlg, IDC_EDIT1, downAdena, TRUE );
WU_SetDlgItemInt64( hDlg, IDC_EDIT2, pcls->m_list1->curMoney, TRUE );
}
void PrivateStoreManageDlg::OnInitDialog( HWND hDlg, LPARAM lParam )
{
//log_error( LOG_OK, "PrivateStoreManageDlg::OnInitDialog()\n" );
// init LV upper
HWND hwndLV = GetDlgItem( hDlg, IDC_LIST1 );
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("Item"), 150, 0 );
WULV_InsertColumn( hwndLV, TEXT("$"), 60, 1 );
WULV_InsertColumn( hwndLV, TEXT("$orig"), 60, 2 );
WULV_InsertColumn( hwndLV, TEXT("cnt"), 50, 3 );
WULV_InsertColumn( hwndLV, TEXT("itemID"), 50, 4 );
WULV_InsertColumn( hwndLV, TEXT("objectID"), 50, 5 );
// init LV down
hwndLV = GetDlgItem( hDlg, IDC_LIST2 );
WULV_SetExtStyle( hwndLV, true, true );
WULV_InsertColumn( hwndLV, TEXT("Item"), 150, 0 );
WULV_InsertColumn( hwndLV, TEXT("$"), 60, 1 );
WULV_InsertColumn( hwndLV, TEXT("$orig"), 60, 2 );
WULV_InsertColumn( hwndLV, TEXT("cnt"), 50, 3 );
WULV_InsertColumn( hwndLV, TEXT("itemID"), 50, 4 );
WULV_InsertColumn( hwndLV, TEXT("objectID"), 50, 5 );
//
PrivateStoreManageDlg *pcls = (PrivateStoreManageDlg *)lParam;
//
switch( pcls->m_type )
{
case PrivateStoreManageDlg::TYPE_BUY:
{
SetDlgItemText( hDlg, IDC_ST_UPPER, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
SetDlgItemText( hDlg, IDC_ST_DOWN, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
} break;
case PrivateStoreManageDlg::TYPE_SELL:
{
SetDlgItemText( hDlg, IDC_ST_UPPER, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
SetDlgItemText( hDlg, IDC_ST_DOWN, TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:") );
} break;
}
// UpdateUI
FillListViews( hDlg, pcls );
}
void PrivateStoreManageDlg::OnDestroy( HWND hDlg )
{
//log_error( LOG_DEBUG, "PrivateStoreManageDlg::OnDestroy()\n" );
PrivateStoreManageDlg *pcls = (PrivateStoreManageDlg *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
delete pcls;
}
void PrivateStoreManageDlg::OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(lParam);
PrivateStoreManageDlg *pcls = (PrivateStoreManageDlg *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
switch( LOWORD( wParam ) )
{
case IDOK:
{
if( pcls->m_list2->itemCount == 0 )
{
log_error( LOG_DEBUG, "PrivateStoreManageDlg(): OnOk: Did not set to buy/sell anything!\n" );
delete pcls->m_list2;
pcls->m_list2 = NULL;
}
PostMessage( pcls->m_hWndNotify, pcls->m_uNotifyMesasage, (WPARAM)(pcls->m_type), (LPARAM)(pcls->m_list2) );
PostMessage( hDlg, WM_QUIT, 0, 0 );
} break;
case IDCANCEL:
{
delete pcls->m_list2;
pcls->m_list2 = NULL;
PostMessage( pcls->m_hWndNotify, pcls->m_uNotifyMesasage, (WPARAM)(pcls->m_type), 0 );
PostMessage( hDlg, WM_QUIT, 0, 0 );
} break;
case IDC_B_MSGSELL:
{
InputStringDlg dlg( TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"), pcls->m_list2->message );
if( dlg.run( hDlg ) ) wcscpy( pcls->m_list2->message, dlg.text );
} break;
}
}
// forward decl
// returns 0 if cancelled
extern long long int BuySellDlg_RequestItemCount( HWND hDlg, TradeItem *it );
void PrivateStoreManageDlg::OnNotify( HWND hDlg, WPARAM wParam, LPARAM lParam )
{
UNREFERENCED_PARAMETER(wParam);
PrivateStoreManageDlg *pcls = (PrivateStoreManageDlg *)GetWindowLongPtr( hDlg, GWLP_USERDATA );
LPNMHDR pnmh = (LPNMHDR)lParam;
HWND hwndLV1 = GetDlgItem( hDlg, IDC_LIST1 );
HWND hwndLV2 = GetDlgItem( hDlg, IDC_LIST2 );
if( pnmh->code == NM_DBLCLK )
{
// The iItem, iSubItem, and ptAction members of this structure contain information about the item.
LPNMITEMACTIVATE lpnmitem = (LPNMITEMACTIVATE)lParam;
if( lpnmitem->iSubItem != 0 ) return;
if( pnmh->hwndFrom == hwndLV1 )
{
TradeItemsList *tl = pcls->m_list1;
TradeItemsList *tl2 = pcls->m_list2;
int clicked_iid = lpnmitem->iItem;
int idx = (int)WULV_GetItemLPARAM( pnmh->hwndFrom, clicked_iid );
TradeItem it( tl->item[idx] );
// request price
wchar_t str_price[32] = {0};
swprintf( str_price, 31, L"%d", it.storePrice );
InputStringDlg dlg( TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"), TEXT("<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>:"), str_price );
if( dlg.run( hDlg ) ) _stscanf( dlg.text, _T("%d"), &(it.price) ); else it.price = 0;
// request count
if( pcls->m_type == PrivateStoreManageDlg::TYPE_BUY ) it.count = 0;
long long int cnt = 1;
if( pcls->m_type == TYPE_BUY ) cnt = BuySellDlg_RequestItemCount( hDlg, &it );
if( pcls->m_type == TYPE_SELL ) cnt = BuySellDlg_RequestItemCount( hDlg, &it );
/*if( pcls->m_type == TYPE_CRAFT ) // do not request count for recipe shop :)
{
unsigned int save_iid = it.itemID;
RecipeInfo recInfo;
if( GetRecipeInfoForRecID( it.itemID, &recInfo ) ) it.itemID = recInfo.rec_itemID;
cnt = BuySellDlg_RequestItemCount( hDlg, &it );
it.itemID = save_iid;
}*/
if( cnt > 0 )
{
// add to second list (increase)
int existing_idx = tl2->findItemIdxByItemId( it.itemID );
if( (existing_idx != -1) && it.isStackableGuess() )
{
//log_error( LOG_OK, "Updating existing item idx %d: add count %d\n", existing_idx, cnt );
tl2->item[existing_idx].count += cnt;
tl2->item[existing_idx].price = it.price;
}
else
{
//log_error( LOG_OK, "Adding new item to idx %d: count %d\n", tl2->itemCount, cnt );
it.count = cnt;
tl2->addItem( it );
}
// update first list
switch( pcls->m_type )
{
case PrivateStoreManageDlg::TYPE_BUY:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
case PrivateStoreManageDlg::TYPE_SELL:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
default:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
}
}
}
if( pnmh->hwndFrom == hwndLV2 )
{
TradeItemsList *tl = pcls->m_list2;
TradeItemsList *tl2 = pcls->m_list1;
int clicked_iid = lpnmitem->iItem;
int idx = (int)WULV_GetItemLPARAM( pnmh->hwndFrom, clicked_iid );
TradeItem it( tl->item[idx] );
// request count
long long int cnt = 1;
if( pcls->m_type == TYPE_BUY ) cnt = BuySellDlg_RequestItemCount( hDlg, &it );
if( pcls->m_type == TYPE_SELL ) cnt = BuySellDlg_RequestItemCount( hDlg, &it );
if( cnt > 0 )
{
// add to first list (increase)
int existing_idx = tl2->findItemIdxByItemId( it.itemID );
if( (existing_idx != -1) && it.isStackableGuess() )
{
//log_error( LOG_OK, "Updating existing item in Lv 1 idx %d: add count %d\n", existing_idx, cnt );
switch( pcls->m_type )
{
case PrivateStoreManageDlg::TYPE_BUY:
{
tl2->item[existing_idx].count += cnt;
tl2->item[existing_idx].price = 0;
} break;
case PrivateStoreManageDlg::TYPE_SELL:
{
tl2->item[existing_idx].count += cnt;
tl2->item[existing_idx].price = 0;
} break;
default:
{
tl2->item[existing_idx].count += cnt;
tl2->item[existing_idx].price = 0;
} break;
}
}
else
{
//log_error( LOG_OK, "Adding new item to Lv 1 to idx %d: count %d\n", tl2->itemCount, cnt );
it.count = cnt;
it.price = 0;
tl2->addItem( it );
}
// remove from second list (decrease) TODO: remove on PrivateStoreBuy
switch( pcls->m_type )
{
case PrivateStoreManageDlg::TYPE_BUY:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
case PrivateStoreManageDlg::TYPE_SELL:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
default:
{
tl->item[idx].count -= cnt;
if( tl->item[idx].count <= 0 ) tl->removeCellAndShift( idx );
} break;
}
}
}
// update list-views contents
FillListViews( hDlg, pcls );
} // NM_DBLCLICK
}

View File

@@ -0,0 +1,34 @@
#ifndef H_PRIVATESTOREDLG
#define H_PRIVATESTOREDLG
#include "BuySellList.h"
class PrivateStoreManageDlg
{
public:
static const int TYPE_BUY = 0;
static const int TYPE_SELL = 1;
static const int TYPE_CRAFT = 2;
static const int TYPE_COMMONCRAFT = 3;
public:
PrivateStoreManageDlg( HWND hWndNotify, UINT uMessage, int type, TradeItemsList *list1, TradeItemsList *list2 );
~PrivateStoreManageDlg();
void run();
protected:
HWND m_hWndNotify;
UINT m_uNotifyMesasage;
int m_type;
TradeItemsList *m_list1;
TradeItemsList *m_list2;
protected:
static DWORD WINAPI Dlg_Thread( LPVOID lpParam );
static INT_PTR CALLBACK Dlg_Proc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
static void OnInitDialog( HWND hDlg, LPARAM lParam );
static void OnDestroy( HWND hDlg );
static void OnCommand( HWND hDlg, WPARAM wParam, LPARAM lParam );
static void OnNotify( HWND hDlg, WPARAM wParam, LPARAM lParam );
protected:
static void FillListViews( HWND hDlg, PrivateStoreManageDlg *pcls );
};
#endif

165
l2ooghelper/ProgressHP.cpp Normal file
View File

@@ -0,0 +1,165 @@
#include "stdafx.h"
#include "Logger.h"
#include "UserInfo_c.h"
WNDPROC OriginalProgressProc = NULL;
LRESULT CALLBACK ProgressHPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK ProgressMPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK ProgressCPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK ProgressWeightDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK ProgressTargetHPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
void SubclassProgressHP( HWND hWnd, UserInfo *pusr )
{
if( OriginalProgressProc == NULL )
{
OriginalProgressProc = (WNDPROC)(LPVOID)GetWindowLongPtr( hWnd, GWLP_WNDPROC );
//log_error( LOG_DEBUG, "Progress user data: 0x%08X\n", GetWindowLongPtr( hWnd, GWLP_USERDATA ) );
}
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR)(LPVOID)ProgressHPDlgProc );
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)pusr );
}
void SubclassProgressMP( HWND hWnd, UserInfo *pusr )
{
if( OriginalProgressProc == NULL ) OriginalProgressProc = (WNDPROC)(LPVOID)GetWindowLongPtr( hWnd, GWLP_WNDPROC );
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR)(LPVOID)ProgressMPDlgProc );
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)pusr );
}
void SubclassProgressCP( HWND hWnd, UserInfo *pusr )
{
if( OriginalProgressProc == NULL ) OriginalProgressProc = (WNDPROC)(LPVOID)GetWindowLongPtr( hWnd, GWLP_WNDPROC );
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR)(LPVOID)ProgressCPDlgProc );
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)pusr );
}
void SubclassProgressWeight( HWND hWnd, UserInfo *pusr )
{
if( OriginalProgressProc == NULL ) OriginalProgressProc = (WNDPROC)(LPVOID)GetWindowLongPtr( hWnd, GWLP_WNDPROC );
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR)(LPVOID)ProgressWeightDlgProc );
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)pusr );
}
void SubclassProgressTargetHP( HWND hWnd, UserInfo *pusr )
{
if( OriginalProgressProc == NULL ) OriginalProgressProc = (WNDPROC)(LPVOID)GetWindowLongPtr( hWnd, GWLP_WNDPROC );
SetWindowLongPtr( hWnd, GWLP_WNDPROC, (LONG_PTR)(LPVOID)ProgressTargetHPDlgProc );
SetWindowLongPtr( hWnd, GWLP_USERDATA, (LONG_PTR)pusr );
}
LRESULT CALLBACK ProgressHPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT ret = CallWindowProc( OriginalProgressProc, hWnd, uMsg, wParam, lParam );
if( uMsg == WM_PAINT )
{
UserInfo *pusr = (UserInfo *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( !pusr ) return ret;
// update HP numbers
HDC hdc;
RECT rc;
TCHAR text[64] = {0};
wsprintf( text, TEXT("%d / %d"), (int)pusr->curHp, (int)pusr->maxHp );
hdc = GetDC( hWnd );
GetClientRect( hWnd, &rc );
SetBkMode( hdc, TRANSPARENT );
HFONT hFntOld = SelectFont( hdc, GetStockFont( ANSI_VAR_FONT ) );
DrawText( hdc, text, lstrlen(text), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
SelectFont( hdc, hFntOld );
ReleaseDC( hWnd, hdc );
}
return ret;
}
LRESULT CALLBACK ProgressMPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT ret = CallWindowProc( OriginalProgressProc, hWnd, uMsg, wParam, lParam );
if( uMsg == WM_PAINT )
{
UserInfo *pusr = (UserInfo *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( !pusr ) return ret;
// update MP numbers
HDC hdc;
RECT rc;
TCHAR text[64] = {0};
wsprintf( text, TEXT("%d / %d"), (int)pusr->curMp, (int)pusr->maxMp );
hdc = GetDC( hWnd );
GetClientRect( hWnd, &rc );
SetBkMode( hdc, TRANSPARENT );
HFONT hFntOld = SelectFont( hdc, GetStockFont( ANSI_VAR_FONT ) );
DrawText( hdc, text, lstrlen(text), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
SelectFont( hdc, hFntOld );
ReleaseDC( hWnd, hdc );
}
return ret;
}
LRESULT CALLBACK ProgressCPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT ret = CallWindowProc( OriginalProgressProc, hWnd, uMsg, wParam, lParam );
if( uMsg == WM_PAINT )
{
UserInfo *pusr = (UserInfo *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( !pusr ) return ret;
// update CP numbers
HDC hdc;
RECT rc;
TCHAR text[64] = {0};
wsprintf( text, TEXT("%d / %d"), (int)pusr->curCp, (int)pusr->maxCp );
hdc = GetDC( hWnd );
GetClientRect( hWnd, &rc );
SetBkMode( hdc, TRANSPARENT );
HFONT hFntOld = SelectFont( hdc, GetStockFont( ANSI_VAR_FONT ) );
DrawText( hdc, text, lstrlen(text), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
SelectFont( hdc, hFntOld );
ReleaseDC( hWnd, hdc );
}
return ret;
}
LRESULT CALLBACK ProgressWeightDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT ret = CallWindowProc( OriginalProgressProc, hWnd, uMsg, wParam, lParam );
if( uMsg == WM_PAINT )
{
UserInfo *pusr = (UserInfo *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( !pusr ) return ret;
// update load
HDC hdc;
RECT rc;
TCHAR text[64] = {0};
wsprintf( text, TEXT("%d / %d"), (int)pusr->curLoad, (int)pusr->maxLoad );
hdc = GetDC( hWnd );
GetClientRect( hWnd, &rc );
SetBkMode( hdc, TRANSPARENT );
HFONT hFntOld = SelectFont( hdc, GetStockFont( ANSI_VAR_FONT ) );
DrawText( hdc, text, lstrlen(text), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
SelectFont( hdc, hFntOld );
ReleaseDC( hWnd, hdc );
}
return ret;
}
LRESULT CALLBACK ProgressTargetHPDlgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
LRESULT ret = CallWindowProc( OriginalProgressProc, hWnd, uMsg, wParam, lParam );
if( uMsg == WM_PAINT )
{
UserInfo *pusr = (UserInfo *)GetWindowLongPtr( hWnd, GWLP_USERDATA );
if( !pusr ) return ret;
// update HP numbers
HDC hdc;
RECT rc;
TCHAR text[64] = {0};
wsprintf( text, TEXT("%d / %d"), (int)pusr->targetCurHp, (int)pusr->targetMaxHp );
hdc = GetDC( hWnd );
GetClientRect( hWnd, &rc );
SetBkMode( hdc, TRANSPARENT );
HFONT hFntOld = SelectFont( hdc, GetStockFont( ANSI_VAR_FONT ) );
DrawText( hdc, text, lstrlen(text), &rc, DT_CENTER | DT_VCENTER | DT_SINGLELINE );
SelectFont( hdc, hFntOld );
ReleaseDC( hWnd, hdc );
}
return ret;
}

10
l2ooghelper/ProgressHP.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef H_PROGRESSHP
#define H_PROGRESSHP
void SubclassProgressHP( HWND hWnd, UserInfo *pusr );
void SubclassProgressMP( HWND hWnd, UserInfo *pusr );
void SubclassProgressCP( HWND hWnd, UserInfo *pusr );
void SubclassProgressWeight( HWND hWnd, UserInfo *pusr );
void SubclassProgressTargetHP( HWND hWnd, UserInfo *pusr );
#endif

8225
l2ooghelper/RecipeData.cpp Normal file

File diff suppressed because it is too large Load Diff

23
l2ooghelper/RecipeData.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef H_RECIPEDATA
#define H_RECIPEDATA
class RecipeInfo
{
public:
RecipeInfo() { name[0] = 0; itemID = rec_itemID = 0; level = resultCount = mpCost = successRate; }
public:
char name[128];
unsigned int itemID;
unsigned int rec_itemID;
int level;
int resultCount;
int mpCost;
int successRate;
};
#define MAX_RECIPE_ID 910
void RecipeData_Init();
bool GetRecipeInfoForRecID( int recID, RecipeInfo *pInfo );
#endif

237
l2ooghelper/Resource.h Normal file
View File

@@ -0,0 +1,237 @@
#define IDC_MYICON 2
#define IDD_L2OOGHELPER_DIALOG 102
#define IDS_APP_TITLE 103
#define IDD_ABOUTBOX 103
#define IDM_ABOUT 104
#define IDM_EXIT 105
#define IDI_L2OOGHELPER 107
#define IDI_SMALL 108
#define IDC_L2OOGHELPER 109
#define IDR_MAINFRAME 128
#define IDD_ACCOUNT 130
#define IDMENU_DEBUG 131
#define IDD_TAB 132
#define IDD_CHOOSESERVER 133
#define IDD_CHOOSECHAR 134
#define IDD_USERINFO 135
#define IDD_USERINV 136
#define IDD_USERSKILLS 137
#define IDD_USERBUFF 138
#define IDD_MAPINFO 139
#define IDD_MBTIMEOUT 140
#define IDD_USERPARTY 141
#define IDD_USERINV_ITEMCOUNT 142
#define IDD_USERINV_DROPITEM 143
#define IDD_NPCHTML 144
#define IDD_BOTCONFIG 145
#define IDD_BOTCFG_SELFHEAL 146
#define IDD_BOTCFG_PARTY 147
#define IDD_BOTCFG_SELF 148
#define IDD_BOTCFG_SELFHEAL_COND 149
#define IDD_FINDINDB 150
#define IDD_TRADEITEMS 151
#define IDD_PRIVATETRADEITEMS 152
#define IDD_INPUTSTRING 153
#define IDD_TRADEP2P 154
#define IDD_CREATECHAR 155
#define IDC_E_LOGIN 1001
#define IDC_E_PASS 1002
#define IDC_E_IP 1003
#define IDC_E_PORT 1004
#define IDC_C_GAME_MANUAL 1005
#define IDC_E_GSID 1006
#define IDC_C_CHAR_MANUAL 1007
#define IDC_E_CHARNAME 1008
#define IDC_CB_CONFIG 1009
#define IDC_LOAD 1010
#define IDC_SAVE 1011
#define IDC_TAB_INFO 1011
#define IDC_CB_L2VER 1012
#define IDC_TAB_CHAT 1013
#define IDC_PR_HP 1014
#define IDC_ST_CHAR_NAME 1015
#define IDC_PR_MP 1016
#define IDC_PR_CP 1017
#define IDC_CHECK1 1018
#define IDC_C_BOTENABLE 1018
#define IDC_C_PARTY_AUTO_ACCEPT 1018
#define IDC_CHECK2 1019
#define IDC_C_BOTCOMBATENABLE 1019
#define IDC_C_PARTY_AUTO_INVITE 1019
#define IDC_C_MAPSHOWMOBS 1020
#define IDC_C_STANDHP 1020
#define IDC_C_MAPSHOWNPCS 1021
#define IDC_C_STANDMP 1021
#define IDC_C_MAPSHOWPCS 1022
#define IDC_C_MAPSHOWITEMS 1023
#define IDC_C_MAPSHOWZONE 1024
#define IDC_E_MAPSHOWDZ 1025
#define IDC_E_CHAT 1027
#define IDC_B_SAY 1028
#define IDC_B_SYSTEM 1029
#define IDC_PR_WEIGHT 1030
#define IDC_B_CLOSETAB 1031
#define IDC_B_CONFIG 1032
#define IDC_LIST1 1033
#define IDC_PR_TARGETHP 1033
#define IDC_E_PROTO 1034
#define IDC_C_MAPSHOWVECTORS 1034
#define IDC_C_PROTOAUTO 1035
#define IDC_PR_CASTING 1035
#define IDC_SLI_SCALE 1036
#define IDC_ST_EXP 1037
#define IDC_ST_SP 1038
#define IDC_ST_PATK 1039
#define IDC_ST_PDEF 1040
#define IDC_ST_ACCURACY 1041
#define IDC_ST_CRITICAL 1042
#define IDC_ST_MATK 1043
#define IDC_ST_MDEF 1044
#define IDC_ST_EVASION 1045
#define IDC_ST_SPEED 1046
#define IDC_ST_STR 1047
#define IDC_ST_DEX 1048
#define IDC_ST_CON 1049
#define IDC_ST_INT 1050
#define IDC_ST_WIT 1051
#define IDC_ST_MEN 1052
#define IDC_ST_KARMA 1053
#define IDC_ST_PVPPK 1054
#define IDC_ST_RECOM 1055
#define IDC_ST_FAME 1056
#define IDC_LISTITEMS 1056
#define IDC_ST_ATKATTRIB 1057
#define IDC_DESTROY 1057
#define IDC_ST_ATTRIBVAL 1058
#define IDC_DROP 1058
#define IDC_ST_FIRE 1059
#define IDC_LINKCHAT 1059
#define IDC_ST_WATER 1060
#define IDC_CRYSTALLIZE 1060
#define IDC_ST_WIND 1061
#define IDC_GIVETOPET 1061
#define IDC_ST_EARTH 1062
#define IDC_ST_INVSIZE 1062
#define IDC_ST_HOLY 1063
#define IDC_ST_DARK 1064
#define IDC_ST_ATKSPD 1065
#define IDC_TAB2 1065
#define IDC_ST_CASTSPEED 1066
#define IDC_B_SCRIPT 1066
#define IDC_CANCELBUFF 1067
#define IDC_ST_VITALITYLEVEL 1067
#define IDC_ST_NBUFFS 1068
#define IDC_B_DEBUG 1069
#define IDC_PROGRESS1 1070
#define IDC_ST_Q 1071
#define IDC_EDITNAME 1071
#define IDC_LEAVEPARTY 1072
#define IDC_R_STWITH 1072
#define IDC_CHANGEPARTYLEADER 1073
#define IDC_ST_TARGETNAME 1073
#define IDC_R_CONTAINS 1073
#define IDC_KICKPARTYMEMBER 1074
#define IDC_R_ENWITH 1074
#define IDC_MAPAREA 1075
#define IDC_B_CANCELTARGET 1076
#define IDC_B_ATTACKTARGET 1077
#define IDC_FIND 1077
#define IDC_B_SITSTAND 1078
#define IDC_B_RUNWALK 1079
#define IDC_ST_WAITTYPE 1080
#define IDC_ST_ITEMNAME 1081
#define IDC_B_ACTIONTARGET 1081
#define IDC_E_COUNT 1082
#define IDC_B_ALL 1083
#define IDC_B_2 1084
#define IDC_B_1 1085
#define IDC_PR_EXP 1085
#define IDC_B_3 1086
#define IDC_B_4 1087
#define IDC_EDIT1 1087
#define IDC_B_6 1088
#define IDC_COMBO1 1088
#define IDC_E_SITMP 1088
#define IDC_B_5 1089
#define IDC_E_STANDHP 1089
#define IDC_CB_MP 1089
#define IDC_B_7 1090
#define IDC_EDIT2 1090
#define IDC_E_STANDMP 1090
#define IDC_B_9 1091
#define IDC_ST_PARTYLEADER 1091
#define IDC_E_MP 1091
#define IDC_B_8 1092
#define IDC_ST_PARTYLOOTTYPE 1092
#define IDC_CB_CP 1092
#define IDC_E_CP 1093
#define IDC_C_MAPSHOWMAP 1094
#define IDC_TREE1 1095
#define IDC_C_SITHP 1097
#define IDC_C_SITMP 1098
#define IDC_E_SITHP 1099
#define IDC_APPLY 1100
#define IDC_E_PARTY_AUTO_ACCEPT 1101
#define IDC_E_PARTY_AUTO_INVITE 1102
#define IDC_CB_PARTY_LOOT 1103
#define IDC_C_FOLLOW_ENABLE 1104
#define IDC_E_FOLLOW_NAME 1105
#define IDC_E_FOLLOW_DIST 1106
#define IDC_C_PARTY_ASSIST 1107
#define IDC_R_GENERAL 1108
#define IDC_R_HEALER 1109
#define IDC_R_NUKER 1110
#define IDC_COMBO2 1111
#define IDC_B_ADD 1112
#define IDC_B_EDIT 1113
#define IDC_B_FIND 1113
#define IDC_B_DEL 1114
#define IDC_DELAYMS 1114
#define IDC_E_DELAYMS 1114
#define IDC_E_ITEM 1115
#define IDC_CB_HP 1116
#define IDC_E_HP 1117
#define IDC_E_ITEMID 1118
#define IDC_CB_AI_MODEL 1119
#define IDC_B_ACTIONS 1120
#define IDC_LIST2 1121
#define IDC_ST_UPPER 1122
#define IDC_ST_DOWN 1123
#define IDC_B_MSGSELL 1124
#define IDC_QUESTION 1125
#define IDC_C_MAPSHOWSELL 1126
#define IDC_C_MAPSHOWBUY 1127
#define IDC_C_MAPSHOWCRAFT 1128
#define IDC_LV_INV 1129
#define IDC_LV_SEND 1130
#define IDC_LV_RECV 1131
#define IDC_ST_TRADECHAR 1132
#define IDC_CHARCREATE 1133
#define IDC_CHARDEL 1134
#define IDC_CHARLDELCANCEL 1135
#define IDC_CB_CLASS 1136
#define IDC_CB_HSTYLE 1137
#define IDC_CB_HCOLOR 1138
#define IDC_CB_FSTYLE 1139
#define IDC_CB_GENDER 1140
#define IDM_LINEAGE_ADD_ACC 32772
#define ID_DEBUG_ENABLE 32773
#define ID_DEBUG_ENABLE32774 32774
#define ID_DEBUG_ENABLECON 32775
#define ID_DEBUG_DISABLECON 32776
#define ID_DEBUG_LOGLEVEL 32777
#define ID_LOGLEVEL_LOG 32778
#define ID_LOGLEVEL_LOG32779 32779
#define ID_LOGLEVEL_OK 32780
#define ID_LOGLEVEL_WARN 32781
#define ID_LOGLEVEL_ERROR 32782
#define ID_LOGLEVEL_USERAI 32783
#define ID_LOGLEVEL_PACKETNAME 32784
#define ID_LOGLEVEL_DEBUG 32785
#define ID_LOGLEVEL_DEBUGDUMP 32786
#define ID_DEBUG_RUNTESTSCRIPT 32787
#define ID_DEBUG_DUMPCHARS 32788
#define ID_32789 32789
#define IDC_STATIC -1

199
l2ooghelper/SEH_global.cpp Normal file
View File

@@ -0,0 +1,199 @@
#include "stdafx.h"
#include "Logger.h"
#ifdef USE_SEH
#ifdef _MSC_VER // only under MS Visual C++
#ifdef _DEBUG
const int SEH_MAX_NAMES = 10000;
class SEH_NAME
{
public:
char *name;
unsigned int addr;
};
SEH_NAME *SEH_names[SEH_MAX_NAMES];
int SEH_loaded_names_count = 0;
bool SEH_loadMap()
{
if( SEH_loaded_names_count > 0 ) return true; // already loaded
log_error( LOG_DEBUG, "SEH_loadMap(): loading L2OOGHelper_d.map...\n" );
FILE *f = fopen( "L2OOGHelper_d.map", "rt" );
if( !f )
{
log_error( LOG_WARNING, "SEH_loadMap(): cannot load L2OOGHelper_d.map!\n" );
return false;
}
//
char line[1024];
bool step1_ok = false;
// pass first several lines
while( !feof(f) )
{
line[0] = 0;
fgets( line, sizeof(line), f );
if( line[0] == 0 ) continue;
if( strstr( line, "Address" ) && strstr( line, "Publics by Value" ) &&
strstr( line, "Rva+Base" ) && strstr( line, "Lib:Object" ) )
{
step1_ok = true;
break;
}
}
if( !step1_ok )
{
log_error( LOG_WARNING, "SEH_loadMap(): Not a valid map file?\n" );
fclose( f );
return false;
}
//
// init seh names array
int i;
for( i=0; i<SEH_MAX_NAMES; i++ ) SEH_names[i] = NULL;
int nSEHNamesLoaded = 0;
//
while( !feof(f) )
{
line[0] = 0;
fgets( line, sizeof(line), f );
if( line[0] == 0 ) continue;
if( strchr( line, ':' ) && (strlen( line ) > 21) )
{
char delimeter[] = " \r\n\t";
char *token1 = strtok( line, delimeter );
char *token2 = strtok( NULL, delimeter );
char *token3 = strtok( NULL, delimeter );
if( token1 && token2 && token3 )
{
unsigned int addr = 0;
sscanf( token3, "%x", &addr );
if( addr > 0 )
{
SEH_NAME *sename = new SEH_NAME();
if( sename )
{
sename->addr = addr;
sename->name = _strdup( token2 );
SEH_names[nSEHNamesLoaded] = sename;
//log_error( LOG_OK, "%d: %s (0x%x)\n",
// nSEHNamesLoaded, sename->name, sename->addr );
nSEHNamesLoaded++;
}
}
}
}
if( nSEHNamesLoaded >= SEH_MAX_NAMES )
{
log_error( LOG_WARNING, "SEH_loadMap(): loaded map names up to limit %d!\n",
SEH_MAX_NAMES );
break;
}
}
//
fclose( f );
SEH_loaded_names_count = nSEHNamesLoaded;
log_error( LOG_OK, "SEH_loadMap(): loaded L2OOGHelper_d.map (%d names).\n", nSEHNamesLoaded );
return true;
}
void SEH_getFuncNameByAddr( unsigned int addr, char *outFN )
{
outFN[0] = 0;
if( !SEH_loadMap() ) return;
int i;
char *prev_name = NULL;
unsigned int prev_addr = 0;
for( i=0; i<SEH_loaded_names_count; i++ )
{
if( SEH_names[i] )
{
if( SEH_names[i]->addr > addr )
{
if( prev_name ) strcpy( outFN, prev_name );
else strcpy( outFN, "<internal error>" );
return;
}
prev_addr = SEH_names[i]->addr;
prev_name = SEH_names[i]->name;
}
}
strcpy( outFN, "<not found>" );
}
#endif
LONG WINAPI GlobalUnhandledExceptionFilter( LPEXCEPTION_POINTERS e )
{
log_error( LOG_ERROR, "Unhandled exception!\n" );
log_error( LOG_ERROR, "Exception code: 0x%08X at address 0x%08X\n",
e->ExceptionRecord->ExceptionCode, e->ExceptionRecord->ExceptionAddress );
if( e->ExceptionRecord->ExceptionCode == 0xE06D7363 ) log_error( LOG_ERROR, "Microsoft C++ Exception?\n" );
#ifdef _DEBUG
char fn[256] = {0};
SEH_getFuncNameByAddr( e->ContextRecord->Eip, fn );
log_error( LOG_ERROR, "In function: [%s]\n", fn );
#endif
ErrorLogger_FlushLogFile();
char errbuf[1024];
sprintf( errbuf,
"Unhandled exception!\n"
"Exception code: 0x%08X at address 0x%08X\n"
"Exception: EIP = %08X\n",
e->ExceptionRecord->ExceptionCode, e->ExceptionRecord->ExceptionAddress,
e->ContextRecord->Eip );
MessageBoxA( NULL, errbuf, "L2OOGHelper unhandled exception handler", MB_ICONSTOP );
return EXCEPTION_EXECUTE_HANDLER;
}
LONG WINAPI ScriptEngineThreadExceptonHandler( LPEXCEPTION_POINTERS e )
{
log_error( LOG_ERROR, "Exception in ScriptEngine thread... possible small memory leak\n" );
log_error( LOG_ERROR, "Exception code: 0x%08X at address 0x%08X\n",
e->ExceptionRecord->ExceptionCode, e->ExceptionRecord->ExceptionAddress );
if( e->ExceptionRecord->ExceptionCode == 0xE06D7363 ) log_error( LOG_ERROR, "Microsoft C++ Exception?\n" );
#ifdef _DEBUG
char fn[256] = {0};
SEH_getFuncNameByAddr( e->ContextRecord->Eip, fn );
log_error( LOG_ERROR, "In function: [%s]\n", fn );
#endif
ErrorLogger_FlushLogFile();
char errbuf[1024];
sprintf( errbuf,
"Exception in ScriptEngine thread... possible small memory leak\n"
"Exception code: 0x%08X at address 0x%08X\n"
"Exception: EIP = %08X\n",
e->ExceptionRecord->ExceptionCode, e->ExceptionRecord->ExceptionAddress,
e->ContextRecord->Eip );
MessageBoxA( NULL, errbuf, "ScriptEngine exception handler", MB_ICONSTOP );
return EXCEPTION_EXECUTE_HANDLER;
}
LONG WINAPI L2ClientThreadExceptonHandler( LPEXCEPTION_POINTERS e )
{
log_error( LOG_ERROR, "Exception in L2Client thread...\n" );
log_error( LOG_ERROR, "Exception code: 0x%08X at address 0x%08X\n",
e->ExceptionRecord->ExceptionCode, e->ExceptionRecord->ExceptionAddress );
if( e->ExceptionRecord->ExceptionCode == 0xE06D7363 ) log_error( LOG_ERROR, "Microsoft C++ Exception?\n" );
#ifdef _DEBUG
char fn[256] = {0};
SEH_getFuncNameByAddr( e->ContextRecord->Eip, fn );
log_error( LOG_ERROR, "In function: [%s]\n", fn );
#endif
ErrorLogger_FlushLogFile();
char errbuf[1024];
sprintf( errbuf,
"Exception in L2Client thread... \n"
"Exception code: 0x%08X at address 0x%08X\n"
"Exception: EIP = %08X\n",
e->ExceptionRecord->ExceptionCode, e->ExceptionRecord->ExceptionAddress,
e->ContextRecord->Eip );
MessageBoxA( NULL, errbuf, "L2ClientThread exception handler", MB_ICONSTOP );
return EXCEPTION_EXECUTE_HANDLER;
}
#endif
#endif

20
l2ooghelper/SEH_global.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef H_SEH_GLOBAL
#define H_SEH_GLOBAL
#ifdef USE_SEH
#ifdef _MSC_VER // only under MS Visual C++
#ifdef _DEBUG
bool SEH_loadMap();
#endif
LONG WINAPI GlobalUnhandledExceptionFilter( LPEXCEPTION_POINTERS e );
LONG WINAPI ScriptEngineThreadExceptonHandler( LPEXCEPTION_POINTERS e );
LONG WINAPI L2ClientThreadExceptonHandler( LPEXCEPTION_POINTERS e );
#endif
#endif
#endif

238
l2ooghelper/SE_funcs.cpp Normal file
View File

@@ -0,0 +1,238 @@
#include "stdafx.h"
#include "Logger.h"
#include "L2Client.h"
#include "SE_funcs.h"
#include "ScriptEngine.h"
void SE_funcs_register( lua_State *L )
{
//lua_register( L, "test_func", test_func );
lua_register( L, "l2h_delay", l2h_delay );
lua_register( L, "l2h_print", l2h_print );
lua_register( L, "l2h_console_enable", l2h_console_enable );
lua_register( L, "l2h_soundAlert", l2h_soundAlert );
lua_register( L, "l2h_time", l2h_time );
lua_register( L, "l2h_timeMsec", l2h_timeMsec );
}
int l2h_print( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs > 0 )
{
int i;
for( i=1; i<=nArgs; i++ )
{
int typ = lua_type( L, i );
switch( typ )
{
case LUA_TNIL: log_error_np( LOG_OK, "NULL" ); break;
case LUA_TNUMBER:
{
double d = lua_tonumber( L, i );
double floor_d = floor( d * 100 ); // 10012.00
__int64 int_d = (__int64)floor_d; // 10012
__int64 eds_cnt = int_d % 100; // 12
if( eds_cnt ) log_error_np( LOG_OK, "%0.2f", d ); // original double
else log_error_np( LOG_OK, "%I64d", int_d/100 ); // rounded integer
} break;
case LUA_TBOOLEAN:
{
lua_toboolean( L, i ) ? log_error_np( LOG_OK, "true" ) : log_error_np( LOG_OK, "false" );
} break;
case LUA_TSTRING: log_error_np( LOG_OK, "%s", lua_tostring( L, i ) ); break;
case LUA_TTABLE: { log_error_np( LOG_OK, "(table)" ); /*lua_pop( L, i );*/ } break;
case LUA_TFUNCTION: { log_error_np( LOG_OK, "(function)" ); /*lua_pop( L, i );*/ } break;
default: lua_pop( L, i ); break;
}
}
}
return 0;
}
int l2h_console_enable( lua_State *L )
{
int n = lua_gettop( L ); // number of arguments
if( n > 0 )
{
if( lua_type( L, 1 ) == LUA_TBOOLEAN )
{
int enable = lua_toboolean( L, 1 );
ErrorLogger_EnableLoggingToConsole( enable ? true : false );
}
}
return 0;
}
int l2h_delay( lua_State *L )
{
int n = lua_gettop( L ); // number of arguments
//log_error_np( LOG_OK, "delay_lua: %d args\n", n );
if( n >= 1 )
{
if( lua_type( L, 1 ) == LUA_TNUMBER )
{
int msec = (int)lua_tonumber( L, 1 );
//log_error_np( LOG_OK, "delay_lua( %d );\n", msec );
Sleep( (DWORD)msec );
}
}
return 0;
}
int l2h_soundAlert( lua_State *L )
{
int nArgs = lua_gettop( L );
TCHAR fileName[256] = {0};
if( nArgs == 0 )
{
GetWindowsDirectory( fileName, 255 );
_tcscat( fileName, _T("\\Media\\ringin.wav") );
}
else
{
const char *astr = lua_tolstring( L, 1, NULL );
MultiByteToWideChar( CP_ACP, 0, astr, -1, fileName, 255 );
}
PlaySound( fileName, NULL, SND_FILENAME|SND_ASYNC );
return 0;
}
int l2h_time( lua_State *L )
{
unsigned int secs = (unsigned int)time( NULL );
lua_pushnumber( L, secs );
return 1;
}
int l2h_timeMsec( lua_State *L )
{
unsigned int msecs = GetTickCount();
lua_pushnumber( L, msecs );
return 1;
}
IL2Client *L2C_func_getClient( lua_State *L )
{
int typ = lua_type( L, lua_upvalueindex( 1 ) );
if( typ == LUA_TLIGHTUSERDATA )
{
IL2Client *cl = (IL2Client *)lua_touserdata( L, lua_upvalueindex( 1 ) );
return cl;
}
return NULL;
}
int sys_should_exit( lua_State *L )
{
int typ = lua_type( L, lua_upvalueindex( 1 ) );
if( typ != LUA_TLIGHTUSERDATA )
{
log_error( LOG_ERROR, "sys_should_exit(): no light user data!\n" );
lua_pushboolean( L, 1 );
return 1;
}
ScriptEngine *se = (ScriptEngine *)lua_touserdata( L, lua_upvalueindex( 1 ) );
//log_error( LOG_DEBUG, "sys_should_exit(): se = 0x%p\n", se );
if( !se )
{
log_error( LOG_ERROR, "sys_should_exit(): ScriptEngine ptr == NULL!\n" );
lua_pushboolean( L, 1 );
return 1;
}
if( se->should_stop ) lua_pushboolean( L, 1 );
else lua_pushboolean( L, 0 );
return 1;
}
void SE_regclientfunc( lua_State *L, void *pvL2Client, lua_CFunction funcPtr, const char *funcName )
{
lua_pushlightuserdata( L, pvL2Client ); // store class pointer as user data to function
lua_pushcclosure( L, funcPtr, 1 ); // 1 - userdata objects count
lua_setfield( L, LUA_GLOBALSINDEX, funcName );
}
void SE_regScriptEngineFunc( lua_State *L, void *ptrScriptEngine, lua_CFunction funcPtr, const char *funcName )
{
lua_pushlightuserdata( L, ptrScriptEngine ); // store scriptEngine pointer as light user data
lua_pushcclosure( L, funcPtr, 1 ); // 1 - user data objects count
lua_setfield( L, LUA_GLOBALSINDEX, funcName );
}
void SE_register_client_funcs( lua_State *L, void *pvL2Client, void *ptrScriptEngine )
{
if( !L || !pvL2Client ) return;
L2Client *pcl = (L2Client *)pvL2Client;
IL2Client *pInterface = pcl->getInterface();
// script engine special func
SE_regScriptEngineFunc( L, ptrScriptEngine, sys_should_exit, "sys_should_exit" );
SE_regScriptEngineFunc( L, ptrScriptEngine, sys_register_onChat, "sys_register_onChat" );
//
SE_regclientfunc( L, pInterface, l2c_is_INGAME, "l2c_is_INGAME" );
// user info
SE_regclientfunc( L, pInterface, l2c_getHPMPCPWeight, "l2c_getHPMPCPWeight" );
SE_regclientfunc( L, pInterface, l2c_getPos, "l2c_getPos" );
SE_regclientfunc( L, pInterface, l2c_getStats, "l2c_getStats" );
// chatting
SE_regclientfunc( L, pInterface, l2c_say, "l2c_say" );
SE_regclientfunc( L, pInterface, l2c_sayPm, "l2c_sayPm" );
SE_regclientfunc( L, pInterface, l2c_npcDlg, "l2c_npcDlg" );
SE_regclientfunc( L, pInterface, l2c_npcDlgClear, "l2c_npcDlgClear" );
SE_regclientfunc( L, pInterface, l2c_npcDlgExists, "l2c_npcDlgExists" );
// moving
SE_regclientfunc( L, pInterface, l2c_moveTo, "l2c_moveTo" );
SE_regclientfunc( L, pInterface, l2c_moveToDelta, "l2c_moveToDelta" );
SE_regclientfunc( L, pInterface, l2c_getSitRun, "l2c_getSitRun" );
SE_regclientfunc( L, pInterface, l2c_sitStand, "l2c_sitStand" );
SE_regclientfunc( L, pInterface, l2c_runWalk, "l2c_runWalk" );
// targeting, attack
SE_regclientfunc( L, pInterface, l2c_action, "l2c_action" );
SE_regclientfunc( L, pInterface, l2c_attack, "l2c_attack" );
SE_regclientfunc( L, pInterface, l2c_targetByName, "l2c_targetByName" );
SE_regclientfunc( L, pInterface, l2c_targetCancel, "l2c_targetCancel" );
SE_regclientfunc( L, pInterface, l2c_getTarget, "l2c_getTarget" );
// skills
SE_regclientfunc( L, pInterface, l2c_useSkill, "l2c_useSkill" );
SE_regclientfunc( L, pInterface, l2c_getSkillLevel, "l2c_getSkillLevel" );
SE_regclientfunc( L, pInterface, l2c_getSkillReuseLeft, "l2c_getSkillReuseLeft" );
SE_regclientfunc( L, pInterface, l2c_isCastingNow, "l2c_isCastingNow" );
// items in inventory, auto SS
SE_regclientfunc( L, pInterface, l2c_autoSoulshot, "l2c_autoSoulshot" );
SE_regclientfunc( L, pInterface, l2c_getItemCount, "l2c_getItemCount" );
SE_regclientfunc( L, pInterface, l2c_useItem, "l2c_useItem" );
SE_regclientfunc( L, pInterface, l2c_useItemByObjectId, "l2c_useItemByObjectId" );
SE_regclientfunc( L, pInterface, l2c_getPaperdollItem, "l2c_getPaperdollItem" );
// buffs
SE_regclientfunc( L, pInterface, l2c_getBuffs, "l2c_getBuffs" );
SE_regclientfunc( L, pInterface, l2c_buffCancel, "l2c_buffCancel" );
// get world objects information
SE_regclientfunc( L, pInterface, l2c_getVisibleChars, "l2c_getVisibleChars" );
SE_regclientfunc( L, pInterface, l2c_getVisibleMobs, "l2c_getVisibleMobs" );
SE_regclientfunc( L, pInterface, l2c_getVisibleNpcs, "l2c_getVisibleNpcs" );
SE_regclientfunc( L, pInterface, l2c_getVisibleItems, "l2c_getVisibleItems" );
// party information
SE_regclientfunc( L, pInterface, l2c_getParty, "l2c_getParty" );
SE_regclientfunc( L, pInterface, l2c_getPartyMemberBuffs, "l2c_getPartyMemberBuffs" );
SE_regclientfunc( L, pInterface, l2c_partySendInvite, "l2c_partySendInvite" );
SE_regclientfunc( L, pInterface, l2c_partyLeave, "l2c_partyLeave" );
SE_regclientfunc( L, pInterface, l2c_partyKickMember, "l2c_partyKickMember" );
SE_regclientfunc( L, pInterface, l2c_partyChangeLeader, "l2c_partyChangeLeader" );
// object information
SE_regclientfunc( L, pInterface, l2c_getCharObjectIdByName, "l2c_getCharObjectIdByName" );
SE_regclientfunc( L, pInterface, l2c_getNpcObjectIdByName, "l2c_getNpcObjectIdByName" );
SE_regclientfunc( L, pInterface, l2c_getObjectInfoByObjectId,"l2c_getObjectInfoByObjectId" );
SE_regclientfunc( L, pInterface, l2c_isCharDead, "l2c_isCharDead" );
// bot config
SE_regclientfunc( L, pInterface, l2ccfg_getInt, "l2ccfg_getInt" );
SE_regclientfunc( L, pInterface, l2ccfg_setInt, "l2ccfg_setInt" );
SE_regclientfunc( L, pInterface, l2ccfg_getStr, "l2ccfg_getStr" );
SE_regclientfunc( L, pInterface, l2ccfg_setStr, "l2ccfg_setStr" );
SE_regclientfunc( L, pInterface, l2ccfg_getAllConfig, "l2ccfg_getAllConfig" );
// botting combat state
SE_regclientfunc( L, pInterface, l2c_isCombatEnabled, "l2c_isCombatEnabled" );
SE_regclientfunc( L, pInterface, l2c_combatEnable, "l2c_combatEnable" );
// dirty hacks
SE_regclientfunc( L, pInterface, l2c_sendPacketHex, "l2c_sendPacketHex" );
}

103
l2ooghelper/SE_funcs.h Normal file
View File

@@ -0,0 +1,103 @@
#ifndef H_SE_FUNCS
#define H_SE_FUNCS
#include "lib/lua/lua.hpp"
#include "IL2Client.h"
void SE_funcs_register( lua_State *L );
void SE_register_client_funcs( lua_State *L, void *pvL2Client, void *ptrScriptEngine );
// function registration
void SE_regclientfunc( lua_State *L, void *pvL2Client, lua_CFunction funcPtr, const char *funcName );
void SE_regScriptEngineFunc( lua_State *L, void *ptrScriptEngine, lua_CFunction funcPtr, const char *funcName );
// "system" functions
int l2h_print( lua_State *L );
int l2h_console_enable( lua_State *L );
int l2h_delay( lua_State *L );
int l2h_soundAlert( lua_State *L );
int l2h_time( lua_State *L );
int l2h_timeMsec( lua_State *L );
IL2Client *L2C_func_getClient( lua_State *L );
// general user info
int l2c_is_INGAME( lua_State *L );
int l2c_getHPMPCPWeight( lua_State *L );
int l2c_getStats( lua_State *L );
// chatting
int l2c_say( lua_State *L );
int l2c_sayPm( lua_State *L );
int l2c_npcDlg( lua_State *L );
int l2c_npcDlgClear( lua_State *L );
int l2c_npcDlgExists( lua_State *L );
// movement
int l2c_getPos( lua_State *L );
int l2c_moveTo( lua_State *L );
int l2c_moveToDelta( lua_State *L );
int l2c_getSitRun( lua_State *L );
int l2c_sitStand( lua_State *L );
int l2c_runWalk( lua_State *L );
// target, attack
int l2c_action( lua_State *L );
int l2c_attack( lua_State *L );
int l2c_targetByName( lua_State *L );
int l2c_targetCancel( lua_State *L );
int l2c_getTarget( lua_State *L );
// skills
int l2c_useSkill( lua_State *L );
int l2c_getSkillLevel( lua_State *L );
int l2c_getSkillReuseLeft( lua_State *L );
int l2c_isCastingNow( lua_State *L );
// items (in inventory)
int l2c_autoSoulshot( lua_State *L );
int l2c_getItemCount( lua_State *L );
int l2c_useItem( lua_State *L );
int l2c_useItemByObjectId( lua_State *L );
int l2c_getPaperdollItem( lua_State *L );
// buffs
int l2c_getBuffs( lua_State *L );
int l2c_buffCancel( lua_State *L );
// world information
int l2c_getVisibleChars( lua_State *L );
int l2c_getVisibleMobs( lua_State *L );
int l2c_getVisibleNpcs( lua_State *L );
int l2c_getVisibleItems( lua_State *L );
// individual world object information, based on objectID
int l2c_getCharObjectIdByName( lua_State *L );
int l2c_getNpcObjectIdByName( lua_State *L );
int l2c_getObjectInfoByObjectId( lua_State *L );
int l2c_isCharDead( lua_State *L );
// party
int l2c_getParty( lua_State *L );
int l2c_getPartyMemberBuffs( lua_State *L );
int l2c_partySendInvite( lua_State *L );
int l2c_partyLeave( lua_State *L );
int l2c_partyKickMember( lua_State *L );
int l2c_partyChangeLeader( lua_State *L );
// botting config
int l2ccfg_getInt( lua_State *L );
int l2ccfg_setInt( lua_State *L );
int l2ccfg_getStr( lua_State *L );
int l2ccfg_setStr( lua_State *L );
int l2ccfg_getAllConfig( lua_State *L );
// botting combat state
int l2c_isCombatEnabled( lua_State *L );
int l2c_combatEnable( lua_State *L );
// handlers
int sys_register_onChat( lua_State *L );
// dirty hacks
int l2c_sendPacketHex( lua_State *L );
#endif

View File

@@ -0,0 +1,53 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
#include "DBLayer.h"
int l2c_getBuffs( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
UserBuffs *b = cl->get_Buffs();
int i;
lua_createtable( L, 0, 0 );
int tableIndex = 1;
for( i=0; i<b->buffCount; i++ )
{
if( b->buff[i].skillID == 0 ) continue;
lua_pushnumber( L, tableIndex );
//
lua_createtable( L, 0, 0 );
//
lua_pushstring( L, "skillID" );
lua_pushnumber( L, b->buff[i].skillID );
lua_settable( L, -3 );
lua_pushstring( L, "skillLvl" );
lua_pushnumber( L, b->buff[i].skillLvl );
lua_settable( L, -3 );
lua_pushstring( L, "durationSecs" );
lua_pushnumber( L, b->buff[i].duration );
lua_settable( L, -3 );
// skill name
wchar_t wstr[256] = {0};
char skillName[256] = {0};
DBLayer_getSkillName( b->buff[i].skillID, wstr, 256 );
WideCharToMultiByte( CP_ACP, 0, wstr, -1, skillName, 255, NULL, NULL );
lua_pushstring( L, "skillName" );
lua_pushstring( L, skillName );
lua_settable( L, -3 );
//
lua_settable( L, -3 );
//
tableIndex++;
}
return 1;
}
int l2c_buffCancel( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
unsigned int skillID = (unsigned int)lua_tonumber( L, 1 );
cl->game_buffCancel( skillID );
return 0;
}

View File

@@ -0,0 +1,89 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
// int l2ccfg_getInt( string varName )
int l2ccfg_getInt( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
int nArgs = lua_gettop( L ); if( nArgs < 1 ) return 0;
const char *varName = lua_tolstring( L, 1, NULL ); if( !varName ) return 0;
BotConfig *cfg = cl->get_BotConfig();
lua_pushnumber( L, cfg->getValInt( varName ) );
return 1;
}
// int l2ccfg_setInt( string varName, int val )
int l2ccfg_setInt( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
return 0;
}
// string l2ccfg_getStr( string varName )
int l2ccfg_getStr( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
int nArgs = lua_gettop( L ); if( nArgs < 1 ) return 0;
const char *varName = lua_tolstring( L, 1, NULL ); if( !varName ) return 0;
BotConfig *cfg = cl->get_BotConfig();
lua_pushstring( L, cfg->getValStr( varName ) );
return 1;
}
// int l2ccfg_setStr( string varName, string val )
int l2ccfg_setStr( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
return 0;
}
// table l2ccfg_getAllConfig()
int l2ccfg_getAllConfig( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
BotConfig *cfg = cl->get_BotConfig();
int i = 0;
//int tableIndex = 1;
lua_createtable( L, 0, 0 );
for( i=0; i<BotConfig::MAX_VALUES; i++ )
{
BotConfigValue val = cfg->getValByIdx( i );
if( val.getType() == CFG_TYPE_NONE ) continue;
const char *valName = val.name();
lua_pushstring( L, valName );
switch( val.getType() )
{
case CFG_TYPE_INT: lua_pushnumber( L, (lua_Number)val.getInt() ); break;
case CFG_TYPE_FLT: lua_pushnumber( L, (lua_Number)val.getFlt() ); break;
case CFG_TYPE_STR: lua_pushstring( L, val.getStr() ); break;
}
lua_settable( L, -3 );
//tableIndex++;
}
return 1;
}
// bool l2c_isCombatEnabled()
int l2c_isCombatEnabled( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushboolean( L, 0 ); return 1; }
int e = 0;
if( cl->isBotCombatEnabled() ) e = 1;
lua_pushboolean( L, e );
return 1;
}
// l2c_combatEnable( bool bEnable = true )
int l2c_combatEnable( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
bool e = true;
int nArgs = lua_gettop( L );
if( nArgs >= 1 ) { e = lua_toboolean( L, 1 ) ? true : false; }
cl->botCombatEnable( e );
return 0;
}

View File

@@ -0,0 +1,138 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
int l2c_say( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs == 0 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
size_t len = 0;
double dchannel = lua_tonumber( L, 1 );
unsigned int ichannel = (unsigned int)dchannel;
const char *mes = luaL_checklstring( L, 2, &len );
//log_error_np( LOG_OK, "SE: l2c_say: %u len, [%s], channel %d\n", len, mes, ichannel );
wchar_t *text = (wchar_t *)malloc( len*2 + 2 );
if( text )
{
memset( text, 0, len*2+2 );
MultiByteToWideChar( CP_ACP, 0, mes, -1, text, len );
cl->game_Say( ichannel, text );
free( text );
}
return 0;
}
int l2c_sayPm( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 2 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
size_t lenmes = 0;
size_t lento = 0;
const char *mes = luaL_checklstring( L, 1, &lenmes );
const char *to = luaL_checklstring( L, 2, &lento );
//log_error_np( LOG_OK, "SE: l2c_say_pm: [%s] [%s]\n", mes, to );
wchar_t *text = (wchar_t *)malloc( lenmes*2 + 2 );
if( text )
{
wchar_t tto[64] = {0};
memset( text, 0, lenmes*2+2 );
memset( tto, 0, sizeof(tto) );
MultiByteToWideChar( CP_ACP, 0, mes, -1, text, lenmes );
MultiByteToWideChar( CP_ACP, 0, to, -1, tto, 63 );
tto[63] = 0;
cl->game_SayPm( text, tto );
free( text );
}
return 0;
}
// l2c_npcDlg( string bypassActionName )
int l2c_npcDlg( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
const char *abypass = lua_tolstring( L, 1, NULL );
if( !abypass ) return 0;
wchar_t bypass[256] = {0};
MultiByteToWideChar( CP_ACP, 0, abypass, -1, bypass, 255 );
if( bypass[0] == 0 ) return 0;
//
unsigned int last_npc_html_oid = 0;
wchar_t *last_html = NULL;
last_html = cl->get_last_NPC_HTML( &last_npc_html_oid );
if( !last_html || (last_npc_html_oid == 0) ) return 0;
// check current target - must match last NPC HTML oid
UserInfo *pusr = cl->get_UserInfo();
if( pusr->targetObjectID != last_npc_html_oid )
{
log_error( LOG_ERROR, "SE: NPCDLG: Tried to talk to NPC that is not on target! NPC must be targeted.\n" );
return 0;
}
//
wchar_t strtofind[512] = {0};
swprintf( strtofind, 511, L">%s</a>", bypass );
//log_error_np( LOG_OK, "NPCDLG: to find: [%S]\n", strtofind );
wchar_t *ps = wcsstr( last_html, strtofind );
if( !ps )
{
char areq[256] = {0};
WideCharToMultiByte( CP_ACP, 0, bypass, -1, areq, 255, NULL, NULL );
log_error( LOG_ERROR, "SE: not found requested NPCDLG [%s]\n", areq );
return 0;
}
while( (ps > last_html) && ((*ps) != L'<') ) ps--;
if( ps == last_html )
{
log_error( LOG_ERROR, "SE: not found bypass link to requested NPCDLG\n" );
return 0;
}
//log_error_np( LOG_OK, "NPCDLG: found: [%S]\n", ps );
wchar_t bypassStr[256];
wchar_t *pbypassStr = bypassStr;
(*pbypassStr) = 0;
// now find first occurence of "
while( (*ps) != L'\"' ) ps++;
ps++;
// now copy till second "
while( (*ps) != L'\"' )
{
(*pbypassStr) = (*ps);
ps++;
pbypassStr++;
(*pbypassStr) = 0;
}
log_error_np( LOG_OK, "NPCDLG: got bypassStr [%S]\n", bypassStr );
cl->game_SendBypass( bypassStr );
//
return 0;
}
// l2c_npcDlgClear()
int l2c_npcDlgClear( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
cl->clear_last_NPC_HTML();
return 0;
}
// bool l2c_npcDlgExists()
int l2c_npcDlgExists( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl )
{
lua_pushboolean( L, 0 );
return 0;
}
wchar_t *html = cl->get_last_NPC_HTML( NULL );
lua_pushboolean( L, html ? 1 : 0 );
return 1;
}

View File

@@ -0,0 +1,16 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
// l2c_sendPacketHex( string packetHex )
int l2c_sendPacketHex( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
const char *hex = lua_tolstring( L, 1, NULL );
if( !hex ) return 0;
cl->game_sendPacketHex( hex );
return 0;
}

View File

@@ -0,0 +1,32 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
#include "ScriptEngine.h"
// sys_register_onChat( function_name )
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> function_name <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Lua
// function onChat( senderObjectID, chatChannelID, chatText, senderName )
int sys_register_onChat( lua_State *L )
{
int typ = lua_type( L, lua_upvalueindex( 1 ) );
if( typ != LUA_TLIGHTUSERDATA )
{
log_error( LOG_ERROR, "sys_register_onChat(): no light user data!\n" );
return 0;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> ScriptEngine <20><><EFBFBD> light user data <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> SE_regScriptEngineFunc)
ScriptEngine *se = (ScriptEngine *)lua_touserdata( L, lua_upvalueindex( 1 ) );
if( se == NULL )
{
log_error( LOG_ERROR, "sys_register_onChat(): ptr to ScriptEngine == NULL!\n" );
return 0;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> Lua <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> sys_register_onChat <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
const char *funcName = lua_tolstring( L, 1, NULL );
// funcName <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> NULL, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
se->set_onChat_handler( funcName );
return 0;
}

View File

@@ -0,0 +1,62 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
int l2c_autoSoulshot( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
unsigned int itemID = (unsigned int)lua_tonumber( L, 1 );
bool bEnable = true;
if( nArgs >= 2 ) bEnable = lua_toboolean( L, 2 ) ? true : false;
cl->game_autoSoulshot( itemID, bEnable );
return 0;
}
// int l2c_getItemCount( int itemID )
int l2c_getItemCount( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
int nArgs = lua_gettop( L );
if( nArgs < 1 )
{
lua_pushnumber( L, 0 );
return 1;
}
unsigned int itemID = (unsigned int)lua_tonumber( L, 1 );
lua_Number cnt = (lua_Number)cl->game_getItemCount( itemID );
lua_pushnumber( L, cnt );
return 1;
}
// l2c_useItem( int itemID )
int l2c_useItem( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
cl->game_UseItemByItemId( (unsigned int)lua_tonumber( L, 1 ) );
return 0;
}
// l2c_useItemByObjectId( int objectID )
int l2c_useItemByObjectId( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
cl->game_UseItemByObjectId( (unsigned int)lua_tonumber( L, 1 ) );
return 0;
}
// int, int l2c_getPaperdollItem( int slot )
int l2c_getPaperdollItem( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
unsigned int slot = (unsigned int)lua_tonumber( L, 1 );
UserInfo *pusr = cl->get_UserInfo();
lua_pushnumber( L, pusr->paperdoll_iid[ slot ] );
lua_pushnumber( L, pusr->paperdoll_oid[ slot ] );
return 2;
}

View File

@@ -0,0 +1,89 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
int l2c_getPos( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs != 0 )
{
lua_pushnumber( L, 0 );
lua_pushnumber( L, 0 );
lua_pushnumber( L, 0 );
return 3;
}
IL2Client *cl = L2C_func_getClient( L );
if( !cl )
{
lua_pushnumber( L, 0 );
lua_pushnumber( L, 0 );
lua_pushnumber( L, 0 );
return 3;
}
UserInfo *usr = cl->get_UserInfo();
lua_pushnumber( L, usr->x );
lua_pushnumber( L, usr->y );
lua_pushnumber( L, usr->z );
return 3;
}
int l2c_moveTo( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 2 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
double x = lua_tonumber( L, 1 );
double y = lua_tonumber( L, 2 );
int z = 0x7FFFFFFF;
if( nArgs == 3 ) z = (int)lua_tonumber( L, 3 );
//log_error_np( LOG_OK, "LUA: lua_moveto( %d, %d, %d ) [%d]\n", (int)x, (int)y, (int)z, nArgs );
cl->game_MoveBackwardToLocation( (int)x, (int)y, z );
return 0;
}
int l2c_moveToDelta( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 2 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
double x = lua_tonumber( L, 1 );
double y = lua_tonumber( L, 2 );
double z = 0.0;
if( nArgs == 3 ) z = lua_tonumber( L, 3 );
//log_error_np( LOG_OK, "LUA: l2c_movetodelta( %d, %d, %d ) [%d]\n", (int)x, (int)y, (int)z, nArgs );
cl->game_MoveToDelta( (int)x, (int)y, (int)z );
return 0;
}
int l2c_getSitRun( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl )
{
lua_pushboolean( L, 0 );
lua_pushboolean( L, 1 );
return 2;
}
UserInfo *usr = cl->get_UserInfo();
lua_pushboolean( L, usr->isSitting );
lua_pushboolean( L, usr->isRunning );
return 2;
}
int l2c_sitStand( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
cl->game_SitStand();
return 0;
}
int l2c_runWalk( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
cl->game_RunWalk();
return 0;
}

View File

@@ -0,0 +1,257 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
#include "DBLayer.h"
// table l2c_getParty()
int l2c_getParty( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl )
{
lua_createtable( L, 0, 0 );
return 1;
}
UserParty *pty = cl->get_Party();
if( !pty )
{
lua_createtable( L, 0, 0 );
return 1;
}
pty->Lock(); // really?
int cnt = pty->getCount();
int i;
lua_createtable( L, 0, 0 );
int tableIndex = 1;
char aname[256] = {0};
for( i=0; i<cnt; i++ )
{
L2Player *pl = pty->getPartyPlayer( i );
if( !pl ) continue;
//
lua_pushnumber( L, tableIndex );
//
lua_createtable( L, 0, 0 );
//
lua_pushstring( L, "objectID" );
lua_pushnumber( L, pl->objectID );
lua_settable( L, -3 );
//
lua_pushstring( L, "name" );
sprintf( aname, "%S", pl->charName );
lua_pushstring( L, aname );
lua_settable( L, -3 );
//
lua_pushstring( L, "level" );
lua_pushnumber( L, pl->level );
lua_settable( L, -3 );
//
lua_pushstring( L, "curHp" );
lua_pushnumber( L, pl->curHp );
lua_settable( L, -3 );
lua_pushstring( L, "maxHp" );
lua_pushnumber( L, pl->maxHp );
lua_settable( L, -3 );
lua_pushstring( L, "curMp" );
lua_pushnumber( L, pl->curMp );
lua_settable( L, -3 );
lua_pushstring( L, "maxMp" );
lua_pushnumber( L, pl->maxMp );
lua_settable( L, -3 );
lua_pushstring( L, "curCp" );
lua_pushnumber( L, pl->curCp );
lua_settable( L, -3 );
lua_pushstring( L, "maxCp" );
lua_pushnumber( L, pl->maxCp );
lua_settable( L, -3 );
//
lua_pushstring( L, "classID" );
lua_pushnumber( L, pl->classID );
lua_settable( L, -3 );
//
lua_pushstring( L, "targetObjectID" );
lua_pushnumber( L, pl->targetObjectID );
lua_settable( L, -3 );
//
lua_settable( L, -3 );
tableIndex++;
}
pty->Unlock();
return 1;
}
// table l2c_getPartyMemberBuffs( int objectID )
int l2c_getPartyMemberBuffs( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl )
{
lua_createtable( L, 0, 0 );
return 1;
}
int nArgs = lua_gettop( L );
if( nArgs < 1 )
{
lua_createtable( L, 0, 0 );
return 1;
}
unsigned int objectID = (unsigned int)lua_tonumber( L, 1 );
if( objectID == 0 )
{
lua_createtable( L, 0, 0 );
return 1;
}
UserParty *pty = cl->get_Party();
if( !pty )
{
lua_createtable( L, 0, 0 );
return 1;
}
if( pty->getCount() < 1 )
{
lua_createtable( L, 0, 0 );
return 1;
}
int idx = -1;
pty->Lock();
if( !pty->isInParty( objectID, &idx ) )
{
pty->Unlock();
lua_createtable( L, 0, 0 );
return 1;
}
if( idx == -1 )
{
pty->Unlock();
lua_createtable( L, 0, 0 );
return 1;
}
UserBuffs *buffs = pty->getPartyPlayerBuffs( idx );
if( !buffs )
{
pty->Unlock();
lua_createtable( L, 0, 0 );
return 1;
}
// at last, we can push buffs :)
lua_createtable( L, 0, 0 );
int tableIndex = 1;
int i = 0;
for( i=0; i<UserBuffs::USER_MAX_BUFFS; i++ )
{
if( buffs->buff[i].skillID == 0 ) continue;
//
lua_pushnumber( L, tableIndex );
//
lua_createtable( L, 0, 0 );
//
lua_pushstring( L, "skillID" );
lua_pushnumber( L, buffs->buff[i].skillID );
lua_settable( L, -3 );
lua_pushstring( L, "skillLvl" );
lua_pushnumber( L, buffs->buff[i].skillLvl );
lua_settable( L, -3 );
lua_pushstring( L, "durationSecs" );
lua_pushnumber( L, buffs->buff[i].duration );
lua_settable( L, -3 );
// skill name
wchar_t wstr[256] = {0};
char skillName[256] = {0};
DBLayer_getSkillName( buffs->buff[i].skillID, wstr, 256 );
WideCharToMultiByte( CP_ACP, 0, wstr, -1, skillName, 255, NULL, NULL );
lua_pushstring( L, "skillName" );
lua_pushstring( L, skillName );
lua_settable( L, -3 );
//
lua_settable( L, -3 );
//
tableIndex++;
}
for( i=0; i<UserBuffs::USER_MAX_SHORT_BUFFS; i++ )
{
if( buffs->short_buff[i].skillID == 0 ) continue;
//
lua_pushnumber( L, tableIndex );
//
lua_createtable( L, 0, 0 );
//
lua_pushstring( L, "skillID" );
lua_pushnumber( L, buffs->short_buff[i].skillID );
lua_settable( L, -3 );
lua_pushstring( L, "skillLvl" );
lua_pushnumber( L, buffs->short_buff[i].skillLvl );
lua_settable( L, -3 );
lua_pushstring( L, "durationSecs" );
lua_pushnumber( L, buffs->short_buff[i].duration );
lua_settable( L, -3 );
// skill name
wchar_t wstr[256] = {0};
char skillName[256] = {0};
DBLayer_getSkillName( buffs->short_buff[i].skillID, wstr, 256 );
WideCharToMultiByte( CP_ACP, 0, wstr, -1, skillName, 255, NULL, NULL );
lua_pushstring( L, "skillName" );
lua_pushstring( L, skillName );
lua_settable( L, -3 );
//
lua_settable( L, -3 );
//
tableIndex++;
}
//
pty->Unlock();
return 1;
}
// l2c_partySendInvite( string name, int loot )
int l2c_partySendInvite( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
int nArgs = lua_gettop( L );
if( nArgs < 2 ) return 0;
const char *aname = lua_tolstring( L, 1, NULL );
int loot = (int)lua_tonumber( L, 2 );
wchar_t name[256] = {0};
MultiByteToWideChar( CP_ACP, 0, aname, -1, name, 255 );
cl->game_Party_InvitePlayer( name, (unsigned int)loot );
return 0;
}
// l2c_partyLeave()
int l2c_partyLeave( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
UserParty *pty = cl->get_Party();
if( pty->getCount() < 1 ) return 0; // no party?
cl->game_Party_Leave(); // ok, leave paarty
return 0;
}
// l2c_partyKickMember( string name )
int l2c_partyKickMember( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
UserParty *pty = cl->get_Party();
if( pty->getCount() < 1 ) return 0; // no party?
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
const char *aname = lua_tolstring( L, 1, NULL );
wchar_t name[256] = {0};
MultiByteToWideChar( CP_ACP, 0, aname, -1, name, 255 );
cl->game_Party_KickPlayer( name );
return 0;
}
// l2c_partyChangeLeader( string name )
int l2c_partyChangeLeader( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L ); if( !cl ) return 0;
UserParty *pty = cl->get_Party();
if( pty->getCount() < 1 ) return 0; // no party?
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
const char *aname = lua_tolstring( L, 1, NULL );
wchar_t name[256] = {0};
MultiByteToWideChar( CP_ACP, 0, aname, -1, name, 255 );
cl->game_Party_ChangeLeader( name );
return 0;
}

View File

@@ -0,0 +1,57 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
// l2c_useSkill( int skillID )
int l2c_useSkill( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
unsigned int skillID = (unsigned int)lua_tonumber( L, 1 );
unsigned int force = 0;
if( nArgs >= 2 ) force = lua_toboolean( L, 2 );
cl->game_SkillUse( skillID, force, 0 );
return 0;
}
// int l2c_getSkillLevel( int skillID )
int l2c_getSkillLevel( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnumber( L, 0 ); return 1; }
int nArgs = lua_gettop( L );
if( nArgs < 1 ) { lua_pushnumber( L, 0 ); return 1; }
unsigned int skillID = (unsigned int)lua_tonumber( L, 1 );
int skillLevel = cl->game_getSkillLevel( skillID );
lua_pushnumber( L, skillLevel );
return 1;
}
// int l2c_getSkillReuseLeft( int skillID )
int l2c_getSkillReuseLeft( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnumber( L, 0 ); return 1; }
int nArgs = lua_gettop( L );
if( nArgs < 1 ) { lua_pushnumber( L, 0 ); return 1; }
unsigned int skillID = (unsigned int)lua_tonumber( L, 1 );
UserSkills *sk = cl->get_Skills();
UserSkill skill;
sk->getSkillInfoBySkillId( skillID, &skill );
lua_pushnumber( L, skill.coolTimeRemaining );
return 1;
}
// boolean l2c_isCastingNow()
int l2c_isCastingNow( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushboolean( L, 0 ); return 1; }
UserSkills *sk = cl->get_Skills();
int b = 0;
if( sk->isCasting() ) b = 1;
lua_pushboolean( L, b );
return 1;
}

View File

@@ -0,0 +1,62 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
int l2c_action( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
unsigned int objectID = (unsigned int)lua_tonumber( L, 1 );
cl->game_Action( objectID );
return 0;
}
int l2c_attack( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
cl->game_Attack();
return 0;
}
int l2c_targetByName( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) return 0;
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
const char *aname = lua_tolstring( L, 1, NULL );
wchar_t wname[256];
memset( wname, 0, sizeof(wname) );
MultiByteToWideChar( CP_ACP, 0, aname, -1, wname, 255 );
cl->game_TargetByName( wname );
return 0;
}
int l2c_targetCancel( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
cl->game_TargetCancel();
return 0;
}
int l2c_getTarget( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl )
{
lua_pushnumber( L, 0 );
lua_pushnumber( L, 0 );
lua_pushnumber( L, 0 );
return 3;
}
UserInfo *pusr = cl->get_UserInfo();
lua_pushnumber( L, pusr->targetObjectID );
lua_pushnumber( L, pusr->targetCurHp );
lua_pushnumber( L, pusr->targetMaxHp );
return 3;
}

View File

@@ -0,0 +1,63 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
int l2c_is_INGAME( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs != 0 ) { lua_pushboolean( L, 0 ); return 1; }
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushboolean( L, 0 ); return 1; }
int st = 0;
st = cl->is_IN_GAME();
lua_pushboolean( L, st );
return 1;
}
int l2c_getHPMPCPWeight( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs != 0 ) { lua_pushnil( L ); return 1; }
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnil( L ); return 1; }
UserInfo *usr = cl->get_UserInfo();
lua_pushnumber( L, usr->curHp );
lua_pushnumber( L, usr->maxHp );
lua_pushnumber( L, usr->curMp );
lua_pushnumber( L, usr->maxMp );
lua_pushnumber( L, usr->curCp );
lua_pushnumber( L, usr->maxCp );
lua_pushnumber( L, usr->curLoad );
lua_pushnumber( L, usr->maxLoad );
return 8;
}
int l2c_getStats( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnil( L ); return 1; }
UserInfo *usr = cl->get_UserInfo();
lua_createtable( L, 0, 0 );
// name
char aname[256] = {0};
sprintf( aname, "%S", usr->charName );
lua_pushstring( L, "name" );
lua_pushstring( L, aname );
lua_settable( L, -3 );
// number stats:
// pAtk, mAtk, pDef, mDef, pAtkSpd, mAtkSpd
#define LUA_PUSHTABLEKEY( sKeyName, keyName ) lua_pushstring( L, sKeyName ); lua_pushnumber( L, usr->keyName ); lua_settable( L, -3 );
LUA_PUSHTABLEKEY( "pAtk", pAtk )
LUA_PUSHTABLEKEY( "pDef", pDef )
LUA_PUSHTABLEKEY( "mAtk", mAtk )
LUA_PUSHTABLEKEY( "mDef", mDef )
LUA_PUSHTABLEKEY( "pAtkSpd", pAtkSpd )
LUA_PUSHTABLEKEY( "mAtkSpd", mAtkSpd )
// self objectID
LUA_PUSHTABLEKEY( "objectID", objectID )
LUA_PUSHTABLEKEY( "heading", heading )
LUA_PUSHTABLEKEY( "karma", karma )
#undef LUA_PUSHTABLEKEY
//
return 1;
}

View File

@@ -0,0 +1,417 @@
#include "stdafx.h"
#include "Logger.h"
#include "SE_funcs.h"
#include "DBLayer.h"
int l2c_getVisibleChars( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
CharArray *ca = cl->get_WorldChars();
ca->Lock();
unsigned int charCount = ca->GetCount();
lua_createtable( L, 0, 0 );
unsigned int i;
unsigned int nPassed = 0;
unsigned int tableIndex = 1;
for( i=0; i<CharArray::CHARARRAY_MAX_CHARS; i++ )
{
if( ca->chars_array[i]->isUnused() ) continue;
nPassed++;
//
lua_pushnumber( L, tableIndex );
lua_pushnumber( L, ca->chars_array[i]->objectID );
lua_settable( L, -3 );
tableIndex++;
//
if( nPassed >= charCount ) break;
}
ca->Unlock();
return 1;
}
int l2c_getVisibleMobs( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
NpcArray *na = cl->get_WorldNpcs();
na->Lock();
unsigned int count = na->getCount();
lua_createtable( L, 0, 0 );
unsigned int i;
unsigned int nPassed = 0;
unsigned int tableIndex = 1;
for( i=0; i<NpcArray::NPCA_MAX_NPCS; i++ )
{
if( na->npcs_array[i]->isUnused() ) continue;
nPassed++;
if( !na->npcs_array[i]->isAttackable ) continue;
//
lua_pushnumber( L, tableIndex );
lua_pushnumber( L, na->npcs_array[i]->objectID );
lua_settable( L, -3 );
tableIndex++;
//
if( nPassed >= count ) break;
}
na->Unlock();
return 1;
}
int l2c_getVisibleNpcs( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
NpcArray *na = cl->get_WorldNpcs();
na->Lock();
unsigned int count = na->getCount();
lua_createtable( L, 0, 0 );
unsigned int i;
unsigned int nPassed = 0;
unsigned int tableIndex = 1;
for( i=0; i<NpcArray::NPCA_MAX_NPCS; i++ )
{
if( na->npcs_array[i]->isUnused() ) continue;
nPassed++;
if( na->npcs_array[i]->isAttackable ) continue;
//
lua_pushnumber( L, tableIndex );
lua_pushnumber( L, na->npcs_array[i]->objectID );
lua_settable( L, -3 );
tableIndex++;
//
if( nPassed >= count ) break;
}
na->Unlock();
return 1;
}
int l2c_getVisibleItems( lua_State *L )
{
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) return 0;
GIArray *a = cl->get_WorldItems();
a->Lock();
unsigned int count = a->getCount();
lua_createtable( L, 0, 0 );
unsigned int i;
unsigned int nPassed = 0;
unsigned int tableIndex = 1;
for( i=0; i<GIArray::GA_MAX_ITEMS; i++ )
{
if( a->gi_array[i]->isUnused() ) continue;
nPassed++;
//
lua_pushnumber( L, tableIndex );
lua_pushnumber( L, a->gi_array[i]->objectID );
lua_settable( L, -3 );
tableIndex++;
//
if( nPassed >= count ) break;
}
a->Unlock();
return 1;
}
int l2c_getCharObjectIdByName( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) { lua_pushnil( L ); return 1; }
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnil( L ); return 1; }
const char *aname = lua_tolstring( L, 1, NULL );
if( !aname ) { lua_pushnil( L ); return 1; }
wchar_t wname[128] = {0};
memset( wname, 0, sizeof(wname) );
MultiByteToWideChar( CP_ACP, 0, aname, -1, wname, 127 );
CharArray *ca = cl->get_WorldChars();
unsigned int nPassed = 0, i = 0, nChars = ca->GetCount();
if( nChars > 0 )
{
ca->Lock();
for( i=0; i<CharArray::CHARARRAY_MAX_CHARS; i++ )
{
if( ca->chars_array[i]->isUnused() ) continue;
nPassed++;
if( _wcsicmp( wname, ca->chars_array[i]->charName ) == 0 )
{
ca->Unlock();
lua_pushnumber( L, ca->chars_array[i]->objectID );
return 1;
}
if( nPassed >= nChars ) break;
}
ca->Unlock();
}
lua_pushnil( L );
return 1;
}
int l2c_getNpcObjectIdByName( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) { lua_pushnil( L ); return 1; }
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnil( L ); return 1; }
const char *aname = lua_tolstring( L, 1, NULL );
if( !aname ) { lua_pushnil( L ); return 1; }
wchar_t wname[128] = {0};
memset( wname, 0, sizeof(wname) );
MultiByteToWideChar( CP_ACP, 0, aname, -1, wname, 127 );
NpcArray *na = cl->get_WorldNpcs();
unsigned int nPassed = 0, i = 0, nChars = na->getCount();
if( nChars > 0 )
{
na->Lock();
for( i=0; i<NpcArray::NPCA_MAX_NPCS; i++ )
{
if( na->npcs_array[i]->isUnused() ) continue;
nPassed++;
if( _wcsicmp( wname, na->npcs_array[i]->charName ) == 0 )
{
na->Unlock();
lua_pushnumber( L, na->npcs_array[i]->objectID );
return 1;
}
if( nPassed >= nChars ) break;
}
na->Unlock();
}
lua_pushnil( L );
return 1;
}
int l2c_getObjectInfoByObjectId( lua_State *L )
{
int nArgs = lua_gettop( L );
if( nArgs < 1 ) { lua_pushnil( L ); return 1; }
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnil( L ); return 1; }
unsigned int objectID = (unsigned int)lua_tonumber( L, 1 );
WorldObjectTree *wt = cl->get_WorldObjectTree();
WorldObjectTreeNode wotNode;
if( wt->GetInfoByObjectID( objectID, &wotNode ) )
{
int idx = wotNode.getArrayIdx();
char ansi[256] = {0};
switch( wotNode.getObjectType() )
{
case L2OT_PC:
{
CharArray *ca = cl->get_WorldChars();
if( ca->chars_array[idx] == NULL ) { lua_pushnil( L ); return 1; }
ca->Lock();
lua_createtable( L, 0, 0 );
//
lua_pushstring( L, "type" );
lua_pushstring( L, "pc" );
lua_settable( L, -3 );
//
lua_pushstring( L, "objectID" );
lua_pushnumber( L, ca->chars_array[idx]->objectID );
lua_settable( L, -3 );
// heading
lua_pushstring( L, "heading" );
lua_pushnumber( L, ca->chars_array[idx]->heading );
lua_settable( L, -3 );
lua_pushstring( L, "targetObjectID" );
lua_pushnumber( L, ca->chars_array[idx]->targetObjectID );
lua_settable( L, -3 );
lua_pushstring( L, "pvpFlag" );
lua_pushnumber( L, ca->chars_array[idx]->pvpFlag );
lua_settable( L, -3 );
lua_pushstring( L, "karma" );
lua_pushnumber( L, ca->chars_array[idx]->karma );
lua_settable( L, -3 );
//
lua_pushstring( L, "x" );
lua_pushnumber( L, ca->chars_array[idx]->x );
lua_settable( L, -3 );
lua_pushstring( L, "y" );
lua_pushnumber( L, ca->chars_array[idx]->y );
lua_settable( L, -3 );
lua_pushstring( L, "z" );
lua_pushnumber( L, ca->chars_array[idx]->z );
lua_settable( L, -3 );
lua_pushstring( L, "xDst" );
lua_pushnumber( L, ca->chars_array[idx]->xDst );
lua_settable( L, -3 );
lua_pushstring( L, "yDst" );
lua_pushnumber( L, ca->chars_array[idx]->yDst );
lua_settable( L, -3 );
lua_pushstring( L, "zDst" );
lua_pushnumber( L, ca->chars_array[idx]->zDst );
lua_settable( L, -3 );
//
lua_pushstring( L, "name" );
sprintf( ansi, "%S", ca->chars_array[idx]->charName );
lua_pushstring( L, ansi );
lua_settable( L, -3 );
//
lua_pushstring( L, "curHp" );
lua_pushnumber( L, ca->chars_array[idx]->curHp );
lua_settable( L, -3 );
lua_pushstring( L, "maxHp" );
lua_pushnumber( L, ca->chars_array[idx]->maxHp );
lua_settable( L, -3 );
lua_pushstring( L, "isAlikeDead" );
lua_pushnumber( L, ca->chars_array[idx]->isAlikeDead );
lua_settable( L, -3 );
// player specific
lua_pushstring( L, "classID" );
lua_pushnumber( L, ca->chars_array[idx]->classID );
lua_settable( L, -3 );
ca->Unlock();
} break;
case L2OT_NPC:
{
NpcArray *na = cl->get_WorldNpcs();
if( na->npcs_array[idx] == NULL ) { lua_pushnil( L ); return 1; }
na->Lock();
lua_createtable( L, 0, 0 );
//
lua_pushstring( L, "type" );
if( na->npcs_array[idx]->isAttackable ) lua_pushstring( L, "mob" );
else lua_pushstring( L, "npc" );
lua_settable( L, -3 );
//
lua_pushstring( L, "objectID" );
lua_pushnumber( L, na->npcs_array[idx]->objectID );
lua_settable( L, -3 );
// heading
lua_pushstring( L, "heading" );
lua_pushnumber( L, na->npcs_array[idx]->heading );
lua_settable( L, -3 );
//
lua_pushstring( L, "x" );
lua_pushnumber( L, na->npcs_array[idx]->x );
lua_settable( L, -3 );
lua_pushstring( L, "y" );
lua_pushnumber( L, na->npcs_array[idx]->y );
lua_settable( L, -3 );
lua_pushstring( L, "z" );
lua_pushnumber( L, na->npcs_array[idx]->z );
lua_settable( L, -3 );
lua_pushstring( L, "xDst" );
lua_pushnumber( L, na->npcs_array[idx]->xDst );
lua_settable( L, -3 );
lua_pushstring( L, "yDst" );
lua_pushnumber( L, na->npcs_array[idx]->yDst );
lua_settable( L, -3 );
lua_pushstring( L, "zDst" );
lua_pushnumber( L, na->npcs_array[idx]->zDst );
lua_settable( L, -3 );
//
lua_pushstring( L, "name" );
sprintf( ansi, "%S", na->npcs_array[idx]->charName );
lua_pushstring( L, ansi );
lua_settable( L, -3 );
//
lua_pushstring( L, "curHp" );
lua_pushnumber( L, na->npcs_array[idx]->curHp );
lua_settable( L, -3 );
lua_pushstring( L, "maxHp" );
lua_pushnumber( L, na->npcs_array[idx]->maxHp );
lua_settable( L, -3 );
lua_pushstring( L, "isAlikeDead" );
lua_pushnumber( L, na->npcs_array[idx]->isAlikeDead );
lua_settable( L, -3 );
// npc specific
lua_pushstring( L, "templateID" );
lua_pushnumber( L, na->npcs_array[idx]->templateID );
lua_settable( L, -3 );
na->Unlock();
} break;
case L2OT_ITEM:
{
GIArray *a = cl->get_WorldItems();
if( !a->gi_array[idx] ) { lua_pushnil( L ); return 1; }
a->Lock();
lua_createtable( L, 0, 0 );
//
lua_pushstring( L, "type" );
lua_pushstring( L, "item" );
lua_settable( L, -3 );
//
lua_pushstring( L, "objectID" );
lua_pushnumber( L, a->gi_array[idx]->objectID );
lua_settable( L, -3 );
//
lua_pushstring( L, "x" );
lua_pushnumber( L, a->gi_array[idx]->x );
lua_settable( L, -3 );
lua_pushstring( L, "y" );
lua_pushnumber( L, a->gi_array[idx]->y );
lua_settable( L, -3 );
lua_pushstring( L, "z" );
lua_pushnumber( L, a->gi_array[idx]->z );
lua_settable( L, -3 );
//
lua_pushstring( L, "name" );
// need to query cached DB; and convert from unicode to ansi >_<
char aitemName[256] = {0};
wchar_t witemName[256] = {0};
DBLayer_getItemName( a->gi_array[idx]->itemID, witemName, 255 );
WideCharToMultiByte( CP_ACP, 0, witemName, -1, aitemName, 255, NULL, NULL );
lua_pushstring( L, aitemName ); // at last
lua_settable( L, -3 );
// item specific
lua_pushstring( L, "itemID" );
lua_pushnumber( L, a->gi_array[idx]->itemID );
lua_settable( L, -3 );
lua_pushstring( L, "stackable" );
lua_pushboolean( L, a->gi_array[idx]->stackable );
lua_settable( L, -3 );
lua_pushstring( L, "count" );
lua_pushnumber( L, (lua_Number)a->gi_array[idx]->count );
lua_settable( L, -3 );
a->Unlock();
} break;
default: lua_pushnil( L ); break;
}
}
else
{
lua_pushnil( L );
}
return 1;
}
// boolean l2c_isCharDead( int objectID )
int l2c_isCharDead( lua_State *L )
{
// get number of arguments
int nArgs = lua_gettop( L );
if( nArgs < 1 ) { lua_pushnil( L ); return 1; }
// get client interface
IL2Client *cl = L2C_func_getClient( L );
if( !cl ) { lua_pushnil( L ); return 1; }
// convert 1st argument to number
unsigned int objectID = (unsigned int)lua_tonumber( L, 1 );
WorldObjectTree *wt = cl->get_WorldObjectTree();
WorldObjectTreeNode wotNode;
int return_value = 1; // default - dead
// find objectID in world
if( wt->GetInfoByObjectID( objectID, &wotNode ) )
{
switch( wotNode.getObjectType() )
{
case L2OT_PC:
{
CharArray *ca = cl->get_WorldChars();
L2Player *pl = ca->chars_array[wotNode.getArrayIdx()];
if( pl ) return_value = pl->isAlikeDead;
} break;
case L2OT_NPC:
{
NpcArray *na = cl->get_WorldNpcs();
L2Npc *pnpc = na->npcs_array[wotNode.getArrayIdx()];
if( pnpc ) return_value = pnpc->isAlikeDead;
} break;
default: return_value = 1; break; // items are always "dead"
}
}
lua_pushboolean( L, return_value );
return 1;
}

View File

@@ -0,0 +1,349 @@
#include "stdafx.h"
#include "logger.h"
#include "IL2Client.h"
#include "SE_funcs.h"
#include "ScriptEngine.h"
#ifdef USE_SEH
#include "SEH_global.h"
#endif
ScriptEngine::ScriptEngine()
{
L = NULL;
m_pvL2Client = NULL;
hThread = NULL;
memset( script_fileName, 0, sizeof(script_fileName) );
should_stop = false;
_isPaused = false;
// handlers
m_onChat_enabled = false;
m_onChat_functionName[0] = 0;
}
ScriptEngine::~ScriptEngine()
{
deinit();
}
void ScriptEngine::init()
{
if( !L )
{
L = luaL_newstate(); // open Lua virtual machine
if( L )
{
luaL_openlibs( L ); // load the Lua libraries: math, io, ..
SE_funcs_register( L ); // register main functions (l2h_*)
}
else log_error( LOG_ERROR, "ScriptEngine::init(): luaL_newstate() returned NULL!\n" );
}
}
void ScriptEngine::deinit()
{
if( L )
{
lua_close( L ); // Destroys all objects in the given Lua state
//(calling the corresponding garbage-collection metamethods, if any)
//and frees all dynamic memory used by this state
L = NULL;
if( hThread ) CloseHandle( hThread );
hThread = NULL;
should_stop = false;
_isPaused = false;
// handlers
m_onChat_enabled = false;
m_onChat_functionName[0] = 0;
}
}
void ScriptEngine::setL2Client( void *pvL2Client )
{
init();
if( L )
{
m_pvL2Client = pvL2Client;
SE_register_client_funcs( L, pvL2Client, (void *)this ); // register client functions (l2c_*)
}
}
void ScriptEngine::startScript( const char *filename )
{
// run a Lua scrip here
int r = luaL_loadfile( L, filename );
if( r == 0 )
{
log_error( LOG_DEBUG, "SE: file [%s] loaded.\n", filename );
// Call main...
r = lua_pcall( L, 0, LUA_MULTRET, 0 );
if( r == 0 ) log_error( LOG_DEBUG, "SE: run OK\n" );
else
{
log_error( LOG_ERROR, "SE: file [%s] run error %d\n", filename, r );
switch( r )
{
case LUA_ERRRUN: log_error( LOG_ERROR, "SE: LUA_ERRRUN\n" ); break;
case LUA_ERRMEM: log_error( LOG_ERROR, "SE: LUA_ERRMEM\n" ); break;
case LUA_ERRERR: log_error( LOG_ERROR, "SE: LUA_ERRERR\n" ); break;
}
int nArgs = lua_gettop( L );
log_error( LOG_ERROR, "SE: nArgs = %d\n", nArgs );
}
}
else log_error( LOG_ERROR, "SE: file [%s] load error %d\n", filename, r );
}
void ScriptEngine::getLastFileName( char *out )
{
if( !out ) return;
out[0] = 0;
if( script_fileName[0] != 0 ) strcpy( out, script_fileName );
}
void ScriptEngine::startScriptThread( const char *filename /*= NULL */ )
{
if( hThread ) return;
DWORD dwThreadID = 0;
if( filename ) strcpy( script_fileName, filename );
hThread = (HANDLE)_beginthreadex( NULL, 0,
(unsigned int (__stdcall *)(void *))scriptEngineThread, (void *)this,
0, (unsigned int *)&dwThreadID );
}
bool ScriptEngine::stopScriptThread( DWORD dwTimeoutMsec, bool bTerminate )
{
if( !hThread ) return true;
this->should_stop = true; // "signal" to stop )
DWORD wait_res = WaitForSingleObject( hThread, dwTimeoutMsec );
if( wait_res != WAIT_OBJECT_0 ) // wait failed :(
{
if( !bTerminate ) return false; // do not do anything, just ret false
TerminateThread( hThread, 0 );
log_error( LOG_ERROR, "ScriptEngine::stopScriptThread(): script thread wait failed, TERMINATED!\n" );
this->deinit();
this->set_onChat_handler( NULL ); // disable onChat() handler
this->init();
if( this->m_pvL2Client ) this->setL2Client( this->m_pvL2Client );
if( L ) log_error( LOG_WARNING, "ScriptEngine::stopScriptThread(): re-initialized ScriptEngine, bugs possible ><\n" );
}
if( hThread ) CloseHandle( hThread ); // cleanup
hThread = NULL;
this->should_stop = false; // no more need to stop...
return true;
}
int ScriptEngine::isScriptThreadRunning() const
{
if( hThread == NULL ) return 0;
return 1;
}
int ScriptEngine::isScriptThreadPaused() const
{
if( _isPaused ) return 1;
return 0;
}
bool ScriptEngine::pauseScriptThread( bool bPause /*= true*/ )
{
if( !isScriptThreadRunning() ) return false;
int prev_suspend_count = 0;
if( bPause )
{
prev_suspend_count = (int)SuspendThread( hThread );
if( prev_suspend_count > 0 )
{
log_error( LOG_WARNING, "ScriptEngine::pauseScriptThread(): PAUSE: thread was already suspended, resuming again\n" );
ResumeThread( hThread );
}
_isPaused = true;
return true;
}
else
{
prev_suspend_count = ResumeThread( hThread );
if( prev_suspend_count > 1 )
{
log_error( LOG_WARNING, "ScriptEngine::pauseScriptThread(): UNPAUSE: possible that thread is still suspended!\n" );
}
_isPaused = false;
return true;
}
}
DWORD WINAPI ScriptEngine::scriptEngineThread( LPVOID lpvClass )
{
if( !lpvClass ) return 0;
ScriptEngine *pcls = (ScriptEngine *)lpvClass;
#ifdef USE_SEH
#ifdef _MSC_VER
__try { // start exception handler
#endif
#endif
// run a Lua script here
int r = luaL_loadfile( pcls->L, pcls->script_fileName );
if( r == 0 )
{
log_error( LOG_DEBUG, "SE: file [%s] loaded.\n", pcls->script_fileName );
// Call main...
#ifndef USE_SEH
try
{
#endif
r = lua_pcall( pcls->L, 0, LUA_MULTRET, 0 );
#ifndef USE_SEH
}
catch(...)
{
log_error( LOG_ERROR, "SE: catched C++ exception after lua_pcall()\n" );
ErrorLogger_FlushLogFile();
}
#endif
if( r == 0 ) log_error( LOG_DEBUG, "SE: run OK\n" );
else
{
log_error( LOG_ERROR, "SE: file [%s] lua_pcall() error %d\n", pcls->script_fileName, r );
switch( r )
{
case LUA_ERRRUN: log_error( LOG_ERROR, "SE: LUA_ERRRUN\n" ); break;
case LUA_ERRMEM: log_error( LOG_ERROR, "SE: LUA_ERRMEM\n" ); break;
case LUA_ERRSYNTAX: log_error( LOG_ERROR, "SE: LUA_ERRSYNTAX\n" ); break;
case LUA_ERRERR: log_error( LOG_ERROR, "SE: LUA_ERRERR\n" ); break;
}
int nArgs = lua_gettop( pcls->L );
if( nArgs >= 1 )
{
if( lua_isstring( pcls->L, 1 ) )
{
log_error( LOG_ERROR, "SE: [%s]\n", lua_tolstring( pcls->L, 1, NULL ) );
//lua_pop( pcls->L, 1 ); // really?
}
}
lua_settop( pcls->L, 0 ); // clear stack
}
}
else
{
log_error( LOG_ERROR, "SE: file [%s] luaL_loadfile() error %d\n", pcls->script_fileName, r );
switch( r )
{
case LUA_ERRRUN: log_error( LOG_ERROR, "SE: LUA_ERRRUN\n" ); break;
case LUA_ERRMEM: log_error( LOG_ERROR, "SE: LUA_ERRMEM\n" ); break;
case LUA_ERRSYNTAX: log_error( LOG_ERROR, "SE: LUA_ERRSYNTAX\n" ); break;
case LUA_ERRERR: log_error( LOG_ERROR, "SE: LUA_ERRERR\n" ); break;
case LUA_ERRFILE: log_error( LOG_ERROR, "SE: LUA_ERRFILE\n" ); break;
}
int nArgs = lua_gettop( pcls->L );
if( nArgs >= 1 )
{
if( lua_isstring( pcls->L, 1 ) )
{
log_error( LOG_ERROR, "SE: [%s]\n", lua_tolstring( pcls->L, 1, NULL ) );
//lua_pop( pcls->L, 1 ); // really?
}
}
lua_settop( pcls->L, 0 ); // clear stack
}
pcls->set_onChat_handler( NULL ); // disable onChat() handler
if( pcls->hThread ) CloseHandle( pcls->hThread ); // cleanup
pcls->hThread = NULL; // mark thread as not running
pcls->should_stop = false;
log_error( LOG_DEBUG, "SE: scriptEngineThread() stopped [%s]\n", pcls->script_fileName );
#ifdef USE_SEH
#ifdef _MSC_VER // exception handler
}
__except( ScriptEngineThreadExceptonHandler( GetExceptionInformation() ) )
{
log_error( LOG_ERROR, "Exception in ScriptEngine thread... possible small memory leak\n" );
ErrorLogger_FlushLogFile();
pcls->hThread = NULL;
pcls->should_stop = false;
}
#endif
#endif
return 1;
}
// http://www.lua.ru/doc/3.7.html
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> Lua:
// a = f('how', t.x, 14)
//
//<2F><> <20><> <20> C:
// lua_getfield(L, LUA_GLOBALSINDEX, 'f'); /* function to be called */
// lua_pushstring(L, 'how'); /* 1st argument */
// lua_getfield(L, LUA_GLOBALSINDEX, 't'); /* table to be indexed */
// lua_getfield(L, -1, 'x'); /* push result of t.x (2nd arg) */
// lua_remove(L, -2); /* remove 't' from the stack */
// lua_pushinteger(L, 14); /* 3rd argument */
// lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */
// lua_setfield(L, LUA_GLOBALSINDEX, 'a'); /* set global 'a' */
//
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>. <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
void ScriptEngine::call_onChat( unsigned int senderObjectId, int channelId, const wchar_t *message, const wchar_t *from )
{
if( !m_onChat_enabled ) return;
if( !message ) return;
if( !isScriptThreadRunning() ) return;
if( isScriptThreadPaused() ) return;
//
pauseScriptThread( true ); // pause script thread
//
// convert strings from Unicode to ANSI
char message_ansi[1024];
char from_ansi[128];
message_ansi[0] = from_ansi[0] = 0;
WideCharToMultiByte( CP_ACP, 0, message, -1, message_ansi, sizeof(message_ansi)-1, NULL, NULL );
if( from ) WideCharToMultiByte( CP_ACP, 0, from, -1, from_ansi, sizeof(from_ansi)-1, NULL, NULL );
message_ansi[sizeof(message_ansi)-1] = 0;
from_ansi[sizeof(from_ansi)-1] = 0;
//
lua_getfield( L, LUA_GLOBALSINDEX, m_onChat_functionName ); // function to be called
lua_pushinteger( L, senderObjectId ); // param 1 - sender object ID
lua_pushinteger( L, channelId ); // param 2 - channel ID
lua_pushstring( L, message_ansi ); // param 3 - chat message
lua_pushstring( L, from_ansi ); // param 4 - sender name (only for PM)
// call onChat with 4 arguments and 0 return values: onChat( senderObjectId, channelId, message, from )
int ret = lua_pcall( L, 4, 0, 0 );
if( ret != 0 )
{
log_error( LOG_ERROR, "SE: call_onChat() [%s] error %d\n", script_fileName, ret );
switch( ret )
{
case LUA_ERRRUN: log_error( LOG_ERROR, "SE: LUA_ERRRUN\n" ); break;
case LUA_ERRMEM: log_error( LOG_ERROR, "SE: LUA_ERRMEM\n" ); break;
case LUA_ERRSYNTAX: log_error( LOG_ERROR, "SE: LUA_ERRSYNTAX\n" ); break;
case LUA_ERRERR: log_error( LOG_ERROR, "SE: LUA_ERRERR\n" ); break;
case LUA_ERRFILE: log_error( LOG_ERROR, "SE: LUA_ERRFILE\n" ); break;
}
int nArgs = lua_gettop( L );
if( nArgs >= 1 )
{
if( lua_isstring( L, 1 ) )
log_error( LOG_ERROR, "SE: [%s]\n", lua_tolstring( L, 1, NULL ) );
}
lua_settop( L, 0 ); // clear stack
}
else log_error( LOG_DEBUG, "SE: call_onChat() [%s] OK\n", script_fileName );
//
pauseScriptThread( false ); // resume script thread
//
}
void ScriptEngine::set_onChat_handler( const char *funcName )
{
if( funcName == NULL ) // disable
{
m_onChat_enabled = false;
m_onChat_functionName[0] = 0;
return;
}
m_onChat_enabled = true;
strncpy( m_onChat_functionName, funcName, sizeof(m_onChat_functionName)-1 );
m_onChat_functionName[sizeof(m_onChat_functionName)-1] = 0;
}

Some files were not shown because too many files have changed in this diff Show More