MADS: Implemented NebularGame::step

This commit is contained in:
Paul Gilbert 2014-03-29 11:18:07 -04:00
parent d801c2ffdd
commit 71b1343adf
19 changed files with 122 additions and 40 deletions

View file

@ -35,8 +35,8 @@ MADSAction::MADSAction(MADSEngine *vm) : _vm(vm) {
_selectedAction = 0; _selectedAction = 0;
_inProgress = false; _inProgress = false;
_savedFields._actionMode = ABORTMODE_0; _savedFields._actionMode = KERNEL_TRIGGER_PARSER;
_savedFields._actionMode2 = ABORTMODE_0; _savedFields._actionMode2 = KERNEL_TRIGGER_PARSER;
_savedFields._selectedRow = -1; _savedFields._selectedRow = -1;
_savedFields._hotspotId = 0; _savedFields._hotspotId = 0;
_savedFields._v86F3A = 0; _savedFields._v86F3A = 0;
@ -272,7 +272,7 @@ void MADSAction::startAction() {
player.cancelCommand(); player.cancelCommand();
_inProgress = true; _inProgress = true;
_v8453A = ABORTMODE_0; _v8453A = KERNEL_TRIGGER_PARSER;
_savedFields._selectedRow = _selectedRow; _savedFields._selectedRow = _selectedRow;
_savedFields._hotspotId = _hotspotId; _savedFields._hotspotId = _hotspotId;
_savedFields._v86F3A = _v86F3A; _savedFields._v86F3A = _v86F3A;

View file

@ -30,7 +30,11 @@ namespace MADS {
enum ActionMode { ACTIONMODE_NONE = 0, ACTIONMODE_VERB = 1, ACTIONMODE_OBJECT = 3, ACTIONMODE_TALK = 6 }; enum ActionMode { ACTIONMODE_NONE = 0, ACTIONMODE_VERB = 1, ACTIONMODE_OBJECT = 3, ACTIONMODE_TALK = 6 };
enum ActionMode2 { ACTIONMODE2_0 = 0, ACTIONMODE2_2 = 2, ACTIONMODE2_4 = 4, ACTIONMODE2_5 = 5 }; enum ActionMode2 { ACTIONMODE2_0 = 0, ACTIONMODE2_2 = 2, ACTIONMODE2_4 = 4, ACTIONMODE2_5 = 5 };
enum AbortTimerMode { ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2 }; enum TriggerMode {
KERNEL_TRIGGER_PARSER = 0, // Triggers parser
KERNEL_TRIGGER_DAEMON = 1, // Triggers step/daemon code
KERNEL_TRIGGER_PREPARE = 2 // Triggers preparser
};
enum InterAwaiting { enum InterAwaiting {
AWAITING_NONE = 0, AWAITING_NONE = 0,

View file

@ -317,7 +317,7 @@ void Animation::startAnimation(int abortTimers) {
_oldFrameEntry = 0; _oldFrameEntry = 0;
_nextFrameTimer = _vm->_game->_scene._frameStartTime; _nextFrameTimer = _vm->_game->_scene._frameStartTime;
_trigger = abortTimers; _trigger = abortTimers;
_abortTimersMode = _vm->_game->_abortTimersMode2; _triggerMode = _vm->_game->_triggerSetupMode;
_vm->_game->_scene._action._activeAction = _actionDetails; _vm->_game->_scene._action._activeAction = _actionDetails;
for (int idx = 0; idx < _header._messagesCount; ++idx) { for (int idx = 0; idx < _header._messagesCount; ++idx) {
@ -532,9 +532,9 @@ void Animation::update() {
// Animation is complete // Animation is complete
if (_trigger != 0) { if (_trigger != 0) {
_vm->_game->_trigger = _trigger; _vm->_game->_trigger = _trigger;
_vm->_game->_abortTimersMode = _abortTimersMode; _vm->_game->_triggerMode = _triggerMode;
if (_abortTimersMode != ABORTMODE_1) { if (_triggerMode != KERNEL_TRIGGER_DAEMON) {
// Copy the noun list // Copy the noun list
scene._action._action = _actionDetails; scene._action._action = _actionDetails;
} }

View file

@ -129,7 +129,7 @@ private:
uint32 _nextScrollTimer; uint32 _nextScrollTimer;
int _messageCtr; int _messageCtr;
int _trigger; int _trigger;
AbortTimerMode _abortTimersMode; TriggerMode _triggerMode;
ActionDetails _actionDetails; ActionDetails _actionDetails;
/** /**

View file

@ -56,8 +56,8 @@ Game::Game(MADSEngine *vm): _vm(vm), _surface(nullptr), _objects(vm),
_aaName = "*I0.AA"; _aaName = "*I0.AA";
_priorFrameTimer = 0; _priorFrameTimer = 0;
_updateSceneFlag = false; _updateSceneFlag = false;
_abortTimersMode = ABORTMODE_0; _triggerMode = KERNEL_TRIGGER_PARSER;
_abortTimersMode2 = ABORTMODE_0; _triggerSetupMode = KERNEL_TRIGGER_PARSER;
_ticksExpiry = 0; _ticksExpiry = 0;
_winStatus = 0; _winStatus = 0;

View file

@ -134,8 +134,8 @@ public:
int _v2; int _v2;
int _trigger; int _trigger;
ScreenTransition _fx; ScreenTransition _fx;
AbortTimerMode _abortTimersMode; TriggerMode _triggerMode;
AbortTimerMode _abortTimersMode2; TriggerMode _triggerSetupMode;
uint32 _priorFrameTimer; uint32 _priorFrameTimer;
Common::String _aaName; Common::String _aaName;
uint32 _ticksExpiry; uint32 _ticksExpiry;
@ -156,6 +156,11 @@ public:
*/ */
virtual void doObjectAction() = 0; virtual void doObjectAction() = 0;
/**
* Global game step
*/
virtual void step() = 0;
// DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs // DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs
void clearQuotes() {} void clearQuotes() {}
void loadQuoteRange(int startNum, int endNum) {} void loadQuoteRange(int startNum, int endNum) {}

View file

@ -75,7 +75,7 @@ int KernelMessages::add(const Common::Point &pt, uint fontColor, uint8 flags,
rec._timeout = timeout; rec._timeout = timeout;
rec._frameTimer = _vm->_game->_priorFrameTimer; rec._frameTimer = _vm->_game->_priorFrameTimer;
rec._trigger = abortTimers; rec._trigger = abortTimers;
rec._abortMode = _vm->_game->_abortTimersMode2; rec._abortMode = _vm->_game->_triggerSetupMode;
rec._actionDetails = scene._action._activeAction; rec._actionDetails = scene._action._activeAction;
@ -177,9 +177,9 @@ void KernelMessages::processText(int msgIndex) {
msg._flags |= KMSG_EXPIRE; msg._flags |= KMSG_EXPIRE;
if (msg._trigger != 0) { if (msg._trigger != 0) {
_vm->_game->_trigger = msg._trigger; _vm->_game->_trigger = msg._trigger;
_vm->_game->_abortTimersMode = msg._abortMode; _vm->_game->_triggerMode = msg._abortMode;
if (_vm->_game->_abortTimersMode != ABORTMODE_1) { if (_vm->_game->_triggerMode != KERNEL_TRIGGER_DAEMON) {
scene._action._activeAction = msg._actionDetails; scene._action._activeAction = msg._actionDetails;
} }
} }

View file

@ -57,7 +57,7 @@ public:
uint32 _frameTimer; uint32 _frameTimer;
uint32 _timeout; uint32 _timeout;
int _trigger; int _trigger;
AbortTimerMode _abortMode; TriggerMode _abortMode;
ActionDetails _actionDetails; ActionDetails _actionDetails;
Common::String _msg; Common::String _msg;

View file

@ -280,6 +280,71 @@ void GameNebular::doObjectAction() {
warning("TODO: GameNebular::doObjectAction"); warning("TODO: GameNebular::doObjectAction");
} }
void GameNebular::step() {
if (_player._visible && _player._stepEnabled && !_player._moving &&
(_player._facing == _player._turnToFacing)) {
if (_scene._frameStartTime >= *((uint32 *)&_globals[kWalkerTiming])) {
if (!_player._stopWalkerIndex) {
int randomVal = _vm->getRandomNumber(29999);;
if (_globals[kSexOfRex] == REX_MALE) {
switch (_player._facing) {
case FACING_SOUTHWEST:
case FACING_SOUTHEAST:
case FACING_NORTHWEST:
case FACING_NORTHEAST:
if (randomVal < 200) {
_player.addWalker(-1, 0);
_player.addWalker(1, 0);
}
break;
case FACING_WEST:
case FACING_EAST:
if (randomVal < 500) {
for (int count = 0; count < 10; ++count) {
_player.addWalker(1, 0);
}
}
break;
case 2:
if (randomVal < 500) {
for (int count = 0; count < 10; ++count) {
_player.addWalker((randomVal < 250) ? 1 : 2, 0);
}
} else if (randomVal < 750) {
for (int count = 0; count < 5; ++count) {
_player.addWalker(1, 0);
}
_player.addWalker(0, 0);
_player.addWalker(0, 0);
for (int count = 0; count < 5; ++count) {
_player.addWalker(2, 0);
}
}
break;
}
}
}
*((uint32 *)&_globals[kWalkerTiming]) += 6;
}
}
// Below is countdown to set the timebomb off in room 604
if (_globals[kTimebombStatus] == TIMEBOMB_ACTIVATED) {
int diff = _scene._frameStartTime - *((uint32 *)&_globals[kTimebombClock]);
if ((diff >= 0) && (diff <= 60)) {
*((uint32 *)&_globals[kTimebombTimer]) += diff;
} else {
++*((uint32 *)&_globals[kTimebombTimer]);
}
*((uint32 *)&_globals[kTimebombClock]) = _scene._frameStartTime;
}
}
} // End of namespace Nebular } // End of namespace Nebular
} // End of namespace MADS } // End of namespace MADS

View file

@ -66,6 +66,8 @@ public:
StoryMode _storyMode; StoryMode _storyMode;
virtual void doObjectAction(); virtual void doObjectAction();
virtual void step();
}; };

View file

@ -207,6 +207,8 @@ enum GlobalId {
/* Enums used for specific individual globals */ /* Enums used for specific individual globals */
/* Section #1 */ /* Section #1 */
// Rex's sex/swimming state
enum { REX_MALE = 0, REX_MALE_SWIMMER = 1, REX_FEMALE = 2 };
// State of Meteorologist in the outpost // State of Meteorologist in the outpost
enum { METEOROLOGIST_ABSENT = 0, METEOROLOGIST_PRESENT = 1, METEOROLOGIST_GONE = 2 }; enum { METEOROLOGIST_ABSENT = 0, METEOROLOGIST_PRESENT = 1, METEOROLOGIST_GONE = 2 };

View file

@ -458,7 +458,7 @@ void Scene202::enter() {
void Scene202::setRandomKernelMessage() { void Scene202::setRandomKernelMessage() {
int vocabId = _vm->getRandomNumber(92, 96); int vocabId = _vm->getRandomNumber(92, 96);
_scene->_kernelMessages.reset(); _scene->_kernelMessages.reset();
_game._abortTimersMode2 = ABORTMODE_1; _game._triggerSetupMode = KERNEL_TRIGGER_DAEMON;
_scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 70, 120, _game.getQuote(vocabId)); _scene->_kernelMessages.add(Common::Point(0, 0), 0x1110, 34, 70, 120, _game.getQuote(vocabId));
_activeMsgFl = true; _activeMsgFl = true;
} }
@ -495,7 +495,7 @@ void Scene202::step() {
action->_activeAction._verbId = 3; action->_activeAction._verbId = 3;
action->_activeAction._objectNameId = 39; action->_activeAction._objectNameId = 39;
action->_activeAction._indirectObjectId = 438; action->_activeAction._indirectObjectId = 438;
_game._abortTimersMode2 = ABORTMODE_0; _game._triggerSetupMode = KERNEL_TRIGGER_PARSER;
_scene->_sequences.addTimer(120, 2); _scene->_sequences.addTimer(120, 2);
_globals._abortVal = -1; _globals._abortVal = -1;
} else if (_globals[kMeteorologistWatch] == 2) { } else if (_globals[kMeteorologistWatch] == 2) {

View file

@ -767,8 +767,8 @@ void Player::newWalk() {
} }
} }
void Player::step() { void Player::addWalker(int walker, int trigger) {
warning("TODO: Player::step"); warning("TODO: Player::addWalker");
} }
} // End of namespace MADS } // End of namespace MADS

View file

@ -60,7 +60,6 @@ private:
int _routeLength; int _routeLength;
int _stopWalkerList[12]; int _stopWalkerList[12];
int _stopWalkerTrigger[12]; int _stopWalkerTrigger[12];
int _stopWalkerIndex;
int _totalDistance; int _totalDistance;
void clearStopList(); void clearStopList();
@ -147,6 +146,7 @@ public:
bool _forceRefresh; bool _forceRefresh;
bool _needToWalk; bool _needToWalk;
bool _readyToWalk; bool _readyToWalk;
int _stopWalkerIndex;
int _centerOfGravity; int _centerOfGravity;
int _currentDepth; int _currentDepth;
int _currentScale; int _currentScale;
@ -218,7 +218,10 @@ public:
void nextFrame(); void nextFrame();
void step(); /**
* Add a walker to the current queue
*/
void addWalker(int walker, int trigger);
}; };
} // End of namespace MADS } // End of namespace MADS

View file

@ -310,7 +310,7 @@ void Scene::doFrame() {
flag = true; flag = true;
} }
if (flag || (_vm->_game->_trigger && _vm->_game->_abortTimersMode == ABORTMODE_2)) { if (flag || (_vm->_game->_trigger && _vm->_game->_triggerMode == KERNEL_TRIGGER_PREPARE)) {
doPreactions(); doPreactions();
} }
@ -320,7 +320,7 @@ void Scene::doFrame() {
if ((_action._inProgress && !player._moving && !player._needToWalk && if ((_action._inProgress && !player._moving && !player._needToWalk &&
player._turnToFacing == player._facing) || player._turnToFacing == player._facing) ||
(_vm->_game->_trigger && _vm->_game->_abortTimersMode == ABORTMODE_0)) { (_vm->_game->_trigger && _vm->_game->_triggerMode == KERNEL_TRIGGER_PARSER)) {
doAction(); doAction();
} }
@ -444,11 +444,11 @@ void Scene::drawElements(ScreenTransition transitionType, bool surfaceFlag) {
void Scene::doPreactions() { void Scene::doPreactions() {
if (_vm->_game->_screenObjects._v832EC == 0 || _vm->_game->_screenObjects._v832EC == 2) { if (_vm->_game->_screenObjects._v832EC == 0 || _vm->_game->_screenObjects._v832EC == 2) {
_vm->_game->_abortTimersMode2 = ABORTMODE_2; _vm->_game->_triggerSetupMode = KERNEL_TRIGGER_PREPARE;
_action.checkAction(); _action.checkAction();
_sceneLogic->preActions(); _sceneLogic->preActions();
if (_vm->_game->_abortTimersMode == ABORTMODE_2) if (_vm->_game->_triggerMode == KERNEL_TRIGGER_PREPARE)
_vm->_game->_trigger = 0; _vm->_game->_trigger = 0;
} }
} }
@ -456,7 +456,7 @@ void Scene::doPreactions() {
void Scene::doAction() { void Scene::doAction() {
int flag = 0; int flag = 0;
_vm->_game->_abortTimersMode2 = ABORTMODE_0; _vm->_game->_triggerSetupMode = KERNEL_TRIGGER_PARSER;
if ((_action._inProgress || _vm->_game->_trigger) && !_action._v8453A) { if ((_action._inProgress || _vm->_game->_trigger) && !_action._v8453A) {
_sceneLogic->actions(); _sceneLogic->actions();
_action._inProgress = true; _action._inProgress = true;
@ -494,19 +494,17 @@ void Scene::doAction() {
} }
_action._inProgress = false; _action._inProgress = false;
if (_vm->_game->_abortTimersMode == ABORTMODE_0) if (_vm->_game->_triggerMode == KERNEL_TRIGGER_PARSER)
_vm->_game->_trigger = 0; _vm->_game->_trigger = 0;
} }
void Scene::doSceneStep() { void Scene::doSceneStep() {
_vm->_game->_abortTimersMode2 = ABORTMODE_1; _vm->_game->_triggerSetupMode = KERNEL_TRIGGER_DAEMON;
_sceneLogic->step(); _sceneLogic->step();
_vm->_game->_sectionHandler->step(); _vm->_game->_sectionHandler->step();
_vm->_game->step();
_vm->_game->_player.step(); if (_vm->_game->_triggerMode == KERNEL_TRIGGER_DAEMON)
_vm->_game->_player._trigger = 0;
if (_vm->_game->_abortTimersMode == ABORTMODE_1)
_vm->_game->_trigger = 0; _vm->_game->_trigger = 0;
} }

View file

@ -65,6 +65,9 @@ private:
void doAction(); void doAction();
/**
* Calls all the necessary step handlers for the current frame
*/
void doSceneStep(); void doSceneStep();
void checkKeyboard(); void checkKeyboard();

View file

@ -50,7 +50,7 @@ KernelMessage::KernelMessage() {
_frameTimer = 0; _frameTimer = 0;
_timeout = 0; _timeout = 0;
_trigger = 0; _trigger = 0;
_abortMode = ABORTMODE_0; _abortMode = KERNEL_TRIGGER_PARSER;
_actionDetails._verbId = 0; _actionDetails._verbId = 0;
_actionDetails._objectNameId = 0; _actionDetails._objectNameId = 0;
_actionDetails._indirectObjectId = 0; _actionDetails._indirectObjectId = 0;

View file

@ -47,7 +47,7 @@ SequenceEntry::SequenceEntry() {
_field22 = 0; _field22 = 0;
_triggerCountdown = 0; _triggerCountdown = 0;
_doneFlag = 0; _doneFlag = 0;
_abortMode = ABORTMODE_0; _abortMode = KERNEL_TRIGGER_PARSER;
_numTicks = 0; _numTicks = 0;
_extraTicks = 0; _extraTicks = 0;
_timeout = 0; _timeout = 0;
@ -135,7 +135,7 @@ int SequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int tri
_entries[seqIndex]._flags = 0; _entries[seqIndex]._flags = 0;
_entries[seqIndex]._dynamicHotspotIndex = -1; _entries[seqIndex]._dynamicHotspotIndex = -1;
_entries[seqIndex]._entries._count = 0; _entries[seqIndex]._entries._count = 0;
_entries[seqIndex]._abortMode = _vm->_game->_abortTimersMode2; _entries[seqIndex]._abortMode = _vm->_game->_triggerSetupMode;
_entries[seqIndex]._actionNouns = _vm->_game->_scene._action._activeAction; _entries[seqIndex]._actionNouns = _vm->_game->_scene._action._activeAction;
@ -160,7 +160,7 @@ int SequenceList::addTimer(int time, int abortVal) {
se._triggerCountdown = true; se._triggerCountdown = true;
se._doneFlag = false; se._doneFlag = false;
se._entries._count = 0; se._entries._count = 0;
se._abortMode = _vm->_game->_abortTimersMode2; se._abortMode = _vm->_game->_triggerSetupMode;
se._actionNouns = _vm->_game->_scene._action._activeAction; se._actionNouns = _vm->_game->_scene._action._activeAction;
addSubEntry(seqIndex, SM_0, 0, abortVal); addSubEntry(seqIndex, SM_0, 0, abortVal);
@ -328,9 +328,9 @@ bool SequenceList::loadSprites(int seqIndex) {
if (idx >= 0) { if (idx >= 0) {
_vm->_game->_trigger = seqEntry._entries._abortVal[idx]; _vm->_game->_trigger = seqEntry._entries._abortVal[idx];
_vm->_game->_abortTimersMode = seqEntry._abortMode; _vm->_game->_triggerMode = seqEntry._abortMode;
if (seqEntry._abortMode == ABORTMODE_1) if (seqEntry._abortMode == KERNEL_TRIGGER_DAEMON)
scene._action._activeAction = seqEntry._actionNouns; scene._action._activeAction = seqEntry._actionNouns;
} }

View file

@ -74,7 +74,7 @@ struct SequenceEntry {
int _triggerCountdown; int _triggerCountdown;
bool _doneFlag; bool _doneFlag;
SequenceSubEntries _entries; SequenceSubEntries _entries;
AbortTimerMode _abortMode; TriggerMode _abortMode;
ActionDetails _actionNouns; ActionDetails _actionNouns;
int _numTicks; int _numTicks;