mirror of
https://github.com/elasota/Aerofoil.git
synced 2026-02-04 10:38:52 +00:00
1172 lines
24 KiB
C++
1172 lines
24 KiB
C++
//============================================================================
|
|
//----------------------------------------------------------------------------
|
|
// Room.c
|
|
//----------------------------------------------------------------------------
|
|
//============================================================================
|
|
|
|
#include "PLKeyEncoding.h"
|
|
#include "PLResources.h"
|
|
#include "PLPasStr.h"
|
|
#include "PLStandardColors.h"
|
|
#include "BitmapImage.h"
|
|
#include "DialogManager.h"
|
|
#include "Externs.h"
|
|
#include "FontFamily.h"
|
|
#include "House.h"
|
|
#include "InputManager.h"
|
|
#include "MainWindow.h"
|
|
#include "MemoryManager.h"
|
|
#include "RectUtils.h"
|
|
#include "ResolveCachingColor.h"
|
|
|
|
|
|
#define kDeleteRoomAlert 1005
|
|
#define kYesDoDeleteRoom 1
|
|
|
|
|
|
Boolean QueryDeleteRoom (void);
|
|
void SetToNearestNeighborRoom (short, short);
|
|
|
|
|
|
roomPtr thisRoom;
|
|
Rect backSrcRect;
|
|
DrawSurface *backSrcMap;
|
|
short numberRooms, thisRoomNumber, previousRoom;
|
|
short leftThresh, rightThresh, lastBackground;
|
|
Boolean autoRoomEdit, newRoomNow, noRoomAtAll;
|
|
Boolean leftOpen, rightOpen, topOpen, bottomOpen;
|
|
Boolean doComplainDialogs;
|
|
|
|
extern short tempTiles[];
|
|
|
|
|
|
//============================================================== Functions
|
|
//-------------------------------------------------------------- SetInitialTiles
|
|
|
|
#ifndef COMPILEDEMO
|
|
void SetInitialTiles (short background, Boolean doRoom)
|
|
{
|
|
short i;
|
|
|
|
if (background >= kUserBackground)
|
|
{
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = i;
|
|
else
|
|
tempTiles[i] = i;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (background)
|
|
{
|
|
case kSimpleRoom:
|
|
case kPaneledRoom:
|
|
case kBasement:
|
|
case kChildsRoom:
|
|
case kAsianRoom:
|
|
case kUnfinishedRoom:
|
|
case kSwingersRoom:
|
|
case kBathroom:
|
|
case kLibrary:
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = 1;
|
|
else
|
|
tempTiles[i] = 1;
|
|
}
|
|
if (doRoom)
|
|
{
|
|
thisRoom->tiles[0] = 0;
|
|
thisRoom->tiles[kNumTiles - 1] = kNumTiles - 1;
|
|
}
|
|
else
|
|
{
|
|
tempTiles[0] = 0;
|
|
tempTiles[kNumTiles - 1] = kNumTiles - 1;
|
|
}
|
|
break;
|
|
|
|
case kSkywalk:
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = i;
|
|
else
|
|
tempTiles[i] = i;
|
|
}
|
|
break;
|
|
|
|
case kField:
|
|
case kGarden:
|
|
case kDirt:
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = 0;
|
|
else
|
|
tempTiles[i] = 0;
|
|
}
|
|
break;
|
|
|
|
case kMeadow:
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = 1;
|
|
else
|
|
tempTiles[i] = 1;
|
|
}
|
|
break;
|
|
|
|
case kRoof:
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = 3;
|
|
else
|
|
tempTiles[i] = 3;
|
|
}
|
|
break;
|
|
|
|
case kSky:
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = 2;
|
|
else
|
|
tempTiles[i] = 2;
|
|
}
|
|
break;
|
|
|
|
case kStratosphere:
|
|
case kStars:
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
if (doRoom)
|
|
thisRoom->tiles[i] = i;
|
|
else
|
|
tempTiles[i] = i;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//-------------------------------------------------------------- CreateNewRoom
|
|
|
|
#ifndef COMPILEDEMO
|
|
Boolean CreateNewRoom (short h, short v)
|
|
{
|
|
long howMuch;
|
|
PLError_t theErr;
|
|
short i, availableRoom;
|
|
char wasState;
|
|
|
|
CopyThisRoomToRoom(); // save off current room
|
|
|
|
memset(thisRoom, 0, sizeof(roomType));
|
|
|
|
PasStringCopy(PSTR("Untitled Room"), thisRoom->name);
|
|
thisRoom->leftStart = 32; // fill out fields of new room
|
|
thisRoom->rightStart = 32;
|
|
thisRoom->bounds = 0;
|
|
thisRoom->unusedByte = 0;
|
|
thisRoom->visited = false;
|
|
thisRoom->background = lastBackground;
|
|
SetInitialTiles(thisRoom->background, true);
|
|
thisRoom->floor = v;
|
|
thisRoom->suite = h;
|
|
thisRoom->openings = 0;
|
|
thisRoom->numObjects = 0;
|
|
for (i = 0; i < kMaxRoomObs; i++) // zero out all objects
|
|
thisRoom->objects[i].what = kObjectIsEmpty;
|
|
|
|
availableRoom = -1; // assume no available rooms
|
|
if ((*thisHouse)->nRooms > 0) // look for an empty room
|
|
for (i = 0; i < (*thisHouse)->nRooms; i++)
|
|
if ((*thisHouse)->rooms[i].suite == kRoomIsEmpty)
|
|
{
|
|
availableRoom = i;
|
|
break;
|
|
}
|
|
|
|
if (availableRoom == -1) // found no available rooms
|
|
{
|
|
// add new room to end of house
|
|
if (!PortabilityLayer::MemoryManager::GetInstance()->ResizeHandle(thisHouse.MMBlock(), thisHouse.MMBlock()->m_size + sizeof(roomType)))
|
|
{
|
|
YellowAlert(kYellowUnaccounted, PLErrors::kOutOfMemory);
|
|
return (false);
|
|
}
|
|
(*thisHouse)->rooms[(*thisHouse)->nRooms] = *thisRoom;
|
|
(*thisHouse)->nRooms++; // increment nRooms
|
|
numberRooms = (*thisHouse)->nRooms;
|
|
previousRoom = thisRoomNumber;
|
|
thisRoomNumber = numberRooms - 1;
|
|
}
|
|
else
|
|
{
|
|
previousRoom = thisRoomNumber;
|
|
thisRoomNumber = availableRoom;
|
|
}
|
|
|
|
if (noRoomAtAll)
|
|
(*thisHouse)->firstRoom = thisRoomNumber;
|
|
|
|
CopyThisRoomToRoom();
|
|
UpdateEditWindowTitle();
|
|
noRoomAtAll = false;
|
|
fileDirty = true;
|
|
UpdateMenus(false);
|
|
|
|
const KeyDownStates *theKeys = PortabilityLayer::InputManager::GetInstance()->GetKeys();
|
|
|
|
if (theKeys->IsSet(PL_KEY_EITHER_SPECIAL(kShift)))
|
|
newRoomNow = false;
|
|
else
|
|
newRoomNow = autoRoomEdit; // Flag to bring up RoomInfo
|
|
|
|
return (true);
|
|
}
|
|
#endif
|
|
|
|
//-------------------------------------------------------------- ReadyBackground
|
|
|
|
void ReadyBackground (short theID, short *theTiles)
|
|
{
|
|
Rect src, dest;
|
|
THandle<BitmapImage> thePicture;
|
|
short i;
|
|
|
|
if ((noRoomAtAll) || (!houseUnlocked))
|
|
{
|
|
PortabilityLayer::ResolveCachingColor ltGrayColor = LtGrayForeColor();
|
|
PortabilityLayer::ResolveCachingColor blackColor = StdColors::Black();
|
|
|
|
workSrcMap->FillRect(workSrcRect, ltGrayColor);
|
|
|
|
PortabilityLayer::RenderedFont *appFont = GetFont(PortabilityLayer::FontPresets::kApplication9);
|
|
|
|
const Point textPoint = Point::Create(10, 20);
|
|
if (houseUnlocked)
|
|
workSrcMap->DrawString(textPoint, PSTR("No rooms"), blackColor, appFont);
|
|
else
|
|
workSrcMap->DrawString(textPoint, PSTR("Nothing to show"), blackColor, appFont);
|
|
|
|
CopyBits((BitMap *)*GetGWorldPixMap(workSrcMap),
|
|
(BitMap *)*GetGWorldPixMap(backSrcMap),
|
|
&workSrcRect, &workSrcRect, srcCopy);
|
|
return;
|
|
}
|
|
|
|
thePicture = LoadHouseResource('PICT', theID).StaticCast<BitmapImage>();
|
|
if (thePicture == nil)
|
|
{
|
|
thePicture = LoadHouseResource('Date', theID).StaticCast<BitmapImage>();
|
|
if (thePicture == nil)
|
|
{
|
|
YellowAlert(kYellowNoBackground, 0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
dest = (*thePicture)->GetRect();
|
|
QOffsetRect(&dest, -dest.left, -dest.top);
|
|
workSrcMap->DrawPicture(thePicture, dest);
|
|
thePicture.Dispose();
|
|
|
|
QSetRect(&src, 0, 0, kTileWide, kTileHigh);
|
|
QSetRect(&dest, 0, 0, kTileWide, kTileHigh);
|
|
for (i = 0; i < kNumTiles; i++)
|
|
{
|
|
src.left = theTiles[i] * kTileWide;
|
|
src.right = src.left + kTileWide;
|
|
CopyBits((BitMap *)*GetGWorldPixMap(workSrcMap),
|
|
(BitMap *)*GetGWorldPixMap(backSrcMap),
|
|
&src, &dest, srcCopy);
|
|
QOffsetRect(&dest, kTileWide, 0);
|
|
}
|
|
|
|
QSetRect(&src, 0, 0, kRoomWide, kTileHigh);
|
|
QSetRect(&dest, 0, 0, kRoomWide, kTileHigh);
|
|
CopyBits((BitMap *)*GetGWorldPixMap(backSrcMap),
|
|
(BitMap *)*GetGWorldPixMap(workSrcMap),
|
|
&src, &dest, srcCopy);
|
|
}
|
|
|
|
//-------------------------------------------------------------- ReflectCurrentRoom
|
|
|
|
void ReflectCurrentRoom (Boolean forceMapRedraw)
|
|
{
|
|
#ifndef COMPILEDEMO
|
|
if (theMode != kEditMode)
|
|
return;
|
|
|
|
if ((noRoomAtAll) || (!houseUnlocked))
|
|
{
|
|
CenterMapOnRoom(64, 1);
|
|
UpdateMapWindow();
|
|
}
|
|
else
|
|
{
|
|
if ((!ThisRoomVisibleOnMap()) || (forceMapRedraw))
|
|
{
|
|
CenterMapOnRoom(thisRoom->suite, thisRoom->floor);
|
|
UpdateMapWindow(); // whole map window redrawm
|
|
}
|
|
else
|
|
{
|
|
FindNewActiveRoomRect(); // find newly selected room rect
|
|
FlagMapRoomsForUpdate(); // redraw only the portions required
|
|
}
|
|
}
|
|
GenerateRetroLinks();
|
|
UpdateEditWindowTitle();
|
|
ReadyBackground(thisRoom->background, thisRoom->tiles);
|
|
GetThisRoomsObjRects();
|
|
DrawThisRoomsObjects();
|
|
|
|
UpdateMainWindow();
|
|
#endif
|
|
}
|
|
|
|
//-------------------------------------------------------------- CopyRoomToThisRoom
|
|
|
|
void CopyRoomToThisRoom (short roomNumber)
|
|
{
|
|
if (roomNumber == -1)
|
|
return;
|
|
|
|
CopyThisRoomToRoom(); // copy back to house
|
|
ForceThisRoom(roomNumber); // load new room from house
|
|
}
|
|
|
|
//-------------------------------------------------------------- CopyThisRoomToRoom
|
|
|
|
void CopyThisRoomToRoom (void)
|
|
{
|
|
char tagByte;
|
|
|
|
if ((noRoomAtAll) || (thisRoomNumber == -1))
|
|
return;
|
|
|
|
(*thisHouse)->rooms[thisRoomNumber] = *thisRoom; // copy back to house
|
|
}
|
|
|
|
//-------------------------------------------------------------- ForceThisRoom
|
|
|
|
void ForceThisRoom (short roomNumber)
|
|
{
|
|
char tagByte;
|
|
|
|
if (roomNumber == -1)
|
|
return;
|
|
|
|
if (roomNumber < (*thisHouse)->nRooms)
|
|
*thisRoom = (*thisHouse)->rooms[roomNumber];
|
|
else
|
|
YellowAlert(kYellowIllegalRoomNum, 0);
|
|
|
|
previousRoom = thisRoomNumber;
|
|
thisRoomNumber = roomNumber;
|
|
}
|
|
|
|
//-------------------------------------------------------------- RoomExists
|
|
|
|
Boolean RoomExists (short suite, short floor, short *roomNum)
|
|
{
|
|
// pass in a suite and floor; returns true is it is a legitimate room
|
|
houseType *thisHousePtr;
|
|
short i;
|
|
char wasState;
|
|
Boolean foundIt;
|
|
|
|
foundIt = false;
|
|
|
|
if (suite < 0)
|
|
return (foundIt);
|
|
|
|
thisHousePtr = *thisHouse;
|
|
|
|
for (i = 0; i < numberRooms; i++)
|
|
{
|
|
if ((thisHousePtr->rooms[i].floor == floor) &&
|
|
(thisHousePtr->rooms[i].suite == suite))
|
|
{
|
|
foundIt = true;
|
|
*roomNum = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (foundIt);
|
|
}
|
|
|
|
//-------------------------------------------------------------- RoomNumExists
|
|
|
|
Boolean RoomNumExists (short roomNum)
|
|
{
|
|
short floor, suite, whoCares;
|
|
Boolean exists;
|
|
|
|
exists = false;
|
|
if (GetRoomFloorSuite(roomNum, &floor, &suite))
|
|
exists = RoomExists(suite, floor, &whoCares);
|
|
|
|
return (exists);
|
|
}
|
|
|
|
//-------------------------------------------------------------- DeleteRoom
|
|
|
|
void DeleteRoom (Boolean doWarn)
|
|
{
|
|
#ifndef COMPILEDEMO
|
|
short wasFloor, wasSuite;
|
|
char wasState;
|
|
Boolean firstDeleted;
|
|
|
|
if ((theMode != kEditMode) || (noRoomAtAll))
|
|
return;
|
|
|
|
if (doWarn)
|
|
{
|
|
if (!QueryDeleteRoom())
|
|
return;
|
|
}
|
|
|
|
DeselectObject();
|
|
|
|
wasFloor = (*thisHouse)->rooms[thisRoomNumber].floor;
|
|
wasSuite = (*thisHouse)->rooms[thisRoomNumber].suite;
|
|
firstDeleted = ((*thisHouse)->firstRoom == thisRoomNumber); // is room "first"
|
|
thisRoom->suite = kRoomIsEmpty;
|
|
(*thisHouse)->rooms[thisRoomNumber].suite = kRoomIsEmpty;
|
|
|
|
noRoomAtAll = (RealRoomNumberCount() == 0); // see if now no rooms
|
|
if (noRoomAtAll)
|
|
thisRoomNumber = kRoomIsEmpty;
|
|
else
|
|
SetToNearestNeighborRoom(wasFloor, wasSuite);
|
|
|
|
if (firstDeleted)
|
|
{
|
|
(*thisHouse)->firstRoom = thisRoomNumber;
|
|
}
|
|
|
|
newRoomNow = false;
|
|
fileDirty = true;
|
|
UpdateMenus(false);
|
|
ReflectCurrentRoom(false);
|
|
#endif
|
|
}
|
|
|
|
//-------------------------------------------------------------- QueryDeleteRoom
|
|
|
|
#ifndef COMPILEDEMO
|
|
Boolean QueryDeleteRoom (void)
|
|
{
|
|
short hitWhat;
|
|
|
|
// CenterAlert(kDeleteRoomAlert);
|
|
hitWhat = PortabilityLayer::DialogManager::GetInstance()->DisplayAlert(kDeleteRoomAlert, nullptr);
|
|
if (hitWhat == kYesDoDeleteRoom)
|
|
return (true);
|
|
else
|
|
return (false);
|
|
}
|
|
#endif
|
|
|
|
//-------------------------------------------------------------- DoesNeighborRoomExist
|
|
|
|
short DoesNeighborRoomExist (short whichNeighbor)
|
|
{
|
|
#ifndef COMPILEDEMO
|
|
short newH, newV, newRoomNumber;
|
|
|
|
if (theMode != kEditMode)
|
|
return(-1);
|
|
|
|
newH = thisRoom->suite;
|
|
newV = thisRoom->floor;
|
|
|
|
switch (whichNeighbor)
|
|
{
|
|
case kRoomAbove:
|
|
newV++;
|
|
break;
|
|
|
|
case kRoomBelow:
|
|
newV--;
|
|
break;
|
|
|
|
case kRoomToRight:
|
|
newH++;
|
|
break;
|
|
|
|
case kRoomToLeft:
|
|
newH--;
|
|
break;
|
|
}
|
|
|
|
if (RoomExists(newH, newV, &newRoomNumber))
|
|
return (newRoomNumber);
|
|
else
|
|
return (-1);
|
|
#endif
|
|
}
|
|
|
|
//-------------------------------------------------------------- SelectNeighborRoom
|
|
|
|
void SelectNeighborRoom (short whichNeighbor)
|
|
{
|
|
#ifndef COMPILEDEMO
|
|
short newRoomNumber;
|
|
|
|
newRoomNumber = DoesNeighborRoomExist(whichNeighbor);
|
|
|
|
if (newRoomNumber != -1)
|
|
{
|
|
DeselectObject();
|
|
CopyRoomToThisRoom(newRoomNumber);
|
|
ReflectCurrentRoom(false);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//-------------------------------------------------------------- GetNeighborRoomNumber
|
|
|
|
short GetNeighborRoomNumber (short which)
|
|
{
|
|
short hDelta, vDelta, i;
|
|
short roomH, roomV;
|
|
short roomNum;
|
|
char wasState;
|
|
|
|
switch (which)
|
|
{
|
|
case kCentralRoom:
|
|
hDelta = 0;
|
|
vDelta = 0;
|
|
break;
|
|
|
|
case kNorthRoom:
|
|
hDelta = 0;
|
|
vDelta = 1;
|
|
break;
|
|
|
|
case kNorthEastRoom:
|
|
hDelta = 1;
|
|
vDelta = 1;
|
|
break;
|
|
|
|
case kEastRoom:
|
|
hDelta = 1;
|
|
vDelta = 0;
|
|
break;
|
|
|
|
case kSouthEastRoom:
|
|
hDelta = 1;
|
|
vDelta = -1;
|
|
break;
|
|
|
|
case kSouthRoom:
|
|
hDelta = 0;
|
|
vDelta = -1;
|
|
break;
|
|
|
|
case kSouthWestRoom:
|
|
hDelta = -1;
|
|
vDelta = -1;
|
|
break;
|
|
|
|
case kWestRoom:
|
|
hDelta = -1;
|
|
vDelta = 0;
|
|
break;
|
|
|
|
case kNorthWestRoom:
|
|
hDelta = -1;
|
|
vDelta = 1;
|
|
break;
|
|
}
|
|
|
|
roomNum = kRoomIsEmpty;
|
|
roomH = (*thisHouse)->rooms[thisRoomNumber].suite + hDelta;
|
|
roomV = (*thisHouse)->rooms[thisRoomNumber].floor + vDelta;
|
|
|
|
for (i = 0; i < numberRooms; i++)
|
|
{
|
|
if (((*thisHouse)->rooms[i].suite == roomH) &&
|
|
((*thisHouse)->rooms[i].floor == roomV))
|
|
{
|
|
roomNum = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (roomNum);
|
|
}
|
|
|
|
//-------------------------------------------------------------- SetToNearestNeighborRoom
|
|
|
|
void SetToNearestNeighborRoom (short wasFloor, short wasSuite)
|
|
{
|
|
// searches in a clockwise spiral pattern (from thisRoom) for aÉ
|
|
// legitimate neighboring room - then sets thisRoom to it
|
|
short distance, h, v;
|
|
short hStep, vStep;
|
|
short testRoomNum, testH, testV;
|
|
char wasState;
|
|
Boolean finished;
|
|
|
|
finished = false;
|
|
distance = 1; // we begin our walk a distance of one from source room
|
|
h = -1; // we begin with the neighbor to the leftÉ
|
|
v = 0; // and on the same floor
|
|
hStep = 0; // we don't 'walk' left or rightÉ
|
|
vStep = -1; // instead, we 'walk' up
|
|
|
|
do
|
|
{
|
|
testH = wasSuite + h;
|
|
testV = wasFloor + v;
|
|
|
|
if (RoomExists(testH, testV, &testRoomNum)) // if a legitimate room
|
|
{
|
|
CopyRoomToThisRoom(testRoomNum);
|
|
finished = true;
|
|
}
|
|
else
|
|
{
|
|
h += hStep;
|
|
v += vStep;
|
|
if ((h > distance) || (h < -distance) || (v > distance) || (v < -distance))
|
|
{ // we have walked beyond the bounds of our spiral
|
|
if ((hStep == -1) && (vStep == 0)) // we expand our spiral out
|
|
{
|
|
distance++;
|
|
hStep = 0; // begin travelling up again
|
|
vStep = -1;
|
|
}
|
|
else
|
|
{
|
|
h -= hStep; // first, back up a step
|
|
v -= vStep;
|
|
|
|
if (hStep == 0) // we were travelling up or down
|
|
{
|
|
if (vStep == -1) // we were travelling upÉ
|
|
hStep = 1; // so begin travelling right
|
|
else // we were travelling downÉ
|
|
hStep = -1; // so begin travelling left
|
|
vStep = 0;
|
|
}
|
|
else
|
|
{
|
|
hStep = 0; // begin travelling down
|
|
vStep = 1;
|
|
}
|
|
h += hStep; // proceed a step now
|
|
v += vStep;
|
|
}
|
|
}
|
|
}
|
|
} while (!finished);
|
|
}
|
|
|
|
//-------------------------------------------------------------- GetRoomFloorSuite
|
|
|
|
Boolean GetRoomFloorSuite (short room, short *floor, short *suite)
|
|
{
|
|
char wasState;
|
|
Boolean isRoom;
|
|
|
|
if ((*thisHouse)->rooms[room].suite == kRoomIsEmpty)
|
|
{
|
|
*floor = 0;
|
|
*suite = kRoomIsEmpty;
|
|
isRoom = false;
|
|
}
|
|
else
|
|
{
|
|
*suite = (*thisHouse)->rooms[room].suite;
|
|
*floor = (*thisHouse)->rooms[room].floor;
|
|
isRoom = true;
|
|
}
|
|
|
|
return (isRoom);
|
|
}
|
|
|
|
//-------------------------------------------------------------- GetRoomNumber
|
|
|
|
short GetRoomNumber (short floor, short suite)
|
|
{
|
|
// pass in a floor and suite; returns the room index into the house file
|
|
short roomNum, i;
|
|
char wasState;
|
|
|
|
roomNum = kRoomIsEmpty;
|
|
|
|
for (i = 0; i < numberRooms; i++)
|
|
{
|
|
if (((*thisHouse)->rooms[i].suite == suite) &&
|
|
((*thisHouse)->rooms[i].floor == floor))
|
|
{
|
|
roomNum = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (roomNum);
|
|
}
|
|
|
|
//-------------------------------------------------------------- IsRoomAStructure
|
|
|
|
Boolean IsRoomAStructure (short roomNum)
|
|
{
|
|
char wasState;
|
|
Boolean isStructure;
|
|
|
|
if (roomNum == kRoomIsEmpty)
|
|
return (false);
|
|
|
|
if ((*thisHouse)->rooms[roomNum].background >= kUserBackground)
|
|
{
|
|
if ((*thisHouse)->rooms[roomNum].bounds != 0)
|
|
{
|
|
isStructure = (((*thisHouse)->rooms[roomNum].bounds & 32) == 32);
|
|
}
|
|
else
|
|
{
|
|
if ((*thisHouse)->rooms[roomNum].background < kUserStructureRange)
|
|
isStructure = true;
|
|
else
|
|
isStructure = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch ((*thisHouse)->rooms[roomNum].background)
|
|
{
|
|
case kPaneledRoom:
|
|
case kSimpleRoom:
|
|
case kChildsRoom:
|
|
case kAsianRoom:
|
|
case kUnfinishedRoom:
|
|
case kSwingersRoom:
|
|
case kBathroom:
|
|
case kLibrary:
|
|
case kSkywalk:
|
|
case kRoof:
|
|
isStructure = true;
|
|
break;
|
|
|
|
default:
|
|
isStructure = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (isStructure);
|
|
}
|
|
|
|
//-------------------------------------------------------------- DetermineRoomOpenings
|
|
|
|
void DetermineRoomOpenings (void)
|
|
{
|
|
short whichBack, leftTile, rightTile;
|
|
short boundsCode;
|
|
|
|
whichBack = thisRoom->background;
|
|
leftTile = thisRoom->tiles[0];
|
|
rightTile = thisRoom->tiles[kNumTiles - 1];
|
|
|
|
if (whichBack >= kUserBackground)
|
|
{
|
|
if (thisRoom->bounds != 0)
|
|
boundsCode = thisRoom->bounds >> 1;
|
|
else
|
|
boundsCode = GetOriginalBounding(whichBack);
|
|
leftOpen = ((boundsCode & 0x0001) == 0x0001);
|
|
rightOpen = ((boundsCode & 0x0004) == 0x0004);
|
|
|
|
if (leftOpen)
|
|
leftThresh = kNoLeftWallLimit;
|
|
else
|
|
leftThresh = kLeftWallLimit;
|
|
|
|
if (rightOpen)
|
|
rightThresh = kNoRightWallLimit;
|
|
else
|
|
rightThresh = kRightWallLimit;
|
|
}
|
|
else
|
|
{
|
|
switch (whichBack)
|
|
{
|
|
case kSimpleRoom:
|
|
case kPaneledRoom:
|
|
case kBasement:
|
|
case kChildsRoom:
|
|
case kAsianRoom:
|
|
case kUnfinishedRoom:
|
|
case kSwingersRoom:
|
|
case kBathroom:
|
|
case kLibrary:
|
|
case kSky:
|
|
if (leftTile == 0)
|
|
leftThresh = kLeftWallLimit;
|
|
else
|
|
leftThresh = kNoLeftWallLimit;
|
|
if (rightTile == (kNumTiles - 1))
|
|
rightThresh = kRightWallLimit;
|
|
else
|
|
rightThresh = kNoRightWallLimit;
|
|
leftOpen = (leftTile != 0);
|
|
rightOpen = (rightTile != (kNumTiles - 1));
|
|
break;
|
|
|
|
case kDirt:
|
|
if (leftTile == 1)
|
|
leftThresh = kLeftWallLimit;
|
|
else
|
|
leftThresh = kNoLeftWallLimit;
|
|
if (rightTile == (kNumTiles - 1))
|
|
rightThresh = kRightWallLimit;
|
|
else
|
|
rightThresh = kNoRightWallLimit;
|
|
leftOpen = (leftTile != 0);
|
|
rightOpen = (rightTile != (kNumTiles - 1));
|
|
break;
|
|
|
|
case kMeadow:
|
|
if (leftTile == 6)
|
|
leftThresh = kLeftWallLimit;
|
|
else
|
|
leftThresh = kNoLeftWallLimit;
|
|
if (rightTile == 7)
|
|
rightThresh = kRightWallLimit;
|
|
else
|
|
rightThresh = kNoRightWallLimit;
|
|
leftOpen = (leftTile != 6);
|
|
rightOpen = (rightTile != 7);
|
|
break;
|
|
|
|
case kGarden:
|
|
case kSkywalk:
|
|
case kField:
|
|
case kStratosphere:
|
|
case kStars:
|
|
leftThresh = kNoLeftWallLimit;
|
|
rightThresh = kNoRightWallLimit;
|
|
leftOpen = true;
|
|
rightOpen = true;
|
|
break;
|
|
|
|
default:
|
|
if (leftTile == 0)
|
|
leftThresh = kLeftWallLimit;
|
|
else
|
|
leftThresh = kNoLeftWallLimit;
|
|
|
|
if (rightTile == (kNumTiles - 1))
|
|
rightThresh = kRightWallLimit;
|
|
else
|
|
rightThresh = kNoRightWallLimit;
|
|
|
|
leftOpen = (leftTile != 0);
|
|
rightOpen = (rightTile != (kNumTiles - 1));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (DoesRoomHaveFloor())
|
|
bottomOpen = false;
|
|
else
|
|
bottomOpen = true;
|
|
|
|
if (DoesRoomHaveCeiling())
|
|
topOpen = false;
|
|
else
|
|
topOpen = true;
|
|
}
|
|
|
|
//-------------------------------------------------------------- GetOriginalBounding
|
|
|
|
short GetOriginalBounding (short theID)
|
|
{
|
|
boundsHand boundsRes;
|
|
short boundCode;
|
|
|
|
boundsRes = LoadHouseResource('bnds', theID).StaticCast<boundsType>();
|
|
if (boundsRes == nil)
|
|
{
|
|
if (PictIDExists(theID))
|
|
YellowAlert(kYellowNoBoundsRes, 0);
|
|
boundCode = 0;
|
|
}
|
|
else
|
|
{
|
|
if (boundsRes.MMBlock()->m_size != sizeof(boundsType))
|
|
return 0; // Corrupted resource
|
|
|
|
boundCode = 0;
|
|
if ((*boundsRes)->left)
|
|
boundCode += 1;
|
|
if ((*boundsRes)->top)
|
|
boundCode += 2;
|
|
if ((*boundsRes)->right)
|
|
boundCode += 4;
|
|
if ((*boundsRes)->bottom)
|
|
boundCode += 8;
|
|
boundsRes.Dispose();
|
|
}
|
|
|
|
return (boundCode);
|
|
}
|
|
|
|
//-------------------------------------------------------------- GetNumberOfLights
|
|
|
|
short GetNumberOfLights (short where)
|
|
{
|
|
houseType *thisHousePtr;
|
|
short i, count;
|
|
char wasState;
|
|
|
|
if (theMode == kEditMode)
|
|
{
|
|
switch (thisRoom->background)
|
|
{
|
|
case kGarden:
|
|
case kSkywalk:
|
|
case kMeadow:
|
|
case kField:
|
|
case kRoof:
|
|
case kSky:
|
|
case kStratosphere:
|
|
case kStars:
|
|
count = 1;
|
|
break;
|
|
|
|
case kDirt:
|
|
count = 0;
|
|
if ((thisRoom->tiles[0] == 0) && (thisRoom->tiles[1] == 0) &&
|
|
(thisRoom->tiles[2] == 0) && (thisRoom->tiles[3] == 0) &&
|
|
(thisRoom->tiles[4] == 0) && (thisRoom->tiles[5] == 0) &&
|
|
(thisRoom->tiles[6] == 0) && (thisRoom->tiles[7] == 0))
|
|
count = 1;
|
|
break;
|
|
|
|
default:
|
|
count = 0;
|
|
break;
|
|
}
|
|
if (count == 0)
|
|
{
|
|
for (i = 0; i < kMaxRoomObs; i++)
|
|
{
|
|
switch (thisRoom->objects[i].what)
|
|
{
|
|
case kDoorInLf:
|
|
case kDoorInRt:
|
|
case kWindowInLf:
|
|
case kWindowInRt:
|
|
case kWallWindow:
|
|
count++;
|
|
break;
|
|
|
|
case kCeilingLight:
|
|
case kLightBulb:
|
|
case kTableLamp:
|
|
case kHipLamp:
|
|
case kDecoLamp:
|
|
case kFlourescent:
|
|
case kTrackLight:
|
|
case kInvisLight:
|
|
if (thisRoom->objects[i].data.f.initial)
|
|
count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
thisHousePtr = *thisHouse;
|
|
switch (thisHousePtr->rooms[where].background)
|
|
{
|
|
case kGarden:
|
|
case kSkywalk:
|
|
case kMeadow:
|
|
case kField:
|
|
case kRoof:
|
|
case kSky:
|
|
case kStratosphere:
|
|
case kStars:
|
|
count = 1;
|
|
break;
|
|
|
|
case kDirt:
|
|
count = 0;
|
|
if ((thisHousePtr->rooms[where].tiles[0] == 0) &&
|
|
(thisHousePtr->rooms[where].tiles[1] == 0) &&
|
|
(thisHousePtr->rooms[where].tiles[2] == 0) &&
|
|
(thisHousePtr->rooms[where].tiles[3] == 0) &&
|
|
(thisHousePtr->rooms[where].tiles[4] == 0) &&
|
|
(thisHousePtr->rooms[where].tiles[5] == 0) &&
|
|
(thisHousePtr->rooms[where].tiles[6] == 0) &&
|
|
(thisHousePtr->rooms[where].tiles[7] == 0))
|
|
count = 1;
|
|
break;
|
|
|
|
default:
|
|
count = 0;
|
|
break;
|
|
}
|
|
if (count == 0)
|
|
{
|
|
for (i = 0; i < kMaxRoomObs; i++)
|
|
{
|
|
switch (thisHousePtr->rooms[where].objects[i].what)
|
|
{
|
|
case kDoorInLf:
|
|
case kDoorInRt:
|
|
case kWindowInLf:
|
|
case kWindowInRt:
|
|
case kWallWindow:
|
|
count++;
|
|
break;
|
|
|
|
case kCeilingLight:
|
|
case kLightBulb:
|
|
case kTableLamp:
|
|
case kHipLamp:
|
|
case kDecoLamp:
|
|
case kFlourescent:
|
|
case kTrackLight:
|
|
case kInvisLight:
|
|
if (thisHousePtr->rooms[where].objects[i].data.f.state)
|
|
count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return (count);
|
|
}
|
|
|
|
//-------------------------------------------------------------- IsShadowVisible
|
|
|
|
Boolean IsShadowVisible (void)
|
|
{
|
|
short boundsCode;
|
|
Boolean hasFloor;
|
|
|
|
if (thisRoom->background >= kUserBackground)
|
|
{
|
|
if (thisRoom->bounds != 0) // is this a version 2.0 house?
|
|
boundsCode = (thisRoom->bounds >> 1);
|
|
else
|
|
boundsCode = GetOriginalBounding(thisRoom->background);
|
|
hasFloor = ((boundsCode & 0x0008) != 0x0008);
|
|
}
|
|
else
|
|
{
|
|
switch (thisRoom->background)
|
|
{
|
|
case kRoof:
|
|
case kSky:
|
|
case kStratosphere:
|
|
case kStars:
|
|
hasFloor = false;
|
|
break;
|
|
|
|
default:
|
|
hasFloor = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (hasFloor);
|
|
}
|
|
|
|
//-------------------------------------------------------------- DoesRoomHaveFloor
|
|
|
|
Boolean DoesRoomHaveFloor (void)
|
|
{
|
|
short boundsCode;
|
|
Boolean hasFloor;
|
|
|
|
if (thisRoom->background >= kUserBackground)
|
|
{
|
|
if (thisRoom->bounds != 0) // is this a version 2.0 house?
|
|
boundsCode = (thisRoom->bounds >> 1);
|
|
else
|
|
boundsCode = GetOriginalBounding(thisRoom->background);
|
|
hasFloor = ((boundsCode & 0x0008) != 0x0008);
|
|
}
|
|
else
|
|
{
|
|
switch (thisRoom->background)
|
|
{
|
|
case kSky:
|
|
case kStratosphere:
|
|
case kStars:
|
|
hasFloor = false;
|
|
break;
|
|
|
|
default:
|
|
hasFloor = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return (hasFloor);
|
|
}
|
|
|
|
//-------------------------------------------------------------- DoesRoomHaveCeiling
|
|
|
|
Boolean DoesRoomHaveCeiling (void)
|
|
{
|
|
short boundsCode;
|
|
Boolean hasCeiling;
|
|
|
|
if (thisRoom->background >= kUserBackground)
|
|
{
|
|
if (thisRoom->bounds != 0) // is this a version 2.0 house?
|
|
boundsCode = (thisRoom->bounds >> 1);
|
|
else
|
|
boundsCode = GetOriginalBounding(thisRoom->background);
|
|
hasCeiling = ((boundsCode & 0x0002) != 0x0002);
|
|
}
|
|
else
|
|
{
|
|
switch (thisRoom->background)
|
|
{
|
|
case kGarden:
|
|
case kMeadow:
|
|
case kField:
|
|
case kRoof:
|
|
case kSky:
|
|
case kStratosphere:
|
|
case kStars:
|
|
hasCeiling = false;
|
|
break;
|
|
|
|
default:
|
|
hasCeiling = true;
|
|
break;
|
|
}
|
|
}
|
|
return (hasCeiling);
|
|
}
|
|
|