746 lines
24 KiB
C++
746 lines
24 KiB
C++
#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 );
|
||
}
|
||
}
|