DM: Rework functions related to Directions in order to make them consistent and remove redundancy

This commit is contained in:
Strangerke 2016-09-11 10:45:20 +02:00
parent f0a6f6b269
commit b17f3490f8
12 changed files with 66 additions and 68 deletions

View File

@ -48,6 +48,13 @@ public:
}
};
const char *Console::debugGetDirectionName(int16 dir) {
static const char *directionNames[] = {"North", "East", "South", "West"};
if (dir < 0 || dir > 3)
return "Invalid direction";
return directionNames[dir];
}
Console::Console(DM::DMEngine* vm) : _vm(vm) {
_debugGodmodeMana = false;
_debugGodmodeHP = false;

View File

@ -45,6 +45,8 @@ private:
bool Cmd_listItems(int argc, const char **argv);
bool Cmd_gimme(int argc, const char **argv);
const char *debugGetDirectionName(int16 dir);
public:
explicit Console(DM::DMEngine *vm);
virtual ~Console(void) {}

View File

@ -68,39 +68,27 @@
#include "dm/sounds.h"
namespace DM {
const char *debugGetDirectionName(Direction dir) {
static const char *directionNames[] = {"North", "East", "South", "West"};
if (dir < 0 || dir > 3)
return "Invalid direction";
return directionNames[dir];
Direction DMEngine::turnDirRight(int16 dir) {
Direction result = (Direction)((dir + 1) & 3);
return result;
}
void DMEngine::turnDirRight(Direction &dir) {
dir = (Direction)((dir + 1) & 3);
Direction DMEngine::returnOppositeDir(int16 dir) {
Direction result = (Direction)((dir + 2) & 3);
return result;
}
void DMEngine::turnDirLeft(Direction &dir) {
dir = (Direction)((dir - 1) & 3);
Direction DMEngine::turnDirLeft(int16 dir) {
Direction result = (Direction)((dir + 3) & 3);
return result;
}
Direction DMEngine::returnOppositeDir(Direction dir) {
return (Direction)((dir + 2) & 3);
}
uint16 DMEngine::returnPrevVal(uint16 val) {
return (Direction)((val + 3) & 3);
}
uint16 DMEngine::returnNextVal(uint16 val) {
return (val + 1) & 0x3;
}
bool DMEngine::isOrientedWestEast(Direction dir) {
bool DMEngine::isOrientedWestEast(int16 dir) {
return dir & 1;
}
uint16 DMEngine::normalizeModulo4(uint16 val) {
return val & 3;
uint16 DMEngine::normalizeModulo4(int16 dir) {
return dir & 3;
}
int32 DMEngine::filterTime(int32 mapTime) {

View File

@ -157,8 +157,6 @@ struct DMADGameDescription {
OriginalSavePlatform _origPlatformToAccept[kDMSavePlatformTotal + 1];
};
const char *debugGetDirectionName(Direction dir);
class Thing {
public:
uint16 _data;
@ -258,13 +256,12 @@ public:
void fuseSequence(); // @ F0446_STARTEND_FuseSequence
Common::Language getGameLanguage();
void turnDirRight(Direction &dir);
void turnDirLeft(Direction &dir);
Direction returnOppositeDir(Direction dir); // @ M18_OPPOSITE
uint16 returnPrevVal(uint16 val); // @ M19_PREVIOUS
uint16 returnNextVal(uint16 val); // @ M17_NEXT
bool isOrientedWestEast(Direction dir); // @ M16_IS_ORIENTED_WEST_EAST
uint16 normalizeModulo4(uint16 val); // @ M21_NORMALIZE
Direction turnDirRight(int16 dir); // @ M17_NEXT
Direction turnDirLeft(int16 dir); // @ M19_PREVIOUS
Direction returnOppositeDir(int16 dir); // @ M18_OPPOSITE
bool isOrientedWestEast(int16 dir); // @ M16_IS_ORIENTED_WEST_EAST
uint16 normalizeModulo4(int16 val); // @ M21_NORMALIZE
int32 filterTime(int32 map_time); // @ M30_TIME
int32 setMapAndTime(int32 &map_time, uint32 map, uint32 time); // @ M33_SET_MAP_AND_TIME
uint16 getMap(int32 map_time); // @ M29_MAP

View File

@ -40,7 +40,7 @@ namespace DM {
void DungeonMan::mapCoordsAfterRelMovement(Direction dir, int16 stepsForward, int16 stepsRight, int16 &posX, int16 &posY) {
posX += _vm->_dirIntoStepCountEast[dir] * stepsForward;
posY += _vm->_dirIntoStepCountNorth[dir] * stepsForward;
_vm->turnDirRight(dir);
dir = _vm->turnDirRight(dir);
posX += _vm->_dirIntoStepCountEast[dir] * stepsRight;
posY += _vm->_dirIntoStepCountNorth[dir] * stepsRight;
}

View File

@ -979,14 +979,18 @@ void EventManager::commandMoveParty(CommandType cmdType) {
commandHighlightBoxEnable(highlightBox->_x1, highlightBox->_x2, highlightBox->_y1, highlightBox->_y2);
int16 partyMapX = _vm->_dungeonMan->_partyMapX;
int16 partyMapY = _vm->_dungeonMan->_partyMapY;
// TODO: refactor Square
uint16 AL1115_ui_Square = _vm->_dungeonMan->getSquare(partyMapX, partyMapY).toByte();
bool isStairsSquare = (Square(AL1115_ui_Square).getType() == k3_StairsElemType);
if (isStairsSquare && (movementArrowIdx == 2)) { /* If moving backward while in stairs */
commandTakeStairs(getFlag(AL1115_ui_Square, k0x0004_StairsUp));
return;
}
_vm->_dungeonMan->mapCoordsAfterRelMovement(_vm->_dungeonMan->_partyDir, movementArrowToStepForwardCount[movementArrowIdx], movementArrowToSepRightCount[movementArrowIdx], partyMapX, partyMapY);
int16 partySquareType = Square(AL1115_ui_Square = _vm->_dungeonMan->getSquare(partyMapX, partyMapY).toByte()).getType();
AL1115_ui_Square = _vm->_dungeonMan->getSquare(partyMapX, partyMapY).toByte();
int16 partySquareType = Square(AL1115_ui_Square).getType();
if (partySquareType == k3_ElementTypeStairs) {
_vm->_moveSens->getMoveResult(Thing::_party, _vm->_dungeonMan->_partyMapX, _vm->_dungeonMan->_partyMapY, kM1_MapXNotOnASquare, 0);
_vm->_dungeonMan->_partyMapX = partyMapX;
@ -1007,11 +1011,11 @@ void EventManager::commandMoveParty(CommandType cmdType) {
if (_vm->_championMan->_partyChampionCount) {
if (isMovementBlocked) {
movementArrowIdx += (_vm->_dungeonMan->_partyDir + 2);
int16 L1124_i_FirstDamagedChampionIndex = _vm->_championMan->getTargetChampionIndex(partyMapX, partyMapY, _vm->normalizeModulo4(movementArrowIdx));
int16 L1125_i_SecondDamagedChampionIndex = _vm->_championMan->getTargetChampionIndex(partyMapX, partyMapY, _vm->returnNextVal(movementArrowIdx));
int16 damage = _vm->_championMan->addPendingDamageAndWounds_getDamage(L1124_i_FirstDamagedChampionIndex, 1, kDMWoundTorso | kDMWoundLegs, kDMAttackTypeSelf);
if (L1124_i_FirstDamagedChampionIndex != L1125_i_SecondDamagedChampionIndex)
damage |= _vm->_championMan->addPendingDamageAndWounds_getDamage(L1125_i_SecondDamagedChampionIndex, 1, kDMWoundTorso | kDMWoundLegs, kDMAttackTypeSelf);
int16 firstDamagedChampionIndex = _vm->_championMan->getTargetChampionIndex(partyMapX, partyMapY, _vm->normalizeModulo4(movementArrowIdx));
int16 secondDamagedChampionIndex = _vm->_championMan->getTargetChampionIndex(partyMapX, partyMapY, _vm->turnDirRight(movementArrowIdx));
int16 damage = _vm->_championMan->addPendingDamageAndWounds_getDamage(firstDamagedChampionIndex, 1, kDMWoundTorso | kDMWoundLegs, kDMAttackTypeSelf);
if (firstDamagedChampionIndex != secondDamagedChampionIndex)
damage |= _vm->_championMan->addPendingDamageAndWounds_getDamage(secondDamagedChampionIndex, 1, kDMWoundTorso | kDMWoundLegs, kDMAttackTypeSelf);
if (damage)
_vm->_sound->requestPlay(k18_soundPARTY_DAMAGED, partyMapX, partyMapY, k0_soundModePlayImmediately);

View File

@ -3281,7 +3281,7 @@ T0115015_DrawProjectileAsObject:
creatureIndexGreen = 0;
twoHalfSquareCreaturesFrontView = group->getCount();
if (((AL_4_groupCells = _vm->_groupMan->getCreatureValue(AL_4_groupCells, AL_0_creatureIndexRed)) == directionParam) || (AL_4_groupCells == _vm->returnPrevVal(directionParam)))
if (((AL_4_groupCells = _vm->_groupMan->getCreatureValue(AL_4_groupCells, AL_0_creatureIndexRed)) == directionParam) || (AL_4_groupCells == _vm->turnDirLeft(directionParam)))
AL_2_viewCell = k0_HalfSizedViewCell_LeftColumn;
else
AL_2_viewCell = k1_HalfSizedViewCell_RightColumn;
@ -3523,7 +3523,7 @@ T0115129_DrawProjectiles:
flipHorizontal = !flipHorizontal;
} else {
flipVertical = false;
flipHorizontal = (_vm->returnNextVal(directionParam) == projectileDirection);
flipHorizontal = (_vm->turnDirRight(directionParam) == projectileDirection);
}
} else {
if ((projectileAspectType >= k2_ProjectileAspectHasRotation) || ((projectileAspectType == k1_ProjectileAspectBackGraphic) && (projectileDirection != directionParam)) || (projectileAspectTypeHasBackGraphicAndRotation && projectileFlipVertical)) /* If the projectile does not have a back graphic or has one but is not seen from the back or if it has a back graphic and rotation and should be flipped vertically */
@ -3679,7 +3679,7 @@ T0115171_BackFromT0115015_DrawProjectileAsObject:;
if (explosion->getCentered()) {
explosionCoordinates = centeredExplosionCoordinates[AL_1_viewSquareExplosionIndex];
} else {
if ((AL_2_cellPurpleMan == directionParam) || (AL_2_cellPurpleMan == _vm->returnPrevVal(directionParam)))
if ((AL_2_cellPurpleMan == directionParam) || (AL_2_cellPurpleMan == _vm->turnDirLeft(directionParam)))
AL_2_viewCell = k0_ViewCellFronLeft;
else
AL_2_viewCell = k1_ViewCellFrontRight;

View File

@ -112,11 +112,11 @@ int16 GroupMan::getCreatureOrdinalInCell(Group *group, uint16 cell) {
byte creatureIndex = group->getCount();
if (getFlag(_vm->_dungeonMan->_creatureInfos[group->_type]._attributes, k0x0003_MaskCreatureInfo_size) == k1_MaskCreatureSizeHalf) {
if ((getGroupDirections(group, currMapIndex) & 1) == (cell & 1))
cell = _vm->returnPrevVal(cell);
cell = _vm->turnDirLeft(cell);
do {
byte creatureCell = getCreatureValue(groupCells, creatureIndex);
if (creatureCell == cell || creatureCell == _vm->returnNextVal(cell)) {
if (creatureCell == cell || creatureCell == _vm->turnDirRight(cell)) {
retval = _vm->indexToOrdinal(creatureIndex);
break;
}
@ -313,11 +313,11 @@ int16 GroupMan::getDirsWhereDestIsVisibleFromSource(int16 srcMapX, int16 srcMapY
int16 curDirection = kDMDirNorth;
for (;;) {
if (isDestVisibleFromSource(curDirection, srcMapX, srcMapY, destMapX, destMapY)) {
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->returnNextVal(curDirection);
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->turnDirRight(curDirection);
if (!isDestVisibleFromSource(_vm->_projexpl->_secondaryDirToOrFromParty, srcMapX, srcMapY, destMapX, destMapY)) {
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->returnPrevVal(curDirection);
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->turnDirLeft(curDirection);
if ((curDirection != kDMDirNorth) || !isDestVisibleFromSource(_vm->_projexpl->_secondaryDirToOrFromParty, srcMapX, srcMapY, destMapX, destMapY)) {
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->returnNextVal((_vm->getRandomNumber(65536) & 0x0002) + curDirection);
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->turnDirRight((_vm->getRandomNumber(65536) & 0x0002) + curDirection);
return curDirection;
}
}
@ -817,14 +817,14 @@ T0209061_MoveGroup:
activeGroup->_targetMapX = _vm->_dungeonMan->_partyMapX;
activeGroup->_targetMapY = _vm->_dungeonMan->_partyMapY;
}
AL0446_i_Direction = _vm->returnNextVal(AL0446_i_Direction);
AL0446_i_Direction = _vm->turnDirRight(AL0446_i_Direction);
} while (AL0446_i_Direction != AL0447_i_ReferenceDirection);
}
if (!newGroupDirectionFound &&
(ticksSinceLastMove != -1) &&
isArchEnemy &&
((eventType == kM3_TMEventTypeCreateReactionEvent29DangerOnSquare) || !_vm->getRandomNumber(4))) { /* BUG0_15 The game hangs when you close a door on Lord Chaos. A condition is missing in the code to manage creatures and this may create an infinite loop between two parts in the code */
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->returnNextVal(primaryDirectionToOrFromParty = _vm->getRandomNumber(4));
_vm->_projexpl->_secondaryDirToOrFromParty = _vm->turnDirRight(primaryDirectionToOrFromParty = _vm->getRandomNumber(4));
goto T0209089_DoubleSquareMove; /* BUG0_69 Memory corruption when you close a door on Lord Chaos. The local variable (L0454_i_PrimaryDirectionToOrFromParty) containing the direction where Lord Chaos tries to move may be used as an array index without being initialized and cause memory corruption */
}
if (newGroupDirectionFound || ((!_vm->getRandomNumber(4) || (distanceToVisibleParty <= creatureInfo.getSmellRange())) && (eventType != kM3_TMEventTypeCreateReactionEvent29DangerOnSquare))) {
@ -986,7 +986,7 @@ T0209096_SetBehavior0_Wander:
(creatureSize == k0_MaskCreatureSizeQuarter) &&
(activeGroup->_cells != k255_CreatureTypeSingleCenteredCreature) &&
((AL0446_i_Cell = getCreatureValue(activeGroup->_cells, AL0447_i_CreatureIndex)) != primaryDirectionToOrFromParty) &&
(AL0446_i_Cell != _vm->returnNextVal(primaryDirectionToOrFromParty))) { /* If the creature cannot cast spells (range = 1) and is not on a cell where it can attack the party directly and is a quarter square sized creature not in the center of the square then the creature moves to another cell and attack does not occur immediately */
(AL0446_i_Cell != _vm->turnDirRight(primaryDirectionToOrFromParty))) { /* If the creature cannot cast spells (range = 1) and is not on a cell where it can attack the party directly and is a quarter square sized creature not in the center of the square then the creature moves to another cell and attack does not occur immediately */
if (!creatureCount && _vm->getRandomNumber(2)) {
activeGroup->_cells = k255_CreatureTypeSingleCenteredCreature;
} else {
@ -1321,7 +1321,7 @@ void GroupMan::setGroupDirection(ActiveGroup *activeGroup, int16 dir, int16 crea
uint16 groupDirections = activeGroup->_directions;
if (_vm->normalizeModulo4(getCreatureValue(groupDirections, creatureIndex) - dir) == 2) { /* If current and new direction are opposites then change direction only one step at a time */
dir = _vm->returnNextVal((_vm->getRandomNumber(65536) & 0x0002) + dir);
dir = _vm->turnDirRight((_vm->getRandomNumber(65536) & 0x0002) + dir);
groupDirections = getGroupValueUpdatedWithCreatureValue(groupDirections, creatureIndex, dir);
} else
groupDirections = getGroupValueUpdatedWithCreatureValue(groupDirections, creatureIndex, dir);
@ -1480,7 +1480,7 @@ bool GroupMan::isCreatureAttacking(Group *group, int16 mapX, int16 mapY, uint16
championIndex = _vm->getRandomNumber(4);
int cpt;
for (cpt = 0; (cpt < 4) && !_vm->_championMan->_champions[championIndex]._currHealth; cpt++)
championIndex = _vm->returnNextVal(championIndex);
championIndex = _vm->turnDirRight(championIndex);
if (cpt == 4)
return false;
@ -1969,7 +1969,7 @@ void GroupMan::fuseAction(uint16 mapX, uint16 mapY) {
int16 destMapX = mapX;
int16 destMapY = mapY;
uint16 fluxcageIndex = _vm->getRandomNumber(4);
for (uint16 i = 5; --i; fluxcageIndex = _vm->returnNextVal(fluxcageIndex)) {
for (uint16 i = 5; --i; fluxcageIndex = _vm->turnDirRight(fluxcageIndex)) {
if (!isFluxcages[fluxcageIndex]) {
isFluxcages[fluxcageIndex] = true;
switch (fluxcageIndex) {

View File

@ -894,7 +894,7 @@ void MenuMan::addChampionSymbol(int16 symbolIndex) {
setFlag(casterChampion->_attributes, kDMAttributeStatistics);
casterChampion->_symbols[symbolStep] = 96 + (symbolStep * 6) + symbolIndex;
casterChampion->_symbols[symbolStep + 1] = '\0';
casterChampion->_symbolStep = symbolStep = _vm->returnNextVal(symbolStep);
casterChampion->_symbolStep = symbolStep = _vm->turnDirRight(symbolStep);
_vm->_eventMan->showMouse();
drawAvailableSymbols(symbolStep);
drawChampionSymbols(casterChampion);
@ -908,7 +908,7 @@ void MenuMan::deleteChampionSymbol() {
if (!strlen(casterChampion->_symbols))
return;
int16 symbolStep = _vm->returnPrevVal(casterChampion->_symbolStep);
int16 symbolStep = _vm->turnDirLeft(casterChampion->_symbolStep);
casterChampion->_symbolStep = symbolStep;
casterChampion->_symbols[symbolStep] = '\0';
_vm->_eventMan->showMouse();
@ -1308,7 +1308,7 @@ bool MenuMan::isActionPerformed(uint16 champIndex, int16 actionIndex) {
break;
case kDMActionThrow:
setChampionDirectionToPartyDirection(curChampion);
actionPerformed = _vm->_championMan->isObjectThrown(champIndex, kDMSlotActionHand, (curChampion->_cell == _vm->returnNextVal(_vm->_dungeonMan->_partyDir)) || (curChampion->_cell == (ViewCell)_vm->returnOppositeDir(_vm->_dungeonMan->_partyDir)));
actionPerformed = _vm->_championMan->isObjectThrown(champIndex, kDMSlotActionHand, (curChampion->_cell == _vm->turnDirRight(_vm->_dungeonMan->_partyDir)) || (curChampion->_cell == (ViewCell)_vm->returnOppositeDir(_vm->_dungeonMan->_partyDir)));
if (actionPerformed)
_vm->_timeline->_events[curChampion->_enableActionEventIndex]._Bu._slotOrdinal = _vm->indexToOrdinal(kDMSlotActionHand);
break;

View File

@ -540,23 +540,23 @@ bool MovesensMan::moveIsKilledByProjectileImpact(int16 srcMapX, int16 srcMapY, i
if ((destMapX >= 0) && ((abs(srcMapX - destMapX) + abs(srcMapY - destMapY)) == 1)) {
/* If source and destination squares are adjacent (if party or group is not being teleported) */
int16 primaryDirection = _vm->_groupMan->getDirsWhereDestIsVisibleFromSource(srcMapX, srcMapY, destMapX, destMapY);
int16 secondaryDirection = _vm->returnNextVal(primaryDirection);
int16 secondaryDirection = _vm->turnDirRight(primaryDirection);
for (int16 i = 0; i < 4; ++i)
intermediaryChampionOrCreatureOrdinalInCell[i] = 0;
intermediaryChampionOrCreatureOrdinalInCell[_vm->returnPrevVal(primaryDirection)] = championOrCreatureOrdinalInCell[primaryDirection];
if (intermediaryChampionOrCreatureOrdinalInCell[_vm->returnPrevVal(primaryDirection)])
intermediaryChampionOrCreatureOrdinalInCell[_vm->turnDirLeft(primaryDirection)] = championOrCreatureOrdinalInCell[primaryDirection];
if (intermediaryChampionOrCreatureOrdinalInCell[_vm->turnDirLeft(primaryDirection)])
checkDestinationSquareProjectileImpacts = true;
intermediaryChampionOrCreatureOrdinalInCell[_vm->returnNextVal(secondaryDirection)] = championOrCreatureOrdinalInCell[secondaryDirection];
if (intermediaryChampionOrCreatureOrdinalInCell[_vm->returnNextVal(secondaryDirection)])
intermediaryChampionOrCreatureOrdinalInCell[_vm->turnDirRight(secondaryDirection)] = championOrCreatureOrdinalInCell[secondaryDirection];
if (intermediaryChampionOrCreatureOrdinalInCell[_vm->turnDirRight(secondaryDirection)])
checkDestinationSquareProjectileImpacts = true;
if (!championOrCreatureOrdinalInCell[primaryDirection])
championOrCreatureOrdinalInCell[primaryDirection] = championOrCreatureOrdinalInCell[_vm->returnPrevVal(primaryDirection)];
championOrCreatureOrdinalInCell[primaryDirection] = championOrCreatureOrdinalInCell[_vm->turnDirLeft(primaryDirection)];
if (!championOrCreatureOrdinalInCell[secondaryDirection])
championOrCreatureOrdinalInCell[secondaryDirection] = championOrCreatureOrdinalInCell[_vm->returnNextVal(secondaryDirection)];
championOrCreatureOrdinalInCell[secondaryDirection] = championOrCreatureOrdinalInCell[_vm->turnDirRight(secondaryDirection)];
}
uint16 projectileMapX = srcMapX; /* Check impacts with projectiles on the source square */
uint16 projectileMapY = srcMapY;

View File

@ -425,7 +425,7 @@ void ProjExpl::processEvents48To49(TimelineEvent *event) {
uint16 projectileDirection = curEvent->_Cu._projectile.getDir();
projectileThingNewCell = Thing(curEvent->_Bu._slot);
uint16 projectileNewCell = projectileThingNewCell.getCell();
bool projectileMovesToOtherSquare = (projectileDirection == projectileNewCell) || (_vm->returnNextVal(projectileDirection) == projectileNewCell);
bool projectileMovesToOtherSquare = (projectileDirection == projectileNewCell) || (_vm->turnDirRight(projectileDirection) == projectileNewCell);
if (projectileMovesToOtherSquare) {
sourceMapX = destinationMapX;
sourceMapY = destinationMapY;

View File

@ -656,7 +656,7 @@ void Timeline::triggerProjectileLauncher(Sensor *sensor, TimelineEvent *event) {
firstProjectileAssociatedThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY);
while (firstProjectileAssociatedThing != Thing::_none) { /* BUG0_19 The game crashes when an object launcher sensor is triggered. Thing::_none should be Thing::_endOfList. If there are no more objects on the square then this loop may return an undefined value, this can crash the game. In the original DM and CSB dungeons, the number of times that these sensors are triggered is always controlled to be equal to the number of available objects (with a countdown sensor or a number of once only sensors) */
uint16 projectiveThingCell = firstProjectileAssociatedThing.getCell();
if ((firstProjectileAssociatedThing.getType() > kDMThingTypeSensor) && ((projectiveThingCell == cell) || (projectiveThingCell == _vm->returnNextVal(cell))))
if ((firstProjectileAssociatedThing.getType() > kDMThingTypeSensor) && ((projectiveThingCell == cell) || (projectiveThingCell == _vm->turnDirRight(cell))))
break;
firstProjectileAssociatedThing = _vm->_dungeonMan->getNextThing(firstProjectileAssociatedThing);
}
@ -668,7 +668,7 @@ void Timeline::triggerProjectileLauncher(Sensor *sensor, TimelineEvent *event) {
secondProjectileAssociatedThing = _vm->_dungeonMan->getSquareFirstThing(mapX, mapY);
while (secondProjectileAssociatedThing != Thing::_none) { /* BUG0_19 The game crashes when an object launcher sensor is triggered. Thing::_none should be Thing::_endOfList. If there are no more objects on the square then this loop may return an undefined value, this can crash the game */
uint16 projectiveThingCell = secondProjectileAssociatedThing.getCell();
if ((secondProjectileAssociatedThing.getType() > kDMThingTypeSensor) && ((projectiveThingCell == cell) || (projectiveThingCell == _vm->returnNextVal(cell))))
if ((secondProjectileAssociatedThing.getType() > kDMThingTypeSensor) && ((projectiveThingCell == cell) || (projectiveThingCell == _vm->turnDirRight(cell))))
break;
secondProjectileAssociatedThing = _vm->_dungeonMan->getNextThing(secondProjectileAssociatedThing);
}
@ -695,7 +695,7 @@ void Timeline::triggerProjectileLauncher(Sensor *sensor, TimelineEvent *event) {
_vm->_projexpl->_createLauncherProjectile = true;
_vm->_projexpl->createProjectile(firstProjectileAssociatedThing, mapX, mapY, projectileCell, (Direction)cell, kineticEnergy, 100, stepEnergy);
if (!launchSingleProjectile)
_vm->_projexpl->createProjectile(secondProjectileAssociatedThing, mapX, mapY, _vm->returnNextVal(projectileCell), (Direction)cell, kineticEnergy, 100, stepEnergy);
_vm->_projexpl->createProjectile(secondProjectileAssociatedThing, mapX, mapY, _vm->turnDirRight(projectileCell), (Direction)cell, kineticEnergy, 100, stepEnergy);
_vm->_projexpl->_createLauncherProjectile = false;
}