LOL: The guards will now attack you when you throw certain items at them. They can't do any damage though, since this isn't implemented yet.

svn-id: r39582
This commit is contained in:
Florian Kagerer 2009-03-21 14:30:25 +00:00
parent bd8b94ee8a
commit b55602180d
8 changed files with 542 additions and 113 deletions

View File

@ -943,7 +943,7 @@ void LoLEngine::gui_initButton(int index, int x, int y, int val) {
}
int LoLEngine::clickedUpArrow(Button *button) {
if (button->data2Val2 && !(_unkGameFlag & 4))
if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty(_currentDirection, ((button->flags2 & 0x1080) == 0x1080) ? 1 : 0, 0, 80);
@ -952,7 +952,7 @@ int LoLEngine::clickedUpArrow(Button *button) {
}
int LoLEngine::clickedDownArrow(Button *button) {
if (button->data2Val2 && !(_unkGameFlag & 4))
if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty(_currentDirection ^ 2, 0, 1, 83);
@ -961,7 +961,7 @@ int LoLEngine::clickedDownArrow(Button *button) {
}
int LoLEngine::clickedLeftArrow(Button *button) {
if (button->data2Val2 && !(_unkGameFlag & 4))
if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty((_currentDirection - 1) & 3, ((button->flags2 & 0x1080) == 0x1080) ? 1 : 0, 2, 82);
@ -970,7 +970,7 @@ int LoLEngine::clickedLeftArrow(Button *button) {
}
int LoLEngine::clickedRightArrow(Button *button) {
if (button->data2Val2 && !(_unkGameFlag & 4))
if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
moveParty((_currentDirection + 1) & 3, ((button->flags2 & 0x1080) == 0x1080) ? 1 : 0, 3, 84);
@ -979,7 +979,7 @@ int LoLEngine::clickedRightArrow(Button *button) {
}
int LoLEngine::clickedTurnLeftArrow(Button *button) {
if (button->data2Val2 && !(_unkGameFlag & 4))
if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
gui_toggleButtonDisplayMode(79, 1);
@ -1001,7 +1001,7 @@ int LoLEngine::clickedTurnLeftArrow(Button *button) {
}
int LoLEngine::clickedTurnRightArrow(Button *button) {
if (button->data2Val2 && !(_unkGameFlag & 4))
if (button->data2Val2 && !_floatingCursorsEnabled)
return 0;
gui_toggleButtonDisplayMode(81, 1);

View File

@ -413,7 +413,7 @@ void LoLEngine::updateObjectFlightPosition(FlyingObject *t) {
}
void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock) {
int r = 0;
uint16 r = 0;
if (objectOnNextBlock == 1) {
runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].blockPropertyIndex, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
@ -432,7 +432,7 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
return;
} else {
r = flyingObjectHitMonsters(x, y);
r = getClosestMonster(x, y);
}
} else if (objectOnNextBlock == 4) {
@ -445,25 +445,13 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
return;
} else {
r = flyingObjectHitParty(x, y);
r = getClosestPartyMember(x, y);
}
}
runItemScript(t->charNum, t->item, 0x8000, r, 0);
}
uint16 LoLEngine::flyingObjectHitMonsters(int x, int y) {
////////////
// TODO
return 0;
}
uint16 LoLEngine::flyingObjectHitParty(int x, int y) {
////////////
// TODO
return 0;
}
void LoLEngine::updateFlyingObjects(FlyingObject *t) {
int x = 0;
int y = 0;

View File

@ -149,7 +149,6 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_tempBuffer5120 = 0;
_flyingItems = 0;
_monsters = 0;
_unkGameFlag = 0;
_lastMouseRegion = 0;
_monsterLastWalkDirection = _monsterCountUnk = _monsterShiftAlt = 0;
_monsterCurBlock = 0;
@ -206,6 +205,10 @@ LoLEngine::LoLEngine(OSystem *system, const GameFlags &flags) : KyraEngine_v1(sy
_activeButtons = 0;
_preserveEvents = false;
_buttonList1 = _buttonList2 = _buttonList3 = _buttonList4 = _buttonList5 = _buttonList6 = _buttonList7 = _buttonList8 = 0;
_monsterDifficulty = 1;
_smoothScrollingEnabled = true;
_floatingCursorsEnabled = false;
}
LoLEngine::~LoLEngine() {
@ -730,7 +733,7 @@ void LoLEngine::startupNew() {
_compassDirection = _compassDirectionIndex = -1;
_lastMouseRegion = -1;
_unkGameFlag |= 0x1B;
/*
_unk5 = 1;
_unk6 = 1;
@ -1080,7 +1083,7 @@ int LoLEngine::calculateProtection(int index) {
if (index & 0x8000) {
// Monster
index &= 0x7fff;
c = (_monsters[index].properties->itemProtection * _monsters[index].properties->protection) >> 8;
c = (_monsters[index].properties->itemProtection * _monsters[index].properties->fightingStats[2]) >> 8;
} else {
// Character
c = _characters[index].itemsProtection + _characters[index].protection;
@ -1521,7 +1524,7 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) {
}
void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
if (!(_unkGameFlag & 1))
if (!_sound->sfxEnabled())
return;
if (_environmentSfx)
@ -1560,7 +1563,7 @@ void LoLEngine::snd_processEnvironmentalSoundEffect(int soundId, int block) {
}
void LoLEngine::snd_loadSoundFile(int track) {
if (_unkGameFlag & 2) {
if (_sound->musicEnabled()) {
char filename[13];
int t = (track - 250) * 3;
@ -1585,7 +1588,7 @@ int LoLEngine::snd_playTrack(int track) {
int res = _lastMusicTrack;
_lastMusicTrack = track;
if (_unkGameFlag & 2) {
if (_sound->musicEnabled()) {
snd_loadSoundFile(track);
int t = (track - 250) * 3;
_sound->playTrack(_musicTrackMap[t + 2]);
@ -1595,7 +1598,7 @@ int LoLEngine::snd_playTrack(int track) {
}
int LoLEngine::snd_stopMusic() {
if (_unkGameFlag & 2) {
if (_sound->musicEnabled()) {
if (_sound->isPlaying()) {
_sound->beginFadeOut();
_system->delayMillis(3 * _tickLength);
@ -1716,7 +1719,7 @@ void LoLEngine::giveItemToMonster(MonsterInPlay *monster, uint16 item) {
}
const uint16 *LoLEngine::getCharacterOrMonsterStats(int id) {
return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->pos : _characters[id].defaultModifiers;
return (id & 0x8000) ? (const uint16*)_monsters[id & 0x7fff].properties->fightingStats : _characters[id].defaultModifiers;
}
void LoLEngine::delay(uint32 millis, bool cUpdate, bool isMainLoop) {
@ -1771,6 +1774,113 @@ bool LoLEngine::notEnoughMagic(int charNum, int spellNum, int spellLevel) {
return false;
}
int LoLEngine::battleHitSkillTest(int16 attacker, int16 target, int skill) {
if (target == -1)
return 0;
if (attacker == -1)
return 1;
if (target & 0x8000) {
if (_monsters[target & 0x7fff].mode >= 13)
return 0;
}
uint16 hitChanceModifier = 0;
uint16 evadeChanceModifier = 0;
int sk = 0;
if (attacker & 0x8000) {
hitChanceModifier = _monsters[target & 0x7fff].properties->fightingStats[0];
sk = 100 - _monsters[target & 0x7fff].properties->skillLevel;
} else {
hitChanceModifier = _characters[attacker].defaultModifiers[0];
uint8 m = _characters[attacker].skillModifiers[skill];
if (skill == 1)
m *= 3;
sk = 100 - (_characters[attacker].skillLevels[skill] + m);
}
if (target & 0x8000) {
evadeChanceModifier = _monsters[target & 0x7fff].properties->fightingStats[3];
_monsters[target & 0x7fff].flags |= 0x10;
} else {
evadeChanceModifier = _characters[target].defaultModifiers[3];
}
int r = _rnd.getRandomNumberRng(1, 100);
if (r >= sk)
return 2;
uint16 v = ((_monsterModifiers[9 + _monsterDifficulty] * evadeChanceModifier) & 0xffffff00) / hitChanceModifier;
if (r < v)
return 0;
return 1;
}
int LoLEngine::calcInflictableDamage(int16 attacker, int16 target, int hitType) {
const uint16 *s = getCharacterOrMonsterStats(attacker);
int res = 0;
for (int i = 0; i < 8; i++)
res += calcInflictableDamagePerStat(attacker, target, s[2 + i], i, hitType);
return res;
}
void LoLEngine::battleHit_sub2(int16 target, int damageInflicted, int16 attacker, uint32 b) {
}
void LoLEngine::battleHit_sub3(MonsterInPlay *monster, int16 target, int16 damageInflicted) {
}
int LoLEngine::calcInflictableDamagePerStat(int16 attacker, int16 target, uint16 stat2m, int index, int hitType) {
return 1;
}
uint16 LoLEngine::getClosestMonster(int x, int y) {
uint16 id = 0xffff;
int minDist = 0x7fff;
for (int i = 0; i < 30; i++) {
if (_monsters[i].mode > 13)
continue;
int d = ABS(x - _monsters[i].x) + ABS(y - _monsters[i].y);
if (d < minDist) {
minDist = d;
id = 0x8000 | i;
}
}
return id;
}
uint16 LoLEngine::getClosestPartyMember(int x, int y) {
uint16 id = 0xffff;
int minDist = 0x7fff;
for (int i = 0; i < 4; i++) {
if (!(_characters[i].flags & 1) || _characters[i].hitPointsCur <= 0)
continue;
int16 charX = 0;
int16 charY = 0;
calcCoordinatesForSingleCharacter(i, charX, charY);
int d = ABS(x - charX) + ABS(y - charY);
if (d < minDist) {
minDist = d;
id = i;
}
}
return id;
}
} // end of namespace Kyra
#endif // ENABLE_LOL

View File

@ -62,9 +62,9 @@ struct LoLCharacter {
uint16 field_34;
uint8 field_36;
uint16 itemsProtection;
uint16 hitPointsCur;
int16 hitPointsCur;
uint16 hitPointsMax;
uint16 magicPointsCur;
int16 magicPointsCur;
uint16 magicPointsMax;
uint8 field_41;
uint16 damageSuffered;
@ -100,15 +100,13 @@ struct LevelBlockProperty {
struct MonsterProperty {
uint8 shapeIndex;
uint8 maxWidth;
uint16 field2[2];
uint16 protection;
uint16 unk[6];
uint16 *pos;
uint16 fightingStats[10];
uint16 unk2[8];
uint16 unk3[8];
uint16 itemProtection;
uint16 might;
uint8 waitTicks;
uint8 speedTotalWaitTicks;
uint8 skillLevel;
uint16 flags;
uint16 unk5;
uint16 unk6[5];
@ -129,10 +127,10 @@ struct MonsterInPlay {
uint8 destDirection;
uint8 anon8;
uint8 anonh;
uint8 anon9;
uint8 currentSubFrame;
uint8 mode;
uint8 field_15;
int8 fightCurTick;
uint8 id;
uint8 direction;
uint8 facing;
@ -140,7 +138,7 @@ struct MonsterInPlay {
uint8 field_1B;
uint8 field_1C;
int16 might;
uint8 tick;
uint8 speedTick;
uint8 type;
MonsterProperty *properties;
uint8 field_25;
@ -163,7 +161,7 @@ struct ItemInPlay {
uint8 destDirection;
uint8 anon8;
uint8 anonh;
uint8 anon9;
uint8 currentSubFrame;
};
struct ItemProperty {
@ -266,6 +264,11 @@ private:
void startup();
void startupNew();
// options
int _monsterDifficulty;
bool _smoothScrollingEnabled;
bool _floatingCursorsEnabled;
// main loop
void runLoop();
void update();
@ -569,7 +572,9 @@ private:
int olol_initMonster(EMCState *script);
int olol_fadeClearSceneWindow(EMCState *script);
int olol_fadeSequencePalette(EMCState *script);
int olol_dummy0(EMCState *script);
int olol_loadMonsterProperties(EMCState *script);
int olol_battleHitSkillTest(EMCState *script);
int olol_moveMonster(EMCState *script);
int olol_dialogueBox(EMCState *script);
int olol_giveTakeMoney(EMCState *script);
@ -597,7 +602,7 @@ private:
int olol_setPaletteBrightness(EMCState *script);
int olol_printMessage(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
int olol_checkForMonsterMode1(EMCState *script);
int olol_checkMonsterTypeHostility(EMCState *script);
int olol_setNextFunc(EMCState *script);
int olol_setDoorState(EMCState *script);
int olol_processButtonClick(EMCState *script);
@ -804,7 +809,9 @@ private:
uint16 calcNewBlockPosition(uint16 curBlock, uint16 direction);
uint16 calcBlockIndex(uint16 x, uint16 y);
void calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs);
void calcCoordinates(uint16 &x, uint16 &y, int block, uint16 xOffs, uint16 yOffs);
void calcCoordinatesForSingleCharacter(int charNum, int16 &x, int16 &y);
void calcCoordinatesAddDirectionOffset(int16 &x, int16 &y, int direction);
int clickedWallShape(uint16 block, uint16 direction);
int clicked2(uint16 block, uint16 direction);
@ -906,7 +913,6 @@ private:
int _lastMouseRegion;
int _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2, _seqTrigger;
uint8 _unkGameFlag;
uint8 *_tempBuffer5120;
@ -979,8 +985,6 @@ private:
void processObjectFlight(FlyingObject *t, int x, int y);
void updateObjectFlightPosition(FlyingObject *t);
void objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock);
uint16 flyingObjectHitMonsters(int x, int y);
uint16 flyingObjectHitParty(int x, int y);
void updateFlyingObjects(FlyingObject *t);
void assignItemToBlock(uint16 *assignedBlockObjects, int id);
@ -1022,11 +1026,12 @@ private:
void loadMonsterShapes(const char *file, int monsterIndex, int b);
void releaseMonsterShapes(int monsterIndex);
int disableMonstersForBlock(int block);
void setMonsterMode(MonsterInPlay *monster, int a);
void setMonsterMode(MonsterInPlay *monster, int mode);
bool updateMonsterAdjustBlocks(MonsterInPlay *monster);
void placeMonster(MonsterInPlay *monster, uint16 x, uint16 y);
int calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2);
void setMonsterDirection(MonsterInPlay *monster, int dir);
void cmzS3(MonsterInPlay *monster);
void monsterDropItems(MonsterInPlay *monster);
void removeAssignedObjectFromBlock(LevelBlockProperty *l, int id);
void removeDrawObjectFromBlock(LevelBlockProperty *l, int id);
void assignMonsterToBlock(uint16 *assignedBlockObjects, int id);
@ -1042,7 +1047,7 @@ private:
void reassignDrawObjects(uint16 direction, uint16 itemIndex, LevelBlockProperty *l, bool flag);
void redrawSceneItem();
int calcItemMonsterPosition(ItemInPlay *i, uint16 direction);
void recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, int &itemY, uint16 direction);
void calcSpriteRelPosition(uint16 x1, uint16 y1, int &x2, int &y2, uint16 direction);
void drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags);
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 fineX, int fineY, int flags, int tblValue, bool flip);
@ -1051,11 +1056,16 @@ private:
void updateMonster(MonsterInPlay *monster);
void moveMonster(MonsterInPlay *monster);
void walkMonster(MonsterInPlay *monster);
bool chasePartyWithDistanceAttacks(MonsterInPlay *monster);
void chasePartyWithCloseAttacks(MonsterInPlay *monster);
int walkMonsterCalcNextStep(MonsterInPlay *monster);
int getMonsterDistance(uint16 block1, uint16 block2);
int walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock);
int walkMonsterCheckDest(int x, int y, MonsterInPlay *monster, int unk);
void getNextStepCoords(int16 monsterX, int16 monsterY, int &newX, int &newY, uint16 direction);
void rearrangeAttackingMonster(MonsterInPlay *monster);
void moveStrayingMonster(MonsterInPlay *monster);
void mode13sub(MonsterInPlay *monster);
MonsterInPlay *_monsters;
MonsterProperty *_monsterProperties;
@ -1093,6 +1103,16 @@ private:
uint8 *_pageBuffer2;
uint32 _rndSpecial;
// fight
int battleHitSkillTest(int16 attacker, int16 target, int skill);
int calcInflictableDamage(int16 attacker, int16 target, int hitType);
void battleHit_sub2(int16 target, int damageInflicted, int16 attacker, uint32 b);
void battleHit_sub3(MonsterInPlay *monster, int16 target, int16 damageInflicted);
int calcInflictableDamagePerStat(int16 attacker, int16 target, uint16 stat2m, int index, int hitType);
uint16 getClosestMonster(int x, int y);
uint16 getClosestPartyMember(int x, int y);
// spells
bool notEnoughMagic(int charNum, int spellNum, int spellLevel);

View File

@ -273,7 +273,7 @@ void LoLEngine::loadLevelCmzFile(int index) {
}
}
loadCMZ_Sub(tmpLvlVal, (_unkGameFlag & 0x30) >> 4);
loadCMZ_Sub(tmpLvlVal, _monsterDifficulty);
delete[] cmzdata;
}
@ -654,11 +654,43 @@ uint16 LoLEngine::calcBlockIndex(uint16 x, uint16 y) {
return ((y & 0xff00) >> 3) | (x >> 8);
}
void LoLEngine::calcCoordinates(uint16 & x, uint16 & y, int block, uint16 xOffs, uint16 yOffs) {
void LoLEngine::calcCoordinates(uint16 &x, uint16 &y, int block, uint16 xOffs, uint16 yOffs) {
x = (block & 0x1f) << 8 | xOffs;
y = ((block & 0xffe0) << 3) | yOffs;
}
void LoLEngine::calcCoordinatesForSingleCharacter(int charNum, int16 &x, int16 &y) {
static const uint8 xOffsets[] = { 0x80, 0x00, 0x00, 0x40, 0xC0, 0x00, 0x40, 0x80, 0xC0 };
int c = countActiveCharacters();
if (!c)
return;
c = (c - 1) * 3 + charNum;
x = xOffsets[c];
y = 0x80;
calcCoordinatesAddDirectionOffset(x, y, _currentDirection);
x |= (_partyPosX & 0xff00);
y |= (_partyPosY & 0xff00);
}
void LoLEngine::calcCoordinatesAddDirectionOffset(int16 &x, int16 &y, int direction) {
if (!direction)
return;
if (direction & 1)
SWAP(x, y);
if (direction == 1)
y = (y - 256) * -1;
if (direction == 3) {
x = (x - 256) * -1;
}
}
bool LoLEngine::checkBlockPassability(uint16 block, uint16 direction) {
if (testWallFlag(block, direction, 1))
return false;
@ -825,7 +857,7 @@ void LoLEngine::openCloseDoor(uint16 block, int openClose) {
}
void LoLEngine::movePartySmoothScrollBlocked(int speed) {
if (!(_unkGameFlag & 8) || ((_unkGameFlag & 8) && _hideInventory))
if (!_smoothScrollingEnabled || (_smoothScrollingEnabled && _hideInventory))
return;
_screen->backupSceneWindow(_sceneDrawPage2 == 2 ? 2 : 6, 6);
@ -863,7 +895,7 @@ void LoLEngine::movePartySmoothScrollBlocked(int speed) {
}
void LoLEngine::movePartySmoothScrollUp(int speed) {
if (!(_unkGameFlag & 8) || ((_unkGameFlag & 8) && _hideInventory))
if (!_smoothScrollingEnabled || (_smoothScrollingEnabled && _hideInventory))
return;
int d = 0;
@ -908,7 +940,7 @@ void LoLEngine::movePartySmoothScrollUp(int speed) {
}
void LoLEngine::movePartySmoothScrollDown(int speed) {
if (!(_unkGameFlag & 8))
if (!_smoothScrollingEnabled)
return;
//int d = smoothScrollDrawSpecialShape(2);
@ -943,7 +975,7 @@ void LoLEngine::movePartySmoothScrollDown(int speed) {
}
void LoLEngine::movePartySmoothScrollLeft(int speed) {
if (!(_unkGameFlag & 8))
if (!_smoothScrollingEnabled)
return;
speed <<= 1;
@ -969,7 +1001,7 @@ void LoLEngine::movePartySmoothScrollLeft(int speed) {
}
void LoLEngine::movePartySmoothScrollRight(int speed) {
if (!(_unkGameFlag & 8))
if (!_smoothScrollingEnabled)
return;
speed <<= 1;
@ -1008,7 +1040,7 @@ void LoLEngine::movePartySmoothScrollRight(int speed) {
}
void LoLEngine::movePartySmoothScrollTurnLeft(int speed) {
if (!(_unkGameFlag & 8))
if (!_smoothScrollingEnabled)
return;
speed <<= 1;
@ -1052,7 +1084,7 @@ void LoLEngine::movePartySmoothScrollTurnLeft(int speed) {
}
void LoLEngine::movePartySmoothScrollTurnRight(int speed) {
if (!(_unkGameFlag & 8))
if (!_smoothScrollingEnabled)
return;
speed <<= 1;

View File

@ -692,7 +692,7 @@ int LoLEngine::olol_initMonster(EMCState *script) {
l->type = stackPos(4);
l->properties = &_monsterProperties[l->type];
l->direction = l->facing << 1;
l->might = (l->properties->might * _monsterModifiers[((_unkGameFlag & 0x30) >> 4)]) >> 8;
l->might = (l->properties->might * _monsterModifiers[_monsterDifficulty]) >> 8;
if (_currentLevel == 12 && l->type == 2)
l->might = (l->might * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
@ -735,6 +735,10 @@ int LoLEngine::olol_fadeSequencePalette(EMCState *script) {
return 1;
}
int LoLEngine::olol_dummy0(EMCState *script) {
return 0;
}
int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_loadMonsterProperties(%p) (%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d)",
(const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5),
@ -757,25 +761,25 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
l->maxWidth = shpWidthMax;
l->field2[0] = (stackPos(2) << 8) / 100;
l->field2[1] = 256;
l->protection = (stackPos(3) << 8) / 100;
l->unk[0] = stackPos(4);
l->unk[1] = (stackPos(5) << 8) / 100;
l->unk[2] = (stackPos(6) << 8) / 100;
l->unk[3] = (stackPos(7) << 8) / 100;
l->unk[4] = (stackPos(8) << 8) / 100;
l->unk[5] = 0;
l->fightingStats[0] = (stackPos(2) << 8) / 100; // hit chance
l->fightingStats[1] = 256; //
l->fightingStats[2] = (stackPos(3) << 8) / 100; // protection
l->fightingStats[3] = stackPos(4); // evade chance
l->fightingStats[4] = (stackPos(5) << 8) / 100; // speed
l->fightingStats[5] = (stackPos(6) << 8) / 100; //
l->fightingStats[6] = (stackPos(7) << 8) / 100; //
l->fightingStats[7] = (stackPos(8) << 8) / 100; //
l->fightingStats[8] = 0;
l->fightingStats[9] = 0;
for (int i = 0; i < 8; i++) {
l->unk2[i] = stackPos(9 + i);
l->unk3[i] = (stackPos(17 + i) << 8) / 100;
}
l->pos = &l->field2[0];
l->itemProtection = stackPos(25);
l->might = stackPos(26);
l->waitTicks = 1;
l->speedTotalWaitTicks = 1;
l->flags = stackPos(27);
l->unk5 = stackPos(28);
// FIXME???
@ -796,6 +800,11 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
return 1;
}
int LoLEngine::olol_battleHitSkillTest(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_battleHitSkillTest(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
return battleHitSkillTest(stackPos(0), stackPos(1), stackPos(2));
}
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)];
@ -1022,7 +1031,8 @@ int LoLEngine::olol_playDialogueTalkText(EMCState *script) {
return 1;
}
int LoLEngine::olol_checkForMonsterMode1(EMCState *script) {
int LoLEngine::olol_checkMonsterTypeHostility(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkMonsterTypeHostility(%p) (%d)", (const void *)script, stackPos(0));
for (int i = 0; i < 30; i++) {
if (stackPos(0) != _monsters[i].type && stackPos(0) != -1)
continue;
@ -1445,11 +1455,11 @@ void LoLEngine::setupOpcodeTable() {
// 0x3C
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_dummy0);
Opcode(olol_loadMonsterProperties);
// 0x40
OpcodeUnImpl();
Opcode(olol_battleHitSkillTest);
OpcodeUnImpl();
OpcodeUnImpl();
OpcodeUnImpl();
@ -1536,7 +1546,7 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_playDialogueTalkText);
Opcode(olol_checkForMonsterMode1);
Opcode(olol_checkMonsterTypeHostility);
// 0x7C
Opcode(olol_setNextFunc);

View File

@ -162,9 +162,10 @@ int LoLEngine::disableMonstersForBlock(int block) {
void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
if (monster->mode == 13 && mode != 14)
return;
if (mode == 7) {
monster->destX = _partyPosX;
monster->destY = _partyPosX;
monster->destY = _partyPosY;
}
if (monster->mode == 1 && mode == 7) {
@ -172,19 +173,19 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
if (monster->mode != 1)
continue;
monster->mode = mode;
monster->field_15 = 0;
monster->fightCurTick = 0;
monster->destX = _partyPosX;
monster->destY = _partyPosY;
setMonsterDirection(monster, calcMonsterDirection(monster->x, monster->y, monster->destX, monster->destY));
}
} else {
monster->mode = mode;
monster->field_15 = 0;
monster->fightCurTick = 0;
if (mode == 14)
monster->might = 0;
if (mode == 13 && (monster->flags & 0x20)) {
monster->mode = 0;
cmzS3(monster);
monsterDropItems(monster);
if (_currentLevel != 29)
setMonsterMode(monster, 14);
runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
@ -195,6 +196,47 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
}
}
bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
static const uint8 dims[] = { 0, 13, 9, 3 };
if (monster->properties->flags & 8)
return true;
uint16 x1 = (monster->x & 0xff00) | 0x80;
uint16 y1 = (monster->y & 0xff00) | 0x80;
int x2 = _partyPosX;
int y2 = _partyPosY;
uint16 dir = 0;
if (monster->properties->flags & 1) {
dir = monster->direction >> 1;
} else {
dir = calcMonsterDirection(x1, y1, x2, y2);
if ((monster->properties->flags & 2) && (dir == (monster->direction ^ 4)))
return false;
dir >>= 1;
}
calcSpriteRelPosition(x1, y1, x2, y2, dir);
x2 >>= 8;
y2 >>= 8;
if (y2 < 0 || y2 > 3)
return false;
int t = (x2 < 0) ? -x2 : x2;
if (t > y2)
return false;
for (int i = 0; i < 18; i++)
_curBlockCaps[i] = &_levelBlockProperties[(monster->blockPropertyIndex + _dscBlockIndex[dir + i]) & 0x3ff];
int16 fx1 = 0;
int16 fx2 = 0;
setLevelShapesDim(x2 + dims[y2], fx1, fx2, 13);
return (fx1 >= fx2) ? false : true;
}
void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
bool cont = true;
int t = monster->blockPropertyIndex;
@ -211,7 +253,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
if (monster->x != x || monster->y != y) {
monster->x = x;
monster->y = y;
monster->anon9 = (++monster->anon9) & 3;
monster->currentSubFrame = (++monster->currentSubFrame) & 3;
}
if (monster->blockPropertyIndex == 0)
@ -224,7 +266,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
if (monster->properties->sounds[0] == 0 || cont == false)
return;
if ((!(monster->properties->flags & 0x100) || ((monster->anon9 & 1) == 0)) && monster->blockPropertyIndex == t)
if ((!(monster->properties->flags & 0x100) || ((monster->currentSubFrame & 1) == 0)) && monster->blockPropertyIndex == t)
return;
if (monster->blockPropertyIndex != t)
@ -238,6 +280,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
int16 r = 0;
int16 t1 = y1 - y2;
if (t1 < 0) {
r++;
@ -247,19 +290,15 @@ int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2)
r <<= 1;
int16 t2 = x2 - x1;
if (t2 < 0) {
r++;
t2 = -t2;
}
uint8 f = 1;
uint8 f = (t1 > t2) ? 1 : 0;
if (t2 >= t1) {
if (t2 > t1)
f = 0;
if (t2 >= t1)
SWAP(t1, t2);
}
r = (r << 1) | f;
@ -281,8 +320,13 @@ void LoLEngine::setMonsterDirection(MonsterInPlay *monster, int dir) {
checkSceneUpdateNeed(monster->blockPropertyIndex);
}
void LoLEngine::cmzS3(MonsterInPlay *l) {
// TODO
void LoLEngine::monsterDropItems(MonsterInPlay *monster) {
uint16 a = monster->assignedItems;
while (a) {
uint16 b = a;
a = _itemsInPlay[a].nextAssignedObject;
setItemPosition(b, monster->x, monster->y, 0, 1);
}
}
void LoLEngine::removeAssignedObjectFromBlock(LevelBlockProperty *l, int id) {
@ -459,7 +503,7 @@ int LoLEngine::calcMonsterSkillLevel(int id, int a) {
int r = (a << 8) / c[4];
if (!(id & 0x8000))
r = (r * _monsterModifiers[3 + ((_unkGameFlag & 0x30) << 4)]) >> 8;
r = (r * _monsterModifiers[3 + _monsterDifficulty]) >> 8;
id &= 0x7fff;
@ -519,7 +563,6 @@ void LoLEngine::drawBlockObjects(int blockArrayIndex) {
if ((_itemProperties[i->itemPropertyIndex].flags & 0x1000) && !(i->shpCurFrame_flg & 0xC000)) {
int shpIndex = _itemProperties[i->itemPropertyIndex].flags & 0x800 ? 7 : _itemProperties[i->itemPropertyIndex].shpIndex;
shpIndex=12;
int ii = 0;
for (; ii < 8; ii++) {
if (!_flyingItems[ii].enable)
@ -612,7 +655,7 @@ void LoLEngine::drawMonster(uint16 id) {
int dW = _screen->getShapeScaledWidth(shp, _dmScaleW) >> 1;
int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1;
int a = (m->mode == 13) ? (m->field_15 << 1) : (m->properties->might / (m->field_1B & 0x7fff));
int a = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->might / (m->field_1B & 0x7fff));
shp = _gameShapes[6];
@ -654,7 +697,7 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
switch (_monsterUnk[m->properties->shapeIndex]) {
case 0:
if (dirFlags) {
return (*m->properties->pos & 0xff) == 13 ? -1 : (dirFlags + m->anon9);
return (m->properties->fightingStats[0] & 0xff) == 13 ? -1 : (dirFlags + m->currentSubFrame);
} else {
if (m->field_1B)
return 12;
@ -663,13 +706,13 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
case 0:
return m->field_1B ? 12 : ((m->properties->flags & 4) ? 13 : 0);
case 3:
return (m->field_15 + 13);
return (m->fightCurTick + 13);
case 6:
return 14;
case 8:
return -1;
default:
return m->field_1B ? 12 : m->anon9;
return m->field_1B ? 12 : m->currentSubFrame;
}
}
break;
@ -738,8 +781,7 @@ void LoLEngine::redrawSceneItem() {
int t = (i << 7) + 1;
while (s) {
if (s & 0x8000) {
s &= 0x7fff;
s = _monsters[i].nextDrawObject;
s = _monsters[s & 0x7fff].nextDrawObject;
} else {
ItemInPlay *item = &_itemsInPlay[s];
@ -769,7 +811,7 @@ int LoLEngine::calcItemMonsterPosition(ItemInPlay *i, uint16 direction) {
int x = i->x;
int y = i->y;
recalcSpritePosition(_partyPosX, _partyPosY, x, y, direction);
calcSpriteRelPosition(_partyPosX, _partyPosY, x, y, direction);
if (y < 0)
y = 0;
@ -780,9 +822,9 @@ int LoLEngine::calcItemMonsterPosition(ItemInPlay *i, uint16 direction) {
return res;
}
void LoLEngine::recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, int &itemY, uint16 direction) {
int a = itemX - partyX;
int b = partyY - itemY;
void LoLEngine::calcSpriteRelPosition(uint16 x1, uint16 y1, int &x2, int &y2, uint16 direction) {
int a = x2 - x1;
int b = y1 - y2;
if (direction) {
if (direction != 2)
@ -796,8 +838,8 @@ void LoLEngine::recalcSpritePosition(uint16 partyX, uint16 partyY, int &itemX, i
}
}
itemX = a;
itemY = b;
x2 = a;
y2 = b;
}
void LoLEngine::drawDoor(uint8 *shape, uint8 *table, int index, int unk2, int w, int h, int flags) {
@ -938,7 +980,7 @@ uint8 *LoLEngine::drawItemOrMonster(uint8 *shape, uint8 *table, int x, int y, in
}
int LoLEngine::calcDrawingLayerParameters(int x1, int y1, int &x2, int &y2, uint16 &w, uint16 &h, uint8 *shape, int flip) {
recalcSpritePosition(_partyPosX, _partyPosY, x1, y1, _currentDirection);
calcSpriteRelPosition(_partyPosX, _partyPosY, x1, y1, _currentDirection);
if (y1 < 0) {
w = h = x2 = y2 = 0;
@ -965,10 +1007,10 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
return;
int f = flags[monster->mode];
if ((monster->tick++ < monster->properties->waitTicks) && (!(f & 4)))
if ((monster->speedTick++ < monster->properties->speedTotalWaitTicks) && (!(f & 4)))
return;
monster->tick = 0;
monster->speedTick = 0;
if (monster->properties->flags & 0x40) {
monster->might += _rnd.getRandomNumberRng(1, 8);
@ -982,9 +1024,10 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
}
if (f & 2) {
/////
// TODO
if (updateMonsterAdjustBlocks(monster)) {
setMonsterMode(monster, 7);
f &= 6;
}
}
if ((f & 1) && (monster->flags & 0x10))
@ -1000,6 +1043,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
switch (monster->mode) {
case 0:
case 1:
// friendly mode
if (monster->flags & 0x10) {
for (int i = 0; i < 30; i++) {
if (_monsters[i].mode == 1)
@ -1009,28 +1053,87 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
moveMonster(monster);
}
break;
case 2:
moveMonster(monster);
break;
case 3:
if (updateMonsterAdjustBlocks(monster))
setMonsterMode(monster, 7);
for (int i = 0; i < 4; i++) {
if (calcNewBlockPosition(monster->blockPropertyIndex, i) == _currentBlock)
setMonsterMode(monster, 7);
}
break;
case 4:
// straying around not tracing the party
moveStrayingMonster(monster);
break;
case 5:
// second recovery phase after delivering an attack
// monsters will rearrange positions in this phase so as to allow a maximum
// number of monsters possible attacking at the same time
_unkDrawLevelBool = true;
monster->fightCurTick--;
if ((monster->fightCurTick <= 0) || (checkDrawObjectSpace(_partyPosX, _partyPosY, monster->x, monster->y) > 256) || (monster->flags & 8))
setMonsterMode(monster, 7);
else
rearrangeAttackingMonster(monster);
break;
case 6:
// same as mode 5, but without rearranging
if (--monster->fightCurTick <= 0)
setMonsterMode(monster, 7);
break;
case 7:
// monster destination is set to current party position
// depending on the flag setting this gets updated each round
// monster can't change mode before arriving at destination and/or attacking the party
if (!chasePartyWithDistanceAttacks(monster))
chasePartyWithCloseAttacks(monster);
checkSceneUpdateNeed(monster->blockPropertyIndex);
break;
case 8:
// first recovery phase after delivering an attack
if (++monster->fightCurTick > 2) {
setMonsterMode(monster, 5);
monster->fightCurTick = (int8) ((((8 << 8) / monster->properties->fightingStats[4]) * _monsterModifiers[6 + _monsterDifficulty]) >> 8);
}
checkSceneUpdateNeed(monster->blockPropertyIndex);
break;
case 9:
if (--monster->fightCurTick) {
chasePartyWithCloseAttacks(monster);
} else {
setMonsterMode(monster, 7);
monster->flags &= 0xfff7;
}
break;
case 12:
checkSceneUpdateNeed(monster->blockPropertyIndex);
if (++monster->fightCurTick > 13)
runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
break;
case 13:
if (++monster->fightCurTick > 2)
mode13sub(monster);
checkSceneUpdateNeed(monster->blockPropertyIndex);
break;
case 14:
monster->field_1B = 0;
break;
default:
break;
}
@ -1087,6 +1190,54 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
placeMonster(monster, fx, fy);
}
bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
if (!monster->field_25)
return false;
return true;
}
void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) {
if (!(monster->flags & 8)) {
int dir = calcMonsterDirection(monster->x & 0xff00, monster->y & 0xff00, _partyPosX & 0xff00, _partyPosY & 0xff00);
int x1 = _partyPosX;
int y1 = _partyPosY;
calcSpriteRelPosition(monster->x, monster->y, x1, y1, dir >> 1);
int t = (x1 < 0) ? -x1 : x1;
if (y1 <= 160 && t <= 80) {
if ((monster->direction == dir) && (monster->facing == (dir >> 1))) {
int dst = getClosestPartyMember(monster->x, monster->y);
snd_playSoundEffect(monster->properties->sounds[1], -1);
int m = monster->id | 0x8000;
int hit = battleHitSkillTest(m, dst, 0);
if (hit) {
int dmg = _rnd.getRandomNumberRng(2, calcInflictableDamage(m, dst, hit));
battleHit_sub2(dst, dmg, m, 0);
battleHit_sub3(monster, dst, dmg);
}
setMonsterMode(monster, 8);
checkSceneUpdateNeed(monster->blockPropertyIndex);
} else {
setMonsterDirection(monster, dir);
checkSceneUpdateNeed(monster->blockPropertyIndex);
}
return;
}
}
if (monster->x != monster->destX || monster->y != monster->destY) {
walkMonster(monster);
} else {
setMonsterDirection(monster, monster->destDirection);
setMonsterMode(monster, (_rnd.getRandomNumberRng(1, 100) <= 50) ? 4 : 3);
}
}
int LoLEngine::walkMonsterCalcNextStep(MonsterInPlay *monster) {
static const int8 walkMonsterTable1[] = { 7, -6, 5, -4, 3, -2, 1, 0 };
static const int8 walkMonsterTable2[] = { -7, 6, -5, 4, -3, 2, -1, 0 };
@ -1206,6 +1357,124 @@ void LoLEngine::getNextStepCoords(int16 srcX, int16 srcY, int &newX, int &newY,
newY = (srcY + shiftTableY[direction]) & 0x1fff;
}
void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
int t = (monster->direction >> 1);
uint16 mx = monster->x;
uint16 my = monster->y;
uint16 *c = (t & 1) ? &my : &mx;
bool centered = (*c & 0x7f) ? false : true;
bool posFlag = true;
if (monster->properties->maxWidth <= 63) {
if (centered) {
bool r = false;
if (_levelBlockProperties[monster->blockPropertyIndex].assignedObjects & 0x8000) {
r = true;
} else {
uint16 id = _levelBlockProperties[monster->blockPropertyIndex].assignedObjects;
id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
if (id != monster->id) {
r = true;
} else {
for (int i = 0; i < 3; i++) {
t = (t + 1) & 3;
calcNewBlockPosition(monster->blockPropertyIndex, t);
id = _levelBlockProperties[monster->blockPropertyIndex].assignedObjects;
id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
if (id != 0xffff)
r = true;
}
}
}
if (r)
posFlag = false;
} else {
posFlag = false;
}
}
if (centered && posFlag)
return;
if (posFlag) {
if (*c & 0x80)
*c -= 32;
else
*c += 32;
} else {
if (*c & 0x80)
*c += 32;
else
*c -= 32;
}
if (walkMonsterCheckDest(mx, my, monster, 4))
return;
int fx = _partyPosX;
int fy = _partyPosY;
calcSpriteRelPosition(mx, my, fx, fy, monster->direction >> 1);
t = (fx < 0) ? -fx : fx;
if (fy > 160 || t > 80)
return;
placeMonster(monster, mx, my);
}
void LoLEngine::moveStrayingMonster(MonsterInPlay *monster) {
int x = 0;
int y = 0;
if (monster->fightCurTick) {
uint8 d = (monster->direction - monster->fightCurTick) & 6;
uint8 id = monster->id;
for (int i = 0; i < 7; i++) {
getNextStepCoords(monster->x, monster->y, x, y, d);
if (!walkMonsterCheckDest(x, y, monster, 4)) {
placeMonster(monster, x, y);
setMonsterDirection(monster, d);
if (!i) {
if (++id > 3)
monster->fightCurTick = 0;
}
return;
}
d = (d + monster->fightCurTick) & 6;
}
setMonsterMode(monster, 3);
} else {
monster->direction &= 6;
getNextStepCoords(monster->x, monster->y, x, y, monster->direction);
if (!walkMonsterCheckDest(x, y, monster, 4)) {
placeMonster(monster, x, y);
} else {
monster->fightCurTick = _rnd.getRandomBit() ? 2 : -2;
monster->direction = (monster->direction + monster->fightCurTick) & 6;
}
}
}
void LoLEngine::mode13sub(MonsterInPlay *monster) {
setMonsterMode(monster, 14);
monsterDropItems(monster);
checkSceneUpdateNeed(monster->blockPropertyIndex);
uint8 w = _levelBlockProperties[monster->blockPropertyIndex].walls[0];
uint8 f = _levelBlockProperties[monster->blockPropertyIndex].flags;
if (_wllVmpMap[w] == 0 && _wllShapeMap[w] == 0 && !(f & 0x40) && !(monster->properties->flags & 0x1000))
_levelBlockProperties[monster->blockPropertyIndex].flags |= 0x80;
placeMonster(monster, 0, 0);
}
} // end of namespace Kyra
#endif // ENABLE_LOL

View File

@ -1001,9 +1001,9 @@ bool StaticResource::loadCharData(const char *filename, void *&ptr, int &size) {
t->field_34 = file->readUint16LE();
t->field_36 = file->readByte();
t->itemsProtection = file->readUint16LE();
t->hitPointsCur = file->readUint16LE();;
t->hitPointsCur = file->readSint16LE();;
t->hitPointsMax = file->readUint16LE();;
t->magicPointsCur = file->readUint16LE();;
t->magicPointsCur = file->readSint16LE();;
t->magicPointsMax = file->readUint16LE();;
t->field_41 = file->readByte();
t->damageSuffered = file->readUint16LE();