diff options
| -rw-r--r-- | engines/kyra/lol.cpp | 36 | ||||
| -rw-r--r-- | engines/kyra/lol.h | 38 | ||||
| -rw-r--r-- | engines/kyra/resource.h | 2 | ||||
| -rw-r--r-- | engines/kyra/scene_lol.cpp | 70 | ||||
| -rw-r--r-- | engines/kyra/script_lol.cpp | 20 | ||||
| -rw-r--r-- | engines/kyra/sprites_lol.cpp | 80 | ||||
| -rw-r--r-- | engines/kyra/staticres.cpp | 11 | ||||
| -rw-r--r-- | engines/kyra/timer.cpp | 23 | ||||
| -rw-r--r-- | engines/kyra/timer.h | 5 | ||||
| -rw-r--r-- | engines/kyra/timer_lol.cpp | 53 | 
10 files changed, 260 insertions, 78 deletions
| diff --git a/engines/kyra/lol.cpp b/engines/kyra/lol.cpp index 399427ec1c..a1cf3e51ab 100644 --- a/engines/kyra/lol.cpp +++ b/engines/kyra/lol.cpp @@ -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; @@ -212,8 +213,8 @@ LoLEngine::~LoLEngine() {  	delete _gui;  	_gui = 0;  	delete _tim; -	_tim = 0;	 -	delete _txt;	 +	_tim = 0; +	delete _txt;  	_txt = 0;  	delete[] _itemsInPlay; @@ -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); @@ -790,7 +781,7 @@ void LoLEngine::runLoop() {  			checkForPartyDeath(_partyDeathFlag);  			_partyDeathFlag = -1;  		}*/ -		 +  		delay(_tickLength);  	}  } @@ -1168,6 +1159,7 @@ void LoLEngine::restoreSceneAfterDialogueSequence(int redraw) {  	}  	_hideInventory = 0; +	enableSysTimer(2);  }  void LoLEngine::resetPortraitsArea() { @@ -1175,7 +1167,7 @@ void LoLEngine::resetPortraitsArea() {  	if (!textEnabled() || (!(_hideControls & 2)))  		timerUpdatePortraitAnimations(1); -	disableSysTimer(2);		 +	disableSysTimer(2);  }  void LoLEngine::fadeText() { @@ -1368,7 +1360,7 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {  	if (block != _currentBlock) {  		static const int8 blockShiftTable[] = { -32, -31, 1, 33, 32, 31, -1, -33 };  		uint16 cbl = _currentBlock; -		 +  		for (int i = 3; i > 0; i--) {  			int dir = calcMonsterDirection(cbl & 0x1f, cbl >> 5, block & 0x1f, block >> 5);  			cbl += blockShiftTable[dir]; @@ -1447,7 +1439,7 @@ bool LoLEngine::characterSays(int track, int charId, bool redraw) {  			charId = 0;  		}  	} -	 +  	bool r = snd_playCharacterSpeech(track, charId, 0);  	if (r && redraw) { @@ -1465,7 +1457,7 @@ bool LoLEngine::characterSays(int track, int charId, bool redraw) {  int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str, EMCState *script, const uint16 *paramList, int16 paramIndex) {  	int ch = 0;  	bool skipAnim = false; -	 +  	if ((charId == -1) || (!(charId & 0x70)))  		charId = ch = (charId == 1) ? (_selectedCharacter ? _characters[_selectedCharacter].id : 0) : charId;  	else @@ -1502,7 +1494,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str  		_updatePortraitSpeechAnimDuration = strlen(str) >> 1;  		_updateCharV3 = unk1;  	} -	 +  	if (script)  		snd_playCharacterSpeech(script->stack[script->sp + 2], ch, 0);  	else if (paramList) @@ -1519,7 +1511,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str  			_txt->printDialogueText(4, str, script, paramList, paramIndex);  			_screen->modifyScreenDim(4, 11, 123, 28, 47); -		} else if (mode == 2) {			 +		} else if (mode == 2) {  			_screen->setScreenDim(4);  			_screen->clearDim(4);  			_screen->modifyScreenDim(4, 9, 133, 30, 60); @@ -1536,7 +1528,7 @@ int LoLEngine::playCharacterScriptChat(int charId, int mode, int unk1, char *str  }  void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) { -	uint16 *c = &monster->assignedItems;	 +	uint16 *c = &monster->assignedItems;  	while (*c)  		c = &_itemsInPlay[*c].next;  	*c = item; @@ -1567,7 +1559,7 @@ bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) {  		return true;  	} else if (_spellProperties[spellNum + 1].unkArr[spellLevel] >= _characters[charNum].hitPointsCur) {  		_txt->printMessage(2, getLangString(0x4179), _characters[charNum].name); -		return true;		 +		return true;  	}  	return false; diff --git a/engines/kyra/lol.h b/engines/kyra/lol.h index ae52627fac..dd1ce58df3 100644 --- a/engines/kyra/lol.h +++ b/engines/kyra/lol.h @@ -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) {} @@ -530,12 +533,12 @@ private:  	int olol_loadLangFile(EMCState *script);  	int olol_playSoundEffect(EMCState *script);  	int olol_stopTimScript(EMCState *script); -	int olol_playCharacterScriptChat(EMCState *script);	 +	int olol_playCharacterScriptChat(EMCState *script);  	int olol_loadSoundFile(EMCState *script);  	int olol_setPaletteBrightness(EMCState *script);  	int olol_printMessage(EMCState *script);  	int olol_playDialogueTalkText(EMCState *script); -	int olol_checkForMonsterMode1(EMCState *script);	 +	int olol_checkForMonsterMode1(EMCState *script);  	int olol_setNextFunc(EMCState *script);  	int olol_setDoorState(EMCState *script);  	int olol_assignCustomSfx(EMCState *script); @@ -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; @@ -720,11 +724,10 @@ private:  	int clickedWallOnlyScript(uint16 block);  	int clickedDoorSwitch(uint16 block, uint16 direction);  	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; @@ -920,7 +932,7 @@ private:  	int checkBlockForWallsAndSufficientSpace(int block, int x, int y, int monsterWidth, int testFlag, int wallFlag);  	bool checkBlockOccupiedByParty(int x, int y, int testFlag);  	const uint16 *getCharacterOrMonsterStats(int id); -	void drawMonstersAndItems(int block);	 +	void drawMonstersAndItems(int block);  	void drawMonster(uint16 id);  	int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags);  	void recalcItemMonsterPositions(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag); @@ -930,13 +942,13 @@ private:  	void drawDoorOrMonsterShape(uint8 *shape, uint8 *table, int x, int y, int flags, const uint8 *ovl);  	uint8 *drawItemOrMonster(uint8 *shape, uint8 *ovl, int x, int y, int w, int h, int flags, int tblValue, bool flip);  	int calcDrawingLayerParameters(int srcX, int srcY, int16 &x2, int16 &y2, int16 &w, int16 &h, uint8 *shape, int flip); -	 +  	void updateMonster(MonsterInPlay *monster);  	void moveMonster(MonsterInPlay *monster);  	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; diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index 06227d58d9..66cc883667 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -230,7 +230,7 @@ enum kKyraResources {  	kLolCharDefsAkshel,  	kLolExpRequirements,  	kLolMonsterModifiers, -	kLolMonsterLevelOffsets, +	kLolMonsterShiftOffsets,  	kLolMonsterDirFlags,  	kLolMonsterScaleY,  	kLolMonsterScaleX, diff --git a/engines/kyra/scene_lol.cpp b/engines/kyra/scene_lol.cpp index 687b6a17cf..3abe72ea60 100644 --- a/engines/kyra/scene_lol.cpp +++ b/engines/kyra/scene_lol.cpp @@ -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; +		} +	} + +	if (s == 0) +		s = (_wllWallFlags[_levelBlockProperties[block].walls[_wllWallFlags[_levelBlockProperties[block].walls[0]] & 8 ? 0 : 1]] & 1) ? 1 : -1; +	openCloseDoor(block, s);  } -void LoLEngine::openDoorSub2(uint16 block, int unk) { +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) { diff --git a/engines/kyra/script_lol.cpp b/engines/kyra/script_lol.cpp index d21494cc85..622332cd3c 100644 --- a/engines/kyra/script_lol.cpp +++ b/engines/kyra/script_lol.cpp @@ -35,7 +35,7 @@  namespace Kyra {  void LoLEngine::runInitScript(const char *filename, int optionalFunc) { -	_suspendScript = true;	 +	_suspendScript = true;  	EMCData scriptData;  	EMCState scriptState;  	memset(&scriptData, 0, sizeof(EMCData)); @@ -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)) { @@ -539,10 +538,10 @@ int LoLEngine::olol_initMonster(EMCState *script) {  	uint16 y = 0;  	calcCoordinates(x, y, stackPos(0), stackPos(1), stackPos(2));  	uint16 w = _monsterProperties[stackPos(4)].maxWidth; -	 +  	if (checkBlockBeforeMonsterPlacement(x, y, w, 7, 7))  		return -1; -	 +  	for (uint8 i = 0; i < 30; i++) {  		MonsterInPlay *l = &_monsters[i];  		if (l->might || l->mode == 13) @@ -577,7 +576,7 @@ int LoLEngine::olol_initMonster(EMCState *script) {  		for (int ii = 0; ii < 4; ii++)  			l->field_2A[ii] = stackPos(7 + ii); -		checkSceneUpdateNeed(l->blockPropertyIndex);		 +		checkSceneUpdateNeed(l->blockPropertyIndex);  		return i;  	} @@ -648,11 +647,10 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {  int LoLEngine::olol_moveMonster(EMCState *script) {  	debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_moveMonster(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));  	MonsterInPlay *m = &_monsters[stackPos(0)]; -	 +  	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(); diff --git a/engines/kyra/sprites_lol.cpp b/engines/kyra/sprites_lol.cpp index b95e95d18f..7180671ec5 100644 --- a/engines/kyra/sprites_lol.cpp +++ b/engines/kyra/sprites_lol.cpp @@ -312,7 +312,7 @@ int LoLEngine::checkBlockBeforeMonsterPlacement(int x, int y, int monsterWidth,  	int xOffs = 0;  	int yOffs = 0;  	int flag = 0; -	 +  	int r = checkBlockForWallsAndSufficientSpace(calcBlockIndex(x, y), x, y, monsterWidth, testFlag, wallFlag);  	if (r)  		return r; @@ -416,7 +416,7 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) {  		return r;  	else if (_characters[id].skillLevels[1] <= 7)  		return (r- (r >> 2)); -	 +  	return (r- (r >> 1));  } @@ -438,7 +438,7 @@ int LoLEngine::checkBlockForWallsAndSufficientSpace(int block, int x, int y, int  	uint16 b = _levelBlockProperties[block].itemMonsterIndex;  	while (b & 0x8000) {  		MonsterInPlay *monster = &_monsters[b & 0x7fff]; -		 +  		if (monster->mode < 13) {  			int r = checkMonsterSpace(x, y, monster->x, monster->y);  			if ((monsterWidth + monster->properties->maxWidth) > r) @@ -460,7 +460,7 @@ bool LoLEngine::checkBlockOccupiedByParty(int x, int y, int testFlag) {  void LoLEngine::drawMonstersAndItems(int block) {  	LevelBlockProperty *l = _curBlockCaps[block]; -	uint16 s = l->itemMonsterIndex;		 +	uint16 s = l->itemMonsterIndex;  	ItemInPlay *i = findItem(s);  	if (l->direction != _currentDirection) { @@ -491,7 +491,7 @@ void LoLEngine::drawMonstersAndItems(int block) {  }  void LoLEngine::drawMonster(uint16 id) { -	MonsterInPlay *m = &_monsters[id];	 +	MonsterInPlay *m = &_monsters[id];  	int16 flg = _monsterDirFlags[(_currentDirection << 2) + m->facing];  	int curFrm = getMonsterCurFrame(m, flg & 0xffef); @@ -505,12 +505,12 @@ void LoLEngine::drawMonster(uint16 id) {  		bool flip = m->properties->flags & 0x200 ? true : false;  		flg &= 0x10;  		uint8 *shp = _monsterShapes[(m->properties->shapeIndex << 4) + curFrm]; -		 +  		if (m->properties->flags & 0x800)  			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; @@ -536,9 +536,9 @@ void LoLEngine::drawMonster(uint16 id) {  		int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1;  		int a = (m->mode == 13) ? (m->field_15 << 1) : (m->properties->might / (m->field_1B & 0x7fff)); -		 +  		shp = _gameShapes[6]; -		 +  		int cF = m->properties->flags & 0xc000;  		if (cF == 0x4000)  			cF = 63; @@ -550,7 +550,7 @@ void LoLEngine::drawMonster(uint16 id) {  			cF = 0;  		uint8 *tbl = new uint8[256]; -		if (cF) {			 +		if (cF) {  			for (int i = 0; i < 256; i++) {  				tbl[i] = i;  				if (i < 2 || i > 7) @@ -772,7 +772,7 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, in  		r = 7 - ((r / 3) - 1);  		r = CLIP(r, 0, 7);  		ovl = _screen->getLevelOverlay(r); -	} else {		 +	} else {  		memset (tmpOvl + 1, tblValue, 15);  		table = tmpOvl;  		ovl = _screen->getLevelOverlay(7); @@ -829,7 +829,7 @@ int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int16 &x2, int16 &y2,  	if (flip)  		y2 = ((120 - y2) >> 1) + _screen->getShapeScaledHeight(shape, _dmScaleH); -	else  +	else  		y2 -= (_screen->getShapeScaledHeight(shape, _dmScaleH) >> 1);  	return l; @@ -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: @@ -923,7 +927,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {  void LoLEngine::moveMonster(MonsterInPlay *monster) {  	static const int8 turnPos[] = { 0, 2, 6, 6, 0, 2, 4, 4, 2, 2, 4, 6, 0, 0, 4, 6, 0 };  	if (monster->x != monster->destX || monster->y != monster->destY) { -		walkMonster(monster);		 +		walkMonster(monster);  	} else if (monster->direction != monster->destDirection) {  		int i = (monster->facing << 2) + (monster->destDirection >> 1);  		setMonsterDirection(monster, turnPos[i]); @@ -935,7 +939,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {  		return;  	int s = walkMonsterCalcNextStep(monster); -	 +  	if (s == -1) {  		if (walkMonsterCheckDest(monster->x, monster->y, monster, 4) != 1)  			return; @@ -951,7 +955,7 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {  						return;  				}  			} -		}		 +		}  	}  	int fx = 0; @@ -973,7 +977,7 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {  	const int8 *tbl = _monsterShiftAlt ? walkMonsterTable2 : walkMonsterTable1;  	int sx = monster->x; -	int sy = monster->y;	 +	int sy = monster->y;  	int s = monster->direction;  	int d = calcMonsterDirection(monster->x, monster->y, monster->destX, monster->destY); @@ -1002,10 +1006,10 @@ int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {  			continue;  		uint8 w = _levelBlockProperties[_monsterCurBlock].walls[(s >> 1) ^ 2]; -		 +  		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) { diff --git a/engines/kyra/staticres.cpp b/engines/kyra/staticres.cpp index 588ce4ac1d..d06957350f 100644 --- a/engines/kyra/staticres.cpp +++ b/engines/kyra/staticres.cpp @@ -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 diff --git a/engines/kyra/timer.cpp b/engines/kyra/timer.cpp index da7e22f684..88b86393c8 100644 --- a/engines/kyra/timer.cpp +++ b/engines/kyra/timer.cpp @@ -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); diff --git a/engines/kyra/timer.h b/engines/kyra/timer.h index 691bac3fb5..3892ecd580 100644 --- a/engines/kyra/timer.h +++ b/engines/kyra/timer.h @@ -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(); diff --git a/engines/kyra/timer_lol.cpp b/engines/kyra/timer_lol.cpp index 39b89416e0..d646b13f0e 100644 --- a/engines/kyra/timer_lol.cpp +++ b/engines/kyra/timer_lol.cpp @@ -35,8 +35,8 @@ 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,13 +56,56 @@ 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) { -	//if (!_updateMonsters) -	//	return; +//	if (!_updateMonsters) +//		return;  	for (int i = timerNum & 0x0f; i < 30; i += 2)  		updateMonster(&_monsters[i]); | 
