1 /***************************************************************************
2             mapeditor.cpp  -  The (not yet supported) map editor
3                              -------------------
4     begin                : Tue Jun 18 2005
5     copyright            : (C) 2005 by Gabor Torok
6     email                : cctorok@yahoo.com
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "common/constants.h"
19 #include "mapeditor.h"
20 #include "render/renderlib.h"
21 #include "rpg/rpglib.h"
22 #include "mapwidget.h"
23 #include "sdlhandler.h"
24 #include "scourge.h"
25 #include "partyeditor.h"
26 #include "item.h"
27 #include "creature.h"
28 #include "shapepalette.h"
29 #include "outdoorgenerator.h"
30 #include "dungeongenerator.h"
31 
32 using namespace std;
33 
34 #define OUTDOOR_TEXTURE_WIDTH 4
35 #define OUTDOOR_TEXTURE_DEPTH 4
36 
37 char *floorTypeName[2][80] = {
38 	{ "FLOOR_TILE", N_( "Tile: Passage" ) },
39 	{ "ROOM_FLOOR_TILE", N_( "Tile: Room" ) }
40 };
41 
42 /**
43   *@author Gabor Torok
44   */
45 
46 
47 /*
48   TODO:
49   - ability to "name" item, shape, creature. Then text file can reference name.
50   - need to call ShapePalette::decrementSkinRefCount() when closing map?
51 */
52 
contains(vector<Shape * > * seen,Shape * shape)53 bool contains( vector<Shape*> *seen, Shape *shape ) {
54 	for ( int i = 0; i < static_cast<int>( seen->size() ); i++ ) {
55 		if ( ( *seen )[i] == shape ) return true;
56 	}
57 	return false;
58 }
59 
MapEditor(Scourge * scourge)60 MapEditor::MapEditor( Scourge *scourge ) {
61 	this->scourge = scourge;
62 
63 	// default map settings
64 	level = 1;
65 	depth = 0;
66 
67 	outdoorTextureAngle = 0;
68 	outdoorTextureHorizFlip = outdoorTextureVertFlip = false;
69 
70 	mapSettings = new EditorMapSettings();
71 
72 	scourge->getMap()->setMapRenderHelper( MapRenderHelper::helpers[ MapRenderHelper::ROOM_HELPER ] );
73 
74 	createNewMapDialog();
75 
76 	scourge->getShapePalette()->loadAllShapes();
77 
78 	int w = 200;
79 	mainWin = new Window( scourge->getSDLHandler(),
80 	                      scourge->getScreenWidth() - w, 0,
81 	                      w, scourge->getScreenHeight(),
82 	                      _( "Map Editor" ), false, Window::BASIC_WINDOW,
83 	                      GuiTheme::DEFAULT_THEME );
84 	mainWin->setVisible( false );
85 	mainWin->setLocked( true );
86 
87 	int startx = 8;
88 	w -= 2;
89 
90 	int yy = 8;
91 	int ystep = 24;
92 
93 	mainWin->createLabel( 5, yy + 10, _( "Name:" ) );
94 	nameText = mainWin->createTextField( 60, yy, 10 );
95 	yy += ystep;
96 
97 	loadButton = mainWin->createButton( startx, yy, ( w - 10 ) / 2, yy + 20, _( "Load" ) );
98 	saveButton = mainWin->createButton( ( w - 10 ) / 2 + 5, yy, w - 5, yy + 20, _( "Save" ) );
99 	yy += ystep;
100 
101 	wallButton = mainWin->createButton( startx, yy, ( w - 10 ) / 2, yy + 20, _( "Wall" ), true );
102 	toggleButtonList.push_back( wallButton );
103 	wallButton->setSelected( true );
104 	doorButton = mainWin->createButton( ( w - 10 ) / 2 + 5, yy, w - 10, yy + 20, _( "Door" ), true );
105 	toggleButtonList.push_back( doorButton );
106 	yy += ystep;
107 
108 
109 
110 	newButton = mainWin->createButton( startx, yy, ( w - 10 ) / 2, yy + 20, _( "New Map" ) );
111 	floorType = mainWin->createButton( ( w - 10 ) / 2 + 5, yy, w - 10, yy + 20, _( floorTypeName[ 1 ][ 1 ] ), true );
112 	yy += ystep;
113 
114 	startPosButton = mainWin->createButton( startx, yy, ( w - 10 ) / 2, yy + 20, _( "Start Pos" ), true );
115 	toggleButtonList.push_back( startPosButton );
116 	yy += ystep;
117 
118 	rugButton = mainWin->createButton( startx, yy, ( w - 10 ) / 2, yy + 20, _( "Rug" ), true );
119 	toggleButtonList.push_back( rugButton );
120 	secretButton = mainWin->createButton( ( w - 10 ) / 2 + 5, yy, w - 10, yy + 20, _( "Secret" ), true );
121 	toggleButtonList.push_back( secretButton );
122 	yy += ystep;
123 	trapButton = mainWin->createButton( startx, yy, ( w - 10 ) / 2, yy + 20, _( "Trap" ), true );
124 	toggleButtonList.push_back( trapButton );
125 	roofButton = mainWin->createButton( ( w - 10 ) / 2 + 5, yy, w - 10, yy + 20, _( "Show Roofs" ), true );
126 	roofButton->setSelected( true );
127 	//toggleButtonList.push_back( roofButton );
128 	yy += ystep;
129 
130 	lowerButton = mainWin->createButton( startx, yy, ( w - 10 ) / 2, yy + 20, _( "Lower" ), true );
131 	toggleButtonList.push_back( lowerButton );
132 	lowerButton->setSelected( false );
133 	lowerButton->setEnabled( false );
134 	raiseButton = mainWin->createButton( ( w - 10 ) / 2 + 5, yy, w - 10, yy + 20, _( "Raise" ), true );
135 	toggleButtonList.push_back( raiseButton );
136 	raiseButton->setSelected( false );
137 	raiseButton->setEnabled( false );
138 	yy += ystep;
139 
140 
141 	// Lists
142 	vector<Shape*> seen;
143 
144 	// items
145 	itemButton = mainWin->createButton( startx, yy, w - 10, yy + 20, _( "Item" ), true );
146 	toggleButtonList.push_back( itemButton );
147 	yy += ystep;
148 	itemList = new ScrollingList( startx, yy, w - 16, 75,
149 	                              scourge->getShapePalette()->getHighlightTexture() );
150 	mainWin->addWidget( itemList );
151 	yy += 79;
152 
153 
154 	furnitureButton = mainWin->createButton( startx, yy, w - 10, yy + 20, _( "Furniture" ), true );
155 	toggleButtonList.push_back( furnitureButton );
156 	yy += ystep;
157 	furnitureList = new ScrollingList( startx, yy, w - 16, 75,
158 	    scourge->getShapePalette()->getHighlightTexture() );
159 	mainWin->addWidget( furnitureList );
160 	yy += 79;
161 
162 	// separate items from furniture
163 	map<string, const RpgItem *> *itemMap = RpgItem::getItemMap();
164 	vector<RpgItem*> itemVector;
165 	vector<RpgItem*> furnitureVector;
166 	for ( map<string, const RpgItem*>::iterator i = itemMap->begin();
167 	        i != itemMap->end(); ++i ) {
168 		string name = i->first;
169 		RpgItem *item = ( RpgItem* )( i->second );
170 		Shape *shape = scourge->getShapePalette()->getShape( item->getShapeIndex() );
171 		seen.push_back( shape );
172 		if ( item->isContainer() || item->isOther() ) {
173 			furnitureVector.push_back( item );
174 		} else {
175 			itemVector.push_back( item );
176 		}
177 	}
178 
179 	itemNames = new string[ itemVector.size() ];
180 	for ( unsigned int i = 0; i < itemVector.size(); i++ ) {
181 		itemNames[ i ] = itemVector[ i ]->getDisplayName();
182 	}
183 	itemList->setLines( itemVector.size(), itemNames );
184 
185 	furnitureNames = new string[ furnitureVector.size() ];
186 	for ( unsigned int i = 0; i < furnitureVector.size(); i++ ) {
187 		furnitureNames[ i ] = furnitureVector[ i ]->getDisplayName();
188 	}
189 	furnitureList->setLines( furnitureVector.size(), furnitureNames );
190 
191 	// creatures
192 	creatureButton = mainWin->createButton( startx, yy, w - 10, yy + 20, _( "Creature" ), true );
193 	toggleButtonList.push_back( creatureButton );
194 	yy += ystep;
195 	creatureList = new ScrollingList( startx, yy, w - 16, 75,
196 	    scourge->getShapePalette()->getHighlightTexture() );
197 	mainWin->addWidget( creatureList );
198 	yy += 79;
199 	map<string, Monster*> *creatureMap = &( Monster::monstersByName );
200 	creatureNames = new string[ creatureMap->size() ];
201 	int count = 0;
202 	for ( map<string, Monster*>::iterator i = creatureMap->begin()
203 	        ; i != creatureMap->end(); ++i ) {
204 		string name = i->first;
205 		Monster *monster = i->second;
206 
207 		// find its place by level
208 		int index = count;
209 		for ( int t = 0; t < count; t++ ) {
210 			Monster *m = creatures[ creatureNames[ t ] ];
211 			if ( m->getLevel() > monster->getLevel() ) {
212 				index = t;
213 				break;
214 			}
215 		}
216 
217 		// make room
218 		for ( int t = count - 1; t >= index; t-- ) {
219 			creatureNames[ t + 1 ] = creatureNames[ t ];
220 		}
221 		count++;
222 
223 		// add new creature
224 		creatureNames[ index ] = monster->isNpc() ? "NPC " : "";
225 		char levelStr[ 20 ];
226 		snprintf( levelStr, 20, "%d - ", monster->getLevel() );
227 		creatureNames[ index ] += levelStr + name;
228 		creatures[ creatureNames[ index ] ] = monster;
229 	}
230 	creatureList->setLines( creatureMap->size(), creatureNames );
231 
232 	// shapes
233 	shapeButton = mainWin->createButton( startx, yy, w - 10, yy + 20, _( "Shape" ), true );
234 	toggleButtonList.push_back( shapeButton );
235 	yy += ystep;
236 	shapeList = new ScrollingList( startx, yy, w - 16, 75,
237 	    scourge->getShapePalette()->getHighlightTexture() );
238 	mainWin->addWidget( shapeList );
239 	yy += 79;
240 
241 	map< string, GLShape* > *shapeMap = scourge->getShapePalette()->getShapeMap();
242 	shapeNames = new std::string[shapeMap->size()];
243 	count = 0;
244 	for ( map<string, GLShape*>::iterator i = shapeMap->begin(); i != shapeMap->end(); ++i ) {
245 		GLShape *shape = i->second;
246 		if ( !contains( &seen, shape ) && shape->isShownInMapEditor() ) {
247 			shapeNames[ count ] = i->first;
248 			count++;
249 		}
250 	}
251 	shapeList->setLines( count, shapeNames );
252 
253 	// outdoor textures
254 	outdoorTexturesButton = mainWin->createButton( startx, yy, w - 10, yy + 20, _( "Outdoor Textures" ), true );
255 	outdoorTexturesButton->setEnabled( false );
256 	toggleButtonList.push_back( outdoorTexturesButton );
257 	yy += ystep;
258 	outdoorTexturesList = new ScrollingList( startx, yy, w - 16, 75, scourge->getShapePalette()->getHighlightTexture() );
259 	mainWin->addWidget( outdoorTexturesList );
260 	yy += 79;
261 
262 	count = 0;
263 	outdoorTextureNames = new string[ WallTheme::OUTDOOR_THEME_REF_COUNT ];
264 	for ( int i = 0; i < WallTheme::OUTDOOR_THEME_REF_COUNT; i++ ) {
265 		outdoorTextureNames[ count++ ] = WallTheme::outdoorThemeRefName[ i ];
266 	}
267 	outdoorTexturesList->setLines( count, outdoorTextureNames );
268 
269 	miniMap = new MiniMap( scourge );
270 }
271 
createNewMapDialog()272 void MapEditor::createNewMapDialog() {
273 	// new map ui
274 	int nw = 450;
275 	int nh = 430;
276 	newMapWin = new Window( scourge->getSDLHandler(),
277 	                        40, 40, nw, nh,
278 	                        _( "Map Properties" ),
279 	                        false,
280 	                        Window::BASIC_WINDOW,
281 	                        GuiTheme::DEFAULT_THEME );
282 	newMapWin->setVisible( false );
283 	newMapWin->setModal( true );
284 	int startx = 8;
285 	enum { TMP_SIZE = 300 };
286 	char tmp[ TMP_SIZE ];
287 	snprintf( tmp, TMP_SIZE, "%s (0-50):", _( "Map level" ) );
288 	newMapWin->createLabel( startx, 20, tmp );
289 	levelText = newMapWin->createTextField( 150, 10, 20 );
290 	snprintf( tmp, TMP_SIZE, "%s (0-10):", _( "Map depth" ) );
291 	newMapWin->createLabel( startx, 40, tmp );
292 	depthText = newMapWin->createTextField( 150, 30, 20 );
293 	newMapWin->createLabel( startx, 60, _( "Map theme:" ) );
294 	nw -= 12;
295 
296 
297 	themeList = new ScrollingList( 150, 50, 220, 60,
298 	    scourge->getShapePalette()->getHighlightTexture() );
299 	newMapWin->addWidget( themeList );
300 	themeNames = new string[ scourge->getShapePalette()->getAllThemeCount() ];
301 
302 	for ( int i = 0; i < scourge->getShapePalette()->getAllThemeCount(); i++ ) {
303 		themeNames[ i ] = scourge->getShapePalette()->getAllThemeName( i );
304 		if ( scourge->getShapePalette()->isThemeSpecial( i ) )
305 			themeNames[i] += "(S)";
306 	}
307 	themeList->setLines( scourge->getShapePalette()->getAllThemeCount(), themeNames );
308 
309 	newMapWin->createLabel( startx, 135, _( "Outdoor Map:" ) );
310 	outdoorMapButton = newMapWin->createButton( startx + 100, 120, startx + 200, 140, "Outdoors", true );
311 
312 	newMapWin->createLabel( startx + 210, 135, _( "Dungeon Map:" ) );
313 	dungeonMapButton = newMapWin->createButton( startx + 310, 120, startx + 410, 140, "Dungeon", true );
314 
315 	newMapWin->createLabel( startx, 160, _( "Select map location: (click on map, drag to move)" ) );
316 	mapWidget = new MapWidget( scourge, newMapWin, startx, 170, nw - startx, 335 );
317 	newMapWin->addWidget( mapWidget->getCanvas() );
318 
319 	int bw = nw / 6;
320 	okButton = newMapWin->createButton( nw - bw * 3 - 10, 375, nw - bw * 2 - 5, 395, _( "New Map" ) );
321 	applyButton = newMapWin->createButton( nw - bw * 2 + 5, 375, nw - bw - 5, 395, _( "Apply" ) );
322 	cancelButton = newMapWin->createButton( nw - bw, 375, nw - 5, 395, _( "Cancel" ) );
323 }
324 
~MapEditor()325 MapEditor::~MapEditor() {
326 //  map< string, GLShape* > *shapeMap = scourge->getShapePalette()->getShapeMap();
327 	delete[] shapeNames;
328 	delete[] itemNames;
329 	delete mainWin;
330 	delete miniMap;
331 }
332 
drawView()333 void MapEditor::drawView() {
334 
335 	scourge->getMap()->preDraw();
336 	scourge->getMap()->draw();
337 	scourge->getMap()->postDraw();
338 
339 	miniMap->drawMap();
340 
341 	glDisable( GL_CULL_FACE );
342 	glDisable( GL_SCISSOR_TEST );
343 
344 	glDisable( GL_CULL_FACE );
345 	glDisable( GL_DEPTH_TEST );
346 	glDisable( GL_TEXTURE_2D );
347 	glPushMatrix();
348 	glColor3f( 1, 0, 0 );
349 
350 	glLoadIdentity();
351 
352 	if ( scourge->getMap()->getCursorFlatMapX() < MAP_WIDTH &&
353 	        scourge->getMap()->getCursorFlatMapY() < MAP_DEPTH ) {
354 		Location *pos = scourge->getMap()->getLocation( scourge->getMap()->getCursorFlatMapX(),
355 		                scourge->getMap()->getCursorFlatMapY(),
356 		                0 );
357 		scourge->getSDLHandler()->texPrint( 50, 120, "F:%d,%d,%d C:%d,%d %s=%s %s=%s %s=%s",
358 		    scourge->getMap()->getCursorFlatMapX(),
359 		    scourge->getMap()->getCursorFlatMapY(),
360 		    scourge->getMap()->cursorZ,
361 		    scourge->getMap()->getCursorChunkX(),
362 		    scourge->getMap()->getCursorChunkY(),
363 		    _( "Shape" ),
364 		    ( pos && pos->shape ? pos->shape->getName() : "NULL" ),
365 		    _( "Item" ),
366 		    ( pos && pos->item ? ( ( Item* )( pos->item ) )->getRpgItem()->getDisplayName() : "NULL" ),
367 		    _( "Creature" ),
368 		    ( pos && pos->creature ? pos->creature->getName() : "NULL" ) );
369 	}
370 	if ( outdoorTexturesButton->isSelected() ) {
371 		glColor3f( 1, 1, 0 );
372 		scourge->getSDLHandler()->texPrint( 50, 130, "Keys: z,x - rotate, q,w - mirror" );
373 		glColor3f( 1, 0, 0 );
374 	}
375 	glTranslatef( 50, 50, 0 );
376 	glRotatef( scourge->getMap()->getZRot(), 0, 0, 1 );
377 
378 	int n = 30;
379 	glBegin( GL_LINES );
380 	glVertex2f( 0, 0 );
381 	glVertex2f( 0, n );
382 
383 	glVertex2f( 0, 0 );
384 	glVertex2f( -n / 2, n / 2 );
385 
386 	glVertex2f( 0, 0 );
387 	glVertex2f( n / 2, n / 2 );
388 	glEnd();
389 
390 	glPopMatrix();
391 
392 
393 }
394 
drawAfter()395 void MapEditor::drawAfter() {
396 }
397 
handleEvent(SDL_Event * event)398 bool MapEditor::handleEvent( SDL_Event *event ) {
399 	scourge->getMap()->cursorWidth = scourge->getMap()->cursorDepth = 1;
400 	scourge->getMap()->cursorHeight = MAP_WALL_HEIGHT;
401 	if ( outdoorTexturesButton->isSelected() ) {
402 		int ref = outdoorTexturesList->getSelectedLine();
403 		scourge->getMap()->cursorWidth = scourge->getShapePalette()->getCurrentTheme()->getOutdoorTextureWidth( ref );
404 		scourge->getMap()->cursorDepth = scourge->getShapePalette()->getCurrentTheme()->getOutdoorTextureHeight( ref );
405 		scourge->getMap()->cursorHeight = 1;
406 	} else {
407 		GLShape *shape;
408 		if ( getShape( &shape ) ) {
409 			scourge->getMap()->cursorWidth = shape->getWidth();
410 			scourge->getMap()->cursorDepth = shape->getDepth();
411 			scourge->getMap()->cursorHeight = shape->getHeight();
412 		}
413 	}
414 
415 	// find the highest point under the cursor
416 	int maxz = 0;
417 	for ( int gx = 0; gx < scourge->getMap()->cursorWidth; gx++ ) {
418 		for ( int gy = 0; gy < scourge->getMap()->cursorDepth; gy++ ) {
419 			for ( int i = MAP_VIEW_HEIGHT - 1; i >= 0; i-- ) {
420 				Location *pos = scourge->getMap()->getLocation( scourge->getMap()->getCursorFlatMapX() + gx,
421 				                scourge->getMap()->getCursorFlatMapY() - gy,
422 				                i );
423 				if ( pos && pos->shape && !( ( GLShape* )pos->shape )->hasVirtualShapes() && !pos->shape->isRoof() && maxz < i + 1 ) {
424 					maxz = i + 1;
425 				}
426 			}
427 		}
428 	}
429 	//scourge->getMap()->cursorZ = ( maxz >= MAP_VIEW_HEIGHT - 1 ? 0 : maxz + 1 );
430 	//int editorZ = scourge->getMap()->cursorZ;
431 	//if( !maxz ) editorZ = 0;
432 
433 	int editorZ = scourge->getMap()->cursorZ = maxz;
434 
435 
436 	scourge->getMap()->handleEvent( event );
437 
438 	switch ( event->type ) {
439 		//case SDL_MOUSEMOTION:
440 		/*
441 		if( event->motion.state == SDL_BUTTON_LEFT &&
442 		    newMapWin->isVisible() ) {
443 		  mapWidget->setPosition( scourge->getMouseX() - newMapWin->getX() - mapWidget->getCanvas()->getX(),
444 		                          scourge->getMouseY() - newMapWin->getY() - mapWidget->getCanvas()->getY() - Window::TOP_HEIGHT );
445 		}
446 		*/
447 	case SDL_MOUSEBUTTONUP:
448 		processMouseMotion( event->button.button, editorZ );
449 		break;
450 	case SDL_KEYUP:
451 		if ( event->key.keysym.sym == SDLK_ESCAPE ) {
452 			hide();
453 			return true;
454 		} else if ( event->key.keysym.sym == SDLK_KP_PLUS ||
455 		            event->key.keysym.sym == SDLK_KP_MINUS ) {
456 			miniMap->setShowMiniMap( miniMap->isMiniMapShown() ? false : true );
457 			return false;
458 		} else if ( event->key.keysym.sym == SDLK_x ) {
459 			outdoorTextureAngle += 90;
460 			if ( outdoorTextureAngle >= 360 ) outdoorTextureAngle -= 360;
461 		} else if ( event->key.keysym.sym == SDLK_z ) {
462 			outdoorTextureAngle -= 90;
463 			if ( outdoorTextureAngle < 360 ) outdoorTextureAngle += 360;
464 		} else if ( event->key.keysym.sym == SDLK_q ) {
465 			outdoorTextureHorizFlip = !( outdoorTextureHorizFlip );
466 		} else if ( event->key.keysym.sym == SDLK_w ) {
467 			outdoorTextureVertFlip = !( outdoorTextureVertFlip );
468 		} else if ( event->key.keysym.sym == SDLK_s ) {
469 			scourge->getSquirrelConsole()->setVisible( scourge->getSquirrelConsole()->isVisible() ? false : true );
470 		} else if ( event->key.keysym.sym == SDLK_g ) {
471 			scourge->getMap()->setGridEnabled( scourge->getMap()->isGridEnabled() ? false : true );
472 		}
473 		break;
474 	default: break;
475 	}
476 	return false;
477 }
478 
handleEvent(Widget * widget,SDL_Event * event)479 bool MapEditor::handleEvent( Widget *widget, SDL_Event *event ) {
480 
481 	int found = -1;
482 	for ( int i = 0; i < static_cast<int>( toggleButtonList.size() ); i++ ) {
483 		if ( toggleButtonList[ i ] == widget ) {
484 			found = i;
485 			break;
486 		}
487 	}
488 	if ( found > -1 ) {
489 		for ( int i = 0; i < static_cast<int>( toggleButtonList.size() ); i++ ) {
490 			toggleButtonList[ i ]->setSelected( i == found );
491 		}
492 	}
493 
494 	string result;
495 	if ( widget == roofButton ) {
496 		scourge->getMap()->setRoofShowing( roofButton->isSelected() );
497 	} else if ( widget == saveButton ) {
498 		string tmp( nameText->getText() );
499 		scourge->getMap()->saveMap( tmp, result );
500 		scourge->showMessageDialog( result.c_str() );
501 //    scourge->getParty()->toggleRound( false );
502 	} else if ( widget == loadButton ) {
503 		string tmp( nameText->getText() );
504 		scourge->getMap()->loadMap( tmp, result );
505 		if ( scourge->getMap()->isHeightMapEnabled() ) {
506 			lowerButton->setEnabled( true );
507 			raiseButton->setEnabled( true );
508 			outdoorTexturesButton->setEnabled( true );
509 		}
510 		scourge->showMessageDialog( result.c_str() );
511 //    scourge->getParty()->toggleRound( false );
512 	} else if ( widget == newButton ) {
513 		newMapWin->setVisible( true );
514 		stringstream tmp;
515 		tmp << this->level;
516 		levelText->setText( tmp.str().c_str() );
517 		tmp.clear();
518 		tmp << this->depth;
519 		depthText->setText( tmp.str().c_str() );
520 		// FIXME: select theme!
521 		cerr << "FIXME: select theme!" << endl;
522 		mapWidget->setSelection( scourge->getMap()->mapGridX, scourge->getMap()->mapGridY );
523 	} else if ( widget == okButton || widget == applyButton ) {
524 		newMapWin->setVisible( false );
525 
526 		this->level = atoi( levelText->getText() );
527 		this->depth = atoi( depthText->getText() );
528 		if ( widget == okButton ) {
529 			scourge->getMap()->reset();
530 			int line = themeList->getSelectedLine();
531 			if ( line > -1 ) {
532 				string str = themeNames[ line ];
533 				int pos = str.rfind( "(S)" );
534 				if ( pos == str.size() - 3 ) str.erase( pos );
535 				scourge->getShapePalette()->loadTheme( str.c_str() );
536 			}
537 
538 			if ( outdoorMapButton->isSelected() ) {
539 				scourge->getMap()->setMapRenderHelper( MapRenderHelper::helpers[ MapRenderHelper::OUTDOOR_HELPER ] );
540 				OutdoorGenerator *og = new OutdoorGenerator( scourge, level, depth, 1, false, false, NULL );
541 				og->toMap( scourge->getMap(), scourge->getShapePalette(), false, false );
542 				delete og;
543 				raiseButton->setEnabled( true );
544 				lowerButton->setEnabled( true );
545 				outdoorTexturesButton->setEnabled( true );
546 			} else if ( dungeonMapButton->isSelected() ) {
547 				scourge->getMap()->setMapRenderHelper( MapRenderHelper::helpers[ MapRenderHelper::ROOM_HELPER ] );
548 				DungeonGenerator *og = new DungeonGenerator( scourge, level, depth, 1, false, false, NULL );
549 				og->toMap( scourge->getMap(), scourge->getShapePalette(), false, false );
550 				delete og;
551 			} else {
552 				scourge->getMap()->setMapRenderHelper( MapRenderHelper::helpers[ MapRenderHelper::ROOM_HELPER ] );
553 				lowerButton->setEnabled( false );
554 				raiseButton->setEnabled( false );
555 				outdoorTexturesButton->setEnabled( false );
556 			}
557 		}
558 		mapWidget->getSelection( &( scourge->getMap()->mapGridX ), &( scourge->getMap()->mapGridY ) );
559 
560 	} else if ( widget == cancelButton ) {
561 		newMapWin->setVisible( false );
562 	} else if ( widget == floorType ) {
563 		floorType->setLabel( _( floorTypeName[ floorType->isSelected() ? 0 : 1 ][ 1 ] ) );
564 	} else if ( widget == mapWidget->getCanvas() ) {
565 //    mapWidget->setPosition( scourge->getMouseX() - newMapWin->getX() - mapWidget->getCanvas()->getX(),
566 //                            scourge->getMouseY() - newMapWin->getY() - mapWidget->getCanvas()->getY() - Window::TOP_HEIGHT );
567 	} else if ( widget == scourge->getSquirrelRun() ||
568 	            widget == scourge->getSquirrelText() ) {
569 		scourge->runSquirrelConsole();
570 	} else if ( widget == scourge->getSquirrelClear() ) {
571 		scourge->clearSquirrelConsole();
572 	} else if ( widget == scourge->getSquirrelReload() ) {
573 		scourge->runSquirrelConsole( "scourgeGame.reloadNuts();" );
574 	}
575 	return false;
576 }
577 
show()578 void MapEditor::show() {
579 	scourge->getMap()->setMapSettings( mapSettings );
580 	scourge->getMap()->reset();
581 	scourge->getMap()->center( MAP_WIDTH / 2, MAP_DEPTH / 2, true );
582 	scourge->getMap()->setViewArea( 0, 0,
583 	    mainWin->getX(),
584 	    mainWin->getY() + mainWin->getHeight() );
585 	scourge->getShapePalette()->loadTheme( "egypt" );
586 	mainWin->setVisible( true );
587 }
588 
hide()589 void MapEditor::hide() {
590 	mainWin->setVisible( false );
591 	scourge->getMap()->setMapSettings( scourge->getMapSettings() );
592 }
593 
getShape(GLShape ** shape,Item ** item,Creature ** creature)594 bool MapEditor::getShape( GLShape **shape,
595                           Item **item,
596                           Creature **creature ) {
597 	*shape = NULL;
598 	if ( item ) *item = NULL;
599 	if ( creature ) *creature = NULL;
600 	if ( creatureButton->isSelected() &&
601 	        creatureList->getSelectedLine() > -1 ) {
602 		string s = creatureNames[ creatureList->getSelectedLine() ];
603 		Monster *monster = creatures[ s ];
604 		//Monster *monster = Monster::getMonsterByName( creatureNames[ creatureList->getSelectedLine() ] );
605 		// cache creature shapes
606 		if ( creatureOutlines.find( monster ) == creatureOutlines.end() ) {
607 			creatureOutlines[ monster ] = scourge->getSession()->getShapePalette()->
608 			                              getCreatureShape( monster->getModelName(),
609 			                                                monster->getSkinName(),
610 			                                                monster->getScale(),
611 			                                                monster );
612 		}
613 		*shape = creatureOutlines[ monster ];
614 		if ( creature ) {
615 			cerr << "new creature" << endl;
616 			*creature = scourge->getSession()->newCreature( monster, *shape );
617 		}
618 		return true;
619 	} else if ( itemButton->isSelected() &&
620 	            itemList->getSelectedLine() > -1 ) {
621 		addNewItem( itemNames[ itemList->getSelectedLine() ].c_str(), shape, item, creature );
622 		return true;
623 	} else if ( furnitureButton->isSelected() &&
624 	            furnitureList->getSelectedLine() > -1 ) {
625 		addNewItem( furnitureNames[ furnitureList->getSelectedLine() ].c_str(), shape, item, creature );
626 		return true;
627 	} else if ( shapeButton->isSelected() &&
628 	            shapeList->getSelectedLine() > -1 ) {
629 		*shape = scourge->getShapePalette()->
630 		         findShapeByName( shapeNames[ shapeList->getSelectedLine() ].c_str() );
631 		return true;
632 	} else {
633 		return false;
634 	}
635 }
636 
addNewItem(char const * name,GLShape ** shape,Item ** item,Creature ** creature)637 void MapEditor::addNewItem( char const* name,
638                             GLShape **shape,
639                             Item **item,
640                             Creature **creature ) {
641 	RpgItem *rpgItem = RpgItem::getItemByName( name );
642 	*shape = scourge->getShapePalette()->getShape( rpgItem->getShapeIndex() );
643 	if ( item ) {
644 		cerr << "new item" << endl;
645 		*item = scourge->getSession()->newItem( rpgItem, level );
646 		// fill the container with random items
647 		if ( rpgItem->isContainer() ) {
648 			// some items
649 			int n = Util::dice( 3 );
650 			for ( int i = 0; i < n; i++ ) {
651 				RpgItem *containedItem = RpgItem::getRandomItem( depth );
652 				if ( containedItem )
653 					( *item )->addContainedItem( scourge->getSession()->
654 					                             newItem( containedItem, level ),
655 					                             true );
656 			}
657 			// some spells
658 			if ( 0 == Util::dice( 25 ) ) {
659 				int n = Util::pickOne( 1, 2 );
660 				int spellLevel = level / 5;
661 				for ( int i = 0; i < n; i++ ) {
662 					Spell *spell = MagicSchool::getRandomSpell( spellLevel );
663 					if ( spell ) {
664 						Item *scroll = scourge->getSession()->
665 						               newItem( RpgItem::getItemByName( "Scroll" ), level, spell );
666 						( *item )->addContainedItem( scroll, true );
667 					}
668 				}
669 			}
670 
671 			// print summary
672 			cerr << "Container contents:" << endl;
673 			for ( int i = 0; i < ( *item )->getContainedItemCount(); i++ ) {
674 				cerr << "\t" << ( *item )->getContainedItem( i )->getRpgItem()->getDisplayName() << endl;
675 			}
676 		}
677 	}
678 }
679 
processMouseMotion(Uint8 button,int editorZ)680 void MapEditor::processMouseMotion( Uint8 button, int editorZ ) {
681 	if ( scourge->getSDLHandler()->mouseX < mainWin->getX() &&
682 	        ( button == SDL_BUTTON_LEFT ||
683 	          button == SDL_BUTTON_RIGHT &&
684 	          ( SDL_GetModState() & KMOD_SHIFT ) ) ) {
685 
686 		// draw the correct walls in this chunk
687 		int xx = scourge->getMap()->getCursorFlatMapX();
688 		int yy = scourge->getMap()->getCursorFlatMapY() - 1;
689 
690 		if ( startPosButton->isSelected() ) {
691 			scourge->getMap()->startx = xx;
692 			scourge->getMap()->starty = yy;
693 			return;
694 		}
695 
696 		int mapx = ( ( xx - MAP_OFFSET )  / MAP_UNIT ) * MAP_UNIT + MAP_OFFSET;
697 		int mapy = ( ( yy - MAP_OFFSET )  / MAP_UNIT ) * MAP_UNIT + MAP_OFFSET;
698 
699 		//int mapx = scourge->getMap()->getCursorChunkX() * MAP_UNIT + MAP_OFFSET;
700 		//int mapy = scourge->getMap()->getCursorChunkY() * MAP_UNIT + MAP_OFFSET;
701 
702 		GLShape *shape;
703 		if ( button == SDL_BUTTON_LEFT ) {
704 			if ( outdoorTexturesButton->isSelected() ) {
705 				if ( outdoorTexturesList->getSelectedLine() > -1 ) {
706 					//string s = outdoorTextureNames[ outdoorTexturesList->getSelectedLine() ];
707 					//NamedOutdoorTexture *ot = scourge->getShapePalette()->getOutdoorNamedTexture( s );
708 					int ref = outdoorTexturesList->getSelectedLine();
709 					int faceCount = scourge->getShapePalette()->getCurrentTheme()->getOutdoorFaceCount( ref );
710 					if ( faceCount == 0 ) {
711 						cerr << "Map Editor Error: no textures for outdoor theme! ref=" << WallTheme::outdoorThemeRefName[ref] << endl;
712 						return;
713 					}
714 //      int w = scourge->getShapePalette()->getCurrentTheme()->getOutdoorTextureWidth( ref );
715 //      int h = scourge->getShapePalette()->getCurrentTheme()->getOutdoorTextureHeight( ref );
716 					scourge->getMap()->setOutdoorTexture( xx, yy + 1,
717 					    0, 0,
718 					    ref,
719 					    outdoorTextureAngle,
720 					    outdoorTextureHorizFlip,
721 					    outdoorTextureVertFlip,
722 					    ROAD_LAYER );
723 				}
724 				return;
725 			} else {
726 				Item *item;
727 				Creature *creature;
728 				if ( getShape( &shape, &item, &creature ) ) {
729 					if ( item ) {
730 						scourge->getMap()->setItem( xx, yy + 1, editorZ, item );
731 					} else if ( creature ) {
732 						scourge->getMap()->setCreature( xx, yy + 1, editorZ, creature );
733 						creature->moveTo( xx, yy + 1, editorZ );
734 					} else if ( shape ) {
735 						if ( shape->getIgnoreHeightMap() && !shape->isRoof() ) {
736 							for ( int sx = mapx; sx < mapx + shape->getWidth(); sx++ ) {
737 								for ( int sy = mapy - shape->getDepth(); sy <= mapy; sy++ ) {
738 									flattenChunk( sx, sy );
739 								}
740 							}
741 						}
742 						scourge->getMap()->setPosition( xx, yy + 1, editorZ, shape );
743 					}
744 					return;
745 				}
746 			}
747 		} else if ( button == SDL_BUTTON_RIGHT ) {
748 			if ( outdoorTexturesButton->isSelected() ) {
749 				int ref = outdoorTexturesList->getSelectedLine();
750 				scourge->getMap()->removeOutdoorTexture( xx, yy + 1, scourge->getShapePalette()->getCurrentTheme()->getOutdoorTextureWidth( ref ), scourge->getShapePalette()->getCurrentTheme()->getOutdoorTextureHeight( ref ), ROAD_LAYER );
751 			} else if ( getShape( &shape ) ) {
752 				for ( int sx = 0; sx < shape->getWidth(); sx++ ) {
753 					for ( int sy = 0; sy < shape->getDepth(); sy++ ) {
754 						for ( int sz = MAP_VIEW_HEIGHT - 1; sz >= 0; sz-- ) {
755 							scourge->getMap()->removeLocation( xx + sx, yy - sy + 1, sz );
756 						}
757 					}
758 				}
759 				return;
760 			}
761 		}
762 
763 		int innerX = xx - mapx;
764 		int innerY = yy - mapy;
765 
766 		//    cerr << "pos: " << mapx << "," << mapy <<
767 		//      " map:" << scourge->getMap()->getCursorFlatMapX() << "," <<
768 		//      scourge->getMap()->getCursorFlatMapX() << endl;
769 
770 
771 		// find the region in the chunk
772 		int mx = -1;
773 		int my = -1;
774 		int dir = -1;
775 		if ( innerX < MAP_UNIT_OFFSET ) {
776 			mx = mapx;
777 			my = mapy;
778 			dir = Constants::WEST;
779 		} else if ( innerY < MAP_UNIT_OFFSET ) {
780 			mx = mapx;
781 			my = mapy;
782 			dir = Constants::NORTH;
783 		} else if ( innerX >= MAP_UNIT - MAP_UNIT_OFFSET ) {
784 			mx = mapx + MAP_UNIT - MAP_UNIT_OFFSET;
785 			my = mapy;
786 			dir = Constants::EAST;
787 		} else if ( innerY >= MAP_UNIT - MAP_UNIT_OFFSET ) {
788 			mx = mapx;
789 			my = mapy + MAP_UNIT - MAP_UNIT_OFFSET;
790 			dir = Constants::SOUTH;
791 		}
792 
793 		if ( dir != -1 ) {
794 			if ( secretButton->isSelected() ) {
795 				if ( button == SDL_BUTTON_RIGHT ) {
796 					removeSecret( xx, yy + 1 );
797 				} else {
798 					addSecret( xx, yy + 1 );
799 				}
800 			} else if ( button == SDL_BUTTON_RIGHT ) {
801 				removeWall( mx, my, dir );
802 			} else if ( wallButton->isSelected() ) {
803 				addWall( mx, my, dir );
804 			} else if ( doorButton->isSelected() ) {
805 				addDoor( mx, my, dir );
806 			}
807 
808 			// blend the corners
809 			for ( int x = -1; x <= 1; x++ ) {
810 				for ( int y = -1; y <= 1; y++ ) {
811 					blendCorners( mapx + ( x * MAP_UNIT ),
812 					              mapy + ( y * MAP_UNIT ) );
813 				}
814 			}
815 		} else {
816 			int chunkX = ( mapx - MAP_OFFSET ) / MAP_UNIT;
817 			int chunkY = ( mapy - MAP_OFFSET ) / MAP_UNIT;
818 			if ( rugButton->isSelected() ) {
819 				if ( button == SDL_BUTTON_RIGHT ) {
820 					scourge->getMap()->removeRugPosition( chunkX, chunkY );
821 				} else {
822 					addRug( chunkX, chunkY );
823 				}
824 			} else if ( trapButton->isSelected() ) {
825 				if ( button == SDL_BUTTON_RIGHT ) {
826 					removeTrap( xx, yy );
827 				} else {
828 					addTrap( xx, yy );
829 				}
830 			} else {
831 				if ( button == SDL_BUTTON_RIGHT ) {
832 					removeFloor( mapx, mapy );
833 				} else if ( lowerButton->isSelected() ) {
834 					lowerGroundHeight( xx, yy );
835 				} else if ( raiseButton->isSelected() ) {
836 					raiseGroundHeight( xx, yy );
837 				} else {
838 					addFloor( mapx, mapy );
839 				}
840 			}
841 		}
842 	}
843 }
844 
addRug(Sint16 mapx,Sint16 mapy)845 void MapEditor::addRug( Sint16 mapx, Sint16 mapy ) {
846 	// pick an orientation
847 	bool isHorizontal = ( Util::dice( 2 ) == 0 ? true : false );
848 
849 	// save it
850 	Rug rug;
851 	rug.isHorizontal = isHorizontal;
852 	rug.texture = scourge->getSession()->getShapePalette()->getRandomRug();
853 	rug.angle = Util::roll( -15.0f, 15.0f );
854 
855 	scourge->getMap()->setRugPosition( mapx, mapy, &rug );
856 }
857 
addSecret(Sint16 mapx,Sint16 mapy)858 void MapEditor::addSecret( Sint16 mapx, Sint16 mapy ) {
859 	Location *pos = scourge->getMap()->getLocation( mapx, mapy, 0 );
860 	if ( pos ) {
861 		scourge->getMap()->addSecretDoor( pos->x, pos->y );
862 	}
863 }
864 
removeSecret(Sint16 mapx,Sint16 mapy)865 void MapEditor::removeSecret( Sint16 mapx, Sint16 mapy ) {
866 	Location *pos = scourge->getMap()->getLocation( mapx, mapy, 0 );
867 	if ( pos ) {
868 		scourge->getMap()->removeSecretDoor( pos->x, pos->y );
869 	}
870 }
871 
addTrap(Sint16 mapx,Sint16 mapy)872 void MapEditor::addTrap( Sint16 mapx, Sint16 mapy ) {
873 	int w = Util::pickOne( 4, 9 );
874 	int h = Util::pickOne( 4, 9 );
875 	scourge->getMap()->addTrap( mapx, mapy, w, h );
876 }
877 
removeTrap(Sint16 mapx,Sint16 mapy)878 void MapEditor::removeTrap( Sint16 mapx, Sint16 mapy ) {
879 	int trapIndex = scourge->getMap()->getTrapAtLoc( mapx, mapy );
880 	if ( trapIndex > -1 ) scourge->getMap()->removeTrap( trapIndex );
881 }
882 
flattenChunk(Sint16 mapX,Sint16 mapY)883 void MapEditor::flattenChunk( Sint16 mapX, Sint16 mapY ) {
884 	int chunkX = ( mapX - MAP_OFFSET ) / MAP_UNIT;
885 	int chunkY = ( mapY - MAP_OFFSET ) / MAP_UNIT;
886 	for ( int x = -OUTDOORS_STEP; x <= MAP_UNIT + OUTDOORS_STEP; x++ ) {
887 		for ( int y = -OUTDOORS_STEP; y <= MAP_UNIT + OUTDOORS_STEP; y++ ) {
888 			int xx = ( MAP_OFFSET + ( chunkX * MAP_UNIT ) + x ) / OUTDOORS_STEP;
889 			int yy = ( MAP_OFFSET + ( chunkY * MAP_UNIT ) + y ) / OUTDOORS_STEP;
890 			scourge->getMap()->setGroundHeight( xx, yy, 0 );
891 		}
892 	}
893 }
894 
addWall(Sint16 mapx,Sint16 mapy,int dir)895 void MapEditor::addWall( Sint16 mapx, Sint16 mapy, int dir ) {
896 	flattenChunk( mapx, mapy );
897 	switch ( dir ) {
898 	case Constants::NORTH: addNSWall( mapx, mapy, 1 ); break;
899 	case Constants::SOUTH: addNSWall( mapx, mapy, -1 ); break;
900 	case Constants::WEST: addEWWall( mapx, mapy, 1 ); break;
901 	case Constants::EAST: addEWWall( mapx, mapy, -1 ); break;
902 	default: cerr << "*** addWall, Unknown dir=" << dir << endl;
903 	}
904 }
905 
addDoor(Sint16 mapx,Sint16 mapy,int dir)906 void MapEditor::addDoor( Sint16 mapx, Sint16 mapy, int dir ) {
907 	flattenChunk( mapx, mapy );
908 	switch ( dir ) {
909 	case Constants::NORTH: addNSDoor( mapx, mapy, 1 ); break;
910 	case Constants::SOUTH: addNSDoor( mapx, mapy, -1 ); break;
911 	case Constants::WEST: addEWDoor( mapx, mapy, 1 ); break;
912 	case Constants::EAST: addEWDoor( mapx, mapy, -1 ); break;
913 	default: cerr << "*** addDoor, Unknown dir=" << dir << endl;
914 	}
915 }
916 
removeWall(Sint16 mapx,Sint16 mapy,int dir)917 void MapEditor::removeWall( Sint16 mapx, Sint16 mapy, int dir ) {
918 	switch ( dir ) {
919 	case Constants::NORTH: removeNSWall( mapx, mapy, 1 ); break;
920 	case Constants::SOUTH: removeNSWall( mapx, mapy, -1 ); break;
921 	case Constants::WEST: removeEWWall( mapx, mapy, 1 ); break;
922 	case Constants::EAST: removeEWWall( mapx, mapy, -1 ); break;
923 	default: cerr << "*** removeWall, Unknown dir=" << dir << endl;
924 	}
925 }
926 
addEWDoor(Sint16 mapx,Sint16 mapy,int dir)927 void MapEditor::addEWDoor( Sint16 mapx, Sint16 mapy, int dir ) {
928 	ShapePalette *shapePal = scourge->getShapePalette();
929 	if ( !scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT / 2, 0 ) ) {
930 		scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT - MAP_UNIT_OFFSET,
931 		    MAP_WALL_HEIGHT - 2, shapePal->findShapeByName( "EW_DOOR_TOP" ) );
932 		scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT_OFFSET +  2,
933 		    0, shapePal->findShapeByName( "DOOR_SIDE" ) );
934 		scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT_OFFSET * 2 +  2,
935 		    0, shapePal->findShapeByName( "DOOR_SIDE" ) );
936 		scourge->getMap()->setPosition( mapx + 1, mapy + MAP_UNIT - MAP_UNIT_OFFSET - 2,
937 		    0, shapePal->findShapeByName( "EW_DOOR" ) );
938 		scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT - MAP_UNIT_OFFSET,
939 		    0, shapePal->findShapeByName( "DOOR_SIDE" ) );
940 
941 		// corners
942 		if ( !scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT_OFFSET, 0 ) ) {
943 			scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT_OFFSET, 0,
944 			    shapePal->findShapeByName( "CORNER" ) );
945 		}
946 		if ( !scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT, 0 ) ) {
947 			scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT, 0,
948 			    shapePal->findShapeByName( "CORNER" ) );
949 		}
950 	}
951 }
952 
addNSDoor(Sint16 mapx,Sint16 mapy,int dir)953 void MapEditor::addNSDoor( Sint16 mapx, Sint16 mapy, int dir ) {
954 	ShapePalette *shapePal = scourge->getShapePalette();
955 	if ( !scourge->getMap()->getLocation( mapx + MAP_UNIT / 2,
956 	        mapy + MAP_UNIT_OFFSET,
957 	        0 ) ) {
958 		scourge->getMap()->setPosition( mapx + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET,
959 		    MAP_WALL_HEIGHT - 2, shapePal->findShapeByName( "NS_DOOR_TOP" ) );
960 		scourge->getMap()->setPosition( mapx + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET,
961 		    0, shapePal->findShapeByName( "DOOR_SIDE" ) );
962 		scourge->getMap()->setPosition( mapx + MAP_UNIT_OFFSET * 2, mapy + MAP_UNIT_OFFSET - 1,
963 		    0, shapePal->findShapeByName( "NS_DOOR" ) );
964 		scourge->getMap()->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET * 2, mapy + MAP_UNIT_OFFSET,
965 		    0, shapePal->findShapeByName( "DOOR_SIDE" ) );
966 		scourge->getMap()->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET * 3, mapy + MAP_UNIT_OFFSET,
967 		    0, shapePal->findShapeByName( "DOOR_SIDE" ) );
968 
969 		// corners
970 		if ( !scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT_OFFSET, 0 ) ) {
971 			scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT_OFFSET, 0,
972 			    shapePal->findShapeByName( "CORNER" ) );
973 		}
974 		if ( !scourge->getMap()->getLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 ) ) {
975 			scourge->getMap()->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0,
976 			    shapePal->findShapeByName( "CORNER" ) );
977 		}
978 	}
979 }
980 
addEWWall(Sint16 mapx,Sint16 mapy,int dir)981 void MapEditor::addEWWall( Sint16 mapx, Sint16 mapy, int dir ) {
982 	// short wall
983 	bool north = false;
984 	bool south = false;
985 	if ( !scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT / 2, 0 ) ) {
986 
987 		// see if EW_WALL to the north and south
988 		north = ( mapy - 1 >= 0 &&
989 		          scourge->getMap()->getLocation( mapx, mapy - 1, 0 ) &&
990 		          !scourge->getMap()->getLocation( mapx + dir * ( MAP_UNIT / 2 ), mapy + 1, 0 ) );
991 		south = ( mapy + MAP_UNIT + 1 < MAP_DEPTH &&
992 		          scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT + 1, 0 ) &&
993 		          !scourge->getMap()->getLocation( mapx + dir * ( MAP_UNIT / 2 ), mapy + MAP_UNIT - 1, 0 ) );
994 
995 		// corner
996 		if ( south ) {
997 			scourge->getMap()->
998 			removeLocation( mapx, mapy + MAP_UNIT, 0 );
999 		} else if ( !scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT, 0 ) ) {
1000 			scourge->getMap()->
1001 			setPosition( mapx, mapy + MAP_UNIT, 0,
1002 			             scourge->getShapePalette()->
1003 			             findShapeByName( "CORNER" ) );
1004 		}
1005 
1006 		// corner
1007 		if ( north ) {
1008 			scourge->getMap()->
1009 			removeLocation( mapx, mapy + MAP_UNIT_OFFSET, 0 );
1010 		} else if ( !scourge->getMap()->getLocation( mapx, mapy + MAP_UNIT_OFFSET, 0 ) ) {
1011 			scourge->getMap()->
1012 			setPosition( mapx, mapy + MAP_UNIT_OFFSET, 0,
1013 			             scourge->getShapePalette()->
1014 			             findShapeByName( "CORNER" ) );
1015 		}
1016 
1017 		if ( north && south ) {
1018 			scourge->getMap()->
1019 			setPosition( mapx, mapy + MAP_UNIT, 0,
1020 			             scourge->getShapePalette()->
1021 			             findShapeByName( "EW_WALL_TWO_EXTRAS" ) );
1022 		} else if ( south ) {
1023 			scourge->getMap()->
1024 			setPosition( mapx, mapy + MAP_UNIT, 0,
1025 			             scourge->getShapePalette()->
1026 			             findShapeByName( "EW_WALL_EXTRA" ) );
1027 		} else if ( north ) {
1028 			scourge->getMap()->
1029 			setPosition( mapx, mapy + MAP_UNIT - MAP_UNIT_OFFSET, 0,
1030 			             scourge->getShapePalette()->
1031 			             findShapeByName( "EW_WALL_EXTRA" ) );
1032 		} else {
1033 			scourge->getMap()->
1034 			setPosition( mapx, mapy + MAP_UNIT - MAP_UNIT_OFFSET, 0,
1035 			             scourge->getShapePalette()->
1036 			             findShapeByName( "EW_WALL" ) );
1037 		}
1038 
1039 		// add a light
1040 		if ( Util::dice( 100 ) <= 25 ) {
1041 			if ( dir == 1 ) {
1042 				scourge->getMap()->
1043 				setPosition( mapx + MAP_UNIT_OFFSET, mapy + MAP_UNIT - 4,
1044 				             6, scourge->getShapePalette()->findShapeByName( "LAMP_WEST" ) );
1045 				scourge->getMap()->
1046 				setPosition( mapx + MAP_UNIT_OFFSET, mapy + MAP_UNIT - 4,
1047 				             4, scourge->getShapePalette()->findShapeByName( "LAMP_BASE" ) );
1048 			} else {
1049 				scourge->getMap()->
1050 				setPosition( mapx - 1, mapy + MAP_UNIT - 4,
1051 				             6, scourge->getShapePalette()->findShapeByName( "LAMP_EAST" ) );
1052 				scourge->getMap()->
1053 				setPosition( mapx - 1, mapy + MAP_UNIT - 4,
1054 				             4, scourge->getShapePalette()->findShapeByName( "LAMP_BASE" ) );
1055 			}
1056 		}
1057 
1058 
1059 		// change north chunk
1060 		//cerr << "Looking north of EW_WALL map=" << mapx << "," << mapy << endl;
1061 		if ( isShape( mapx, mapy - MAP_UNIT_OFFSET, 0, "EW_WALL" ) &&
1062 		        isShape( mapx, mapy, 0, "CORNER" ) &&
1063 		        !scourge->getMap()->getLocation( mapx + dir * ( MAP_UNIT / 2 ), mapy - 1, 0 ) ) {
1064 			//cerr << "Success!" << endl;
1065 			scourge->getMap()->removeLocation( mapx, mapy - MAP_UNIT_OFFSET, 0 );
1066 			scourge->getMap()->removeLocation( mapx, mapy, 0 );
1067 			scourge->getMap()->
1068 			setPosition( mapx, mapy, 0, scourge->getShapePalette()->
1069 			             findShapeByName( "EW_WALL_EXTRA" ) );
1070 		}
1071 
1072 		//cerr << "Looking north of EW_WALL_EXTRA map=" << mapx << "," << mapy << endl;
1073 		if ( isShape( mapx, mapy - MAP_UNIT_OFFSET, 0, "EW_WALL_EXTRA" ) &&
1074 		        isShape( mapx, mapy, 0, "CORNER" ) &&
1075 		        !scourge->getMap()->getLocation( mapx + dir * ( MAP_UNIT / 2 ), mapy - 1, 0 ) ) {
1076 			//cerr << "Success!" << endl;
1077 			scourge->getMap()->removeLocation( mapx, mapy - MAP_UNIT_OFFSET, 0 );
1078 			scourge->getMap()->removeLocation( mapx, mapy, 0 );
1079 			scourge->getMap()->
1080 			setPosition( mapx, mapy, 0, scourge->getShapePalette()->
1081 			             findShapeByName( "EW_WALL_TWO_EXTRAS" ) );
1082 		}
1083 
1084 		// change the south chunk
1085 		//cerr << "Looking south of EW_WALL map=" << mapx << "," << mapy << endl;
1086 		if ( isShape( mapx, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0, "EW_WALL" ) &&
1087 		        isShape( mapx, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1088 		        !scourge->getMap()->getLocation( mapx + dir * ( MAP_UNIT / 2 ), mapy + MAP_UNIT + 1, 0 ) ) {
1089 			//cerr << "Success!" << endl;
1090 			scourge->getMap()->removeLocation( mapx, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0 );
1091 			scourge->getMap()->removeLocation( mapx, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0 );
1092 			scourge->getMap()->
1093 			setPosition( mapx, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0,
1094 			             scourge->getShapePalette()->
1095 			             findShapeByName( "EW_WALL_EXTRA" ) );
1096 		}
1097 		//cerr << "Looking south of EW_WALL_EXTRA map=" << mapx << "," << mapy << endl;
1098 		if ( isShape( mapx, mapy + MAP_UNIT + MAP_UNIT, 0, "EW_WALL_EXTRA" ) &&
1099 		        isShape( mapx, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1100 		        !scourge->getMap()->getLocation( mapx + dir * ( MAP_UNIT / 2 ), mapy + MAP_UNIT + 1, 0 ) ) {
1101 			//cerr << "Success!" << endl;
1102 			scourge->getMap()->removeLocation( mapx, mapy + MAP_UNIT + MAP_UNIT, 0 );
1103 			scourge->getMap()->removeLocation( mapx, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0 );
1104 			scourge->getMap()->
1105 			setPosition( mapx, mapy + MAP_UNIT + MAP_UNIT, 0,
1106 			             scourge->getShapePalette()->
1107 			             findShapeByName( "EW_WALL_TWO_EXTRAS" ) );
1108 		}
1109 		//cerr << "----------------------------------------------------" << endl;
1110 	}
1111 }
1112 
addNSWall(Sint16 mapx,Sint16 mapy,int dir)1113 void MapEditor::addNSWall( Sint16 mapx, Sint16 mapy, int dir ) {
1114 
1115 	bool east = false;
1116 	bool west = false;
1117 
1118 	// short wall
1119 	if ( !scourge->getMap()->getLocation( mapx + MAP_UNIT / 2,
1120 	        mapy + MAP_UNIT_OFFSET,
1121 	        0 ) ) {
1122 
1123 		// see if NS_WALL to the east and west
1124 		east = ( mapx + MAP_UNIT < MAP_WIDTH &&
1125 		         scourge->getMap()->getLocation( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0 ) &&
1126 		         !scourge->getMap()->getLocation( mapx + MAP_UNIT - 1, mapy + dir * ( MAP_UNIT / 2 ), 0 ) );
1127 		west = ( mapx - 1 >= 0 &&
1128 		         scourge->getMap()->getLocation( mapx - 1, mapy + MAP_UNIT_OFFSET, 0 ) &&
1129 		         !scourge->getMap()->getLocation( mapx, mapy + dir * ( MAP_UNIT / 2 ), 0 ) );
1130 
1131 		// corner
1132 		if ( west ) {
1133 			scourge->getMap()->
1134 			removeLocation( mapx, mapy + MAP_UNIT_OFFSET, 0 );
1135 		} else if ( !scourge->getMap()->getLocation( mapx,
1136 		            mapy + MAP_UNIT_OFFSET,
1137 		            0 ) ) {
1138 			scourge->getMap()->
1139 			setPosition( mapx, mapy + MAP_UNIT_OFFSET, 0,
1140 			             scourge->getShapePalette()->
1141 			             findShapeByName( "CORNER" ) );
1142 		}
1143 
1144 		// corner
1145 		if ( east ) {
1146 			scourge->getMap()->
1147 			removeLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1148 		} else if ( !scourge->getMap()->getLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET,
1149 		            mapy + MAP_UNIT_OFFSET,
1150 		            0 ) ) {
1151 			scourge->getMap()->
1152 			setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0,
1153 			             scourge->getShapePalette()->
1154 			             findShapeByName( "CORNER" ) );
1155 		}
1156 
1157 
1158 		if ( east && west ) {
1159 			scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT_OFFSET, 0,
1160 			    scourge->getShapePalette()->findShapeByName( "NS_WALL_TWO_EXTRAS" ) );
1161 		} else if ( west ) {
1162 			scourge->getMap()->setPosition( mapx, mapy + MAP_UNIT_OFFSET, 0,
1163 			    scourge->getShapePalette()->findShapeByName( "NS_WALL_EXTRA" ) );
1164 		} else if ( east ) {
1165 			scourge->getMap()->setPosition( mapx + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0,
1166 			    scourge->getShapePalette()->findShapeByName( "NS_WALL_EXTRA" ) );
1167 		} else {
1168 			scourge->getMap()->setPosition( mapx + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0,
1169 			    scourge->getShapePalette()->findShapeByName( "NS_WALL" ) );
1170 		}
1171 
1172 		// Add a light
1173 		if ( Util::dice( 100 ) <= 25 ) {
1174 			if ( dir == 1 ) {
1175 				scourge->getMap()->
1176 				setPosition( mapx + 4, mapy + MAP_UNIT_OFFSET + 1, 6,
1177 				             scourge->getShapePalette()->findShapeByName( "LAMP_NORTH" ) );
1178 				scourge->getMap()->
1179 				setPosition( mapx + 4, mapy + MAP_UNIT_OFFSET + 1, 4,
1180 				             scourge->getShapePalette()->findShapeByName( "LAMP_BASE" ) );
1181 			} else {
1182 				/*
1183 				See gltorch.cpp on why there aren't southern torches... <sigh>
1184 				cerr << "adding South light" << endl;
1185 				scourge->getMap()->
1186 				  setPosition(mapx + 4, mapy, 6,
1187 				              scourge->getShapePalette()->findShapeByName("LAMP_SOUTH", true));
1188 				scourge->getMap()->
1189 				  setPosition(mapx + 4, mapy, 4,
1190 				              scourge->getShapePalette()->findShapeByName("LAMP_BASE", true));
1191 
1192 				*/
1193 			}
1194 		}
1195 
1196 		// change west chunk
1197 		if ( isShape( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL" ) &&
1198 		        isShape( mapx - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1199 		        !scourge->getMap()->getLocation( mapx - MAP_UNIT_OFFSET, mapy + dir * ( MAP_UNIT / 2 ), 0 ) ) {
1200 			scourge->getMap()->removeLocation( mapx - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1201 			scourge->getMap()->removeLocation( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1202 			scourge->getMap()->
1203 			setPosition( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0,
1204 			             scourge->getShapePalette()->findShapeByName( "NS_WALL_EXTRA" ) );
1205 		}
1206 		if ( isShape( mapx - MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL_EXTRA" ) &&
1207 		        isShape( mapx - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1208 		        !scourge->getMap()->getLocation( mapx - MAP_UNIT_OFFSET, mapy + dir * ( MAP_UNIT / 2 ), 0 ) ) {
1209 			scourge->getMap()->removeLocation( mapx - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1210 			scourge->getMap()->removeLocation( mapx - MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0 );
1211 			scourge->getMap()->
1212 			setPosition( mapx - MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0,
1213 			             scourge->getShapePalette()->findShapeByName( "NS_WALL_TWO_EXTRAS" ) );
1214 		}
1215 
1216 		// change the east chunk
1217 		if ( isShape( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL" ) &&
1218 		        isShape( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1219 		        !scourge->getMap()->getLocation( mapx + MAP_UNIT, mapy + dir * ( MAP_UNIT / 2 ), 0 ) ) {
1220 			scourge->getMap()->removeLocation( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1221 			scourge->getMap()->removeLocation( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0 );
1222 			scourge->getMap()->
1223 			setPosition( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0,
1224 			             scourge->getShapePalette()->
1225 			             findShapeByName( "NS_WALL_EXTRA" ) );
1226 		}
1227 		if ( isShape( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL_EXTRA" ) &&
1228 		        isShape( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1229 		        !scourge->getMap()->getLocation( mapx + MAP_UNIT, mapy + dir * ( MAP_UNIT / 2 ), 0 ) ) {
1230 			scourge->getMap()->removeLocation( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1231 			scourge->getMap()->removeLocation( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0 );
1232 			scourge->getMap()->
1233 			setPosition( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0,
1234 			             scourge->getShapePalette()->
1235 			             findShapeByName( "NS_WALL_TWO_EXTRAS" ) );
1236 		}
1237 	}
1238 }
1239 
addFloor(Sint16 mapx,Sint16 mapy,bool doFlattenChunk)1240 void MapEditor::addFloor( Sint16 mapx, Sint16 mapy, bool doFlattenChunk ) {
1241 	if ( scourge->getMap()->getFloorPosition( mapx, mapy + MAP_UNIT ) ) return;
1242 	if ( doFlattenChunk ) flattenChunk( mapx, mapy );
1243 	scourge->getMap()->
1244 	setFloorPosition( mapx, mapy + MAP_UNIT,
1245 	                  scourge->getShapePalette()->
1246 	                  findShapeByName( floorTypeName[ floorType->isSelected() ? 0 : 1 ][ 0 ] ) );
1247 }
1248 
lowerGroundHeight(Sint16 mapx,Sint16 mapy)1249 void MapEditor::lowerGroundHeight( Sint16 mapx, Sint16 mapy ) {
1250 	scourge->getMap()->setGroundHeight( mapx / OUTDOORS_STEP, mapy / OUTDOORS_STEP, Util::roll( 0, 2 ) );
1251 }
1252 
raiseGroundHeight(Sint16 mapx,Sint16 mapy)1253 void MapEditor::raiseGroundHeight( Sint16 mapx, Sint16 mapy ) {
1254 	scourge->getMap()->setGroundHeight( mapx / OUTDOORS_STEP, mapy / OUTDOORS_STEP, Util::roll( 14.0f, 20.0f ) );
1255 }
1256 
changePathChunk(Sint16 mapx,Sint16 mapy,bool lower)1257 void MapEditor::changePathChunk( Sint16 mapx, Sint16 mapy, bool lower ) {
1258 	//if( !scourge->getMap()->getFloorPosition( mapx, mapy + MAP_UNIT ) ) return;
1259 	int chunkX = ( mapx - MAP_OFFSET ) / MAP_UNIT;
1260 	int chunkY = ( mapy - MAP_OFFSET ) / MAP_UNIT;
1261 	for ( int x = OUTDOORS_STEP; x <= MAP_UNIT - OUTDOORS_STEP; x++ ) {
1262 		for ( int y = OUTDOORS_STEP; y <= MAP_UNIT - OUTDOORS_STEP; y++ ) {
1263 			int xx = ( MAP_OFFSET + ( chunkX * MAP_UNIT ) + x ) / OUTDOORS_STEP;
1264 			int yy = ( MAP_OFFSET + ( chunkY * MAP_UNIT ) + y ) / OUTDOORS_STEP;
1265 			scourge->getMap()->setGroundHeight( xx, yy, ( lower ? 0 : Util::roll( 7, 10 ) ) );
1266 		}
1267 	}
1268 	for ( int x = OUTDOORS_STEP; x <= MAP_UNIT - OUTDOORS_STEP; x++ ) {
1269 		if ( scourge->getMap()->getFloorPosition( mapx, mapy ) ) {
1270 			int y = 0;
1271 			int xx = ( MAP_OFFSET + ( chunkX * MAP_UNIT ) + x ) / OUTDOORS_STEP;
1272 			int yy = ( MAP_OFFSET + ( chunkY * MAP_UNIT ) + y ) / OUTDOORS_STEP;
1273 			scourge->getMap()->setGroundHeight( xx, yy, ( lower ? 0 : Util::roll( 7, 10 ) ) );
1274 		}
1275 		if ( scourge->getMap()->getFloorPosition( mapx, mapy + MAP_UNIT + MAP_UNIT ) ) {
1276 			int y = MAP_UNIT - 1;
1277 			int xx = ( MAP_OFFSET + ( chunkX * MAP_UNIT ) + x ) / OUTDOORS_STEP;
1278 			int yy = ( MAP_OFFSET + ( chunkY * MAP_UNIT ) + y ) / OUTDOORS_STEP;
1279 			scourge->getMap()->setGroundHeight( xx, yy, ( lower ? 0 : Util::roll( 7, 10 ) ) );
1280 		}
1281 	}
1282 	for ( int y = OUTDOORS_STEP; y <= MAP_UNIT - OUTDOORS_STEP; y++ ) {
1283 		if ( scourge->getMap()->getFloorPosition( mapx - MAP_UNIT, mapy + MAP_UNIT ) ) {
1284 			int x = 0;
1285 			int xx = ( MAP_OFFSET + ( chunkX * MAP_UNIT ) + x ) / OUTDOORS_STEP;
1286 			int yy = ( MAP_OFFSET + ( chunkY * MAP_UNIT ) + y ) / OUTDOORS_STEP;
1287 			scourge->getMap()->setGroundHeight( xx, yy, ( lower ? 0 : Util::roll( 7, 10 ) ) );
1288 		}
1289 		if ( scourge->getMap()->getFloorPosition( mapx + MAP_UNIT, mapy + MAP_UNIT ) ) {
1290 			int x = MAP_UNIT - 1;
1291 			int xx = ( MAP_OFFSET + ( chunkX * MAP_UNIT ) + x ) / OUTDOORS_STEP;
1292 			int yy = ( MAP_OFFSET + ( chunkY * MAP_UNIT ) + y ) / OUTDOORS_STEP;
1293 			scourge->getMap()->setGroundHeight( xx, yy, ( lower ? 0 : Util::roll( 7, 10 ) ) );
1294 		}
1295 	}
1296 }
1297 
removeFloor(Sint16 mapx,Sint16 mapy)1298 void MapEditor::removeFloor( Sint16 mapx, Sint16 mapy ) {
1299 	scourge->getMap()->removeFloorPosition( mapx, mapy + MAP_UNIT );
1300 }
1301 
removeEWWall(Sint16 mapx,Sint16 mapy,int dir)1302 void MapEditor::removeEWWall( Sint16 mapx, Sint16 mapy, int dir ) {
1303 	for ( int y = 1; y <= MAP_UNIT; y++ ) {
1304 		for ( int z = 0; z < MAP_VIEW_HEIGHT; z++ ) {
1305 			scourge->getMap()->removeLocation( mapx + 1, mapy + y, z );
1306 		}
1307 	}
1308 }
1309 
removeNSWall(Sint16 mapx,Sint16 mapy,int dir)1310 void MapEditor::removeNSWall( Sint16 mapx, Sint16 mapy, int dir ) {
1311 	for ( int x = 0; x < MAP_UNIT; x++ ) {
1312 		for ( int z = 0; z < MAP_VIEW_HEIGHT; z++ ) {
1313 			scourge->getMap()->removeLocation( mapx + x, mapy + MAP_UNIT_OFFSET - 1, z );
1314 		}
1315 	}
1316 }
1317 
blendCorners(Sint16 mapx,Sint16 mapy)1318 void MapEditor::blendCorners( Sint16 mapx, Sint16 mapy ) {
1319 
1320 	if ( !( mapx >= 0 && mapx < MAP_WIDTH &&
1321 	        mapy >= 0 && mapy < MAP_DEPTH ) )
1322 		return;
1323 
1324 
1325 	Map *levelMap = scourge->getMap();
1326 	ShapePalette *pal = scourge->getShapePalette();
1327 
1328 	// check NW corner
1329 	if ( isShape( mapx - 1, mapy + 1, 0, "CORNER" ) &&
1330 	        isShape( mapx, mapy - 1, 0, "CORNER" ) &&
1331 	        !levelMap->getLocation( mapx, mapy + MAP_UNIT_OFFSET, 0 ) ) {
1332 
1333 		bool nsWall = ( isShape( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL" ) ? true : false );
1334 		bool nsWallExtra = ( isShape( mapx - MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL_EXTRA" ) ? true : false );
1335 		bool ewWall = ( isShape( mapx, mapy - MAP_UNIT_OFFSET, 0, "EW_WALL" ) ? true : false );
1336 		bool ewWallExtra = ( isShape( mapx, mapy - MAP_UNIT_OFFSET, 0, "EW_WALL_EXTRA" ) ? true : false );
1337 
1338 		if ( ( nsWall || nsWallExtra ) && ( ewWall || ewWallExtra ) ) {
1339 
1340 			levelMap->setPosition( mapx, mapy + MAP_UNIT_OFFSET, 0,
1341 			                       pal->findShapeByName( "CORNER" ) );
1342 			levelMap->removeLocation( mapx - 1, mapy + 1, 0 );
1343 			levelMap->removeLocation( mapx, mapy - 1, 0 );
1344 
1345 			// change west chunk
1346 			if ( nsWall ) {
1347 				levelMap->removeLocation( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1348 				levelMap->setPosition( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0,
1349 				                       pal->findShapeByName( "NS_WALL_EXTRA" ) );
1350 			} else if ( nsWallExtra ) {
1351 				levelMap->removeLocation( mapx - MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0 );
1352 				levelMap->setPosition( mapx - MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0,
1353 				                       pal->findShapeByName( "NS_WALL_TWO_EXTRAS" ) );
1354 			}
1355 
1356 			// change north chunk
1357 			if ( ewWall ) {
1358 				levelMap->removeLocation( mapx, mapy - MAP_UNIT_OFFSET, 0 );
1359 				levelMap->setPosition( mapx, mapy, 0,
1360 				                       pal->findShapeByName( "EW_WALL_EXTRA" ) );
1361 			} else if ( ewWallExtra ) {
1362 				levelMap->removeLocation( mapx, mapy - MAP_UNIT_OFFSET, 0 );
1363 				levelMap->setPosition( mapx, mapy, 0,
1364 				                       pal->findShapeByName( "EW_WALL_TWO_EXTRAS" ) );
1365 			}
1366 		}
1367 	}
1368 
1369 	// check NE corner
1370 	if ( isShape( mapx + MAP_UNIT, mapy + 1, 0, "CORNER" ) &&
1371 	        isShape( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy - 1, 0, "CORNER" ) &&
1372 	        !levelMap->getLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 ) ) {
1373 
1374 		bool nsWall = ( isShape( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL" ) ? true : false );
1375 		bool nsWallExtra = ( isShape( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0, "NS_WALL_EXTRA" ) ? true : false );
1376 		bool ewWall = ( isShape( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy - MAP_UNIT_OFFSET, 0, "EW_WALL" ) ? true : false );
1377 		bool ewWallExtra = ( isShape( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy - MAP_UNIT_OFFSET, 0, "EW_WALL_EXTRA" ) ? true : false );
1378 
1379 		if ( ( nsWall || nsWallExtra ) && ( ewWall || ewWallExtra ) ) {
1380 
1381 			levelMap->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0,
1382 			                       pal->findShapeByName( "CORNER" ) );
1383 			levelMap->removeLocation( mapx + MAP_UNIT, mapy + 1, 0 );
1384 			levelMap->removeLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy - 1, 0 );
1385 
1386 			// change west chunk
1387 			if ( nsWall ) {
1388 				levelMap->removeLocation( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1389 				levelMap->setPosition( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0,
1390 				                       pal->findShapeByName( "NS_WALL_EXTRA" ) );
1391 			} else if ( nsWallExtra ) {
1392 				levelMap->removeLocation( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT_OFFSET, 0 );
1393 				levelMap->setPosition( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0,
1394 				                       pal->findShapeByName( "NS_WALL_TWO_EXTRAS" ) );
1395 			}
1396 
1397 			// change north chunk
1398 			if ( ewWall ) {
1399 				levelMap->removeLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy - MAP_UNIT_OFFSET, 0 );
1400 				levelMap->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy, 0,
1401 				                       pal->findShapeByName( "EW_WALL_EXTRA" ) );
1402 			} else if ( ewWallExtra ) {
1403 				levelMap->removeLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy - MAP_UNIT_OFFSET, 0 );
1404 				levelMap->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy, 0,
1405 				                       pal->findShapeByName( "EW_WALL_TWO_EXTRAS" ) );
1406 			}
1407 		}
1408 	}
1409 
1410 	// check SE corner
1411 	if ( isShape( mapx + MAP_UNIT, mapy + MAP_UNIT, 0, "CORNER" ) &&
1412 	        isShape( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1413 	        !levelMap->getLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0 ) ) {
1414 
1415 		bool nsWall = ( isShape( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0, "NS_WALL" ) ? true : false );
1416 		bool nsWallExtra = ( isShape( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0, "NS_WALL_EXTRA" ) ? true : false );
1417 		bool ewWall = ( isShape( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0, "EW_WALL" ) ? true : false );
1418 		bool ewWallExtra = ( isShape( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT, 0, "EW_WALL_EXTRA" ) ? true : false );
1419 
1420 		if ( ( nsWall || nsWallExtra ) && ( ewWall || ewWallExtra ) ) {
1421 
1422 			levelMap->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0,
1423 			                       pal->findShapeByName( "CORNER" ) );
1424 			levelMap->removeLocation( mapx + MAP_UNIT, mapy + MAP_UNIT_OFFSET, 0 );
1425 			levelMap->removeLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0 );
1426 
1427 			// change west chunk
1428 			if ( nsWall ) {
1429 				levelMap->removeLocation( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0 );
1430 				levelMap->setPosition( mapx + MAP_UNIT, mapy + MAP_UNIT, 0,
1431 				                       pal->findShapeByName( "NS_WALL_EXTRA" ) );
1432 			} else if ( nsWallExtra ) {
1433 				levelMap->removeLocation( mapx + MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0 );
1434 				levelMap->setPosition( mapx + MAP_UNIT, mapy + MAP_UNIT, 0,
1435 				                       pal->findShapeByName( "NS_WALL_TWO_EXTRAS" ) );
1436 			}
1437 
1438 			// change north chunk
1439 			if ( ewWall ) {
1440 				levelMap->removeLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0 );
1441 				levelMap->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0,
1442 				                       pal->findShapeByName( "EW_WALL_EXTRA" ) );
1443 			} else if ( ewWallExtra ) {
1444 				levelMap->removeLocation( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT, 0 );
1445 				levelMap->setPosition( mapx + MAP_UNIT - MAP_UNIT_OFFSET, mapy + MAP_UNIT + MAP_UNIT, 0,
1446 				                       pal->findShapeByName( "EW_WALL_TWO_EXTRAS" ) );
1447 			}
1448 		}
1449 	}
1450 
1451 	// check SW corner
1452 	if ( isShape( mapx - MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0, "CORNER" ) &&
1453 	        isShape( mapx, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0, "CORNER" ) &&
1454 	        !levelMap->getLocation( mapx, mapy + MAP_UNIT, 0 ) ) {
1455 
1456 		bool nsWall = ( isShape( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0, "NS_WALL" ) ? true : false );
1457 		bool nsWallExtra = ( isShape( mapx - MAP_UNIT, mapy + MAP_UNIT, 0, "NS_WALL_EXTRA" ) ? true : false );
1458 		bool ewWall = ( isShape( mapx, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0, "EW_WALL" ) ? true : false );
1459 		bool ewWallExtra = ( isShape( mapx, mapy + MAP_UNIT + MAP_UNIT, 0, "EW_WALL_EXTRA" ) ? true : false );
1460 
1461 		if ( ( nsWall || nsWallExtra ) && ( ewWall || ewWallExtra ) ) {
1462 
1463 			levelMap->setPosition( mapx, mapy + MAP_UNIT, 0,
1464 			                       pal->findShapeByName( "CORNER" ) );
1465 			levelMap->removeLocation( mapx - MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0 );
1466 			levelMap->removeLocation( mapx, mapy + MAP_UNIT + MAP_UNIT_OFFSET, 0 );
1467 
1468 			// change west chunk
1469 			if ( nsWall ) {
1470 				levelMap->removeLocation( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0 );
1471 				levelMap->setPosition( mapx - MAP_UNIT + MAP_UNIT_OFFSET, mapy + MAP_UNIT, 0,
1472 				                       pal->findShapeByName( "NS_WALL_EXTRA" ) );
1473 			} else if ( nsWallExtra ) {
1474 				levelMap->removeLocation( mapx - MAP_UNIT, mapy + MAP_UNIT, 0 );
1475 				levelMap->setPosition( mapx - MAP_UNIT, mapy + MAP_UNIT, 0,
1476 				                       pal->findShapeByName( "NS_WALL_TWO_EXTRAS" ) );
1477 			}
1478 
1479 			// change north chunk
1480 			if ( ewWall ) {
1481 				levelMap->removeLocation( mapx, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0 );
1482 				levelMap->setPosition( mapx, mapy + MAP_UNIT + MAP_UNIT - MAP_UNIT_OFFSET, 0,
1483 				                       pal->findShapeByName( "EW_WALL_EXTRA" ) );
1484 			} else if ( ewWallExtra ) {
1485 				levelMap->removeLocation( mapx, mapy + MAP_UNIT + MAP_UNIT, 0 );
1486 				levelMap->setPosition( mapx, mapy + MAP_UNIT + MAP_UNIT, 0,
1487 				                       pal->findShapeByName( "EW_WALL_TWO_EXTRAS" ) );
1488 			}
1489 		}
1490 	}
1491 }
1492 
isShape(Sint16 mapx,Sint16 mapy,Sint16 mapz,const char * name)1493 bool MapEditor::isShape( Sint16 mapx, Sint16 mapy, Sint16 mapz, const char *name ) {
1494 //  cerr << "\ttesting map=" << mapx << "," << mapy << " looking for " << name;
1495 	if ( mapx >= 0 && mapx < MAP_WIDTH &&
1496 	        mapy >= 0 && mapy < MAP_DEPTH &&
1497 	        mapz >= 0 && mapz < MAP_VIEW_HEIGHT ) {
1498 		Location *pos = scourge->getMap()->getLocation( mapx, mapy, mapz );
1499 //    cerr << " found=" << ( !pos ? "NULL" : pos->shape->getName() ) << endl;
1500 		return( pos && pos->shape && !strcmp( pos->shape->getName(), name ) );
1501 	} else {
1502 //    cerr << " found nothing." << endl;
1503 		return false;
1504 	}
1505 }
1506 
1507