|
|
|
@ -96,10 +96,6 @@ int numobjfiles; |
|
|
|
/** Tracks progress through the tome sequence that spawns Na-Krul (see OperateNakrulBook()) */ |
|
|
|
/** Tracks progress through the tome sequence that spawns Na-Krul (see OperateNakrulBook()) */ |
|
|
|
int NaKrulTomeSequence; |
|
|
|
int NaKrulTomeSequence; |
|
|
|
|
|
|
|
|
|
|
|
/** Specifies the X-coordinate delta between barrels. */ |
|
|
|
|
|
|
|
int bxadd[8] = { -1, 0, 1, -1, 1, -1, 0, 1 }; |
|
|
|
|
|
|
|
/** Specifies the Y-coordinate delta between barrels. */ |
|
|
|
|
|
|
|
int byadd[8] = { -1, -1, -1, 0, 0, 1, 1, 1 }; |
|
|
|
|
|
|
|
/** Maps from shrine_id to shrine name. */ |
|
|
|
/** Maps from shrine_id to shrine name. */ |
|
|
|
const char *const ShrineNames[] = { |
|
|
|
const char *const ShrineNames[] = { |
|
|
|
// TRANSLATORS: Shrine Name Block
|
|
|
|
// TRANSLATORS: Shrine Name Block
|
|
|
|
@ -291,19 +287,36 @@ _speech_id StoryText[3][3] = { |
|
|
|
{ TEXT_BOOK31, TEXT_BOOK32, TEXT_BOOK33 } |
|
|
|
{ TEXT_BOOK31, TEXT_BOOK32, TEXT_BOOK33 } |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
bool RndLocOk(int xp, int yp) |
|
|
|
bool IsAvailableObjectPosition(Point position) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (dMonster[xp][yp] != 0) |
|
|
|
return dMonster[position.x][position.y] == 0 |
|
|
|
return false; |
|
|
|
&& dPlayer[position.x][position.y] == 0 |
|
|
|
if (dPlayer[xp][yp] != 0) |
|
|
|
&& !IsObjectAtPosition(position) |
|
|
|
return false; |
|
|
|
&& !TileContainsSetPiece(position) |
|
|
|
if (IsObjectAtPosition({ xp, yp })) |
|
|
|
&& !nSolidTable[dPiece[position.x][position.y]] |
|
|
|
return false; |
|
|
|
&& (IsNoneOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CRYPT) || dPiece[position.x][position.y] <= 126 || dPiece[position.x][position.y] >= 144); |
|
|
|
if (TileContainsSetPiece({ xp, yp })) |
|
|
|
} |
|
|
|
return false; |
|
|
|
|
|
|
|
if (nSolidTable[dPiece[xp][yp]]) |
|
|
|
bool IsAvailableObjectPosition(Rectangle area) |
|
|
|
return false; |
|
|
|
{ |
|
|
|
return IsNoneOf(leveltype, DTYPE_CATHEDRAL, DTYPE_CRYPT) || dPiece[xp][yp] <= 126 || dPiece[xp][yp] >= 144; |
|
|
|
for (Point testPosition : PointsInRectangleRange(area)) { |
|
|
|
|
|
|
|
if (!IsAvailableObjectPosition(testPosition)) { |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Point GetRandomAvailableObjectPosition() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
|
|
|
Point position = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 }; |
|
|
|
|
|
|
|
if (IsAvailableObjectPosition(position)) |
|
|
|
|
|
|
|
return position; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool CanPlaceWallTrap(int xp, int yp) |
|
|
|
bool CanPlaceWallTrap(int xp, int yp) |
|
|
|
@ -316,24 +329,15 @@ bool CanPlaceWallTrap(int xp, int yp) |
|
|
|
return nTrapTable[dPiece[xp][yp]]; |
|
|
|
return nTrapTable[dPiece[xp][yp]]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void InitRndLocObj(int min, int max, _object_id objtype) |
|
|
|
void InitRndLocObj(int min, int max, _object_id objtype, int range = 1) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int numobjs = GenerateRnd(max - min) + min; |
|
|
|
int numobjs = GenerateRnd(max - min) + min; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < numobjs; i++) { |
|
|
|
for (int i = 0; i < numobjs; i++) { |
|
|
|
while (true) { |
|
|
|
while (true) { |
|
|
|
int xp = GenerateRnd(80) + 16; |
|
|
|
Point position = GetRandomAvailableObjectPosition(); |
|
|
|
int yp = GenerateRnd(80) + 16; |
|
|
|
if (IsAvailableObjectPosition(Rectangle { position, range })) { |
|
|
|
if (RndLocOk(xp - 1, yp - 1) |
|
|
|
AddObject(objtype, position); |
|
|
|
&& RndLocOk(xp, yp - 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp + 1, yp - 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp - 1, yp) |
|
|
|
|
|
|
|
&& RndLocOk(xp, yp) |
|
|
|
|
|
|
|
&& RndLocOk(xp + 1, yp) |
|
|
|
|
|
|
|
&& RndLocOk(xp - 1, yp + 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp, yp + 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp + 1, yp + 1)) { |
|
|
|
|
|
|
|
AddObject(objtype, { xp, yp }); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -343,57 +347,19 @@ void InitRndLocObj(int min, int max, _object_id objtype) |
|
|
|
void InitRndLocBigObj(int min, int max, _object_id objtype) |
|
|
|
void InitRndLocBigObj(int min, int max, _object_id objtype) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int numobjs = GenerateRnd(max - min) + min; |
|
|
|
int numobjs = GenerateRnd(max - min) + min; |
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < numobjs; i++) { |
|
|
|
for (int i = 0; i < numobjs; i++) { |
|
|
|
while (true) { |
|
|
|
while (true) { |
|
|
|
int xp = GenerateRnd(80) + 16; |
|
|
|
Point position = GetRandomAvailableObjectPosition(); |
|
|
|
int yp = GenerateRnd(80) + 16; |
|
|
|
if (IsAvailableObjectPosition(Rectangle { position + Displacement { 0, -2 }, { 2, 1 } }) |
|
|
|
if (RndLocOk(xp - 1, yp - 2) |
|
|
|
&& IsAvailableObjectPosition(Rectangle { position, 1 })) { |
|
|
|
&& RndLocOk(xp, yp - 2) |
|
|
|
AddObject(objtype, position); |
|
|
|
&& RndLocOk(xp + 1, yp - 2) |
|
|
|
|
|
|
|
&& RndLocOk(xp - 1, yp - 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp, yp - 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp + 1, yp - 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp - 1, yp) |
|
|
|
|
|
|
|
&& RndLocOk(xp, yp) |
|
|
|
|
|
|
|
&& RndLocOk(xp + 1, yp) |
|
|
|
|
|
|
|
&& RndLocOk(xp - 1, yp + 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp, yp + 1) |
|
|
|
|
|
|
|
&& RndLocOk(xp + 1, yp + 1)) { |
|
|
|
|
|
|
|
AddObject(objtype, { xp, yp }); |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void InitRndLocObj5x5(int min, int max, _object_id objtype) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
int numobjs = min + GenerateRnd(max - min); |
|
|
|
|
|
|
|
for (int i = 0; i < numobjs; i++) { |
|
|
|
|
|
|
|
int xp; |
|
|
|
|
|
|
|
int yp; |
|
|
|
|
|
|
|
int cnt = 0; |
|
|
|
|
|
|
|
bool exit = false; |
|
|
|
|
|
|
|
while (!exit) { |
|
|
|
|
|
|
|
exit = true; |
|
|
|
|
|
|
|
xp = GenerateRnd(80) + 16; |
|
|
|
|
|
|
|
yp = GenerateRnd(80) + 16; |
|
|
|
|
|
|
|
for (int n = -2; n <= 2; n++) { |
|
|
|
|
|
|
|
for (int m = -2; m <= 2; m++) { |
|
|
|
|
|
|
|
if (!RndLocOk(xp + m, yp + n)) |
|
|
|
|
|
|
|
exit = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!exit) { |
|
|
|
|
|
|
|
cnt++; |
|
|
|
|
|
|
|
if (cnt > 20000) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
AddObject(objtype, { xp, yp }); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void ClrAllObjects() |
|
|
|
void ClrAllObjects() |
|
|
|
{ |
|
|
|
{ |
|
|
|
memset(Objects, 0, sizeof(Objects)); |
|
|
|
memset(Objects, 0, sizeof(Objects)); |
|
|
|
@ -450,87 +416,47 @@ void AddCandles() |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
void AddBookLever(Rectangle affectedArea, _speech_id msg) |
|
|
|
void AddBookLever(Rectangle affectedArea, _speech_id msg) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int cnt = 0; |
|
|
|
for (int tries = 0; tries < 19999; tries++) { |
|
|
|
Point position; |
|
|
|
Point position = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 }; |
|
|
|
bool exit = false; |
|
|
|
if (IsAvailableObjectPosition(Rectangle { position, 2 })) { |
|
|
|
while (!exit) { |
|
|
|
if (Quests[Q_BLIND].IsAvailable()) |
|
|
|
exit = true; |
|
|
|
AddObject(OBJ_BLINDBOOK, position); |
|
|
|
position = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 }; |
|
|
|
else if (Quests[Q_WARLORD].IsAvailable()) |
|
|
|
for (int n = -2; n <= 2; n++) { |
|
|
|
AddObject(OBJ_STEELTOME, position); |
|
|
|
for (int m = -2; m <= 2; m++) { |
|
|
|
else if (Quests[Q_BLOOD].IsAvailable()) { |
|
|
|
if (!RndLocOk(position.x + m, position.y + n)) |
|
|
|
position = SetPiece.position.megaToWorld() + Displacement { 9, 24 }; |
|
|
|
exit = false; |
|
|
|
AddObject(OBJ_BLOODBOOK, position); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
ObjectAtPosition(position)->InitializeQuestBook(affectedArea, leverid, msg); |
|
|
|
if (!exit) { |
|
|
|
leverid++; |
|
|
|
cnt++; |
|
|
|
break; |
|
|
|
if (cnt > 20000) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (Quests[Q_BLIND].IsAvailable()) |
|
|
|
|
|
|
|
AddObject(OBJ_BLINDBOOK, position); |
|
|
|
|
|
|
|
if (Quests[Q_WARLORD].IsAvailable()) |
|
|
|
|
|
|
|
AddObject(OBJ_STEELTOME, position); |
|
|
|
|
|
|
|
if (Quests[Q_BLOOD].IsAvailable()) { |
|
|
|
|
|
|
|
position = SetPiece.position.megaToWorld() + Displacement { 9, 24 }; |
|
|
|
|
|
|
|
AddObject(OBJ_BLOODBOOK, position); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ObjectAtPosition(position)->InitializeQuestBook(affectedArea, leverid, msg); |
|
|
|
|
|
|
|
leverid++; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void InitRndBarrels() |
|
|
|
void InitRndBarrels(_object_id barrelId = OBJ_BARREL, _object_id explosiveBarrelId = OBJ_BARRELEX) |
|
|
|
{ |
|
|
|
{ |
|
|
|
_object_id barrelId = OBJ_BARREL; |
|
|
|
|
|
|
|
_object_id explosiveBarrelId = OBJ_BARRELEX; |
|
|
|
|
|
|
|
if (leveltype == DTYPE_NEST) { |
|
|
|
|
|
|
|
barrelId = OBJ_POD; |
|
|
|
|
|
|
|
explosiveBarrelId = OBJ_PODEX; |
|
|
|
|
|
|
|
} else if (leveltype == DTYPE_CRYPT) { |
|
|
|
|
|
|
|
barrelId = OBJ_URN; |
|
|
|
|
|
|
|
explosiveBarrelId = OBJ_URNEX; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** number of groups of barrels to generate */ |
|
|
|
/** number of groups of barrels to generate */ |
|
|
|
int numobjs = GenerateRnd(5) + 3; |
|
|
|
int groups = GenerateRnd(5) + 3; |
|
|
|
for (int i = 0; i < numobjs; i++) { |
|
|
|
|
|
|
|
int xp; |
|
|
|
for (int i = 0; i < groups; i++) { |
|
|
|
int yp; |
|
|
|
Point position = GetRandomAvailableObjectPosition(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AddObject(GenerateRnd(4) != 0 ? barrelId : explosiveBarrelId, position); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int barrelsInGroup = 1; |
|
|
|
do { |
|
|
|
do { |
|
|
|
xp = GenerateRnd(80) + 16; |
|
|
|
for (int tries = 0;; tries++) { |
|
|
|
yp = GenerateRnd(80) + 16; |
|
|
|
if (tries >= 3) |
|
|
|
} while (!RndLocOk(xp, yp)); |
|
|
|
return; |
|
|
|
_object_id o = (GenerateRnd(4) != 0) ? barrelId : explosiveBarrelId; |
|
|
|
position += static_cast<Direction>(GenerateRnd(8)); |
|
|
|
AddObject(o, { xp, yp }); |
|
|
|
if (IsAvailableObjectPosition(position)) { |
|
|
|
bool found = true; |
|
|
|
AddObject(GenerateRnd(5) != 0 ? barrelId : explosiveBarrelId, position); |
|
|
|
/** regulates chance to stop placing barrels in current group */ |
|
|
|
barrelsInGroup++; |
|
|
|
int p = 0; |
|
|
|
|
|
|
|
/** number of barrels in current group */ |
|
|
|
|
|
|
|
int c = 1; |
|
|
|
|
|
|
|
while (GenerateRnd(p) == 0 && found) { |
|
|
|
|
|
|
|
/** number of tries of placing next barrel in current group */ |
|
|
|
|
|
|
|
int t = 0; |
|
|
|
|
|
|
|
found = false; |
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
|
|
|
if (t >= 3) |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
int dir = GenerateRnd(8); |
|
|
|
|
|
|
|
xp += bxadd[dir]; |
|
|
|
|
|
|
|
yp += byadd[dir]; |
|
|
|
|
|
|
|
found = RndLocOk(xp, yp); |
|
|
|
|
|
|
|
t++; |
|
|
|
|
|
|
|
if (found) |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
if (found) { |
|
|
|
} while (GenerateRnd(barrelsInGroup / 2) == 0); |
|
|
|
o = (GenerateRnd(5) != 0) ? barrelId : explosiveBarrelId; |
|
|
|
|
|
|
|
AddObject(o, { xp, yp }); |
|
|
|
|
|
|
|
c++; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
p = c / 2; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -804,7 +730,7 @@ void SetupObject(Object &object, Point position, _object_id ot) |
|
|
|
object._oDoorFlag = false; |
|
|
|
object._oDoorFlag = false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AddCryptBook(_object_id ot, int v2, int ox, int oy) |
|
|
|
void AddCryptBook(_object_id ot, int v2, Point position) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (ActiveObjectCount >= MAXOBJECTS) |
|
|
|
if (ActiveObjectCount >= MAXOBJECTS) |
|
|
|
return; |
|
|
|
return; |
|
|
|
@ -812,47 +738,41 @@ void AddCryptBook(_object_id ot, int v2, int ox, int oy) |
|
|
|
int oi = AvailableObjects[0]; |
|
|
|
int oi = AvailableObjects[0]; |
|
|
|
AvailableObjects[0] = AvailableObjects[MAXOBJECTS - 1 - ActiveObjectCount]; |
|
|
|
AvailableObjects[0] = AvailableObjects[MAXOBJECTS - 1 - ActiveObjectCount]; |
|
|
|
ActiveObjects[ActiveObjectCount] = oi; |
|
|
|
ActiveObjects[ActiveObjectCount] = oi; |
|
|
|
dObject[ox][oy] = oi + 1; |
|
|
|
dObject[position.x][position.y] = oi + 1; |
|
|
|
Object &object = Objects[oi]; |
|
|
|
Object &object = Objects[oi]; |
|
|
|
SetupObject(object, { ox, oy }, ot); |
|
|
|
SetupObject(object, position, ot); |
|
|
|
AddCryptObject(object, v2); |
|
|
|
AddCryptObject(object, v2); |
|
|
|
ActiveObjectCount++; |
|
|
|
ActiveObjectCount++; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AddCryptStoryBook(int s) |
|
|
|
Point FindPositionForStoryBook() |
|
|
|
{ |
|
|
|
{ |
|
|
|
int cnt = 0; |
|
|
|
Point position; |
|
|
|
int xp; |
|
|
|
for (int tries = 0; tries < 19999; tries++) { |
|
|
|
int yp; |
|
|
|
position = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 }; |
|
|
|
bool exit = false; |
|
|
|
if (IsAvailableObjectPosition({ position + Displacement { -3, -2 }, { 7, 5 } })) |
|
|
|
while (!exit) { |
|
|
|
break; |
|
|
|
exit = true; |
|
|
|
|
|
|
|
xp = GenerateRnd(80) + 16; |
|
|
|
|
|
|
|
yp = GenerateRnd(80) + 16; |
|
|
|
|
|
|
|
for (int n = -2; n <= 2; n++) { |
|
|
|
|
|
|
|
for (int m = -3; m <= 3; m++) { |
|
|
|
|
|
|
|
if (!RndLocOk(xp + m, yp + n)) |
|
|
|
|
|
|
|
exit = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!exit) { |
|
|
|
|
|
|
|
cnt++; |
|
|
|
|
|
|
|
if (cnt > 20000) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
AddCryptBook(OBJ_L5BOOKS, s, xp, yp); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, { xp - 2, yp + 1 }); |
|
|
|
return position; |
|
|
|
AddObject(OBJ_L5CANDLE, { xp - 2, yp }); |
|
|
|
} |
|
|
|
AddObject(OBJ_L5CANDLE, { xp - 1, yp - 1 }); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, { xp + 1, yp - 1 }); |
|
|
|
void AddCryptStoryBook(int s) |
|
|
|
AddObject(OBJ_L5CANDLE, { xp + 2, yp }); |
|
|
|
{ |
|
|
|
AddObject(OBJ_L5CANDLE, { xp + 2, yp + 1 }); |
|
|
|
Point position = FindPositionForStoryBook(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AddCryptBook(OBJ_L5BOOKS, s, position); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, position + Displacement { -2, 1 }); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, position + Displacement { -2, 0 }); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, position + Displacement { -1, -1 }); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, position + Displacement { 1, -1 }); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, position + Displacement { 2, 0 }); |
|
|
|
|
|
|
|
AddObject(OBJ_L5CANDLE, position + Displacement { 2, 1 }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AddNakrulBook(int a1, int a2, int a3) |
|
|
|
void AddNakrulBook(int a1, int a2, int a3) |
|
|
|
{ |
|
|
|
{ |
|
|
|
AddCryptBook(OBJ_L5BOOKS, a1, a2, a3); |
|
|
|
AddCryptBook(OBJ_L5BOOKS, a1, { a2, a3 }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AddNakrulGate() |
|
|
|
void AddNakrulGate() |
|
|
|
@ -894,33 +814,15 @@ void AddNakrulGate() |
|
|
|
|
|
|
|
|
|
|
|
void AddStoryBooks() |
|
|
|
void AddStoryBooks() |
|
|
|
{ |
|
|
|
{ |
|
|
|
int cnt = 0; |
|
|
|
Point position = FindPositionForStoryBook(); |
|
|
|
int xp; |
|
|
|
|
|
|
|
int yp; |
|
|
|
AddObject(OBJ_STORYBOOK, position); |
|
|
|
bool done = false; |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { -2, 1 }); |
|
|
|
while (!done) { |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { -2, 0 }); |
|
|
|
done = true; |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { -1, -1 }); |
|
|
|
xp = GenerateRnd(80) + 16; |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { 1, -1 }); |
|
|
|
yp = GenerateRnd(80) + 16; |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { 2, 0 }); |
|
|
|
for (int yy = -2; yy <= 2; yy++) { |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { 2, 1 }); |
|
|
|
for (int xx = -3; xx <= 3; xx++) { |
|
|
|
|
|
|
|
if (!RndLocOk(xx + xp, yy + yp)) |
|
|
|
|
|
|
|
done = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!done) { |
|
|
|
|
|
|
|
cnt++; |
|
|
|
|
|
|
|
if (cnt > 20000) |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
AddObject(OBJ_STORYBOOK, { xp, yp }); |
|
|
|
|
|
|
|
AddObject(OBJ_STORYCANDLE, { xp - 2, yp + 1 }); |
|
|
|
|
|
|
|
AddObject(OBJ_STORYCANDLE, { xp - 2, yp }); |
|
|
|
|
|
|
|
AddObject(OBJ_STORYCANDLE, { xp - 1, yp - 1 }); |
|
|
|
|
|
|
|
AddObject(OBJ_STORYCANDLE, { xp + 1, yp - 1 }); |
|
|
|
|
|
|
|
AddObject(OBJ_STORYCANDLE, { xp + 2, yp }); |
|
|
|
|
|
|
|
AddObject(OBJ_STORYCANDLE, { xp + 2, yp + 1 }); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AddHookedBodies(int freq) |
|
|
|
void AddHookedBodies(int freq) |
|
|
|
@ -979,38 +881,27 @@ void AddL4Goodies() |
|
|
|
|
|
|
|
|
|
|
|
void AddLazStand() |
|
|
|
void AddLazStand() |
|
|
|
{ |
|
|
|
{ |
|
|
|
int cnt = 0; |
|
|
|
Point position; |
|
|
|
int xp; |
|
|
|
for (int tries = 0;; tries++) { |
|
|
|
int yp; |
|
|
|
if (tries >= 9999) { |
|
|
|
bool found = false; |
|
|
|
AddObject(OBJ_LAZSTAND, { 1, 1 }); |
|
|
|
while (!found) { |
|
|
|
return; |
|
|
|
found = true; |
|
|
|
|
|
|
|
xp = GenerateRnd(80) + 16; |
|
|
|
|
|
|
|
yp = GenerateRnd(80) + 16; |
|
|
|
|
|
|
|
for (int yy = -3; yy <= 3; yy++) { |
|
|
|
|
|
|
|
for (int xx = -2; xx <= 3; xx++) { |
|
|
|
|
|
|
|
if (!RndLocOk(xp + xx, yp + yy)) |
|
|
|
|
|
|
|
found = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!found) { |
|
|
|
|
|
|
|
cnt++; |
|
|
|
|
|
|
|
if (cnt > 10000) { |
|
|
|
|
|
|
|
InitRndLocObj(1, 1, OBJ_LAZSTAND); |
|
|
|
|
|
|
|
return; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
position = Point { GenerateRnd(80), GenerateRnd(80) } + Displacement { 16, 16 }; |
|
|
|
|
|
|
|
if (IsAvailableObjectPosition({ position + Displacement { -3, -2 }, { 7, 6 } })) |
|
|
|
|
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
AddObject(OBJ_LAZSTAND, { xp, yp }); |
|
|
|
|
|
|
|
AddObject(OBJ_TNUDEM2, { xp, yp + 2 }); |
|
|
|
AddObject(OBJ_LAZSTAND, position); |
|
|
|
AddObject(OBJ_STORYCANDLE, { xp + 1, yp + 2 }); |
|
|
|
AddObject(OBJ_TNUDEM2, position + Displacement { 0, 2 }); |
|
|
|
AddObject(OBJ_TNUDEM3, { xp + 2, yp + 2 }); |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { 1, 2 }); |
|
|
|
AddObject(OBJ_TNUDEW1, { xp, yp - 2 }); |
|
|
|
AddObject(OBJ_TNUDEM3, position + Displacement { 2, 2 }); |
|
|
|
AddObject(OBJ_STORYCANDLE, { xp + 1, yp - 2 }); |
|
|
|
AddObject(OBJ_TNUDEW1, position + Displacement { 0, -2 }); |
|
|
|
AddObject(OBJ_TNUDEW2, { xp + 2, yp - 2 }); |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { 1, -2 }); |
|
|
|
AddObject(OBJ_STORYCANDLE, { xp - 1, yp - 1 }); |
|
|
|
AddObject(OBJ_TNUDEW2, position + Displacement { 2, -2 }); |
|
|
|
AddObject(OBJ_TNUDEW3, { xp - 1, yp }); |
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { -1, -1 }); |
|
|
|
AddObject(OBJ_STORYCANDLE, { xp - 1, yp + 1 }); |
|
|
|
AddObject(OBJ_TNUDEW3, position + Displacement { -1, 0 }); |
|
|
|
|
|
|
|
AddObject(OBJ_STORYCANDLE, position + Displacement { -1, 1 }); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void DeleteObject(int oi, int i) |
|
|
|
void DeleteObject(int oi, int i) |
|
|
|
@ -1341,41 +1232,33 @@ void AddTorturedBody(int i) |
|
|
|
Objects[i]._oPreFlag = true; |
|
|
|
Objects[i]._oPreFlag = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void GetRndObjLoc(int randarea, int *xx, int *yy) |
|
|
|
/**
|
|
|
|
|
|
|
|
* @brief Make 999 attempts at randmly finding a area of the requested size, try a single time more for each size smaller then requested |
|
|
|
|
|
|
|
* @return Found location |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
Point GetRndObjLoc(int randarea) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (randarea == 0) |
|
|
|
Point position; |
|
|
|
return; |
|
|
|
for (int tries = 0;; tries++) { |
|
|
|
|
|
|
|
if (tries > 999 && randarea > 1) |
|
|
|
int tries = 0; |
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
|
|
|
tries++; |
|
|
|
|
|
|
|
if (tries > 1000 && randarea > 1) |
|
|
|
|
|
|
|
randarea--; |
|
|
|
randarea--; |
|
|
|
*xx = GenerateRnd(MAXDUNX); |
|
|
|
position = Point { GenerateRnd(MAXDUNX), GenerateRnd(MAXDUNY) }; |
|
|
|
*yy = GenerateRnd(MAXDUNY); |
|
|
|
if (IsAvailableObjectPosition({ position, { randarea, randarea } })) |
|
|
|
bool failed = false; |
|
|
|
|
|
|
|
for (int i = 0; i < randarea && !failed; i++) { |
|
|
|
|
|
|
|
for (int j = 0; j < randarea && !failed; j++) { |
|
|
|
|
|
|
|
failed = !RndLocOk(i + *xx, j + *yy); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!failed) |
|
|
|
|
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return position; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void AddMushPatch() |
|
|
|
void AddMushPatch() |
|
|
|
{ |
|
|
|
{ |
|
|
|
int y; |
|
|
|
|
|
|
|
int x; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (ActiveObjectCount < MAXOBJECTS) { |
|
|
|
if (ActiveObjectCount < MAXOBJECTS) { |
|
|
|
int i = AvailableObjects[0]; |
|
|
|
int i = AvailableObjects[0]; |
|
|
|
GetRndObjLoc(5, &x, &y); |
|
|
|
Point position = GetRndObjLoc(5); |
|
|
|
dObject[x + 1][y + 1] = -(i + 1); |
|
|
|
dObject[position.x + 1][position.y + 1] = -(i + 1); |
|
|
|
dObject[x + 2][y + 1] = -(i + 1); |
|
|
|
dObject[position.x + 2][position.y + 1] = -(i + 1); |
|
|
|
dObject[x + 1][y + 2] = -(i + 1); |
|
|
|
dObject[position.x + 1][position.y + 2] = -(i + 1); |
|
|
|
AddObject(OBJ_MUSHPATCH, { x + 2, y + 2 }); |
|
|
|
AddObject(OBJ_MUSHPATCH, position + Displacement { 2, 2 }); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ -4492,11 +4375,7 @@ void AddCryptObjects(int x1, int y1, int x2, int y2) |
|
|
|
|
|
|
|
|
|
|
|
void AddSlainHero() |
|
|
|
void AddSlainHero() |
|
|
|
{ |
|
|
|
{ |
|
|
|
int x; |
|
|
|
AddObject(OBJ_SLAINHERO, GetRndObjLoc(5) + Displacement { 2, 2 }); |
|
|
|
int y; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GetRndObjLoc(5, &x, &y); |
|
|
|
|
|
|
|
AddObject(OBJ_SLAINHERO, { x + 2, y + 2 }); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void InitObjects() |
|
|
|
void InitObjects() |
|
|
|
@ -4540,9 +4419,9 @@ void InitObjects() |
|
|
|
} |
|
|
|
} |
|
|
|
if (leveltype == DTYPE_CATACOMBS) { |
|
|
|
if (leveltype == DTYPE_CATACOMBS) { |
|
|
|
if (Quests[Q_ROCK].IsAvailable()) |
|
|
|
if (Quests[Q_ROCK].IsAvailable()) |
|
|
|
InitRndLocObj5x5(1, 1, OBJ_STAND); |
|
|
|
InitRndLocObj(1, 1, OBJ_STAND, 2); |
|
|
|
if (Quests[Q_SCHAMB].IsAvailable()) |
|
|
|
if (Quests[Q_SCHAMB].IsAvailable()) |
|
|
|
InitRndLocObj5x5(1, 1, OBJ_BOOK2R); |
|
|
|
InitRndLocObj(1, 1, OBJ_BOOK2R, 2); |
|
|
|
AddL2Objs(0, 0, MAXDUNX, MAXDUNY); |
|
|
|
AddL2Objs(0, 0, MAXDUNX, MAXDUNY); |
|
|
|
AddL2Torches(); |
|
|
|
AddL2Torches(); |
|
|
|
if (Quests[Q_BLIND].IsAvailable()) { |
|
|
|
if (Quests[Q_BLIND].IsAvailable()) { |
|
|
|
@ -4636,12 +4515,12 @@ void InitObjects() |
|
|
|
AddL4Goodies(); |
|
|
|
AddL4Goodies(); |
|
|
|
} |
|
|
|
} |
|
|
|
if (leveltype == DTYPE_NEST) { |
|
|
|
if (leveltype == DTYPE_NEST) { |
|
|
|
InitRndBarrels(); |
|
|
|
InitRndBarrels(OBJ_POD, OBJ_PODEX); |
|
|
|
} |
|
|
|
} |
|
|
|
if (leveltype == DTYPE_CRYPT) { |
|
|
|
if (leveltype == DTYPE_CRYPT) { |
|
|
|
InitRndLocBigObj(10, 15, OBJ_L5SARC); |
|
|
|
InitRndLocBigObj(10, 15, OBJ_L5SARC); |
|
|
|
AddCryptObjects(0, 0, MAXDUNX, MAXDUNY); |
|
|
|
AddCryptObjects(0, 0, MAXDUNX, MAXDUNY); |
|
|
|
InitRndBarrels(); |
|
|
|
InitRndBarrels(OBJ_URN, OBJ_URNEX); |
|
|
|
} |
|
|
|
} |
|
|
|
InitRndLocObj(5, 10, OBJ_CHEST1); |
|
|
|
InitRndLocObj(5, 10, OBJ_CHEST1); |
|
|
|
InitRndLocObj(3, 6, OBJ_CHEST2); |
|
|
|
InitRndLocObj(3, 6, OBJ_CHEST2); |
|
|
|
@ -4654,7 +4533,7 @@ void InitObjects() |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void SetMapObjects(const uint16_t *dunData, int startx, int starty) |
|
|
|
void SetMapObjects(const uint16_t *dunData, Point start) |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool filesLoaded[65] = {}; |
|
|
|
bool filesLoaded[65] = {}; |
|
|
|
|
|
|
|
|
|
|
|
@ -4672,9 +4551,9 @@ void SetMapObjects(const uint16_t *dunData, int startx, int starty) |
|
|
|
|
|
|
|
|
|
|
|
const uint16_t *objectLayer = &dunData[layer2Offset + width * height * 2]; |
|
|
|
const uint16_t *objectLayer = &dunData[layer2Offset + width * height * 2]; |
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < height; j++) { |
|
|
|
for (int y = 0; y < height; y++) { |
|
|
|
for (int i = 0; i < width; i++) { |
|
|
|
for (int x = 0; x < width; x++) { |
|
|
|
auto objectId = static_cast<uint8_t>(SDL_SwapLE16(objectLayer[j * width + i])); |
|
|
|
auto objectId = static_cast<uint8_t>(SDL_SwapLE16(objectLayer[x + y * width])); |
|
|
|
if (objectId != 0) { |
|
|
|
if (objectId != 0) { |
|
|
|
filesLoaded[AllObjects[ObjTypeConv[objectId]].ofindex] = true; |
|
|
|
filesLoaded[AllObjects[ObjTypeConv[objectId]].ofindex] = true; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -4683,11 +4562,12 @@ void SetMapObjects(const uint16_t *dunData, int startx, int starty) |
|
|
|
|
|
|
|
|
|
|
|
LoadLevelObjects(filesLoaded); |
|
|
|
LoadLevelObjects(filesLoaded); |
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < height; j++) { |
|
|
|
for (int y = 0; y < height; y++) { |
|
|
|
for (int i = 0; i < width; i++) { |
|
|
|
for (int x = 0; x < width; x++) { |
|
|
|
auto objectId = static_cast<uint8_t>(SDL_SwapLE16(objectLayer[j * width + i])); |
|
|
|
auto objectId = static_cast<uint8_t>(SDL_SwapLE16(objectLayer[x + y * width])); |
|
|
|
if (objectId != 0) { |
|
|
|
if (objectId != 0) { |
|
|
|
AddObject(ObjTypeConv[objectId], { startx + 16 + i, starty + 16 + j }); |
|
|
|
AddObject(ObjTypeConv[objectId], start + Displacement { x, y }); |
|
|
|
|
|
|
|
SDL_Log("Object at %dx%d", start.x + x, start.y + y); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|