Initial MSVC 2008 projects workspace
This commit is contained in:
103
l2ooghelper/Account.cpp
Normal file
103
l2ooghelper/Account.cpp
Normal 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
35
l2ooghelper/Account.h
Normal 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
236
l2ooghelper/AccountDlg.cpp
Normal 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
21
l2ooghelper/AccountDlg.h
Normal 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
434
l2ooghelper/BinTree.cpp
Normal 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
47
l2ooghelper/BinTree.h
Normal 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
276
l2ooghelper/BotCfgDlg.cpp
Normal 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
13
l2ooghelper/BotCfgDlg.h
Normal 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
|
||||
93
l2ooghelper/BotCfgDlg_Party.cpp
Normal file
93
l2ooghelper/BotCfgDlg_Party.cpp
Normal 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 ) );
|
||||
}
|
||||
68
l2ooghelper/BotCfgDlg_Self.cpp
Normal file
68
l2ooghelper/BotCfgDlg_Self.cpp
Normal 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 ) );
|
||||
}
|
||||
606
l2ooghelper/BotCfgDlg_SelfHeal.cpp
Normal file
606
l2ooghelper/BotCfgDlg_SelfHeal.cpp
Normal 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
321
l2ooghelper/BotConfig.cpp
Normal 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
76
l2ooghelper/BotConfig.h
Normal 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
|
||||
36
l2ooghelper/BotConfigIDList.cpp
Normal file
36
l2ooghelper/BotConfigIDList.cpp
Normal 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;
|
||||
}
|
||||
6
l2ooghelper/BotConfigIDList.h
Normal file
6
l2ooghelper/BotConfigIDList.h
Normal 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
415
l2ooghelper/BuySellDlg.cpp
Normal 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
34
l2ooghelper/BuySellDlg.h
Normal 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
128
l2ooghelper/BuySellList.cpp
Normal 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
58
l2ooghelper/BuySellList.h
Normal 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
237
l2ooghelper/CharArray.cpp
Normal 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
43
l2ooghelper/CharArray.h
Normal 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_ */
|
||||
127
l2ooghelper/ChooseCharDlg.cpp
Normal file
127
l2ooghelper/ChooseCharDlg.cpp
Normal 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;
|
||||
}
|
||||
9
l2ooghelper/ChooseCharDlg.h
Normal file
9
l2ooghelper/ChooseCharDlg.h
Normal 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
|
||||
97
l2ooghelper/ChooseServerDlg.cpp
Normal file
97
l2ooghelper/ChooseServerDlg.cpp
Normal 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;
|
||||
}
|
||||
9
l2ooghelper/ChooseServerDlg.h
Normal file
9
l2ooghelper/ChooseServerDlg.h
Normal 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
244
l2ooghelper/ClanList.cpp
Normal 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
41
l2ooghelper/ClanList.h
Normal 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_ */
|
||||
54
l2ooghelper/ClanTreeNode.cpp
Normal file
54
l2ooghelper/ClanTreeNode.cpp
Normal 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;
|
||||
}
|
||||
33
l2ooghelper/ClanTreeNode.h
Normal file
33
l2ooghelper/ClanTreeNode.h
Normal 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_ */
|
||||
134
l2ooghelper/CreateCharDlg.cpp
Normal file
134
l2ooghelper/CreateCharDlg.cpp
Normal 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;
|
||||
}
|
||||
19
l2ooghelper/CreateCharDlg.h
Normal file
19
l2ooghelper/CreateCharDlg.h
Normal 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
351
l2ooghelper/DBLayer.cpp
Normal 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
18
l2ooghelper/DBLayer.h
Normal 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
|
||||
171
l2ooghelper/Dlg_FindInDB.cpp
Normal file
171
l2ooghelper/Dlg_FindInDB.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
31
l2ooghelper/Dlg_FindInDB.h
Normal file
31
l2ooghelper/Dlg_FindInDB.h
Normal 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
201
l2ooghelper/GIArray.cpp
Normal 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
40
l2ooghelper/GIArray.h
Normal 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
|
||||
220
l2ooghelper/GlobalMapImages.cpp
Normal file
220
l2ooghelper/GlobalMapImages.cpp
Normal 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;
|
||||
}
|
||||
|
||||
47
l2ooghelper/GlobalMapImages.h
Normal file
47
l2ooghelper/GlobalMapImages.h
Normal 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
|
||||
19
l2ooghelper/GroundItem.cpp
Normal file
19
l2ooghelper/GroundItem.cpp
Normal 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
17
l2ooghelper/GroundItem.h
Normal 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
253
l2ooghelper/HWID.cpp
Normal 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
7
l2ooghelper/HWID.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef H_HWID
|
||||
#define H_HWID
|
||||
|
||||
bool verifyHWID();
|
||||
bool verifyTimeLimit();
|
||||
|
||||
#endif
|
||||
427
l2ooghelper/IL2Client.cpp
Normal file
427
l2ooghelper/IL2Client.cpp
Normal 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
108
l2ooghelper/IL2Client.h
Normal 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
|
||||
78
l2ooghelper/InputStringDlg.cpp
Normal file
78
l2ooghelper/InputStringDlg.cpp
Normal 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];
|
||||
};*/
|
||||
19
l2ooghelper/InputStringDlg.h
Normal file
19
l2ooghelper/InputStringDlg.h
Normal 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
1553
l2ooghelper/L2Client.cpp
Normal file
File diff suppressed because it is too large
Load Diff
448
l2ooghelper/L2Client.h
Normal file
448
l2ooghelper/L2Client.h
Normal 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
197
l2ooghelper/L2ClientAI.cpp
Normal 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
80
l2ooghelper/L2ClientAI.h
Normal 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;
|
||||
};
|
||||
22
l2ooghelper/L2Client_BotIPC.cpp
Normal file
22
l2ooghelper/L2Client_BotIPC.cpp
Normal 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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
389
l2ooghelper/L2Client_GameLoop.cpp
Normal file
389
l2ooghelper/L2Client_GameLoop.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
443
l2ooghelper/L2Client_Login.cpp
Normal file
443
l2ooghelper/L2Client_Login.cpp
Normal 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;
|
||||
}
|
||||
|
||||
97
l2ooghelper/L2Client_Packets.cpp
Normal file
97
l2ooghelper/L2Client_Packets.cpp
Normal 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() );
|
||||
}
|
||||
205
l2ooghelper/L2Client_Thread.cpp
Normal file
205
l2ooghelper/L2Client_Thread.cpp
Normal 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" );
|
||||
}
|
||||
63
l2ooghelper/L2Client_World.cpp
Normal file
63
l2ooghelper/L2Client_World.cpp
Normal 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
195
l2ooghelper/Logger.cpp
Normal 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
37
l2ooghelper/Logger.h
Normal 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
381
l2ooghelper/MainWindow.cpp
Normal 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
6
l2ooghelper/MainWindow.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_MAINWINDOW
|
||||
#define H_MAINWINDOW
|
||||
|
||||
#define WMMY_DELETETAB (WM_USER+1) // lparam is tab_id
|
||||
|
||||
#endif
|
||||
320
l2ooghelper/MapItemsTabDlg.cpp
Normal file
320
l2ooghelper/MapItemsTabDlg.cpp
Normal 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();
|
||||
}
|
||||
6
l2ooghelper/MapItemsTabDlg.h
Normal file
6
l2ooghelper/MapItemsTabDlg.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef H_MAPITEMSTABDLG
|
||||
#define H_MAPITEMSTABDLG
|
||||
|
||||
HWND MapItemsTabDlg_Create( HWND hWndParent, IL2Client *pcl );
|
||||
|
||||
#endif
|
||||
18
l2ooghelper/MapShowParams.cpp
Normal file
18
l2ooghelper/MapShowParams.cpp
Normal 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;
|
||||
}
|
||||
23
l2ooghelper/MapShowParams.h
Normal file
23
l2ooghelper/MapShowParams.h
Normal 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
745
l2ooghelper/MapWnd.cpp
Normal 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
7
l2ooghelper/MapWnd.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef H_MAPWND
|
||||
#define H_MAPWND
|
||||
#include "IL2Client.h"
|
||||
|
||||
void SubclassMapWindowProc( HWND hWnd, IL2Client *pcl );
|
||||
|
||||
#endif
|
||||
188
l2ooghelper/MessageBoxTimeout.cpp
Normal file
188
l2ooghelper/MessageBoxTimeout.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
40
l2ooghelper/MessageBoxTimeout.h
Normal file
40
l2ooghelper/MessageBoxTimeout.h
Normal 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
225
l2ooghelper/NpcArray.cpp
Normal 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
40
l2ooghelper/NpcArray.h
Normal 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
|
||||
422
l2ooghelper/NpcHtmlMessageDlg.cpp
Normal file
422
l2ooghelper/NpcHtmlMessageDlg.cpp
Normal 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 );
|
||||
}
|
||||
39
l2ooghelper/NpcHtmlMessageDlg.h
Normal file
39
l2ooghelper/NpcHtmlMessageDlg.h
Normal 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
|
||||
339
l2ooghelper/PngJpegImage.cpp
Normal file
339
l2ooghelper/PngJpegImage.cpp
Normal 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();
|
||||
}
|
||||
|
||||
43
l2ooghelper/PngJpegImage.h
Normal file
43
l2ooghelper/PngJpegImage.h
Normal 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
|
||||
19
l2ooghelper/PostBuildEvent.cmd
Normal file
19
l2ooghelper/PostBuildEvent.cmd
Normal 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%]
|
||||
403
l2ooghelper/PrivateStoreDlg.cpp
Normal file
403
l2ooghelper/PrivateStoreDlg.cpp
Normal 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
|
||||
}
|
||||
|
||||
|
||||
|
||||
34
l2ooghelper/PrivateStoreDlg.h
Normal file
34
l2ooghelper/PrivateStoreDlg.h
Normal 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
165
l2ooghelper/ProgressHP.cpp
Normal 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
10
l2ooghelper/ProgressHP.h
Normal 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
8225
l2ooghelper/RecipeData.cpp
Normal file
File diff suppressed because it is too large
Load Diff
23
l2ooghelper/RecipeData.h
Normal file
23
l2ooghelper/RecipeData.h
Normal 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
237
l2ooghelper/Resource.h
Normal 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
199
l2ooghelper/SEH_global.cpp
Normal 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
20
l2ooghelper/SEH_global.h
Normal 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
238
l2ooghelper/SE_funcs.cpp
Normal 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
103
l2ooghelper/SE_funcs.h
Normal 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
|
||||
53
l2ooghelper/SE_funcs_buffs.cpp
Normal file
53
l2ooghelper/SE_funcs_buffs.cpp
Normal 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;
|
||||
}
|
||||
89
l2ooghelper/SE_funcs_cfg.cpp
Normal file
89
l2ooghelper/SE_funcs_cfg.cpp
Normal 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;
|
||||
}
|
||||
|
||||
138
l2ooghelper/SE_funcs_chat.cpp
Normal file
138
l2ooghelper/SE_funcs_chat.cpp
Normal 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;
|
||||
}
|
||||
|
||||
16
l2ooghelper/SE_funcs_hacks.cpp
Normal file
16
l2ooghelper/SE_funcs_hacks.cpp
Normal 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;
|
||||
}
|
||||
32
l2ooghelper/SE_funcs_handlers.cpp
Normal file
32
l2ooghelper/SE_funcs_handlers.cpp
Normal 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;
|
||||
}
|
||||
62
l2ooghelper/SE_funcs_items.cpp
Normal file
62
l2ooghelper/SE_funcs_items.cpp
Normal 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;
|
||||
}
|
||||
89
l2ooghelper/SE_funcs_move.cpp
Normal file
89
l2ooghelper/SE_funcs_move.cpp
Normal 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;
|
||||
}
|
||||
257
l2ooghelper/SE_funcs_party.cpp
Normal file
257
l2ooghelper/SE_funcs_party.cpp
Normal 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;
|
||||
}
|
||||
57
l2ooghelper/SE_funcs_skills.cpp
Normal file
57
l2ooghelper/SE_funcs_skills.cpp
Normal 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;
|
||||
}
|
||||
62
l2ooghelper/SE_funcs_targ.cpp
Normal file
62
l2ooghelper/SE_funcs_targ.cpp
Normal 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;
|
||||
}
|
||||
|
||||
63
l2ooghelper/SE_funcs_userInfo.cpp
Normal file
63
l2ooghelper/SE_funcs_userInfo.cpp
Normal 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;
|
||||
}
|
||||
417
l2ooghelper/SE_funcs_world.cpp
Normal file
417
l2ooghelper/SE_funcs_world.cpp
Normal 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;
|
||||
}
|
||||
349
l2ooghelper/ScriptEngine.cpp
Normal file
349
l2ooghelper/ScriptEngine.cpp
Normal 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
Reference in New Issue
Block a user