mirror of https://github.com/AbePralle/FGB.git
1659 lines
46 KiB
C++
1659 lines
46 KiB
C++
// MapWin.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "LevelEditor.h"
|
|
#include "MapWin.h"
|
|
#include "Controls.h"
|
|
#include "ChildView.h"
|
|
#include <strstrea.h>
|
|
#include <fstream.h>
|
|
#include "MainFrm.h"
|
|
#include <iomanip.h>
|
|
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#include "ChildView.h"
|
|
#include "Controls.h"
|
|
#include "WayPointList.h"
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMapWin
|
|
|
|
CMapWin::CMapWin()
|
|
{
|
|
|
|
// Member initializations
|
|
showGrids = false;
|
|
backgroundColor = 0x808080;
|
|
gridColor = 0x0000ff;
|
|
curTile = 0;
|
|
for(int i=0;i<256;i++)
|
|
for(int j=0;j<256;j++)
|
|
envArray[i][j].index = 0;
|
|
|
|
totalTilesUsed = 1;
|
|
for(i=0;i<=256;i++)
|
|
listOfTilesUsed[i] = -1;
|
|
for(i=0;i<65536;i++)
|
|
listOfAllTiles[i] = 0;
|
|
|
|
lmb_isDown = rmb_isDown = 0;
|
|
drawingPath = 0;
|
|
selectedZone = 1;
|
|
pathStartX = pathStartY = 0;
|
|
|
|
clearLevel();
|
|
|
|
gkWinShape buffer;
|
|
buffer.LoadBMP("exitTiles.bmp");
|
|
for(i=0; i<7; i++){
|
|
exitTiles[i+1].GetShape(&buffer,i*16,0,16,16);
|
|
exitTiles[i+1].SetAlpha(192);
|
|
}
|
|
copyWidth = copyHeight = 0;
|
|
}
|
|
|
|
CMapWin::~CMapWin()
|
|
{
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CMapWin, CWnd)
|
|
//{{AFX_MSG_MAP(CMapWin)
|
|
ON_WM_PAINT()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_ERASEBKGND()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_SIZE()
|
|
ON_WM_HSCROLL()
|
|
ON_WM_VSCROLL()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_RBUTTONUP()
|
|
ON_WM_KEYDOWN()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CMapWin message handlers
|
|
|
|
void CMapWin::OnPaint()
|
|
{
|
|
//MODIFIED 12.30.1999 ABE
|
|
CPaintDC realdc(this); // device context for painting
|
|
|
|
//get client window size MOVED 12.30.1999 ABE
|
|
CRect rect;
|
|
::GetClientRect(this->m_hWnd,&rect);
|
|
|
|
//NEW 12.30.1999 ABE
|
|
//variables for double-buffering
|
|
//static CBitmap backbuffer;
|
|
static int backbufferWidth=0, backbufferHeight=0, needSetup=1;
|
|
static gkWinShape tileBuffer;
|
|
static gkWinShape wayPoint;
|
|
|
|
if(needSetup){
|
|
//Create orange dot waypoint
|
|
needSetup = 0;
|
|
wayPoint.Create(16,16);
|
|
wayPoint.Cls();
|
|
wayPoint.RectFill(5,5,6,6,gkRGB(255,128,0));
|
|
wayPoint.SetColorAlpha(gkRGB(0,0,0), 0);
|
|
}
|
|
|
|
//check to see if we need to (re)create bitmap
|
|
if(backbufferWidth < rect.Width() || backbufferHeight < rect.Height()){
|
|
backbufferWidth = rect.Width();
|
|
backbufferHeight = rect.Height();
|
|
//if(backbuffer.GetSafeHandle() != 0){
|
|
// backbuffer.DeleteObject();
|
|
//}
|
|
//backbuffer.CreateCompatibleBitmap(&realdc, backbufferWidth, backbufferHeight);
|
|
tileBuffer.Create(backbufferWidth, backbufferHeight);
|
|
}
|
|
|
|
//create a temporary device context & select the bitmap into it for drawing
|
|
//CDC dc;
|
|
//dc.CreateCompatibleDC(0);
|
|
//CBitmap *oldBitmap = (CBitmap*) dc.SelectObject(&backbuffer);
|
|
//END NEW
|
|
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
// how many tiles by X?
|
|
int numX;
|
|
//how many tiles by Y?
|
|
int numY;
|
|
|
|
numX = (rect.Width()>>4) + 1;
|
|
numY = (rect.Height()>>4) + 1;
|
|
|
|
//see how far the screen is scrolled over
|
|
int tileOff_x = controls->GetOffsetX() >> 4;
|
|
int tileOff_y = controls->GetOffsetY() >> 4;
|
|
|
|
//dc.FillSolidRect(0,0, rect.Width(), rect.Height(), backgroundColor);
|
|
tileBuffer.Cls(gkRGB(backgroundColor&0xff,(backgroundColor>>8)&0xff,
|
|
(backgroundColor>>16)&0xff));
|
|
|
|
//figure out how far to scoot each tile to the left because of scrolling
|
|
int pixOff_x = controls->GetOffsetX() & 15;
|
|
int pixOff_y = controls->GetOffsetY() & 15;
|
|
|
|
|
|
|
|
//go ahead and draw the environment tiles
|
|
|
|
//blit all the tiles to the tile backbuffer (to allow for transparency etc)
|
|
//then blit the tile backbuffer to the regular backbuffer
|
|
for(int i=0;i<numX;i++){
|
|
for(int j=0;j<numY;j++){
|
|
int ti = i+tileOff_x;
|
|
int tj = j+tileOff_y;
|
|
|
|
if(ti<0 || tj<0 || ti>=controls->GetMapWidth() || tj>=controls->GetMapHeight()){
|
|
continue;
|
|
}
|
|
|
|
int dx = (i<<4)-pixOff_x;
|
|
int dy = (j<<4)-pixOff_y;
|
|
|
|
if(controls->GetDrawingZones()==-1){
|
|
if(envArray[i+tileOff_x][j+tileOff_y].index){
|
|
//envArray[i+tileOff_x][j+tileOff_y].pic->
|
|
//BlitToDC(&dc,(i<<4)-pixOff_x,(j<<4)-pixOff_y);
|
|
envArray[ti][tj].pic->Blit(&tileBuffer, dx, dy, 0);
|
|
}
|
|
|
|
if(controls->GetDrawingExits()>0){ //overlay exit if necessary
|
|
if(exitArray[ti][tj])
|
|
exitTiles[exitArray[ti][tj]].Blit(&tileBuffer,dx,dy);
|
|
}else{
|
|
//flag too much open space
|
|
if(tooMuchOpenSpace[i+tileOff_x][j+tileOff_y]==1){
|
|
tileBuffer.RectFillAlpha(dx, dy, 16, 16, gkRGB(128,0,0), 128);
|
|
}
|
|
}
|
|
}else{
|
|
if(envArray[i+tileOff_x][j+tileOff_y].index){
|
|
//envArray[i+tileOff_x][j+tileOff_y].pic->
|
|
//BlitToDC(&dc,(i<<4)-pixOff_x,(j<<4)-pixOff_y);
|
|
envArray[ti][tj].pic->BlitHalfBrite(&tileBuffer, dx, dy, 0);
|
|
}
|
|
|
|
//blit the zone if necessary
|
|
if(controls->GetDrawingZones()>-1){
|
|
int color = CZoneList::GetZoneColor(zoneArray[ti][tj]);
|
|
//tileBuffer.RectFillAlpha(dx, dy, 16, 16, gkRGB(0,0,0), 128);
|
|
int r= color & 0xff;
|
|
int g = (color>>8) & 0xff;
|
|
int b = (color>>16) & 0xff;
|
|
tileBuffer.RectFillAlpha(dx, dy, 16, 16, gkRGB(r,g,b), 128);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
//draw WayPoints
|
|
if(controls->GetDrawingZones()>-1){
|
|
int nPoints = g_wayPointList.GetNumWayPoints();
|
|
|
|
int n;
|
|
for(n=1; n<=nPoints; n++){
|
|
int p = g_wayPointList.GetWayPoint(n);
|
|
|
|
int i = p & 0xff;
|
|
int j = (p>>8) & 0xff;
|
|
int dx = (i<<4) - controls->GetOffsetX();
|
|
int dy = (j<<4) - controls->GetOffsetY();
|
|
wayPoint.Blit(&tileBuffer, dx, dy);
|
|
}
|
|
}
|
|
|
|
// show grids if showGrids is true
|
|
if(showGrids){
|
|
|
|
//CPen gridPen;
|
|
//if(!gridPen.CreatePen(PS_SOLID,1,gridColor))
|
|
//{
|
|
// //doh!
|
|
// ::AfxMessageBox("Pen Creation Failed drawing grids", MB_OK);
|
|
// ::AfxAbort();
|
|
//}
|
|
|
|
gkRGB lineColor;
|
|
lineColor.SetR(gridColor & 0xff);
|
|
lineColor.SetG((gridColor>>8) & 0xff);
|
|
lineColor.SetB((gridColor>>16) & 0xff);
|
|
|
|
//save the old pen
|
|
//CPen* oldPen = dc.SelectObject(&gridPen);
|
|
|
|
int off_x = controls->GetOffsetX();
|
|
int off_y = controls->GetOffsetY();
|
|
|
|
//draw vertical lines
|
|
for(int i=0;i<(controls->GetMapWidth() + 1);i++)
|
|
{
|
|
tileBuffer.Line((i<<4)-off_x,0,(i<<4)-off_x,rect.Height(),lineColor);
|
|
//dc.MoveTo((i<<4)-off_x,0);
|
|
//dc.LineTo((i<<4)-off_x,rect.Height());
|
|
}
|
|
//draw Horizontal lines
|
|
for(i=0;i<(controls->GetMapHeight() + 1);i++)
|
|
{
|
|
tileBuffer.Line(0,(i<<4)-off_y,rect.Width(),(i<<4)-off_y,lineColor);
|
|
//dc.MoveTo(0, (i<<4)-off_y);
|
|
//dc.LineTo(rect.Width(), (i<<4)-off_y);
|
|
}
|
|
|
|
|
|
//reset old pen
|
|
//dc.SelectObject(oldPen);
|
|
|
|
}// end if(showGrids)
|
|
|
|
|
|
|
|
//if we're currently drawing a path then draw just the path so far
|
|
if(drawingPath){
|
|
this->DrawPath(selectedZone, drawingPath, tileBuffer);
|
|
}else{
|
|
//draw all the paths that originate at the selected zone
|
|
if(selectedZone && controls->GetDrawingZones()>-1){
|
|
int otherZone;
|
|
for(otherZone=1; otherZone<16; otherZone++){
|
|
int path = g_wayPointList.GetPath(selectedZone, otherZone);
|
|
if(path){
|
|
this->DrawPath(otherZone, path, tileBuffer);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//if we're doing a selection rectangle then draw that
|
|
if(drawingRect){
|
|
if(controls->GetDrawingZones()!=0){
|
|
int sx = min(rectStartX,rectEndX)<<4;
|
|
int sy = min(rectStartY,rectEndY)<<4;
|
|
int dx = (max(rectStartX,rectEndX)<<4)+15;
|
|
int dy = (max(rectStartY,rectEndY)<<4)+15;
|
|
sx -= controls->GetOffsetX();
|
|
dx -= controls->GetOffsetX();
|
|
sy -= controls->GetOffsetY();
|
|
dy -= controls->GetOffsetY();
|
|
gkRGB color = gkRGB(255,255,255);
|
|
int curZone = controls->GetDrawingZones();
|
|
if(curZone>0){
|
|
int c = CZoneList::GetZoneColor(curZone);
|
|
color.SetR(c&0xff);
|
|
color.SetG((c>>8)&0xff);
|
|
color.SetB((c>>16)&0xff);
|
|
}
|
|
tileBuffer.RectFillAlpha(sx,sy,(dx-sx)+1, (dy-sy)+1, color, 128);
|
|
}else{
|
|
//moving a waypoint
|
|
int sx = rectStartX<<4;
|
|
int sy = rectStartY<<4;
|
|
int dx = rectEndX<<4;
|
|
int dy = rectEndY<<4;
|
|
sx -= controls->GetOffsetX();
|
|
dx -= controls->GetOffsetX();
|
|
sy -= controls->GetOffsetY();
|
|
dy -= controls->GetOffsetY();
|
|
gkRGB color = gkRGB(255,255,255);
|
|
tileBuffer.Line(sx+7,sy+7,dx+7,dy+7,color);
|
|
wayPoint.Blit(&tileBuffer, dx, dy);
|
|
}
|
|
}
|
|
|
|
tileBuffer.BlitToDC(&realdc, 0, 0);
|
|
|
|
|
|
//NEW 12.30.1999 ABE
|
|
//Blit the backbuffer to the screen
|
|
//realdc.BitBlt(0,0,rect.Width(), rect.Height(), &dc, 0, 0, SRCCOPY);
|
|
|
|
//take bitmap out of temporary DC before the tempDC is destroyed
|
|
//dc.SelectObject(oldBitmap);
|
|
//END NEW
|
|
|
|
// Do not call CWnd::OnPaint() for painting messages
|
|
}
|
|
|
|
void CMapWin::SetGrids(bool on){
|
|
showGrids = on;
|
|
this->InvalidateRect(0);
|
|
}
|
|
|
|
|
|
BOOL CMapWin::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
// TODO: Add your message handler code here and/or call default
|
|
return true;
|
|
|
|
//return CWnd::OnEraseBkgnd(pDC);
|
|
}
|
|
|
|
|
|
int CMapWin::getBackgroundColor(){
|
|
return backgroundColor;
|
|
}
|
|
|
|
|
|
void CMapWin::setBackgroundColor(int color)
|
|
{
|
|
backgroundColor = color;
|
|
}
|
|
|
|
void CMapWin::setGridColor(int color)
|
|
{
|
|
gridColor = color;
|
|
}
|
|
|
|
void CMapWin::getEnvArray(PicStruct arg[256][256])
|
|
{
|
|
for(int i=0;i<256;i++)
|
|
for(int j=0;j<256;j++)
|
|
arg[i][j] = envArray[i][j];
|
|
}
|
|
unsigned char CMapWin::getTotalTilesUsed()
|
|
{
|
|
return totalTilesUsed;
|
|
}
|
|
|
|
short int* CMapWin::getListOfTilesUsed()
|
|
{
|
|
return listOfTilesUsed;
|
|
}
|
|
|
|
//load a level from the file
|
|
|
|
void CMapWin::loadLevel(char *str){
|
|
|
|
ifstream input(str, ios::in | ios::binary | ios::nocreate);
|
|
//unsigned char trash;//used to through away unnecessary info on reads
|
|
int i;
|
|
CControls *controls;
|
|
|
|
controls = (CControls*)(((CChildView*)this->GetParent())->GrabControls());
|
|
|
|
if(input.fail()){
|
|
this->MessageBox("Could not open file");
|
|
return;
|
|
}
|
|
|
|
//clear the current level
|
|
clearLevel();
|
|
|
|
// Member initializations
|
|
showGrids = false;
|
|
curTile = 0;
|
|
|
|
int firstCharacterID = (E_TILEBMPSIZEX >> 4) * (E_TILEBMPSIZEY >> 4);
|
|
|
|
int version = input.get() & 0xff;
|
|
//------------load in total classes used-----------------------
|
|
input.read(&totalTilesUsed, sizeof(unsigned char));
|
|
totalTilesUsed++;//must add 1 to compensate for 0 index
|
|
//--------------throw away 1rst character index----------------
|
|
int firstCharacterIndex = input.get() & 0xff;
|
|
int oldFirstID = (input.get() & 0xff);
|
|
oldFirstID |= (input.get() & 0xff) << 8;
|
|
|
|
//----------------read monster list into listOfTilesUsed-------
|
|
for(i=1;i<totalTilesUsed;i++){
|
|
input.read((char*)&(listOfTilesUsed[i]),sizeof(short int));
|
|
if(i>=firstCharacterIndex){
|
|
listOfTilesUsed[i] += (firstCharacterID - oldFirstID);
|
|
}
|
|
}
|
|
//-------------------set up listOfAllTiles----------------------
|
|
for(i=0;i<256;i++)
|
|
if(listOfTilesUsed[i] != -1)
|
|
listOfAllTiles[listOfTilesUsed[i]] = 1;
|
|
//----------------read level width-----------------------------
|
|
unsigned char width;
|
|
input.read(&width,sizeof(unsigned char));
|
|
controls->SetMapWidth(width);
|
|
//----------------get pitch-----------------------------
|
|
int pitch = input.get() & 0xff;
|
|
g_wayPointList.SetPitch(pitch);
|
|
//-----------------read level height---------------------------
|
|
unsigned char height;
|
|
input.read(&height,sizeof(unsigned char));
|
|
controls->SetMapHeight(height);
|
|
//-----------------read in level--------------------------------
|
|
for(i=0;i<height;i++)
|
|
for(int j=0;j<width;j++)
|
|
{
|
|
//input.read(&envArray[j][i].index,sizeof(unsigned char));
|
|
int index = input.get() & 0xff;
|
|
|
|
if(listOfTilesUsed[index]==-1) index = 0; //kludge to fix class -1 bug
|
|
envArray[j][i].index = index;
|
|
if(envArray[j][i].index)
|
|
envArray[j][i].pic = controls->GrabPicAt(listOfTilesUsed[envArray[j][i].index]);
|
|
}
|
|
//-------------------get the backgruond color-------------------
|
|
int bgByte0 = input.get() & 0xff;
|
|
int bgByte1 = input.get() & 0xff;
|
|
int bgColor = (bgByte1<<8) | bgByte0;
|
|
int bg_r = (bgColor & 0x1f) << 3;
|
|
int bg_g = ((bgColor>>5) & 0x1f) << 3;
|
|
int bg_b = ((bgColor>>10) & 0x1f) << 3;
|
|
backgroundColor = (bg_b << 16) | (bg_g << 8) | (bg_r);
|
|
|
|
g_wayPointList.Read(input);
|
|
|
|
ReadZones(input);
|
|
|
|
if(version>=2){
|
|
ReadExits(input);
|
|
}
|
|
|
|
if(version>=3){
|
|
//read links
|
|
input.get(); //1st link always null
|
|
input.get();
|
|
for(i=1; i<8; i++){
|
|
int n = (input.get() & 0xff);
|
|
n |= (input.get() & 0xff) << 8;
|
|
controls->links[i] = n;
|
|
}
|
|
}
|
|
|
|
//be a good poopy
|
|
input.close();
|
|
this->SetScrollBarPositions();
|
|
this->InvalidateRect(0);
|
|
FlagTooMuchOpenSpace();
|
|
|
|
}
|
|
|
|
//we need to remap all the monsters so that listOfTilesUsed is in decending order
|
|
void CMapWin::remapMonsters()
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
//----get the ID of the first monster--------------------------------
|
|
short int firstCharacterID;
|
|
firstCharacterID = (E_TILEBMPSIZEX >> 4) * (E_TILEBMPSIZEY >> 4);
|
|
|
|
//----initialize the sort data--------------------------------------
|
|
unsigned char tempArray[257];
|
|
SwapStruct SortMeArray[257];
|
|
int i,j;
|
|
|
|
for(i = 0; i<=256; i++)
|
|
{
|
|
SortMeArray[i].index = i;
|
|
SortMeArray[i].classID = listOfTilesUsed[i];
|
|
}
|
|
|
|
|
|
if(controls->GetSortClassesBy()==0){
|
|
//sort linear low to high
|
|
//--------------bubble sort here... hehehe -------------------------
|
|
|
|
for(i=0;i<=totalTilesUsed;i++)
|
|
{
|
|
for( j=0;j<(totalTilesUsed-1);j++)
|
|
{
|
|
if(SortMeArray[j].classID > SortMeArray[j+1].classID)
|
|
{//SWAP!!
|
|
SwapStruct tmp;
|
|
tmp.classID = SortMeArray[j].classID;
|
|
tmp.index = SortMeArray[j].index;
|
|
SortMeArray[j].classID = SortMeArray[j+1].classID;
|
|
SortMeArray[j].index = SortMeArray[j+1].index;
|
|
SortMeArray[j+1].classID = tmp.classID;
|
|
SortMeArray[j+1].index = tmp.index;
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
//keep same order except all monsters after all bg tiles
|
|
for(i=0;i<=totalTilesUsed;i++)
|
|
{
|
|
for( j=0;j<(totalTilesUsed-1);j++)
|
|
{
|
|
if(SortMeArray[j].classID>=firstCharacterID && SortMeArray[j+1].classID<firstCharacterID)
|
|
{//SWAP!!
|
|
SwapStruct tmp;
|
|
tmp.classID = SortMeArray[j].classID;
|
|
tmp.index = SortMeArray[j].index;
|
|
SortMeArray[j].classID = SortMeArray[j+1].classID;
|
|
SortMeArray[j].index = SortMeArray[j+1].index;
|
|
SortMeArray[j+1].classID = tmp.classID;
|
|
SortMeArray[j+1].index = tmp.index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------whew..that was a little embarrassing--------------------------
|
|
|
|
//Now we create a remapping array
|
|
for(i=0;i<257;i++)
|
|
{
|
|
listOfTilesUsed[i] = SortMeArray[i].classID;
|
|
tempArray[SortMeArray[i].index] = i;
|
|
}
|
|
|
|
|
|
//finally we loop through envArray and replace all the positions
|
|
for(i=0;i<controls->GetMapWidth();i++)
|
|
for(j=0;j<controls->GetMapHeight();j++)
|
|
if(envArray[i][j].index)
|
|
envArray[i][j].index = tempArray[envArray[i][j].index];
|
|
|
|
}
|
|
|
|
//Clear the level and start fresh...
|
|
void CMapWin::clearLevel()
|
|
{
|
|
// Member initializations
|
|
showGrids = false;
|
|
backgroundColor = 0x808080;
|
|
gridColor = 0x0000ff;
|
|
curTile = 0;
|
|
for(int i=0;i<256;i++){
|
|
for(int j=0;j<256;j++){
|
|
envArray[i][j].index = 0;
|
|
zoneArray[i][j] = 1;
|
|
exitArray[i][j] = 0;
|
|
}
|
|
}
|
|
|
|
totalTilesUsed = 1;
|
|
for(i=0;i<=256;i++)
|
|
listOfTilesUsed[i] = -1;
|
|
for(i=0;i<65536;i++)
|
|
listOfAllTiles[i] = 0;
|
|
|
|
drawingPath=0;
|
|
pathStartX=0;
|
|
pathStartY=0;
|
|
selectedZone=0;
|
|
drawingRect = 0;
|
|
|
|
g_wayPointList.Reset();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// Mouse Methods
|
|
//--------------------------------------------------------------------------
|
|
|
|
void CMapWin::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
rmb_isDown = 1;
|
|
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = (CControls*) view->GrabControls();
|
|
|
|
if(controls->GetDrawingZones()!=0){
|
|
this->EraseTile(point);
|
|
}else{
|
|
//screwing around with path stuff
|
|
CPoint tPoint = point;
|
|
tPoint.x += controls->GetOffsetX();
|
|
tPoint.y += controls->GetOffsetY();
|
|
|
|
int i = tPoint.x >> 4;
|
|
int j = tPoint.y >> 4;
|
|
|
|
if(i >= controls->GetMapWidth())
|
|
return;
|
|
if(j >= controls->GetMapHeight())
|
|
return;
|
|
|
|
if(drawingPath==0){
|
|
//start drawing a path?
|
|
if(!g_wayPointList.WayPointExists(i,j)){
|
|
pathStartX = i;
|
|
pathStartY = j;
|
|
selectedZone = zoneArray[i][j];
|
|
drawingPath = g_wayPointList.BeginPath(selectedZone);
|
|
}else{
|
|
//delete waypoint
|
|
g_wayPointList.RemoveWayPoint(i,j);
|
|
}
|
|
this->InvalidateRect(0);
|
|
}
|
|
}
|
|
|
|
CWnd::OnRButtonDown(nFlags, point);
|
|
}
|
|
|
|
|
|
void CMapWin::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
this->SetFocus();
|
|
|
|
lmb_isDown = 1;
|
|
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = (CControls*) view->GrabControls();
|
|
|
|
if(controls->GetDrawingZones()!=0){
|
|
if(::GetAsyncKeyState(VK_SHIFT) & 0x8000){
|
|
drawingRect = 1;
|
|
rectStartX = (point.x + controls->GetOffsetX()) >> 4;
|
|
rectStartY = (point.y + controls->GetOffsetY()) >> 4;
|
|
rectEndX = rectStartX;
|
|
rectEndY = rectStartY;
|
|
|
|
}else{
|
|
this->PlaceCurrentTile(point);
|
|
FlagTooMuchOpenSpace();
|
|
}
|
|
}else{
|
|
//make a waypoint or add to a path
|
|
|
|
//account for scrolling
|
|
CPoint tPoint = point;
|
|
tPoint.x += controls->GetOffsetX();
|
|
tPoint.y += controls->GetOffsetY();
|
|
|
|
int i = tPoint.x >> 4;
|
|
int j = tPoint.y >> 4;
|
|
|
|
|
|
if(i >= controls->GetMapWidth())
|
|
return;
|
|
if(j >= controls->GetMapHeight())
|
|
return;
|
|
|
|
if(drawingPath){
|
|
if(g_wayPointList.WayPointExists(i,j)){
|
|
g_wayPointList.AddWayPointToPath(i,j);
|
|
}else{
|
|
int pathnum = g_wayPointList.EndPath(zoneArray[i][j]);
|
|
if(::GetAsyncKeyState(VK_SHIFT) & 0x8000){ //make a new path
|
|
//make a separate path that is the same w/o last waypoint
|
|
int wpcount = 0;
|
|
if(g_wayPointList.GetFirstWayPoint(pathnum)>0){
|
|
wpcount++;
|
|
while(g_wayPointList.GetNextWayPoint(pathnum)>0) wpcount++;
|
|
}
|
|
drawingPath = g_wayPointList.BeginPath(selectedZone);
|
|
wpcount--;
|
|
|
|
if(wpcount>0){
|
|
g_wayPointList.AddWayPointToPath(
|
|
g_wayPointList.GetWayPoint(g_wayPointList.GetFirstWayPoint(pathnum)));
|
|
int x;
|
|
for(x=1; x<wpcount; x++){
|
|
g_wayPointList.AddWayPointToPath(
|
|
g_wayPointList.GetWayPoint(g_wayPointList.GetNextWayPoint(pathnum)));
|
|
}
|
|
}
|
|
}else{
|
|
drawingPath = 0;
|
|
}
|
|
}
|
|
}else{
|
|
if(::GetAsyncKeyState(VK_SHIFT) & 0x8000){
|
|
//move the waypoint?
|
|
drawingRect = 1;
|
|
rectStartX = rectEndX = i;
|
|
rectStartY = rectEndY = j;
|
|
}
|
|
|
|
g_wayPointList.CreateWayPoint(i,j);
|
|
}
|
|
|
|
this->InvalidateRect(0);
|
|
}
|
|
|
|
//CWnd::OnLButtonDown(nFlags, point);
|
|
}
|
|
|
|
|
|
void CMapWin::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CWnd::OnSize(nType, cx, cy);
|
|
|
|
this->SetScrollBarPositions();
|
|
this->InvalidateRect(0);
|
|
}
|
|
|
|
void CMapWin::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
{
|
|
SCROLLINFO scrollInfo;
|
|
scrollInfo.cbSize = sizeof(SCROLLINFO);
|
|
scrollInfo.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
|
|
this->GetScrollInfo(SB_HORZ, &scrollInfo, SIF_ALL);
|
|
int pos = this->GetScrollPos(SB_HORZ);
|
|
|
|
switch(nSBCode){
|
|
case SB_LEFT: //Scroll to far left.
|
|
pos = 0;
|
|
break;
|
|
case SB_ENDSCROLL: //End scroll.
|
|
break;
|
|
case SB_LINELEFT: //Scroll left.
|
|
pos -= 128;
|
|
break;
|
|
case SB_LINERIGHT: //Scroll right.
|
|
pos += 128;
|
|
break;
|
|
case SB_PAGELEFT: //Scroll one page left.
|
|
pos -= (scrollInfo.nPage * 3) / 4;
|
|
break;
|
|
case SB_PAGERIGHT: //Scroll one page right.
|
|
pos += (scrollInfo.nPage * 3) / 4;
|
|
break;
|
|
case SB_RIGHT: //Scroll to far right.
|
|
pos = scrollInfo.nMax;
|
|
break;
|
|
case SB_THUMBPOSITION: //Scroll to absolute position
|
|
case SB_THUMBTRACK:
|
|
pos = nPos;
|
|
break;
|
|
}
|
|
|
|
//adjust pos so it won't be out of bounds (looks nicer than letting win do it)
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
|
|
int mapWidth = controls->GetMapWidth() * 16;
|
|
CRect rect;
|
|
this->GetClientRect(&rect);
|
|
if(pos<0){
|
|
pos = 0;
|
|
}else if(pos + rect.Width() > mapWidth){
|
|
pos = mapWidth - rect.Width();
|
|
}
|
|
|
|
|
|
scrollInfo.nPos = pos;
|
|
this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask);
|
|
|
|
controls->SetOffsetX(pos);
|
|
this->InvalidateRect(0);
|
|
}
|
|
|
|
void CMapWin::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
{
|
|
SCROLLINFO scrollInfo;
|
|
scrollInfo.cbSize = sizeof(SCROLLINFO);
|
|
scrollInfo.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
|
|
this->GetScrollInfo(SB_VERT, &scrollInfo, SIF_ALL);
|
|
int pos = this->GetScrollPos(SB_VERT);
|
|
|
|
switch(nSBCode){
|
|
case SB_LEFT: //Scroll to far left.
|
|
pos = 0;
|
|
break;
|
|
case SB_ENDSCROLL: //End scroll.
|
|
break;
|
|
case SB_LINELEFT: //Scroll left.
|
|
pos -= 128;
|
|
break;
|
|
case SB_LINERIGHT: //Scroll right.
|
|
pos += 128;
|
|
break;
|
|
case SB_PAGELEFT: //Scroll one page left.
|
|
pos -= (scrollInfo.nPage * 3) / 4;
|
|
break;
|
|
case SB_PAGERIGHT: //Scroll one page right.
|
|
pos += (scrollInfo.nPage * 3) / 4;
|
|
break;
|
|
case SB_RIGHT: //Scroll to far right.
|
|
pos = scrollInfo.nMax;
|
|
break;
|
|
case SB_THUMBPOSITION: //Scroll to absolute position
|
|
case SB_THUMBTRACK:
|
|
pos = nPos;
|
|
break;
|
|
}
|
|
|
|
//adjust pos so it won't be out of bounds (looks nicer than letting win do it)
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
|
|
int mapHeight = controls->GetMapHeight() * 16;
|
|
CRect rect;
|
|
this->GetClientRect(&rect);
|
|
if(pos<0){
|
|
pos = 0;
|
|
}else if(pos + rect.Height() > mapHeight){
|
|
pos = mapHeight - rect.Height();
|
|
}
|
|
|
|
|
|
scrollInfo.nPos = pos;
|
|
this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask);
|
|
|
|
controls->SetOffsetY(pos);
|
|
this->InvalidateRect(0);
|
|
|
|
CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
|
|
}
|
|
|
|
void CMapWin::SetScrollBarPositions()
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
CRect rect;
|
|
this->GetClientRect(&rect);
|
|
|
|
int mapWidth = (controls->GetMapWidth() * 16);
|
|
int mapHeight = (controls->GetMapHeight() * 16);
|
|
int extraWidth = rect.Width() - mapWidth;
|
|
int extraHeight = rect.Height() - mapHeight;
|
|
|
|
SCROLLINFO scrollInfo;
|
|
scrollInfo.cbSize = sizeof(SCROLLINFO);
|
|
|
|
if(extraWidth>=0){
|
|
//don't need the scroll bar
|
|
scrollInfo.fMask = SIF_POS | SIF_RANGE;
|
|
scrollInfo.nMin = scrollInfo.nMax = scrollInfo.nPos = 0;
|
|
this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask);
|
|
}else{
|
|
scrollInfo.fMask = SIF_RANGE | SIF_PAGE;
|
|
scrollInfo.nMin = 0;
|
|
scrollInfo.nMax = mapWidth;
|
|
scrollInfo.nPos = 0;
|
|
scrollInfo.nPage = rect.Width();
|
|
controls->SetOffsetX(this->GetScrollPos(SB_HORZ));
|
|
this->SetScrollInfo(SB_HORZ, &scrollInfo, scrollInfo.fMask);
|
|
|
|
}
|
|
|
|
if(extraHeight>=0){
|
|
scrollInfo.fMask = SIF_POS | SIF_RANGE;
|
|
scrollInfo.nMin = scrollInfo.nMax = scrollInfo.nPos = 0;
|
|
this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask);
|
|
}else{
|
|
scrollInfo.fMask = SIF_RANGE | SIF_PAGE;
|
|
scrollInfo.nMin = 0;
|
|
scrollInfo.nMax = mapHeight+15;
|
|
scrollInfo.nPos = 0;
|
|
scrollInfo.nPage = rect.Height();
|
|
controls->SetOffsetY(this->GetScrollPos(SB_VERT));
|
|
this->SetScrollInfo(SB_VERT, &scrollInfo, scrollInfo.fMask);
|
|
}
|
|
}
|
|
|
|
void CMapWin::PlaceCurrentTile(CPoint point)
|
|
{
|
|
|
|
|
|
CPoint originalPoint = point;
|
|
|
|
|
|
if(!::IsWindow(this->m_hWnd))
|
|
return;
|
|
|
|
//grab a pointer to the view
|
|
CChildView* papa;
|
|
papa = (CChildView*)this->GetParent();
|
|
CControls *controls = papa->GrabControls();
|
|
|
|
//account for scrolling
|
|
point.x += controls->GetOffsetX();
|
|
point.y += controls->GetOffsetY();
|
|
|
|
if((point.x>>4) >= controls->GetMapWidth())
|
|
return;
|
|
if((point.y>>4) >= controls->GetMapHeight())
|
|
return;
|
|
|
|
if(controls->GetDrawingZones()==-1){
|
|
if(controls->GetDrawingExits()==-1){
|
|
int index = controls->GrabCurTileIndex();
|
|
if(index==1){
|
|
EraseTile(originalPoint);
|
|
controls->SetCurTilePointer(1);
|
|
return;
|
|
}
|
|
|
|
int i,j;
|
|
int width = controls->metaWidth;
|
|
for(j=0; j<controls->metaHeight; j++){
|
|
for(i=0; i<width; i++){
|
|
CPoint newPoint(point.x+(i<<4),point.y+(j<<4));
|
|
PlaceTile(index + (width*j)+i, newPoint);
|
|
}
|
|
}
|
|
}else{
|
|
//drawing exits
|
|
exitArray[point.x>>4][point.y>>4] = controls->GetDrawingExits();
|
|
}
|
|
}else if(controls->GetDrawingZones()>0){
|
|
//drawing zones, not tiles:
|
|
int i = point.x>>4;
|
|
int j = point.y>>4;
|
|
zoneArray[i][j] = controls->GetDrawingZones();
|
|
}else{
|
|
//placing a waypoint
|
|
}
|
|
|
|
this->InvalidateRect(0);
|
|
}
|
|
|
|
void CMapWin::PlaceTile(int tileIndex, CPoint point)
|
|
{
|
|
//grab a pointer to the view
|
|
CChildView* papa;
|
|
papa = (CChildView*)this->GetParent();
|
|
CControls *controls = papa->GrabControls();
|
|
|
|
//lets see if we are placing a new tile
|
|
int whatsCurTile;
|
|
whatsCurTile = tileIndex;
|
|
|
|
int tileExists = listOfAllTiles[whatsCurTile];
|
|
if(controls->isWall){
|
|
int i;
|
|
for(i=0; i<16; i++){
|
|
if(!listOfAllTiles[whatsCurTile+i]) tileExists = 0;
|
|
}
|
|
}
|
|
|
|
if(!tileExists)
|
|
{//looks like this is a new one :-)
|
|
if(totalTilesUsed > 256 || (controls->isWall && totalTilesUsed > 256-15))
|
|
{//have we used 255 tiles yet?
|
|
this->MessageBox("You've used too many tiles Bitch Ass");
|
|
return;
|
|
}
|
|
|
|
if(!controls->isWall){
|
|
listOfTilesUsed[totalTilesUsed++] = whatsCurTile;
|
|
listOfAllTiles[whatsCurTile] = 1;
|
|
}else{
|
|
int i;
|
|
for(i=0; i<16; i++){
|
|
listOfTilesUsed[totalTilesUsed++] = whatsCurTile + i;
|
|
listOfAllTiles[whatsCurTile + i] = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// find game index of tile
|
|
int tempIndex;
|
|
for(int i = 0; i < totalTilesUsed; i++){
|
|
if(listOfTilesUsed[i] == whatsCurTile){
|
|
tempIndex = i;
|
|
}
|
|
}
|
|
|
|
int dx = point.x >> 4;
|
|
int dy = point.y >> 4;
|
|
|
|
//if part of a wall, change the drawn index based on surrounding similar walls
|
|
int offsetOriginal=0;
|
|
int offset = 0;
|
|
|
|
static int offsetRemap[16] =
|
|
{ 0, 12, 1, 13,
|
|
4, 8, 5, 9,
|
|
3, 15, 2, 14,
|
|
7, 11, 6, 10
|
|
};
|
|
|
|
static int offsetRemapBack[16] =
|
|
{ 0, 2, 10, 8,
|
|
4, 6, 14, 12,
|
|
5, 7, 15, 13,
|
|
1, 3, 11, 9
|
|
};
|
|
|
|
if(controls->isWall){
|
|
if(dy > 0 && (((envArray[dx][dy-1].index - tempIndex) | 15) == 15)) offset |= 1;
|
|
if(dx < controls->GetMapWidth()-1 && (((envArray[dx+1][dy].index - tempIndex) | 15)) == 15) offset |= 2;
|
|
if(dy < controls->GetMapHeight()-1 && (((envArray[dx][dy+1].index - tempIndex) | 15)) == 15) offset |= 4;
|
|
if(dx > 0 && (((envArray[dx-1][dy].index - tempIndex) | 15) == 15)) offset |= 8;
|
|
|
|
/*
|
|
{ 0, 2, 10, 8,
|
|
4, 6, 14, 12,
|
|
5, 7, 15, 13,
|
|
1, 3, 11, 9};
|
|
*/
|
|
|
|
offsetOriginal = offset;
|
|
offset = offsetRemap[offset];
|
|
}
|
|
|
|
//CHANGE grab real index from controls
|
|
envArray[dx][dy].index = (tempIndex+offset);
|
|
envArray[dx][dy].pic = papa->GrabControls()->GrabTilePointer(tileIndex+offset);
|
|
|
|
//make sure adjacent similar walls are modified accordingly
|
|
if(offsetOriginal & 1){
|
|
int off = offsetRemap[offsetRemapBack[envArray[dx][dy-1].index - tempIndex] | 4];
|
|
envArray[dx][dy-1].index = tempIndex + off;
|
|
envArray[dx][dy-1].pic = controls->GrabTilePointer(tileIndex + off);
|
|
}
|
|
if(offsetOriginal & 2){
|
|
int off = offsetRemap[offsetRemapBack[envArray[dx+1][dy].index - tempIndex] | 8];
|
|
envArray[dx+1][dy].index = tempIndex + off;
|
|
envArray[dx+1][dy].pic = controls->GrabTilePointer(tileIndex + off);
|
|
}
|
|
if(offsetOriginal & 4){
|
|
int off = offsetRemap[offsetRemapBack[envArray[dx][dy+1].index - tempIndex] | 1];
|
|
envArray[dx][dy+1].index = tempIndex + off;
|
|
envArray[dx][dy+1].pic = controls->GrabTilePointer(tileIndex + off);
|
|
}
|
|
if(offsetOriginal & 8){
|
|
int off = offsetRemap[offsetRemapBack[envArray[dx-1][dy].index - tempIndex] | 2];
|
|
envArray[dx-1][dy].index = tempIndex + off;
|
|
envArray[dx-1][dy].pic = controls->GrabTilePointer(tileIndex + off);
|
|
}
|
|
}
|
|
|
|
void CMapWin::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
lmb_isDown = 0;
|
|
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
if(drawingRect){
|
|
|
|
drawingRect = 0;
|
|
|
|
if(controls->GetDrawingZones()!=0){
|
|
{
|
|
int temp;
|
|
if(rectEndY < rectStartY){
|
|
temp = rectStartY;
|
|
rectStartY = rectEndY;
|
|
rectEndY = temp;
|
|
}
|
|
if(rectEndX < rectStartX){
|
|
temp = rectStartX;
|
|
rectStartX = rectEndX;
|
|
rectEndX = temp;
|
|
}
|
|
}
|
|
if(controls->areaSpecial==0){ //no special fx
|
|
//loop through every tile in the rect, drawing an item there
|
|
int i,j;
|
|
int lineToggle = 1;
|
|
for(j=rectStartY; j<=rectEndY; j+=controls->metaHeight){
|
|
int toggle = lineToggle;
|
|
lineToggle ^= 1;
|
|
for(i=rectStartX; i<=rectEndX; i+=controls->metaWidth){
|
|
CPoint curPoint;
|
|
if(!(::GetKeyState(VK_MENU) & 0x8000) || toggle){
|
|
curPoint.x = (i<<4) - controls->GetOffsetX();
|
|
curPoint.y = (j<<4) - controls->GetOffsetY();
|
|
PlaceCurrentTile(curPoint);
|
|
}
|
|
toggle ^= 1;
|
|
}
|
|
}
|
|
FlagTooMuchOpenSpace();
|
|
}else{
|
|
//do a special effect in the rect
|
|
|
|
//if paste force the rect to be at least as large as the copy size
|
|
if(controls->areaSpecial & 64){
|
|
int width = rectEndX - rectStartX + 1;
|
|
int height = rectEndY - rectStartY + 1;
|
|
if(width < copyWidth) width = copyWidth;
|
|
if(height < copyHeight) height = copyHeight;
|
|
rectEndX = rectStartX + width - 1;
|
|
rectEndY = rectStartY + height - 1;
|
|
}
|
|
|
|
//clip the rect first
|
|
if(rectStartX<0) rectStartX = 0;
|
|
if(rectStartY<0) rectStartY = 0;
|
|
if(rectEndX >= controls->GetMapWidth()) rectEndX = controls->GetMapWidth()-1;
|
|
if(rectEndY >= controls->GetMapHeight()) rectEndY = controls->GetMapHeight()-1;
|
|
|
|
int i,j;
|
|
picstruct temp;
|
|
|
|
if(controls->areaSpecial & 1){ //shift up
|
|
for(i=rectStartX; i<=rectEndX; i++){
|
|
temp = envArray[i][rectStartY];
|
|
for(j=rectStartY; j<rectEndY; j++){
|
|
envArray[i][j] = envArray[i][j+1];
|
|
}
|
|
envArray[i][rectEndY] = temp;
|
|
}
|
|
}
|
|
if(controls->areaSpecial & 2){ //shift right
|
|
for(j=rectStartY; j<=rectEndY; j++){
|
|
temp = envArray[rectEndX][j];
|
|
for(i=rectEndX; i>rectStartX; i--){
|
|
envArray[i][j] = envArray[i-1][j];
|
|
}
|
|
envArray[rectStartX][j] = temp;
|
|
}
|
|
}
|
|
if(controls->areaSpecial & 4){ //shift down
|
|
for(i=rectStartX; i<=rectEndX; i++){
|
|
temp = envArray[i][rectEndY];
|
|
for(j=rectEndY; j>rectStartY; j--){
|
|
envArray[i][j] = envArray[i][j-1];
|
|
}
|
|
envArray[i][rectStartY] = temp;
|
|
}
|
|
}
|
|
if(controls->areaSpecial & 8){ //shift left
|
|
for(j=rectStartY; j<=rectEndY; j++){
|
|
temp = envArray[rectStartX][j];
|
|
for(i=rectStartX; i<rectEndX; i++){
|
|
envArray[i][j] = envArray[i+1][j];
|
|
}
|
|
envArray[rectEndX][j] = temp;
|
|
}
|
|
}
|
|
|
|
|
|
int rectWidth = (rectEndX - rectStartX) + 1;
|
|
int rectHeight = (rectEndY - rectStartY) + 1;
|
|
|
|
if(controls->areaSpecial & 16){ //copy up (cut)
|
|
for(i=rectStartX; i<=rectEndX; i++){
|
|
for(j=rectStartY; j<=rectEndY; j++){
|
|
copyBuffer[i-rectStartX][j-rectStartY] = envArray[i][j];
|
|
envArray[i][j].index = 0;
|
|
}
|
|
}
|
|
copyWidth = rectEndX - rectStartX + 1;
|
|
copyHeight = rectEndY - rectStartY + 1;
|
|
}
|
|
if(controls->areaSpecial & 32){ //copy right (copy)
|
|
for(i=rectStartX; i<=rectEndX; i++){
|
|
for(j=rectStartY; j<=rectEndY; j++){
|
|
copyBuffer[i-rectStartX][j-rectStartY] = envArray[i][j];
|
|
}
|
|
}
|
|
copyWidth = rectEndX - rectStartX + 1;
|
|
copyHeight = rectEndY - rectStartY + 1;
|
|
}
|
|
if(controls->areaSpecial & 64){ //copy down (paste)
|
|
for(i=rectStartX; i<=rectEndX; i++){
|
|
for(j=rectStartY; j<=rectEndY; j++){
|
|
envArray[i][j] = copyBuffer[(i-rectStartX)%copyWidth][(j-rectStartY)%copyHeight];
|
|
}
|
|
}
|
|
}
|
|
if(controls->areaSpecial & 128){ //copy left
|
|
for(i=rectStartX; i<=rectEndX; i++){
|
|
for(j=rectStartY; j<=rectEndY; j++){
|
|
int di = i - rectWidth;
|
|
int dj = j;
|
|
if(di<0||dj<0||di>255||dj>255) continue;
|
|
|
|
envArray[di][dj] = envArray[i][j];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}else{
|
|
//moving waypoint
|
|
g_wayPointList.MoveWayPoint(rectStartX, rectStartY, rectEndX, rectEndY);
|
|
}
|
|
|
|
this->InvalidateRect(0);
|
|
this->FlagTooMuchOpenSpace();
|
|
}
|
|
|
|
CWnd::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CMapWin::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
CMainFrame *frame = (CMainFrame*) this->GetParentFrame();
|
|
|
|
if(lmb_isDown){
|
|
if(drawingRect){
|
|
rectEndX = (point.x + controls->GetOffsetX())>>4;
|
|
rectEndY = (point.y + controls->GetOffsetY())>>4;
|
|
this->InvalidateRect(0);
|
|
}else{
|
|
this->PlaceCurrentTile(point);
|
|
FlagTooMuchOpenSpace();
|
|
}
|
|
}else if(rmb_isDown){
|
|
this->EraseTile(point);
|
|
}else if(drawingPath){
|
|
this->InvalidateRect(0);
|
|
}
|
|
|
|
int i = (point.x + controls->GetOffsetX()) >> 4;
|
|
int j = (point.y + controls->GetOffsetY()) >> 4;
|
|
|
|
char st[80];
|
|
ostrstream stout(st,80);
|
|
stout << "(" << i << "," << j;
|
|
g_wayPointList.GetPitch();
|
|
stout << " / $" << (hex) << (0xd000 + (j * g_wayPointList.GetPitch()) + i);
|
|
stout << (dec) << ") index: " << envArray[i][j].index;
|
|
stout << " class: " << listOfTilesUsed[envArray[i][j].index];
|
|
stout << " zone: " << (int) zoneArray[i][j] << ends;
|
|
frame->ShowStatus(st);
|
|
|
|
CWnd::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
void CMapWin::EraseTile(CPoint point)
|
|
{
|
|
if(!::IsWindow(this->m_hWnd))
|
|
return;
|
|
//grab a pointer to the view
|
|
CControls *controls;
|
|
controls = (CControls*)(((CChildView*)this->GetParent())->GrabControls());
|
|
|
|
//account for scrolling
|
|
point.x += controls->GetOffsetX();
|
|
point.y += controls->GetOffsetY();
|
|
|
|
int i = point.x>>4;
|
|
int j = point.y>>4;
|
|
if(i>=0 && j>=0 && i<controls->GetMapWidth() && j<controls->GetMapHeight()){
|
|
if(controls->GetDrawingZones()==-1){
|
|
if(controls->GetDrawingExits()==-1){
|
|
int curIndex = envArray[i][j].index;
|
|
|
|
if(curIndex>0){
|
|
//set the current tile
|
|
controls->SetCurTilePointer(listOfTilesUsed[envArray[point.x>>4][point.y>>4].index]);
|
|
}
|
|
|
|
//reset index to zero
|
|
envArray[point.x>>4][point.y>>4].index = 0;
|
|
}else{
|
|
//erasing exits
|
|
exitArray[point.x>>4][point.y>>4] = 0;
|
|
}
|
|
}else if(!drawingPath){
|
|
//"erase" selects a zone when drawing zones
|
|
this->selectedZone = zoneArray[i][j];
|
|
this->pathStartX = i;
|
|
this->pathStartY = j;
|
|
}
|
|
}
|
|
|
|
this->InvalidateRect(0);
|
|
FlagTooMuchOpenSpace();
|
|
}
|
|
|
|
void CMapWin::OnRButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
rmb_isDown = 0;
|
|
|
|
CWnd::OnRButtonUp(nFlags, point);
|
|
}
|
|
|
|
void CMapWin::DrawPath(int destZone, int nPath, gkWinShape &tileBuffer)
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
int c = CZoneList::GetZoneColor(destZone);
|
|
gkRGB color(c&0xff, (c>>8)&0xff, (c>>16)&0xff);
|
|
int prev_i = pathStartX;
|
|
int prev_j = pathStartY;
|
|
int next_i;
|
|
int next_j;
|
|
//CPoint tempP;
|
|
//if(::GetCursorPos(&tempP)){
|
|
// if(tempP.x > 600) ASSERT(0);
|
|
// }
|
|
int afterFirst = 0;
|
|
int nextWP = g_wayPointList.GetFirstWayPoint(nPath);
|
|
while(nextWP){
|
|
|
|
int wp = g_wayPointList.GetWayPoint(nextWP);
|
|
next_i = wp & 0xff;
|
|
next_j = (wp>>8) & 0xff;
|
|
int si = (prev_i<<4) - controls->GetOffsetX() + (destZone&afterFirst);
|
|
int sj = (prev_j<<4) - controls->GetOffsetY() + (destZone&afterFirst);
|
|
int di = (next_i<<4) - controls->GetOffsetX() + destZone;
|
|
int dj = (next_j<<4) - controls->GetOffsetY() + destZone;
|
|
afterFirst = 0xffffffff;
|
|
|
|
tileBuffer.Line(si,sj,di,dj,color);
|
|
|
|
prev_i = next_i;
|
|
prev_j = next_j;
|
|
nextWP = g_wayPointList.GetNextWayPoint(nPath);
|
|
}
|
|
|
|
//connect to mouse if currently drawing
|
|
if(drawingPath){
|
|
CPoint mousePoint;
|
|
::GetCursorPos(&mousePoint);
|
|
this->ScreenToClient(&mousePoint);
|
|
|
|
int si = (prev_i<<4) - controls->GetOffsetX() + destZone;
|
|
int sj = (prev_j<<4) - controls->GetOffsetY() + destZone;
|
|
int di = mousePoint.x;
|
|
int dj = mousePoint.y;
|
|
|
|
tileBuffer.Line(si,sj,di,dj,color);
|
|
}
|
|
}
|
|
|
|
void CMapWin::WriteZones(ostream &out)
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
//pack the zone bytes 2:1
|
|
int compressed[128][256];
|
|
int i,j;
|
|
for(j=0; j<controls->GetMapHeight(); j++){
|
|
for(i=0; i<controls->GetMapWidth(); i+=2){
|
|
int byte1 = this->zoneArray[i][j] & 0x0f;
|
|
int byte2 = zoneArray[i+1][j] & 0x0f;
|
|
compressed[i/2][j] = (byte1<<4) | byte2;
|
|
}
|
|
}
|
|
|
|
//write out zone info using RLE
|
|
int numContinuous = 0;
|
|
int continuousByte = compressed[0][0];
|
|
for(j=0; j<controls->GetMapHeight(); j++){
|
|
for(i=0; i<(controls->GetMapWidth()>>1); i++){
|
|
if(compressed[i][j] == continuousByte){
|
|
numContinuous++;
|
|
}else{
|
|
out.put((char) numContinuous);
|
|
out.put((char) continuousByte);
|
|
continuousByte = compressed[i][j];
|
|
numContinuous = 1;
|
|
}
|
|
if(numContinuous == 256){
|
|
out.put((char) 255);
|
|
out.put((char) continuousByte);
|
|
numContinuous = 1;
|
|
}
|
|
}
|
|
}
|
|
out.put((char) numContinuous);
|
|
out.put((char) continuousByte);
|
|
// if(numContinuous != 0){
|
|
// out.put((char) 0);
|
|
// out.put((char) 0);
|
|
// }
|
|
}
|
|
|
|
void CMapWin::ReadZones(istream &in)
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
//reads & inflates zones stored using Run Lengh Encoding and compressed 2:1
|
|
int i,j,continuousByte,numContinuous;
|
|
|
|
int temp = in.tellg();
|
|
numContinuous = in.get() & 0xff;
|
|
if(in.eof()) return;
|
|
continuousByte = in.get() & 0xff;
|
|
|
|
for(j=0; j<controls->GetMapHeight(); j++){
|
|
for(i=0; i<controls->GetMapWidth(); i+=2){
|
|
if(!numContinuous){
|
|
numContinuous = in.get() & 0xff;
|
|
continuousByte = in.get() & 0xff;
|
|
}
|
|
zoneArray[i][j] = (continuousByte>>4) & 0x0f;
|
|
zoneArray[i+1][j] = continuousByte & 0x0f;
|
|
numContinuous--;
|
|
}
|
|
}
|
|
|
|
//in.get(); //junk null terminator
|
|
//in.get();
|
|
}
|
|
|
|
short int * CMapWin::getListOfAllTiles()
|
|
{
|
|
return this->listOfAllTiles;
|
|
}
|
|
|
|
void CMapWin::RemakeListOfTilesUsed()
|
|
{
|
|
//regenerates the tiles used list using the tiles from the map and the tiles
|
|
//in the list of all tiles. Called after the "classes used" dialog finishes.
|
|
|
|
//first off flag any of the classes used in the map in the "listOfAllClasses"
|
|
//and convert the map indices into actual classes
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
int i,j;
|
|
for(i=0; i<256; i++){
|
|
for(j=0; j<256; j++){
|
|
if(envArray[i][j].index){
|
|
if(i<controls->GetMapWidth() && j<controls->GetMapHeight()){
|
|
listOfAllTiles[listOfTilesUsed[envArray[i][j].index]] = 1;
|
|
envArray[i][j].index = listOfTilesUsed[envArray[i][j].index];
|
|
}else{
|
|
envArray[i][j].index = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//clear the list of tiles used
|
|
totalTilesUsed = 1;
|
|
for(i=0;i<=256;i++)
|
|
listOfTilesUsed[i] = -1;
|
|
|
|
//refresh the listOfTilesUsed from the listOfAllTiles
|
|
for(i=0; i<65536; i++){
|
|
if(listOfAllTiles[i]){
|
|
listOfTilesUsed[totalTilesUsed++] = i;
|
|
}
|
|
}
|
|
|
|
//remap each location in the map back to an index
|
|
for(i=0; i<256; i++){
|
|
for(j=0; j<256; j++){
|
|
int lookfor = envArray[i][j].index;
|
|
if(lookfor){
|
|
int n;
|
|
for(n=1; n<=totalTilesUsed; n++){
|
|
if(listOfTilesUsed[n]==lookfor){
|
|
envArray[i][j].index = n;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CMapWin::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
controls->SendToKeyDown(nChar,nRepCnt,nFlags);
|
|
|
|
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CMapWin::WriteExits(ostream &out)
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
//pack the exit bytes 2:1
|
|
int compressed[128][256];
|
|
int i,j;
|
|
for(j=0; j<controls->GetMapHeight(); j++){
|
|
for(i=0; i<controls->GetMapWidth(); i+=2){
|
|
int byte1 = this->exitArray[i][j] & 0x0f;
|
|
int byte2 = exitArray[i+1][j] & 0x0f;
|
|
compressed[i/2][j] = (byte1<<4) | byte2;
|
|
}
|
|
}
|
|
|
|
//int temp = out.tellp();
|
|
//char st[80];
|
|
//ostrstream stout(st,80);
|
|
//stout << temp << ends;
|
|
//this->MessageBox(st);
|
|
|
|
//write out exit info using RLE
|
|
int numContinuous = 0;
|
|
int continuousByte = compressed[0][0];
|
|
for(j=0; j<controls->GetMapHeight(); j++){
|
|
for(i=0; i<(controls->GetMapWidth()>>1); i++){
|
|
if(compressed[i][j] == continuousByte){
|
|
numContinuous++;
|
|
}else{
|
|
out.put((char) numContinuous);
|
|
out.put((char) continuousByte);
|
|
continuousByte = compressed[i][j];
|
|
numContinuous = 1;
|
|
}
|
|
if(numContinuous == 256){
|
|
out.put((char) 255);
|
|
out.put((char) continuousByte);
|
|
numContinuous = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
out.put((char) numContinuous);
|
|
out.put((char) continuousByte);
|
|
//if(numContinuous != 0){
|
|
//out.put((char) 0);
|
|
//out.put((char) 0);
|
|
//}
|
|
}
|
|
|
|
void CMapWin::ReadExits(istream &in)
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
|
|
//reads & inflates zones stored using Run Lengh Encoding and compressed 2:1
|
|
int i,j,continuousByte,numContinuous;
|
|
|
|
//int temp = in.tellg();
|
|
//char st[80];
|
|
//ostrstream stout(st,80);
|
|
//stout << temp << ends;
|
|
//this->MessageBox(st);
|
|
|
|
numContinuous = in.get() & 0xff;
|
|
if(in.eof()) return;
|
|
continuousByte = in.get() & 0xff;
|
|
|
|
for(j=0; j<controls->GetMapHeight(); j++){
|
|
for(i=0; i<controls->GetMapWidth(); i+=2){
|
|
if(!numContinuous){
|
|
numContinuous = in.get() & 0xff;
|
|
continuousByte = in.get() & 0xff;
|
|
}
|
|
exitArray[i][j] = (continuousByte>>4) & 0x0f;
|
|
exitArray[i+1][j] = continuousByte & 0x0f;
|
|
numContinuous--;
|
|
}
|
|
}
|
|
|
|
//in.get(); //junk null terminator
|
|
//in.get();
|
|
}
|
|
|
|
|
|
|
|
|
|
void CMapWin::FlagTooMuchOpenSpace()
|
|
{
|
|
CChildView *view = (CChildView*) this->GetParent();
|
|
CControls *controls = view->GrabControls();
|
|
int width = controls->GetMapWidth();
|
|
int height = controls->GetMapHeight();
|
|
|
|
int max_x = 18;
|
|
int max_y = 16;
|
|
|
|
int count, start_i, start_j;
|
|
int i,j;
|
|
|
|
//set all flags to zero
|
|
for(j=0; j<height; j++){
|
|
for(i=0; i<width; i++){
|
|
this->tooMuchOpenSpace[i][j] = 0;
|
|
}
|
|
}
|
|
|
|
//loop row by row
|
|
for(j=0; j<height; j++){
|
|
count = 0;
|
|
|
|
for(i=0; i<width; i++){
|
|
if(count==0){ //looking for first open space
|
|
if(envArray[i][j].index==0 || listOfTilesUsed[envArray[i][j].index]>=E_FIRSTOBJ){
|
|
start_i = i;
|
|
count++;
|
|
}
|
|
}else{
|
|
//continue finding open space
|
|
if(envArray[i][j].index==0 || listOfTilesUsed[envArray[i][j].index]>=E_FIRSTOBJ) count++;
|
|
else{
|
|
if(count > max_x){
|
|
while(start_i < i){
|
|
tooMuchOpenSpace[start_i++][j] = 1;
|
|
}
|
|
}
|
|
count = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//loop again column by column
|
|
for(i=0; i<width; i++){
|
|
count = 0;
|
|
for(j=0; j<height; j++){
|
|
if(count==0){ //looking for first open space
|
|
if(envArray[i][j].index==0 || listOfTilesUsed[envArray[i][j].index]>=E_FIRSTOBJ){
|
|
start_j = j;
|
|
count++;
|
|
}
|
|
}else{
|
|
//continue finding open space
|
|
if(envArray[i][j].index==0 || listOfTilesUsed[envArray[i][j].index]>=E_FIRSTOBJ) count++;
|
|
else{
|
|
if(count > max_y){
|
|
while(start_j < j){
|
|
tooMuchOpenSpace[i][start_j++] = 1;
|
|
}
|
|
}
|
|
count = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|