Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1686 lines
42 KiB
C++
1686 lines
42 KiB
C++
// Arrangement2Dlg.cpp : 구현 파일
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "Arrangement2.h"
|
|
#include "Arrangement2Dlg.h"
|
|
#include "ijl.h"
|
|
|
|
#include "MemUtils.h"
|
|
#include "DelimitedFile.h"
|
|
|
|
#include <algorithm>
|
|
#include ".\arrangement2dlg.h"
|
|
|
|
#include <Utility/Math/Math.h>
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
|
|
// 응용 프로그램 정보에 사용되는 CAboutDlg 대화 상자입니다.
|
|
|
|
class CAboutDlg : public CDialog
|
|
{
|
|
public:
|
|
CAboutDlg();
|
|
|
|
// 대화 상자 데이터
|
|
enum { IDD = IDD_ABOUTBOX };
|
|
|
|
protected:
|
|
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV 지원
|
|
|
|
// 구현
|
|
protected:
|
|
DECLARE_MESSAGE_MAP()
|
|
};
|
|
|
|
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
|
|
{
|
|
}
|
|
|
|
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
// CArrangement2Dlg 대화 상자
|
|
|
|
|
|
|
|
CArrangement2Dlg::CArrangement2Dlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CArrangement2Dlg::IDD, pParent)
|
|
, m_nMapStartX(0)
|
|
, m_nMapStartZ(0)
|
|
, m_nPositionX(0)
|
|
, m_nPositionY(0)
|
|
, m_nPositionZ(0)
|
|
, m_nNumOfWorld(0)
|
|
, m_nNumOfKID(0)
|
|
, m_bVisualKID(FALSE)
|
|
, m_nProcess(0)
|
|
, m_strName(_T(""))
|
|
, m_strLevel(_T(""))
|
|
, m_strClass(_T(""))
|
|
, m_nPID(0)
|
|
, m_bVisualPID(FALSE)
|
|
, m_imageData(NULL)
|
|
, m_bmp(NULL)
|
|
, m_wRespawnArea(DEFAULT_DISTANCE)
|
|
, m_bVisualLevel(FALSE)
|
|
, m_nPartyMemNum(0)
|
|
, m_dwPageX(MAP_PAGE_X)
|
|
, m_dwPageZ(MAP_PAGE_Z)
|
|
, m_nPrevX(0)
|
|
, m_nPrevY(0)
|
|
, m_nNextX(0)
|
|
, m_nNextY(0)
|
|
, m_nGapX(0)
|
|
, m_nGapY(0)
|
|
{
|
|
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
|
|
}
|
|
|
|
|
|
void CArrangement2Dlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
DDX_Text(pDX, IDC_POSITIONX, m_nPositionX);
|
|
DDX_Text(pDX, IDC_POSITIONZ, m_nPositionZ);
|
|
DDX_Text(pDX, IDC_NUMINWORLD, m_nNumOfWorld);
|
|
DDX_Text(pDX, IDC_NUMOFKID, m_nNumOfKID);
|
|
DDX_Text(pDX, IDC_NAME, m_strName);
|
|
DDX_Text(pDX, IDC_LEVEL, m_strLevel);
|
|
DDX_Text(pDX, IDC_CLASS, m_strClass);
|
|
DDX_Text(pDX, IDC_RESPAWNEDIT, m_wRespawnArea);
|
|
|
|
DDX_Check(pDX, IDC_VISUALKID, m_bVisualKID);
|
|
DDX_Check(pDX, IDC_VISUALPID, m_bVisualPID);
|
|
DDX_Check(pDX, IDC_VISUALLEVEL, m_bVisualLevel);
|
|
|
|
DDX_Control(pDX, IDC_KIDCOMBO, m_ctrKIDCombo);
|
|
DDX_Control(pDX, IDC_PIDCOMBO, m_ctrPIDCombo);
|
|
|
|
DDX_Radio(pDX, IDC_ARRANGEMENT, m_nProcess);
|
|
|
|
DDV_MinMaxShort(pDX, m_wRespawnArea, 0, 30000);
|
|
DDX_Text(pDX, IDC_PARTYMEM_NUM, m_nPartyMemNum);
|
|
DDV_MinMaxInt(pDX, m_nPartyMemNum, 0, 1000000);
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CArrangement2Dlg, CDialog)
|
|
ON_WM_SYSCOMMAND()
|
|
ON_WM_PAINT()
|
|
ON_WM_QUERYDRAGICON()
|
|
ON_WM_HSCROLL()
|
|
ON_WM_VSCROLL()
|
|
ON_COMMAND_RANGE(ID__50, ID__800, OnZoom)
|
|
ON_UPDATE_COMMAND_UI_RANGE(ID__50, ID__800, OnUpdateZoom)
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MOUSEWHEEL()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_RBUTTONUP()
|
|
|
|
ON_BN_CLICKED(IDC_CREATESCRIPT, OnBnClickedCreatescript)
|
|
ON_BN_CLICKED(IDC_VISUALKID, OnBnClickedVisualkid)
|
|
ON_CBN_SELCHANGE(IDC_KIDCOMBO, OnCbnSelchangeKidcombo)
|
|
ON_BN_CLICKED(IDC_VISUALPID, OnBnClickedVisualpid)
|
|
|
|
ON_COMMAND_RANGE(ID__ZONE1, ID__ZONE16, OnZone)
|
|
ON_UPDATE_COMMAND_UI_RANGE(ID__ZONE1, ID__ZONE16, OnUpdateZone)
|
|
ON_COMMAND(ID_APP_EXIT, OnAppExit)
|
|
|
|
ON_WM_TIMER()
|
|
|
|
// ON_CBN_SELCHANGE(IDC_PIDCOMBO, OnCbnSelchangePidcombo)
|
|
ON_CBN_SELCHANGE(IDC_PIDCOMBO, OnCbnSelchangePidcombo)
|
|
ON_WM_SIZE()
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
// CArrangement2Dlg 메시지 처리기
|
|
|
|
BOOL CArrangement2Dlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
// 시스템 메뉴에 "정보..." 메뉴 항목을 추가합니다.
|
|
|
|
// IDM_ABOUTBOX는 시스템 명령 범위에 있어야 합니다.
|
|
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
|
|
ASSERT(IDM_ABOUTBOX < 0xF000);
|
|
|
|
CMenu* pSysMenu = GetSystemMenu(FALSE);
|
|
if (pSysMenu != NULL)
|
|
{
|
|
CString strAboutMenu;
|
|
strAboutMenu.LoadString(IDS_ABOUTBOX);
|
|
if (!strAboutMenu.IsEmpty())
|
|
{
|
|
pSysMenu->AppendMenu(MF_SEPARATOR);
|
|
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
|
|
}
|
|
}
|
|
|
|
// ===============================================================================
|
|
// Version History
|
|
// -------------------------------------------------------------------------------
|
|
//
|
|
// - 1.12
|
|
// + 16번존의 석상 ID 를 그대로 두기위해 "석상 ID 유지하기" 체크박스 추가
|
|
//
|
|
// - 1.11
|
|
// + 사용하지 않는 UI 삭제 (스카우트, 이동패턴) 및 수정
|
|
// + 존 16번 로드시 8번존 이미지가 나오던 버그 수정
|
|
//
|
|
// - 1.10
|
|
// + 존 16번(다크 카나번) 추가
|
|
//
|
|
// - 1.09
|
|
// + 이미 사용한 PID의 경우 몇 마리가 그룹에 묶여있는지 표시해주는 기능 추가
|
|
//
|
|
// - 1.08
|
|
// + PID 설정후 그룹(파티)이 설정되지 않던 버그 수정
|
|
//
|
|
// - 1.07
|
|
// + PID 콤보박스 수정
|
|
//
|
|
// - 1.06
|
|
// + 몬스터 스크립트에 LOD 여부 추가
|
|
//
|
|
// - 1.05
|
|
// + 몬스터를 배치, 삭제가 자주 있어서 중복된 CID의 몬스터가 생기던 버그 수정
|
|
// + (스크립트를 생성할때 CID를 부여하는 식으로 변경되었음)
|
|
//
|
|
// - 1.04
|
|
// + 몬스터 리스트의 레벨이 경험점의 수치로 표시되던 버그 수정
|
|
//
|
|
// - 1.03
|
|
// + 통합존 (12번) 추가
|
|
//
|
|
// - 1.02
|
|
// + 1.01 버젼의 CID 가 중복으로 생성되던 버그 수정
|
|
//
|
|
// - 1.01
|
|
// + Monster CID 넘버링 수정 (KID 별로 넘버링되어서 CID를 만들어낸다.)
|
|
// + 한 종류의 몬스터는 2047 마리까지 배치 가능하다.
|
|
//
|
|
// - 1.00
|
|
// + 버전 넘버링 시작
|
|
// + 치프 몬스터 추가에 더불어 배포
|
|
//
|
|
// ===============================================================================
|
|
SetWindowText("Arrangement Tool - Ver. 1.12");
|
|
|
|
// 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
|
|
// 프레임워크가 이 작업을 자동으로 수행합니다.
|
|
SetIcon(m_hIcon, TRUE); // 큰 아이콘을 설정합니다.
|
|
SetIcon(m_hIcon, FALSE); // 작은 아이콘을 설정합니다.
|
|
|
|
CMenu menu;
|
|
menu.LoadMenu(IDR_MENU1);
|
|
SetMenu(&menu);
|
|
menu.Detach();
|
|
|
|
m_nSelectedZoom = ID__100;
|
|
m_fMagnification = 1;
|
|
|
|
m_nTimer = SetTimer(1, 1000, 0);
|
|
|
|
m_bBlink = false;
|
|
m_bDragObject = false;
|
|
m_bDragScreen = false;
|
|
|
|
ZeroMemory(&m_bmi, sizeof(BITMAPINFO));
|
|
m_bmp = NULL;
|
|
|
|
char strTemp[ID_LENGTH];
|
|
for (int i = 0; i < MAX_NUM; ++i)
|
|
{
|
|
sprintf(strTemp, "%d", i);
|
|
m_ctrPIDCombo.InsertString(i, strTemp);
|
|
m_ctrPIDCombo.SetItemData(i, i);
|
|
}
|
|
|
|
ClearBitmap();
|
|
return TRUE; // 컨트롤에 대한 포커스를 설정하지 않을 경우 TRUE를 반환합니다.
|
|
}
|
|
|
|
void CArrangement2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
|
|
{
|
|
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
|
|
{
|
|
CAboutDlg dlgAbout;
|
|
dlgAbout.DoModal();
|
|
}
|
|
else
|
|
{
|
|
CDialog::OnSysCommand(nID, lParam);
|
|
}
|
|
}
|
|
|
|
// 대화 상자에 최소화 단추를 추가할 경우 아이콘을 그리려면
|
|
// 아래 코드가 필요합니다. 문서/뷰 모델을 사용하는 MFC 응용 프로그램의 경우에는
|
|
// 프레임워크에서 이 작업을 자동으로 수행합니다.
|
|
|
|
|
|
class CDrawMonster
|
|
{
|
|
public:
|
|
|
|
CDrawMonster(Graphics& graphics, Pen& pen, const int nWidth, const int nHeight)
|
|
: m_graphics(graphics), m_pen(pen), m_nWidth(nWidth), m_nHeight(nHeight) { }
|
|
~CDrawMonster() { }
|
|
|
|
void DrawEllipse(SolidBrush& brush, int nX, int nY)
|
|
{
|
|
m_graphics.DrawEllipse(&m_pen, nX, nY, m_nWidth, m_nHeight);
|
|
m_graphics.FillEllipse(&brush, nX, nY, m_nWidth, m_nHeight);
|
|
}
|
|
|
|
void DrawRectangle(SolidBrush& brush, int nX, int nY)
|
|
{
|
|
m_graphics.DrawRectangle(&m_pen, nX, nY, m_nWidth, m_nHeight);
|
|
m_graphics.FillRectangle(&brush, nX, nY, m_nWidth, m_nHeight);
|
|
}
|
|
|
|
void DrawRespawnArea(SolidBrush& brush, int nLeft, int nTop, int nRight, int nBottom)
|
|
{
|
|
m_graphics.DrawEllipse(&m_pen, nLeft, nTop, nRight - nLeft, nBottom - nTop);
|
|
m_graphics.FillEllipse(&brush, nLeft, nTop, nRight - nLeft, nBottom - nTop);
|
|
}
|
|
|
|
private:
|
|
|
|
Graphics& m_graphics;
|
|
Pen& m_pen;
|
|
|
|
const int m_nWidth;
|
|
const int m_nHeight;
|
|
};
|
|
|
|
|
|
void CArrangement2Dlg::OnPaint()
|
|
{
|
|
CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트
|
|
|
|
if (IsIconic())
|
|
{
|
|
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
|
|
|
|
// 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
|
|
int cxIcon = GetSystemMetrics(SM_CXICON);
|
|
int cyIcon = GetSystemMetrics(SM_CYICON);
|
|
|
|
CRect rect;
|
|
GetClientRect(&rect);
|
|
|
|
int x = (rect.Width() - cxIcon + 1) / 2;
|
|
int y = (rect.Height() - cyIcon + 1) / 2;
|
|
|
|
// 아이콘을 그립니다.
|
|
dc.DrawIcon(x, y, m_hIcon);
|
|
}
|
|
else
|
|
{
|
|
HDC hdcCompatible = CreateCompatibleDC(dc.m_hDC);
|
|
HBITMAP hbmScreen = CreateCompatibleBitmap(dc.m_hDC,
|
|
GetDeviceCaps(dc.m_hDC, HORZRES),
|
|
GetDeviceCaps(dc.m_hDC, VERTRES));
|
|
|
|
SelectObject(hdcCompatible, hbmScreen);
|
|
|
|
StretchDIBits(hdcCompatible,
|
|
0, 0, m_dwPageX, m_dwPageZ,
|
|
m_nMapStartX, (int)(m_imageDims.cy-m_dwPageZ / m_fMagnification-m_nMapStartZ),
|
|
(int)(m_dwPageX / m_fMagnification), (int)(m_dwPageZ / m_fMagnification),
|
|
m_bmp, &m_bmi, DIB_RGB_COLORS, SRCCOPY);
|
|
|
|
Graphics graphics(hdcCompatible);
|
|
|
|
Pen hBlackPen(Color(255, 0, 0, 0));
|
|
|
|
SolidBrush hRedBrush(Color(255, 255, 0, 0));
|
|
SolidBrush hGreenBrush(Color(255, 0, 255, 0));
|
|
SolidBrush hBlueBrush(Color(255, 0, 0, 255));
|
|
SolidBrush hWhiteBrush(Color(255, 255, 255, 255));
|
|
SolidBrush hYellowBrush(Color(255, 255, 255, 0));
|
|
SolidBrush hGrayBrush(Color(127, 128, 128, 128));
|
|
SolidBrush hBlackBrush(Color(255, 0, 0, 0));
|
|
|
|
FontFamily fontFamily(L"굴림");
|
|
Font font(&fontFamily, 11, FontStyleRegular, UnitPixel);
|
|
|
|
CDrawMonster draw(graphics, hBlackPen, 4, 4);
|
|
wchar_t szID[ID_LENGTH];
|
|
|
|
MonsterList::iterator begin = m_lstMonster.begin();
|
|
MonsterList::iterator end = m_lstMonster.end();
|
|
|
|
for (;begin != end; ++begin)
|
|
{
|
|
Monster* lpMonster = *begin;
|
|
|
|
int nPosInScreenX = (int)((lpMonster->m_nPosX - m_nMapStartX - SECTOR_SIZE) * m_fMagnification);
|
|
int nPosInScreenZ = (int)((lpMonster->m_nPosZ + m_nMapStartZ - m_imageDims.cy + SECTOR_SIZE) * m_fMagnification * (-1));
|
|
|
|
if (0 <= nPosInScreenX && nPosInScreenX <= m_dwPageX - 4 &&
|
|
0 <= nPosInScreenZ && nPosInScreenZ <= m_dwPageZ)
|
|
{
|
|
SolidBrush* lpSolidBrush = NULL;
|
|
|
|
switch (lpMonster->m_nMovingPattern)
|
|
{
|
|
case PATTERN_AREA: lpSolidBrush = &hRedBrush; break;
|
|
case PATTERN_FIX: lpSolidBrush = &hGreenBrush; break;
|
|
case PATTERN_ROUTE: lpSolidBrush = &hBlueBrush; break;
|
|
case PATTERN_NONAREA: lpSolidBrush = &hWhiteBrush; break;
|
|
}
|
|
|
|
if (0 != lpMonster->m_wRespawnArea && lpMonster->m_wRespawnArea != DEFAULT_DISTANCE)
|
|
{
|
|
int nLeft = (int)((lpMonster->m_nPosX - m_nMapStartX - SECTOR_SIZE - lpMonster->m_wRespawnArea) * m_fMagnification);
|
|
int nTop = (int)((lpMonster->m_nPosZ + m_nMapStartZ - m_imageDims.cy + SECTOR_SIZE - lpMonster->m_wRespawnArea) * m_fMagnification * (-1));
|
|
int nRight = (int)((lpMonster->m_nPosX - m_nMapStartX - SECTOR_SIZE + lpMonster->m_wRespawnArea) * m_fMagnification);
|
|
int nBottom = (int)((lpMonster->m_nPosZ + m_nMapStartZ - m_imageDims.cy + SECTOR_SIZE + lpMonster->m_wRespawnArea) * m_fMagnification * (-1));
|
|
|
|
draw.DrawRespawnArea(hGrayBrush, nLeft, nTop, nRight, nBottom);
|
|
}
|
|
|
|
if (true == m_bBlink && lpMonster->m_nPID == m_nPID && 0 != m_nPID)
|
|
{
|
|
lpSolidBrush = &hYellowBrush;
|
|
}
|
|
|
|
nPosInScreenX -= 2;
|
|
nPosInScreenZ -= 2;
|
|
|
|
if (NULL != lpSolidBrush && lpMonster->m_bScout)
|
|
{
|
|
draw.DrawEllipse(*lpSolidBrush, nPosInScreenX, nPosInScreenZ);
|
|
}
|
|
else
|
|
{
|
|
draw.DrawRectangle(*lpSolidBrush, nPosInScreenX, nPosInScreenZ);
|
|
}
|
|
|
|
if (nPosInScreenX <= m_dwPageX - 20)
|
|
{
|
|
if (m_bVisualKID)
|
|
{
|
|
PointF pointF((REAL)nPosInScreenX, (REAL)nPosInScreenZ + 2);
|
|
_snwprintf(szID, ID_LENGTH, L"K %d", lpMonster->m_nKID);
|
|
DrawOutLineText(graphics, font, pointF, szID);
|
|
}
|
|
|
|
if (m_bVisualLevel)
|
|
{
|
|
PointF pointF((REAL)nPosInScreenX, (REAL)nPosInScreenZ + 12);
|
|
_snwprintf(szID, ID_LENGTH, L"L %d", lpMonster->m_nLevel);
|
|
DrawOutLineText(graphics, font, pointF, szID);
|
|
}
|
|
|
|
if (m_bVisualPID && 0 != lpMonster->m_nPID)
|
|
{
|
|
PointF pointF((REAL)nPosInScreenX, (REAL)nPosInScreenZ + 22);
|
|
_snwprintf(szID, ID_LENGTH, L"P %d", lpMonster->m_nPID);
|
|
DrawOutLineText(graphics, font, pointF, szID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BitBlt(dc.m_hDC, 0, 0, m_dwPageX, m_dwPageZ, hdcCompatible, 0, 0, SRCCOPY);
|
|
DeleteObject(hbmScreen);
|
|
DeleteDC(hdcCompatible);
|
|
|
|
m_nNumOfWorld = (int)(m_lstMonster.size());
|
|
UpdateData(FALSE);
|
|
|
|
CDialog::OnPaint();
|
|
}
|
|
}
|
|
|
|
void CArrangement2Dlg::DrawOutLineText(Graphics& graphics, Font& font, PointF pointF, wchar_t* strText)
|
|
{
|
|
SolidBrush hWhiteBrush(Color(255, 255, 255, 255));
|
|
SolidBrush hBlackBrush(Color(255, 0, 0, 0));
|
|
|
|
++pointF.X;
|
|
++pointF.Y;
|
|
graphics.DrawString(strText, static_cast<int>(wcslen(strText)), &font, pointF, &hBlackBrush);
|
|
|
|
pointF.X -= 2;
|
|
graphics.DrawString(strText, static_cast<int>(wcslen(strText)), &font, pointF, &hBlackBrush);
|
|
|
|
pointF.Y -= 2;
|
|
graphics.DrawString(strText, static_cast<int>(wcslen(strText)), &font, pointF, &hBlackBrush);
|
|
|
|
pointF.X += 2;
|
|
graphics.DrawString(strText, static_cast<int>(wcslen(strText)), &font, pointF, &hBlackBrush);
|
|
|
|
--pointF.X;
|
|
++pointF.Y;
|
|
graphics.DrawString(strText, static_cast<int>(wcslen(strText)), &font, pointF, &hWhiteBrush);
|
|
}
|
|
|
|
// 사용자가 최소화된 창을 끄는 동안에 커서가 표시되도록 시스템에서
|
|
// 이 함수를 호출합니다.
|
|
HCURSOR CArrangement2Dlg::OnQueryDragIcon()
|
|
{
|
|
return static_cast<HCURSOR>(m_hIcon);
|
|
}
|
|
|
|
|
|
BOOL CArrangement2Dlg::DestroyWindow()
|
|
{
|
|
ClearData();
|
|
|
|
KillTimer(m_nTimer);
|
|
|
|
return CDialog::DestroyWindow();
|
|
}
|
|
|
|
|
|
void CArrangement2Dlg::ClearData()
|
|
{
|
|
SAFE_DELETE_ARRAY(m_imageData);
|
|
SAFE_DELETE_ARRAY(m_bmp);
|
|
|
|
std::for_each(m_lstMonster.begin(), m_lstMonster.end(), MemUtils::fnDelete());
|
|
|
|
m_lstMonster.clear();
|
|
m_lstMonsterInfo.clear();
|
|
m_mapStatueID.clear() ;
|
|
}
|
|
|
|
void CArrangement2Dlg::OnTimer(UINT nIDEvent)
|
|
{
|
|
UpdateData(TRUE);
|
|
m_bBlink = !m_bBlink;
|
|
Invalidate(FALSE);
|
|
|
|
CDialog::OnTimer(nIDEvent);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 스크롤 바
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CArrangement2Dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
{
|
|
switch (nSBCode)
|
|
{
|
|
case SB_LEFT:
|
|
m_nMapStartX = 0;
|
|
break;
|
|
|
|
case SB_RIGHT:
|
|
m_nMapStartX = (int)(m_imageDims.cx-m_dwPageX/m_fMagnification);
|
|
break;
|
|
|
|
case SB_ENDSCROLL:
|
|
break;
|
|
|
|
case SB_LINELEFT:
|
|
m_nMapStartX--;
|
|
if (m_nMapStartX<0) { m_nMapStartX = 0; }
|
|
break;
|
|
|
|
case SB_LINERIGHT:
|
|
m_nMapStartX++;
|
|
break;
|
|
|
|
case SB_PAGELEFT:
|
|
m_nMapStartX -= (int)(m_dwPageX/m_fMagnification);
|
|
if (m_nMapStartX<0) { m_nMapStartX = 0; }
|
|
break;
|
|
|
|
case SB_PAGERIGHT:
|
|
m_nMapStartX += (int)(m_dwPageX/m_fMagnification);
|
|
if (m_nMapStartX>(int)(m_imageDims.cx-m_dwPageX/m_fMagnification))
|
|
m_nMapStartX = (int)(m_imageDims.cx-m_dwPageX/m_fMagnification);;
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
m_nMapStartX = nPos;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
m_nMapStartX = nPos;
|
|
break;
|
|
}
|
|
|
|
SetScrollPos(SB_HORZ, m_nMapStartX);
|
|
|
|
Invalidate(FALSE);
|
|
|
|
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
{
|
|
switch (nSBCode)
|
|
{
|
|
case SB_TOP:
|
|
m_nMapStartZ = 0;
|
|
break;
|
|
|
|
case SB_BOTTOM:
|
|
m_nMapStartZ = (int)(m_imageDims.cy-m_dwPageZ/m_fMagnification);
|
|
break;
|
|
|
|
case SB_ENDSCROLL:
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
m_nMapStartZ++;
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
m_nMapStartZ--;
|
|
if (m_nMapStartZ<0) { m_nMapStartZ = 0; }
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
m_nMapStartZ += (int)(m_dwPageZ/m_fMagnification);
|
|
if (m_nMapStartZ>(int)(m_imageDims.cy-m_dwPageZ/m_fMagnification))
|
|
m_nMapStartZ = (int)(m_imageDims.cy-m_dwPageZ/m_fMagnification);
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
m_nMapStartZ -= (int)(m_dwPageZ/m_fMagnification);
|
|
if (m_nMapStartZ<0) { m_nMapStartZ = 0; }
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
|
m_nMapStartZ = nPos;
|
|
break;
|
|
|
|
case SB_THUMBTRACK:
|
|
m_nMapStartZ = nPos;
|
|
break;
|
|
}
|
|
|
|
SetScrollPos(SB_VERT, m_nMapStartZ);
|
|
|
|
Invalidate(FALSE);
|
|
|
|
CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 이미지 로딩 하기전에 m_bmp 를 검은색 화면으로 지워주는 함수
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CArrangement2Dlg::ClearBitmap()
|
|
{
|
|
m_imageChannels = 3;
|
|
m_imageDims.cx = m_dwPageX;
|
|
m_imageDims.cy = m_dwPageZ;
|
|
int imageSize = m_dwPageX * m_imageChannels * m_dwPageZ;
|
|
|
|
m_bmp = new BYTE[ imageSize ];
|
|
::ZeroMemory(m_bmp, sizeof(imageSize));
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 이미지 로딩
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
BOOL CArrangement2Dlg::OpenJPGFile(LPCTSTR lpszPathName)
|
|
{
|
|
JPEG_CORE_PROPERTIES image;
|
|
ZeroMemory( &image, sizeof( JPEG_CORE_PROPERTIES ) );
|
|
BYTE* imageData;
|
|
|
|
BeginWaitCursor();
|
|
|
|
TRY
|
|
if ( ijlInit( &image ) != IJL_OK )
|
|
{
|
|
TRACE( "Cannot initialize Intel JPEG library\n" );
|
|
AfxThrowUserException();
|
|
}
|
|
|
|
image.JPGFile = const_cast<char*>(lpszPathName);
|
|
if ( ijlRead( &image, IJL_JFILE_READPARAMS ) != IJL_OK )
|
|
{
|
|
TRACE( "Cannot read JPEG file header from %s file\n",
|
|
image.JPGFile );
|
|
AfxThrowUserException();
|
|
}
|
|
|
|
// Set the JPG color space ... this will always be
|
|
// somewhat of an educated guess at best because JPEG
|
|
// is "color blind" (i.e., nothing in the bit stream
|
|
// tells you what color space the data was encoded from).
|
|
// However, in this example we assume that we are
|
|
// reading JFIF files which means that 3 channel images
|
|
// are in the YCbCr color space and 1 channel images are
|
|
// in the Y color space.
|
|
switch(image.JPGChannels)
|
|
{
|
|
case 1:
|
|
image.JPGColor = IJL_G;
|
|
image.DIBChannels = 3;
|
|
image.DIBColor = IJL_BGR;
|
|
break;
|
|
|
|
case 3:
|
|
image.JPGColor = IJL_YCBCR;
|
|
image.DIBChannels = 3;
|
|
image.DIBColor = IJL_BGR;
|
|
break;
|
|
|
|
case 4:
|
|
image.JPGColor = IJL_YCBCRA_FPX;
|
|
image.DIBChannels = 4;
|
|
image.DIBColor = IJL_RGBA_FPX;
|
|
break;
|
|
|
|
default:
|
|
// This catches everything else, but no
|
|
// color twist will be performed by the IJL.
|
|
image.DIBColor = (IJL_COLOR)IJL_OTHER;
|
|
image.JPGColor = (IJL_COLOR)IJL_OTHER;
|
|
image.DIBChannels = image.JPGChannels;
|
|
break;
|
|
}
|
|
|
|
image.DIBWidth = image.JPGWidth;
|
|
image.DIBHeight = image.JPGHeight;
|
|
image.DIBPadBytes = IJL_DIB_PAD_BYTES(image.DIBWidth,image.DIBChannels);
|
|
|
|
int imageSize = (image.DIBWidth * image.DIBChannels + image.DIBPadBytes) *
|
|
image.DIBHeight;
|
|
|
|
imageData = new BYTE[ imageSize ];
|
|
if ( imageData == NULL )
|
|
{
|
|
TRACE( "Cannot allocate memory for image\n" );
|
|
AfxThrowUserException();
|
|
}
|
|
|
|
image.DIBBytes = imageData;
|
|
|
|
if ( ijlRead( &image, IJL_JFILE_READWHOLEIMAGE ) != IJL_OK )
|
|
{
|
|
TRACE( "Cannot read image data from %s file\n", image.JPGFile );
|
|
delete[] imageData;
|
|
AfxThrowUserException();
|
|
}
|
|
|
|
if ( ijlFree( &image ) != IJL_OK )
|
|
{
|
|
TRACE( "Cannot free Intel(R) JPEG library" );
|
|
}
|
|
|
|
if (image.DIBColor == IJL_RGBA_FPX)
|
|
{
|
|
RGBA_FPX_to_BGRA(imageData,image.DIBWidth,image.DIBHeight);
|
|
}
|
|
|
|
CATCH_ALL( e )
|
|
|
|
EndWaitCursor();
|
|
ijlFree( &image );
|
|
|
|
AfxMessageBox( "Error opening JPEG file" );
|
|
return FALSE;
|
|
|
|
END_CATCH_ALL
|
|
|
|
// 이미 로드되어 있었다면 메모리를 해제시켜준다.
|
|
SAFE_DELETE_ARRAY(m_imageData);
|
|
SAFE_DELETE_ARRAY(m_bmp);
|
|
|
|
// initializing incapsulated image with correct values
|
|
m_imageData = imageData;
|
|
m_imageDims.cx = image.DIBWidth;
|
|
m_imageDims.cy = image.DIBHeight;
|
|
m_imageChannels = image.DIBChannels;
|
|
|
|
EndWaitCursor();
|
|
|
|
// now we have
|
|
// m_imageData containing image data, and
|
|
// m_imageDims with image dimensions, and
|
|
// m_imageChannels with image number of channels
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CArrangement2Dlg::RGBA_FPX_to_BGRA(BYTE* data,int width,int height)
|
|
{
|
|
int i;
|
|
int j;
|
|
int pad;
|
|
int line_width;
|
|
BYTE r, g, b, a;
|
|
BYTE* ptr;
|
|
|
|
ptr = data;
|
|
pad = IJL_DIB_PAD_BYTES(width,4);
|
|
line_width = width * 4 + pad;
|
|
|
|
for(i = 0; i < height; i++)
|
|
{
|
|
ptr = data + line_width*i;
|
|
for(j = 0; j < width; j++)
|
|
{
|
|
r = ptr[0];
|
|
g = ptr[1];
|
|
b = ptr[2];
|
|
a = ptr[3];
|
|
ptr[2] = (BYTE)( (r*a+1) >> 8 );
|
|
ptr[1] = (BYTE)( (g*a+1) >> 8 );
|
|
ptr[0] = (BYTE)( (b*a+1) >> 8 );
|
|
ptr += 4;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
void CArrangement2Dlg::InitialUpdate()
|
|
{
|
|
BITMAPINFOHEADER& bih = m_bmi.bmiHeader;
|
|
|
|
::ZeroMemory( &bih, sizeof( BITMAPINFOHEADER ) );
|
|
|
|
bih.biSize = sizeof( BITMAPINFOHEADER );
|
|
bih.biWidth = m_imageDims.cx;
|
|
bih.biHeight = -m_imageDims.cy;
|
|
bih.biCompression = BI_RGB;
|
|
bih.biPlanes = 1;
|
|
|
|
switch(m_imageChannels)
|
|
{
|
|
case 3:
|
|
bih.biBitCount = 24;
|
|
break;
|
|
|
|
case 4:
|
|
bih.biBitCount = 32;
|
|
break;
|
|
|
|
default:
|
|
TRACE("Unsupported number of channels!\n");
|
|
break;
|
|
}
|
|
|
|
if ( m_bmp != NULL )
|
|
delete[] m_bmp;
|
|
|
|
int pad = IJL_DIB_PAD_BYTES(m_imageDims.cx,m_imageChannels);
|
|
|
|
int imageSize = (m_imageDims.cx * m_imageChannels + pad) * m_imageDims.cy;
|
|
|
|
m_bmp = new BYTE[ imageSize ];
|
|
|
|
if ( m_bmp == NULL )
|
|
return;
|
|
|
|
::ZeroMemory(m_bmp,imageSize);
|
|
::CopyMemory(m_bmp,m_imageData,imageSize);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 존 로딩
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CArrangement2Dlg::OnZone(UINT nID)
|
|
{
|
|
m_nLoadedZone = nID;
|
|
ClearData();
|
|
|
|
switch (m_nLoadedZone)
|
|
{
|
|
case ID__ZONE1:
|
|
OpenJPGFile("Zone01.jpg");
|
|
break;
|
|
|
|
case ID__ZONE2:
|
|
OpenJPGFile("Zone02.jpg");
|
|
break;
|
|
|
|
case ID__ZONE3:
|
|
OpenJPGFile("Zone03.jpg");
|
|
break;
|
|
|
|
case ID__ZONE4:
|
|
OpenJPGFile("Zone04.jpg");
|
|
break;
|
|
|
|
case ID__ZONE5:
|
|
OpenJPGFile("Zone05.jpg");
|
|
break;
|
|
|
|
case ID__ZONE8:
|
|
OpenJPGFile("Zone08.jpg");
|
|
break;
|
|
|
|
case ID__ZONE9:
|
|
OpenJPGFile("Zone09.jpg");
|
|
break;
|
|
|
|
case ID__ZONE12:
|
|
OpenJPGFile("Zone12.jpg");
|
|
break;
|
|
|
|
case ID__ZONE16:
|
|
OpenJPGFile("Zone16.jpg");
|
|
break;
|
|
|
|
case ID__ZONE100:
|
|
// OpenJPGFile("Zone100.jpg");
|
|
return;
|
|
break;
|
|
}
|
|
|
|
InitialUpdate();
|
|
|
|
LoadScript();
|
|
|
|
SetScrollRange(SB_HORZ, 0, m_imageDims.cx - m_dwPageX);
|
|
SetScrollRange(SB_VERT, 0, m_imageDims.cy - m_dwPageZ);
|
|
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnUpdateZone(CCmdUI *pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(m_nLoadedZone == pCmdUI->m_nID);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 줌
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CArrangement2Dlg::OnZoom(UINT nID)
|
|
{
|
|
m_nSelectedZoom = nID;
|
|
|
|
switch (m_nSelectedZoom)
|
|
{
|
|
case ID__50:
|
|
m_fMagnification = 0.5;
|
|
break;
|
|
case ID__100:
|
|
m_fMagnification = 1;
|
|
break;
|
|
case ID__200:
|
|
m_fMagnification = 2;
|
|
break;
|
|
case ID__400:
|
|
m_fMagnification = 4;
|
|
break;
|
|
case ID__800:
|
|
m_fMagnification = 8;
|
|
break;
|
|
}
|
|
|
|
SetScrollRange(SB_HORZ, 0, (int)(m_imageDims.cx-m_dwPageX/m_fMagnification));
|
|
SetScrollRange(SB_VERT, 0, (int)(m_imageDims.cy-m_dwPageZ/m_fMagnification));
|
|
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnUpdateZoom(CCmdUI *pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(m_nSelectedZoom == pCmdUI->m_nID);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 마우스 인터페이스
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CArrangement2Dlg::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bDragScreen)
|
|
{
|
|
m_nMapStartX += DragScreenStartPoint.x - point.x;
|
|
m_nMapStartZ += DragScreenStartPoint.y - point.y;
|
|
|
|
if (m_nMapStartX < 0)
|
|
m_nMapStartX = 0;
|
|
if (m_nMapStartX > (int)(m_imageDims.cx-m_dwPageX / m_fMagnification))
|
|
m_nMapStartX = (int)(m_imageDims.cx-m_dwPageX / m_fMagnification);
|
|
if (m_nMapStartZ < 0)
|
|
m_nMapStartZ = 0;
|
|
if (m_nMapStartZ > (int)(m_imageDims.cy-m_dwPageZ / m_fMagnification))
|
|
m_nMapStartZ = (int)(m_imageDims.cy-m_dwPageZ / m_fMagnification);
|
|
|
|
SetScrollPos(SB_HORZ, m_nMapStartX);
|
|
SetScrollPos(SB_VERT, m_nMapStartZ);
|
|
|
|
Invalidate(FALSE);
|
|
|
|
DragScreenStartPoint = point;
|
|
}
|
|
else
|
|
{
|
|
UpdateData(TRUE);
|
|
|
|
m_nPositionX = m_nMapStartX + (int)(point.x / m_fMagnification) + SECTOR_SIZE;
|
|
m_nPositionY = 0;
|
|
m_nPositionZ = m_imageDims.cy - (int)(m_nMapStartZ + point.y / m_fMagnification) - SECTOR_SIZE;
|
|
|
|
if (point.x >= 0 && point.x <= m_dwPageX && point.y >= 0 && point.y <= m_dwPageZ)
|
|
{
|
|
if (m_bDragObject)
|
|
{
|
|
m_lstMonster[m_DragObjectIndex]->m_nPosX = m_nPositionX;
|
|
m_lstMonster[m_DragObjectIndex]->m_nPosZ = m_nPositionZ;
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
}
|
|
|
|
CDialog::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
|
|
void CArrangement2Dlg::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
int nPosInScreenX, nPosInScreenZ;
|
|
|
|
switch (m_nProcess)
|
|
{
|
|
case ARRANGEMENT:
|
|
{
|
|
for (int i = 0; i < (int)(m_lstMonster.size()); i++)
|
|
{
|
|
nPosInScreenX = (int)((m_lstMonster[i]->m_nPosX - m_nMapStartX - SECTOR_SIZE) * m_fMagnification);
|
|
nPosInScreenZ = (int)((m_lstMonster[i]->m_nPosZ + m_nMapStartZ - m_imageDims.cy + SECTOR_SIZE) * m_fMagnification * (-1));
|
|
|
|
if (nPosInScreenX - 3 <= point.x && point.x < nPosInScreenX + 3 &&
|
|
nPosInScreenZ - 3 <= point.y && point.y < nPosInScreenZ + 3)
|
|
{
|
|
m_bDragObject = true;
|
|
m_DragObjectIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
} break;
|
|
|
|
case ERASE:
|
|
case PARTY:
|
|
{
|
|
if (0 <= point.x && point.x < m_dwPageX && 0 <= point.y && point.y < m_dwPageZ)
|
|
{
|
|
CRectTracker tracker;
|
|
|
|
if (tracker.TrackRubberBand(this, point, TRUE))
|
|
{
|
|
tracker.m_rect.NormalizeRect();
|
|
|
|
long temp;
|
|
|
|
if (tracker.m_rect.left > tracker.m_rect.right)
|
|
{
|
|
temp = tracker.m_rect.left;
|
|
tracker.m_rect.left = tracker.m_rect.right;
|
|
tracker.m_rect.right = temp;
|
|
}
|
|
if (tracker.m_rect.top > tracker.m_rect.bottom)
|
|
{
|
|
temp = tracker.m_rect.top;
|
|
tracker.m_rect.top = tracker.m_rect.bottom;
|
|
tracker.m_rect.bottom = temp;
|
|
}
|
|
|
|
for (int i = 0; i < (int)(m_lstMonster.size()); i++)
|
|
{
|
|
nPosInScreenX = (int)((m_lstMonster[i]->m_nPosX - m_nMapStartX - SECTOR_SIZE) * m_fMagnification);
|
|
nPosInScreenZ = (int)((m_lstMonster[i]->m_nPosZ + m_nMapStartZ - m_imageDims.cy + SECTOR_SIZE) * m_fMagnification * (-1));
|
|
|
|
if (tracker.m_rect.left <= nPosInScreenX && nPosInScreenX < tracker.m_rect.right &&
|
|
tracker.m_rect.top <= nPosInScreenZ && nPosInScreenZ < tracker.m_rect.bottom)
|
|
{
|
|
if (ERASE == m_nProcess)
|
|
{
|
|
m_lstMonster.erase(m_lstMonster.begin() + i);
|
|
i--;
|
|
}
|
|
else
|
|
{
|
|
m_lstMonster[i]->m_nPID = m_nPID;
|
|
}
|
|
}
|
|
}
|
|
|
|
CalculateNumOfPID();
|
|
if (MAX_PARTY_MEMBER_NUM < m_nPartyMemNum)
|
|
{
|
|
AfxMessageBox("파티원의 인원이 최대수치 10을 넘어 갔습니다.");
|
|
|
|
}
|
|
UpdateData(FALSE);
|
|
|
|
Invalidate(FALSE);
|
|
}
|
|
}
|
|
|
|
} break;
|
|
|
|
}
|
|
|
|
CDialog::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
UpdateData(TRUE);
|
|
|
|
int nKID = static_cast<int>(m_ctrKIDCombo.GetItemData(m_ctrKIDCombo.GetCurSel()));
|
|
|
|
if (m_lstMonsterInfo.end() == m_lstMonsterInfo.find(nKID))
|
|
{
|
|
if (m_bDragObject)
|
|
{
|
|
m_bDragObject = false;
|
|
}
|
|
|
|
CDialog::OnLButtonUp(nFlags, point);
|
|
return;
|
|
}
|
|
|
|
if (0 <= point.x && point.x < m_dwPageX && 0 <= point.y && point.y < m_dwPageZ)
|
|
{
|
|
if (false == m_bDragObject)
|
|
{
|
|
if (0xFFFF == m_nNumOfKID)
|
|
{
|
|
AfxMessageBox("한 종류의 몬스터를 최대로 배치했습니다.\n더이상 이 몬스터를 배치할수 없습니다.");
|
|
}
|
|
else
|
|
{
|
|
Monster* tempMonster = new Monster;
|
|
|
|
tempMonster->m_dwCID = 0;
|
|
tempMonster->m_bScout = false;
|
|
tempMonster->m_nKID = nKID;
|
|
tempMonster->m_nMovingPattern = 0;
|
|
tempMonster->m_wRespawnArea = m_wRespawnArea;
|
|
tempMonster->m_nPosX = m_nPositionX;
|
|
tempMonster->m_nPosY = m_nPositionY;
|
|
tempMonster->m_nPosZ = m_nPositionZ;
|
|
|
|
MonsterInfoList::iterator itr = m_lstMonsterInfo.find(nKID);
|
|
if (itr != m_lstMonsterInfo.end())
|
|
{
|
|
tempMonster->m_nLevel = atoi( (itr->second).m_strLevel );
|
|
}
|
|
|
|
m_lstMonster.push_back(tempMonster);
|
|
|
|
m_nNumOfKID++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_bDragObject = false;
|
|
}
|
|
|
|
Invalidate(FALSE);
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
CDialog::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
BOOL CArrangement2Dlg::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
|
|
{
|
|
m_nMapStartZ += (int)(m_dwPageZ/m_fMagnification/(-240/zDelta));
|
|
|
|
if (m_nMapStartZ<0)
|
|
m_nMapStartZ = 0;
|
|
if (m_nMapStartZ>(int)(m_imageDims.cy-m_dwPageZ/m_fMagnification))
|
|
m_nMapStartZ = (int)(m_imageDims.cy-m_dwPageZ/m_fMagnification);
|
|
|
|
SetScrollPos(SB_VERT, m_nMapStartZ);
|
|
|
|
Invalidate(FALSE);
|
|
|
|
return CDialog::OnMouseWheel(nFlags, zDelta, pt);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
m_bDragScreen = true;
|
|
|
|
DragScreenStartPoint = point;
|
|
|
|
CDialog::OnRButtonDown(nFlags, point);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnRButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
m_bDragScreen = false;
|
|
|
|
CDialog::OnRButtonUp(nFlags, point);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 스크립트
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CArrangement2Dlg::OnBnClickedCreatescript()
|
|
{
|
|
char ArrangementFileName[MAX_PATH] = ".\\Arrangement";
|
|
|
|
switch (m_nLoadedZone)
|
|
{
|
|
case ID__ZONE1: strcat(ArrangementFileName, "1.txt"); break;
|
|
case ID__ZONE2: strcat(ArrangementFileName, "2.txt"); break;
|
|
case ID__ZONE3: strcat(ArrangementFileName, "3.txt"); break;
|
|
case ID__ZONE4: strcat(ArrangementFileName, "4.txt"); break;
|
|
case ID__ZONE5: strcat(ArrangementFileName, "5.txt"); break;
|
|
case ID__ZONE8: strcat(ArrangementFileName, "8.txt"); break;
|
|
case ID__ZONE9: strcat(ArrangementFileName, "9.txt"); break;
|
|
case ID__ZONE12: strcat(ArrangementFileName, "12.txt"); break;
|
|
case ID__ZONE16: strcat(ArrangementFileName, "16.txt"); break;
|
|
case ID__ZONE100: strcat(ArrangementFileName, "100.txt"); break;
|
|
default:
|
|
::AfxMessageBox("Arrangement Script 파일 이름을 설정할\n존 ID가 잘못되었습니다.");
|
|
return;
|
|
}
|
|
|
|
FILE *fp;
|
|
if (NULL == (fp = fopen(ArrangementFileName, "wt")))
|
|
{
|
|
::AfxMessageBox("스크립트 작성에 실패하였습니다.");
|
|
return;
|
|
}
|
|
|
|
fprintf(fp, "CID KID PID X Y Z Scout MovingPattern RespawnArea\n");
|
|
|
|
typedef std::map<unsigned long, unsigned short> NumOfKIDMap;
|
|
NumOfKIDMap lstNumOfKID;
|
|
|
|
for (int i = 0; i < (int)(m_lstMonster.size()); ++i)
|
|
{
|
|
lstNumOfKID.insert(std::make_pair(m_lstMonster[i]->m_nKID, 0));
|
|
}
|
|
|
|
unsigned short nNumOfKID = 0;
|
|
for (int i = 0; i < (int)(m_lstMonster.size()); i++)
|
|
{
|
|
unsigned long pid = 0;
|
|
if (0 != m_lstMonster[i]->m_nPID)
|
|
{
|
|
pid = (MONSTER_PARTY_BIT | m_lstMonster[i]->m_nPID);
|
|
}
|
|
|
|
// CID 생성
|
|
if ( IsStatue(m_lstMonster[i]->m_nKID) )
|
|
{
|
|
StatueIDMap::iterator itr = m_mapStatueID.find( sStatueKey(m_lstMonster[i]->m_nPosX, m_lstMonster[i]->m_nPosZ) ) ;
|
|
if ( itr != m_mapStatueID.end() )
|
|
{
|
|
m_lstMonster[i]->m_dwCID = itr->second ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NumOfKIDMap::iterator itr = lstNumOfKID.find(m_lstMonster[i]->m_nKID);
|
|
if (itr != lstNumOfKID.end())
|
|
{
|
|
nNumOfKID = lstNumOfKID[m_lstMonster[i]->m_nKID];
|
|
++lstNumOfKID[m_lstMonster[i]->m_nKID];
|
|
}
|
|
else
|
|
{
|
|
lstNumOfKID.insert(std::make_pair(m_lstMonster[i]->m_nKID, 0));
|
|
nNumOfKID = 0;
|
|
}
|
|
|
|
m_lstMonster[i]->m_dwCID = MONSTER_BIT + m_lstMonster[i]->m_nKID + (nNumOfKID << 16);
|
|
}
|
|
|
|
fprintf(fp, "0x%08x\t%d\t0x%08x\t%d\t%d\t%d\t%d\t%d\t%d\n",
|
|
m_lstMonster[i]->m_dwCID, m_lstMonster[i]->m_nKID, pid,
|
|
m_lstMonster[i]->m_nPosX, m_lstMonster[i]->m_nPosY, m_lstMonster[i]->m_nPosZ,
|
|
m_lstMonster[i]->m_bScout, m_lstMonster[i]->m_nMovingPattern, m_lstMonster[i]->m_wRespawnArea);
|
|
|
|
Sleep(0);
|
|
}
|
|
|
|
lstNumOfKID.clear();
|
|
fclose(fp);
|
|
|
|
::AfxMessageBox("스크립트 작성이 완료되었습니다.");
|
|
}
|
|
|
|
void CArrangement2Dlg::LoadScript(void)
|
|
{
|
|
char MonsterProtoTypeFileName[MAX_PATH] = ".\\MonsterProtoType.txt";
|
|
char ArrangementFileName[MAX_PATH] = ".\\Arrangement";
|
|
|
|
switch (m_nLoadedZone)
|
|
{
|
|
case ID__ZONE1: strcat(ArrangementFileName, "1.txt"); break;
|
|
case ID__ZONE2: strcat(ArrangementFileName, "2.txt"); break;
|
|
case ID__ZONE3: strcat(ArrangementFileName, "3.txt"); break;
|
|
case ID__ZONE4: strcat(ArrangementFileName, "4.txt"); break;
|
|
case ID__ZONE5: strcat(ArrangementFileName, "5.txt"); break;
|
|
case ID__ZONE8: strcat(ArrangementFileName, "8.txt"); break;
|
|
case ID__ZONE9: strcat(ArrangementFileName, "9.txt"); break;
|
|
case ID__ZONE12: strcat(ArrangementFileName, "12.txt"); break;
|
|
case ID__ZONE16: strcat(ArrangementFileName, "16.txt"); break;
|
|
case ID__ZONE100: strcat(ArrangementFileName, "100.txt"); break;
|
|
default:
|
|
::AfxMessageBox("Arrangement Script 파일 이름을 설정할\n존 ID가 잘못되었습니다.");
|
|
return;
|
|
}
|
|
|
|
CDelimitedFile DelimitedFile;
|
|
|
|
// 몬스터 프로토 타입 파일을 읽어들인다.
|
|
if (DelimitedFile.Open(MonsterProtoTypeFileName) == FALSE)
|
|
{
|
|
::AfxMessageBox("MonsterProtoType.txt 파일이 없습니다.");
|
|
return;
|
|
}
|
|
|
|
int nWasteBasket = 0;
|
|
MonsterInfo tempMonsterInfo;
|
|
|
|
while (DelimitedFile.ReadLine())
|
|
{
|
|
memset(&tempMonsterInfo, 0, sizeof(MonsterInfo));
|
|
|
|
DelimitedFile.ReadData(tempMonsterInfo.m_nKID);
|
|
DelimitedFile.ReadString((LPSTR)(LPCTSTR)tempMonsterInfo.m_strName, MAX_STRING_LENGTH);
|
|
|
|
DelimitedFile.ReadData(nWasteBasket); // 형태 플래그
|
|
DelimitedFile.ReadData(nWasteBasket); // LOD 여부
|
|
DelimitedFile.ReadData(nWasteBasket); // Nation
|
|
|
|
DelimitedFile.ReadString((LPSTR)(LPCTSTR)tempMonsterInfo.m_strClass, MAX_STRING_LENGTH);
|
|
|
|
for (int i=0; i<14; i++)
|
|
{
|
|
DelimitedFile.ReadData(nWasteBasket);
|
|
}
|
|
|
|
DelimitedFile.ReadString((LPSTR)(LPCTSTR)tempMonsterInfo.m_strLevel, MAX_STRING_LENGTH);
|
|
|
|
m_lstMonsterInfo[tempMonsterInfo.m_nKID] = tempMonsterInfo;
|
|
}
|
|
|
|
DelimitedFile.Close();
|
|
|
|
|
|
std::vector<int> kidList;
|
|
kidList.reserve(m_lstMonsterInfo.size());
|
|
|
|
MonsterInfoList::iterator pos_monlist = m_lstMonsterInfo.begin();
|
|
MonsterInfoList::iterator end_monlist = m_lstMonsterInfo.end();
|
|
|
|
for(;pos_monlist != end_monlist; ++pos_monlist)
|
|
{
|
|
kidList.push_back(pos_monlist->first);
|
|
}
|
|
|
|
char szKID[MAX_PATH];
|
|
|
|
std::sort(kidList.begin(), kidList.end(), std::less<int>());
|
|
|
|
std::vector<int>::const_iterator pos = kidList.begin();
|
|
std::vector<int>::const_iterator end = kidList.end();
|
|
|
|
for(;pos != end; ++pos)
|
|
{
|
|
int nKID = *pos;
|
|
int nInsertIndex = m_ctrKIDCombo.GetCount();
|
|
|
|
_snprintf(szKID, MAX_PATH - 1, "%d(%s)",
|
|
nKID, m_lstMonsterInfo[nKID].m_strName);
|
|
szKID[MAX_PATH - 1] = 0;
|
|
|
|
m_ctrKIDCombo.InsertString(nInsertIndex, szKID);
|
|
m_ctrKIDCombo.SetItemData(nInsertIndex, nKID);
|
|
}
|
|
|
|
// Arrangement 파일을 읽어들인다.
|
|
if (DelimitedFile.Open(ArrangementFileName, 1) == FALSE)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int nOldKID = 0xFFFF;
|
|
while (DelimitedFile.ReadLine())
|
|
{
|
|
Monster* tempMonster = new Monster;
|
|
|
|
char strTemp[MAX_PATH];
|
|
DelimitedFile.ReadString(strTemp, MAX_PATH); // CID
|
|
unsigned long dwCID = Math::Convert::Atoi(strTemp);
|
|
DelimitedFile.ReadData(tempMonster->m_nKID); // KID
|
|
|
|
if (nOldKID != tempMonster->m_nKID)
|
|
{
|
|
CalculateNumOfKID(tempMonster->m_nKID);
|
|
nOldKID = tempMonster->m_nKID;
|
|
}
|
|
|
|
tempMonster->m_dwCID = 0;
|
|
DelimitedFile.ReadString(strTemp, MAX_PATH);
|
|
tempMonster->m_nPID = static_cast<int>(Math::Convert::Atoi(strTemp) & ~MONSTER_PARTY_BIT);
|
|
|
|
DelimitedFile.ReadData(tempMonster->m_nPosX);
|
|
DelimitedFile.ReadData(tempMonster->m_nPosY);
|
|
DelimitedFile.ReadData(tempMonster->m_nPosZ);
|
|
DelimitedFile.ReadData(tempMonster->m_bScout);
|
|
DelimitedFile.ReadData(tempMonster->m_nMovingPattern);
|
|
DelimitedFile.ReadData(tempMonster->m_wRespawnArea);
|
|
|
|
MonsterInfoList::iterator itr = m_lstMonsterInfo.find(tempMonster->m_nKID);
|
|
if (itr != m_lstMonsterInfo.end())
|
|
{
|
|
tempMonster->m_nLevel = atoi( (itr->second).m_strLevel );
|
|
}
|
|
|
|
m_lstMonster.push_back(tempMonster);
|
|
|
|
++m_nNumOfKID;
|
|
|
|
// 석상이라면...
|
|
if (IsStatue(tempMonster->m_nKID))
|
|
{
|
|
m_mapStatueID.insert( std::make_pair( sStatueKey(tempMonster->m_nPosX, tempMonster->m_nPosZ), dwCID ) ).second ;
|
|
}
|
|
}
|
|
|
|
DelimitedFile.Close();
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// 정보 표시
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
void CArrangement2Dlg::OnBnClickedVisualkid()
|
|
{
|
|
UpdateData(TRUE);
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnBnClickedVisualpid()
|
|
{
|
|
UpdateData(TRUE);
|
|
Invalidate(FALSE);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnCbnSelchangeKidcombo()
|
|
{
|
|
UpdateData(TRUE);
|
|
|
|
// 이 종류의 몬스터 개체수.
|
|
int nKID = static_cast<int>(m_ctrKIDCombo.GetItemData(m_ctrKIDCombo.GetCurSel()));
|
|
|
|
CalculateNumOfKID(nKID);
|
|
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CArrangement2Dlg::OnCbnSelchangePidcombo()
|
|
{
|
|
UpdateData(TRUE);
|
|
|
|
// 선택된 PID 설정
|
|
m_nPID = static_cast<int>(m_ctrPIDCombo.GetItemData(m_ctrPIDCombo.GetCurSel()));
|
|
|
|
CalculateNumOfPID();
|
|
UpdateData(FALSE);
|
|
}
|
|
|
|
void CArrangement2Dlg::CalculateNumOfKID(int nKID)
|
|
{
|
|
m_nNumOfKID = 0;
|
|
|
|
MonsterInfoList::iterator pos_moninfo = m_lstMonsterInfo.find(nKID);
|
|
MonsterInfoList::iterator end_moninfo = m_lstMonsterInfo.end();
|
|
|
|
if(pos_moninfo != end_moninfo)
|
|
{
|
|
const MonsterInfo& monsterInfo = pos_moninfo->second;
|
|
|
|
m_strName = monsterInfo.m_strName;
|
|
m_strLevel = monsterInfo.m_strLevel;
|
|
m_strClass = monsterInfo.m_strClass;
|
|
|
|
MonsterList::const_iterator pos_mon = m_lstMonster.begin();
|
|
MonsterList::const_iterator end_mon = m_lstMonster.end();
|
|
|
|
for(; pos_mon != end_mon; ++pos_mon)
|
|
{
|
|
if(nKID == (*pos_mon)->m_nKID)
|
|
{
|
|
++m_nNumOfKID;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_strName = m_strLevel = m_strClass = "NULL";
|
|
}
|
|
}
|
|
|
|
void CArrangement2Dlg::CalculateNumOfPID()
|
|
{
|
|
m_nPartyMemNum = 0;
|
|
|
|
MonsterList::const_iterator pos_mon = m_lstMonster.begin();
|
|
MonsterList::const_iterator end_mon = m_lstMonster.end();
|
|
|
|
for(; pos_mon != end_mon; ++pos_mon)
|
|
{
|
|
if (m_nPID == (*pos_mon)->m_nPID && m_nPID != 0)
|
|
{
|
|
++m_nPartyMemNum;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CArrangement2Dlg::OnAppExit()
|
|
{
|
|
// TODO: 여기에 명령 처리기 코드를 추가합니다.
|
|
int ret = ::AfxMessageBox("정말로 종료하시겠습니까?", MB_YESNO);
|
|
if (ret == IDYES)
|
|
{
|
|
DestroyWindow();
|
|
}
|
|
}
|
|
|
|
BOOL CArrangement2Dlg::IsStatue(unsigned short wKID) CONST
|
|
{
|
|
if (wKID >= MIN_STATUE_KID && wKID <= MAX_STATUE_KID)
|
|
{
|
|
return TRUE ;
|
|
}
|
|
|
|
return FALSE ;
|
|
}
|
|
void CArrangement2Dlg::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CDialog::OnSize(nType, cx, cy);
|
|
|
|
// TODO: 여기에 메시지 처리기 코드를 추가합니다.
|
|
/*m_nNextX = cx;
|
|
m_nNextY = cy;
|
|
|
|
if(0 != m_nPrevX || 0 != m_nPrevY)
|
|
{
|
|
m_nGapX = m_nNextX - m_nPrevX;
|
|
m_nGapY = m_nNextY - m_nPrevY;
|
|
}
|
|
|
|
m_dwPageX = cx - 300;
|
|
m_dwPageZ = cy;
|
|
|
|
CDialog *pDialog;
|
|
this->GetWindowRect(&m_rectWindow);
|
|
|
|
CButton* pButton = NULL;
|
|
CStatic* pStatic = NULL;
|
|
CEdit* pEdit = NULL;
|
|
CComboBox* pComboBox = NULL;
|
|
CCheckListBox* pCheckBox = NULL;
|
|
|
|
pButton = static_cast<CButton*> (GetDlgItem(IDC_CREATESCRIPT));
|
|
SetObjectPos(pButton);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATIC1));
|
|
SetObjectPos(pStatic);
|
|
|
|
pButton = static_cast<CButton*> (GetDlgItem(IDC_ARRANGEMENT));
|
|
SetObjectPos(pButton);
|
|
|
|
pButton = static_cast<CButton*> (GetDlgItem(IDC_ERASE));
|
|
SetObjectPos(pButton);
|
|
|
|
pButton = static_cast<CButton*> (GetDlgItem(IDC_GROUP));
|
|
SetObjectPos(pButton);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATIC2));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICKID));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICNAME));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICLEVEL));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICCLASS));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICOBJNUM));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICRESPAWN));
|
|
SetObjectPos(pStatic);
|
|
|
|
pComboBox = static_cast<CComboBox*> (GetDlgItem(IDC_KIDCOMBO));
|
|
SetObjectPos(pComboBox);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_NAME));
|
|
SetObjectPos(pEdit);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_LEVEL));
|
|
SetObjectPos(pEdit);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_CLASS));
|
|
SetObjectPos(pEdit);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_NUMOFKID));
|
|
SetObjectPos(pEdit);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_RESPAWNEDIT));
|
|
SetObjectPos(pEdit);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATIC3));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICPID));
|
|
SetObjectPos(pStatic);
|
|
|
|
pComboBox = static_cast<CComboBox*> (GetDlgItem(IDC_PIDCOMBO));
|
|
SetObjectPos(pComboBox);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_PARTYMEM_NUM));
|
|
SetObjectPos(pEdit);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATIC4));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATIC5));
|
|
SetObjectPos(pStatic);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICX));
|
|
SetObjectPos(pStatic);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_POSITIONX));
|
|
SetObjectPos(pEdit);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICZ));
|
|
SetObjectPos(pStatic);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_POSITIONZ));
|
|
SetObjectPos(pEdit);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATICMONTNUM));
|
|
SetObjectPos(pStatic);
|
|
|
|
pEdit = static_cast<CEdit*> (GetDlgItem(IDC_NUMINWORLD));
|
|
SetObjectPos(pEdit);
|
|
|
|
pStatic = static_cast<CStatic*> (GetDlgItem(IDC_STATIC6));
|
|
SetObjectPos(pStatic);
|
|
|
|
pCheckBox = static_cast<CCheckListBox*> (GetDlgItem(IDC_STATICMONTNUM));
|
|
SetObjectPos(pCheckBox);
|
|
|
|
pCheckBox = static_cast<CCheckListBox*> (GetDlgItem(IDC_VISUALKID));
|
|
SetObjectPos(pCheckBox);
|
|
|
|
pCheckBox = static_cast<CCheckListBox*> (GetDlgItem(IDC_VISUALLEVEL));
|
|
SetObjectPos(pCheckBox);
|
|
|
|
pCheckBox = static_cast<CCheckListBox*> (GetDlgItem(IDC_VISUALPID));
|
|
SetObjectPos(pCheckBox);
|
|
|
|
m_nPrevX = m_nNextX;
|
|
m_nPrevY = m_nNextY;
|
|
|
|
Invalidate();*/
|
|
}
|
|
|
|
template <class T>
|
|
void CArrangement2Dlg::SetObjectPos(T* pObject)
|
|
{
|
|
RECT rectObject;
|
|
|
|
if(NULL != pObject)
|
|
{
|
|
pObject->GetWindowRect(&rectObject);
|
|
pObject->SetWindowPos(NULL,
|
|
rectObject.left, rectObject.top,
|
|
0, 0, SWP_NOSIZE|SW_SHOW);
|
|
}
|
|
}
|