LOL: - doors can now be opened and closed

- some more work on monster walk code

svn-id: r39166
This commit is contained in:
Florian Kagerer 2009-03-06 22:53:08 +00:00
parent 3753d0b5f8
commit 8639e34b41
10 changed files with 260 additions and 78 deletions

View File

@ -189,6 +189,7 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
memset(_activeTim, 0, 10 * sizeof(TIM*));
memset(_activeVoiceFile, 0, sizeof(_activeVoiceFile));
memset(&_openDoorState, 0, sizeof(OpenDoorState) * 3);
_pageBuffer1 = _pageBuffer2 = 0;
@ -359,7 +360,7 @@ Common::Error LoLEngine::init() {
memset(_itemsInPlay, 0, sizeof(ItemInPlay) * 400);
_characters = new LoLCharacter[4];
memset(_characters, 0, sizeof(LoLCharacter) * 3);
memset(_characters, 0, sizeof(LoLCharacter) * 4);
if (!_sound->init())
error("Couldn't init sound");
@ -752,16 +753,6 @@ void LoLEngine::startupNew() {
_screen->showMouse();
}
void LoLEngine::enableSysTimer(int sysTimer) {
if (sysTimer == 2)
_timer->pause(false);
}
void LoLEngine::disableSysTimer(int sysTimer) {
if (sysTimer == 2)
_timer->pause(true);
}
void LoLEngine::runLoop() {
enableSysTimer(2);
@ -1168,6 +1159,7 @@ void LoLEngine::restoreSceneAfterDialogueSequence(int redraw) {
}
_hideInventory = 0;
enableSysTimer(2);
}
void LoLEngine::resetPortraitsArea() {

View File

@ -127,7 +127,7 @@ struct MonsterInPlay {
uint16 blockPropertyIndex;
uint16 x;
uint16 y;
int8 level;
int8 shiftStep;
uint16 destX;
uint16 destY;
uint8 destDirection;
@ -306,7 +306,7 @@ private:
void setupTimers();
void enableTimer(int id);
void timerProcessOpenDoor(int timerNum);
void timerProcessDoors(int timerNum);
void timerProcessMonsters(int timerNum);
void timerSub3(int timerNum);
void timerSub4(int timerNum);
@ -316,6 +316,9 @@ private:
void timerUpdateLampState(int timerNum);
void timerFadeMessageText(int timerNum);
static const uint8 _clock2Timers[];
static const uint8 _numClock2Timers;
// sound
void loadTalkFile(int index);
void snd_playVoiceFile(int track) {}
@ -558,6 +561,7 @@ private:
int tlol_initDialogueSequence(const TIM *tim, const uint16 *param);
int tlol_restoreSceneAfterDialogueSequence(const TIM *tim, const uint16 *param);
int tlol_fadeClearWindow(const TIM *tim, const uint16 *param);
int tlol_update(const TIM *tim, const uint16 *param);
int tlol_playDialogueTalkText(const TIM *tim, const uint16 *param);
Common::Array<const TIMOpcode*> _timIngameOpcodes;
@ -722,9 +726,8 @@ private:
int clicked6(uint16 block, uint16 direction);
bool clickedShape(int shapeIndex);
void openDoorSub1(uint16 block, int unk);
void openDoorSub2(uint16 block, int unk);
int _emcDoorState;
void processDoorSwitch(uint16 block, int unk);
void openCloseDoor(uint16 block, int openClose);
void movePartySmoothScrollBlocked(int speed);
void movePartySmoothScrollUp(int speed);
@ -737,6 +740,15 @@ private:
int smoothScrollDrawSpecialShape(int pageNum);
void setLF2(int block);
struct OpenDoorState {
uint16 block;
int8 field_2;
int8 state;
};
OpenDoorState _openDoorState[3];
int _emcDoorState;
uint8 *_scrollSceneBuffer;
uint32 _smoothScrollTimer;
int _smoothScrollModeNormal;
@ -936,7 +948,7 @@ private:
void walkMonster(MonsterInPlay *monster);
int walkMonsterCalcNextStep(MonsterInPlay *monster);
int getMonsterDistance(uint16 block1, uint16 block2);
int walkMonster_s3(uint16 monsterBlock, int unk1, int unk2, uint16 curBlock);
int walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk);
void walkMonsterGetNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 unk);
@ -953,8 +965,8 @@ private:
const uint16 *_monsterModifiers;
int _monsterModifiersSize;
const int8 *_monsterLevelOffs;
int _monsterLevelOffsSize;
const int8 *_monsterShiftOffs;
int _monsterShiftOffsSize;
const uint8 *_monsterDirFlags;
int _monsterDirFlagsSize;
const int8 *_monsterScaleX;

View File

@ -230,7 +230,7 @@ enum kKyraResources {
kLolCharDefsAkshel,
kLolExpRequirements,
kLolMonsterModifiers,
kLolMonsterLevelOffsets,
kLolMonsterShiftOffsets,
kLolMonsterDirFlags,
kLolMonsterScaleY,
kLolMonsterScaleX,

View File

@ -719,7 +719,7 @@ int LoLEngine::clickedDoorSwitch(uint16 block, uint16 direction) {
if (!_emcDoorState) {
delay(15 * _tickLength);
openDoorSub1(block, 0);
processDoorSwitch(block, 0);
}
return 1;
@ -753,12 +753,76 @@ bool LoLEngine::clickedShape(int shapeIndex) {
return false;
}
void LoLEngine::openDoorSub1(uint16 block, int unk) {
void LoLEngine::processDoorSwitch(uint16 block, int unk) {
if ((block == _currentBlock) || (_levelBlockProperties[block].itemMonsterIndex & 0x8000))
return;
int s = 0;
if (!unk) {
for (int i = 0; i < 3; i++) {
if (_openDoorState[i].block != block)
continue;
s = -_openDoorState[i].state;
break;
}
}
void LoLEngine::openDoorSub2(uint16 block, int unk) {
if (s == 0)
s = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1;
openCloseDoor(block, s);
}
void LoLEngine::openCloseDoor(uint16 block, int openClose) {
int s1 = -1;
int s2 = -1;
int c = (_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8) ? 0 : 1;
int v = _levelBlockProperties[block].walls[c];
int flg = (openClose == 1) ? 0x10 : (openClose == -1 ? 0x20 : 0);
if (_wllWallFlags[v] & flg)
return;
for (int i = 0; i < 3; i++) {
if (_openDoorState[i].block == block) {
s1 = i;
break;
} else if (_openDoorState[i].block == 0 && s2 == -1) {
s2 = i;
}
}
if (s1 != -1 || s2 != -1) {
if (s1 == -1)
s1 = s2;
_openDoorState[s1].block = block;
_openDoorState[s1].state = openClose;
_openDoorState[s1].field_2 = c;
flg = (-openClose == 1) ? 0x10 : (-openClose == -1 ? 0x20 : 0);
if (_wllWallFlags[v] & flg) {
_levelBlockProperties[block].walls[c] += openClose;
_levelBlockProperties[block].walls[c ^ 2] += openClose;
int snd = (openClose == -1) ? 32 : 31;
snd_processEnvironmentalSoundEffect(snd, block);
if (!checkSceneUpdateNeed(block))
updateEnvironmentalSfx(0);
}
enableTimer(0);
} else {
while (!(flg & _wllWallFlags[v]))
v += openClose;
_levelBlockProperties[block].walls[c] = _levelBlockProperties[block].walls[c ^ 2] = v;
checkSceneUpdateNeed(block);
}
}
void LoLEngine::movePartySmoothScrollBlocked(int speed) {

View File

@ -449,7 +449,6 @@ int LoLEngine::olol_setUnkArrayVal(EMCState *script) {
int LoLEngine::olol_setGlobalVar(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_setGlobalVar(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
//uint16 a = stackPos(1);
uint16 b = stackPos(2);
switch (stackPos(0)) {
@ -652,7 +651,6 @@ int LoLEngine::olol_moveMonster(EMCState *script) {
if (m->mode == 1 || m->mode == 2) {
calcCoordinates(m->destX, m->destY, stackPos(1), stackPos(2), stackPos(3));
m->destDirection = stackPos(4) << 1;
if (m->x != m->destX || m->y != m->destY)
setMonsterDirection(m, calcMonsterDirection(m->x, m->y, m->destX, m->destY));
}
@ -954,6 +952,12 @@ int LoLEngine::tlol_fadeClearWindow(const TIM *tim, const uint16 *param) {
return 1;
}
int LoLEngine::tlol_update(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_update(%p, %p)", (const void*)tim, (const void*)param);
update();
return 1;
}
int LoLEngine::tlol_playDialogueTalkText(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_playDialogueTalkText(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
if (!snd_playCharacterSpeech(param[0], 0, 0) || textEnabled())
@ -1296,7 +1300,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x08
OpcodeTimUnImpl();
OpcodeTimUnImpl();
OpcodeTim(tlol_update);
OpcodeTimUnImpl();
OpcodeTimUnImpl();

View File

@ -510,7 +510,7 @@ void LoLEngine::drawMonster(uint16 id) {
flg |= 0x20;
uint8 *ovl1 = d ? _monsterPalettes[(m->properties->shapeIndex << 4) + (curFrm & 0x0f)] + (shp[10] * (d - 1)) : 0;
uint8 *ovl2 = drawItemOrMonster(shp, ovl1, m->x + _monsterLevelOffs[m->level << 1], m->y + _monsterLevelOffs[(m->level << 1) + 1], 0, 0, flg | 1, -1, flip);
uint8 *ovl2 = drawItemOrMonster(shp, ovl1, m->x + _monsterShiftOffs[m->shiftStep << 1], m->y + _monsterShiftOffs[(m->shiftStep << 1) + 1], 0, 0, flg | 1, -1, flip);
for (int i = 0; i < 4; i++) {
int v = m->field_2A[i] - 1;
@ -868,8 +868,12 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
if ((s & 1) && (monster->flags & 0x10))
setMonsterMode(monster, 7);
////
// TODO
if ((monster->mode != 11) && (monster->mode != 14)) {
if (!(_rnd.getRandomNumberRng(1, 100) & 3)) {
monster->shiftStep = (++monster->shiftStep) & 0x0f;
checkSceneUpdateNeed(monster->blockPropertyIndex);
}
}
switch (monster->mode) {
case 0:
@ -1005,7 +1009,7 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
if (_wllWallFlags[w] & 0x20) {
if (_wllBuffer3[w] == 5)
openDoorSub2(_monsterCurBlock, 1);
openCloseDoor(_monsterCurBlock, 1);
}
if (_wllWallFlags[w] & 8)
@ -1017,9 +1021,9 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) {
int8 b1x = block1 & 0x1f;
int8 b1y = (block1 >> 8) & 0x1f;
int8 b1y = block1 >> 5;
int8 b2x = block2 & 0x1f;
int8 b2y = (block2 >> 8) & 0x1f;
int8 b2y = block2 >> 5;
uint8 dy = ABS(b2y - b1y);
uint8 dx = ABS(b2x - b1x);
@ -1030,8 +1034,36 @@ int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) {
return (dx << 1) + dy;
}
int LoLEngine::walkMonster_s3(uint16 monsterBlock, int unk1, int unk2, uint16 curBlock) {
return 0;
int LoLEngine::walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock) {
int mdist = getMonsterDistance(curBlock, monsterBlock);
if (mdist > distance)
return 5;
int dir = calcMonsterDirection(monsterBlock & 0x1f, monsterBlock >> 5, curBlock & 0x1f, curBlock >> 5);
if ((dir & 1) || ((dir << 1) != direction))
return 5;
if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) || ((monsterBlock & 0xffe0) != (curBlock & 0xffe0)))
return 5;
if (distance < 0)
return 5;
for (int i = 0; i < distance; i++) {
int p = calcNewBlockPosition(monsterBlock, direction);
if (p == curBlock)
return direction;
if (_wllWallFlags[_levelBlockProperties[p].walls[direction ^ 2]] & 2)
return 5;
if (_levelBlockProperties[p].itemMonsterIndex & 0x8000)
return 5;
}
return 5;
}
int LoLEngine::walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk) {

View File

@ -391,7 +391,7 @@ bool StaticResource::init() {
{ kLolCharDefsAkshel, kLolRawDataBe16, "CHAKSHEL.DEF" },
{ kLolExpRequirements, kLolRawDataBe32, "EXPERIENCE.DEF" },
{ kLolMonsterModifiers, kLolRawDataBe16, "MONSTMOD.DEF" },
{ kLolMonsterLevelOffsets, kRawData, "MONSTLVL.DEF" },
{ kLolMonsterShiftOffsets, kRawData, "MONSTLVL.DEF" },
{ kLolMonsterDirFlags, kRawData, "MONSTDIR.DEF" },
{ kLolMonsterScaleY, kRawData, "MONSTZY.DEF" },
{ kLolMonsterScaleX, kRawData, "MONSTZX.DEF" },
@ -1762,7 +1762,7 @@ void LoLEngine::initStaticResource() {
_charDefsAkshel = _staticres->loadRawDataBe16(kLolCharDefsAkshel, _charDefsAkshelSize);
_expRequirements = (const int32*)_staticres->loadRawDataBe32(kLolExpRequirements, _expRequirementsSize);
_monsterModifiers = _staticres->loadRawDataBe16(kLolMonsterModifiers, _monsterModifiersSize);
_monsterLevelOffs = (const int8*)_staticres->loadRawData(kLolMonsterLevelOffsets, _monsterLevelOffsSize);
_monsterShiftOffs = (const int8*)_staticres->loadRawData(kLolMonsterShiftOffsets, _monsterShiftOffsSize);
_monsterDirFlags = _staticres->loadRawData(kLolMonsterDirFlags, _monsterDirFlagsSize);
_monsterScaleX = (const int8*)_staticres->loadRawData(kLolMonsterScaleX, _monsterScaleXSize);
_monsterScaleY = (const int8*)_staticres->loadRawData(kLolMonsterScaleY, _monsterScaleYSize);
@ -2988,6 +2988,13 @@ const uint8 LoLEngine::_charInfoFrameTable[] = {
0x8, 0x9, 0xA, 0xB, 0xA, 0x9, 0x8, 0x7
};
const uint8 LoLEngine::_clock2Timers[] = {
0x00, 0x10, 0x11, 0x03, 0x04, 0x50,
0x51, 0x52, 0x08, 0x09, 0x0A
};
const uint8 LoLEngine::_numClock2Timers = ARRAYSIZE(LoLEngine::_clock2Timers);
#endif // ENABLE_LOL
} // End of namespace Kyra

View File

@ -108,6 +108,7 @@ void TimerManager::addTimer(uint8 id, TimerFunc *func, int countdown, bool enabl
newTimer.enabled = enabled ? 1 : 0;
newTimer.lastUpdate = newTimer.nextRun = 0;
newTimer.func = func;
newTimer.pauseStartTime = 0;
_timers.push_back(newTimer);
}
@ -217,6 +218,28 @@ uint32 TimerManager::getNextRun(uint8 id) const {
return 0xFFFFFFFF;
}
void TimerManager::pauseSingleTimer(uint8 id, bool p) {
debugC(9, kDebugLevelTimer, "TimerManager::pauseSingleTimer(%d, %d)", id, (int) p);
Iterator timer = Common::find_if(_timers.begin(), _timers.end(), TimerEqual(id));
if (timer == _timers.end()) {
warning("TimerManager::pauseSingleTimer: No timer %d", id);
return;
}
if (p) {
timer->pauseStartTime = _system->getMillis();
timer->enabled = 0;
} else if (timer->pauseStartTime) {
int32 elapsedTime = _system->getMillis() - timer->pauseStartTime;
timer->enabled = 1;
timer->lastUpdate += elapsedTime;
timer->nextRun += elapsedTime;
resync();
timer->pauseStartTime = 0;
}
}
bool TimerManager::isEnabled(uint8 id) const {
debugC(9, kDebugLevelTimer, "TimerManager::isEnabled(%d)", id);

View File

@ -45,6 +45,8 @@ struct TimerEntry {
uint32 nextRun;
TimerFunc *func;
uint32 pauseStartTime;
};
class TimerManager {
@ -70,12 +72,15 @@ public:
void setNextRun(uint8 id, uint32 nextRun);
uint32 getNextRun(uint8 id) const;
void pauseSingleTimer(uint8 id, bool p);
bool isEnabled(uint8 id) const;
void enable(uint8 id);
void disable(uint8 id);
void loadDataFromFile(Common::SeekableReadStream &file, int version);
void saveDataToFile(Common::WriteStream &file) const;
private:
void resync();

View File

@ -36,7 +36,7 @@ namespace Kyra {
void LoLEngine::setupTimers() {
debugC(9, kDebugLevelMain | kDebugLevelTimer, "LoLEngine::setupTimers()");
_timer->addTimer(0, TimerV2(timerProcessOpenDoor), 15, true);
_timer->addTimer(0, TimerV2(timerProcessDoors), 15, true);
_timer->addTimer(0x10, TimerV2(timerProcessMonsters), 6, true);
_timer->addTimer(0x11, TimerV2(timerProcessMonsters), 6, true);
_timer->setNextRun(0x11, _system->getMillis() + 3 * _tickLength);
@ -56,8 +56,51 @@ void LoLEngine::enableTimer(int id) {
_timer->setNextRun(id, _system->getMillis() + _timer->getDelay(id) * _tickLength);
}
void LoLEngine::timerProcessOpenDoor(int timerNum) {
void LoLEngine::enableSysTimer(int sysTimer) {
if (sysTimer != 2)
return;
for (int i = 0; i < _numClock2Timers; i++)
_timer->pauseSingleTimer(_clock2Timers[i], false);
}
void LoLEngine::disableSysTimer(int sysTimer) {
if (sysTimer != 2)
return;
for (int i = 0; i < _numClock2Timers; i++)
_timer->pauseSingleTimer(_clock2Timers[i], true);
}
void LoLEngine::timerProcessDoors(int timerNum) {
for (int i = 0; i < 3; i++) {
uint16 b = _openDoorState[i].block;
if (!b)
continue;
int v = _openDoorState[i].state;
int c = _openDoorState[i].field_2;
_levelBlockProperties[b].walls[c] += v;
_levelBlockProperties[b].walls[c ^ 2] += v;
int snd = 31;
int flg = _wllWallFlags[_levelBlockProperties[b].walls[c]];
if (flg & 0x20)
snd = 33;
else if (v == -1)
snd = 32;
if (!(_updateFlags & 1)) {
snd_processEnvironmentalSoundEffect(snd, b);
if (!checkSceneUpdateNeed(b))
updateEnvironmentalSfx(0);
}
if (flg & 0x30)
_openDoorState[i].block = 0;
}
}
void LoLEngine::timerProcessMonsters(int timerNum) {