LOL: - Started implementing the fighting system. The damage inflicted is wrong, however (at least the damage inflicted by the monsters). I'm sowewhat clueless about that bug atm.

- added support for monsters with distance attacks (like those orcs in front of roland's house)
- lots of small bug fixes
- Some startup support for the pc-98 16 color version. The intro will run, but the font drawing/coloring is still wrong.

svn-id: r40144
This commit is contained in:
Florian Kagerer 2009-04-25 13:15:05 +00:00
parent f1893d8f25
commit ccb64ad81e
31 changed files with 1856 additions and 572 deletions

Binary file not shown.

View File

@ -43,36 +43,35 @@ struct KYRAGameDescription {
namespace {
#define FLAGS(x, y, z, a, b, c, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, id }
#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, id }
#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id }
#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA1)
#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, Kyra::GI_KYRA1)
#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1)
#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1)
#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_KYRA2)
#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_KYRA2)
#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2)
#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2)
#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2)
#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, true, true, Kyra::GI_KYRA3)
#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, true, false, Kyra::GI_KYRA3)
#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, true, false, Kyra::GI_KYRA3)
#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3)
#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3)
#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3)
#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, Kyra::GI_LOL)
#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, true, Kyra::GI_LOL)
#define LOL_PC98_FLAGS FLAGS(false, false, false, false, false, false, Kyra::GI_LOL)
#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, false, false, Kyra::GI_LOL)
#define LOL_DEMO_FLAGS FLAGS(true, false, false, false, false, false, Kyra::GI_KYRA2)
#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL)
#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL)
#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL)
#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL)
#define LOL_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2)
const KYRAGameDescription adGameDescs[] = {
/* disable these targets until they get supported
@ -1020,23 +1019,6 @@ const KYRAGameDescription adGameDescs[] = {
LOL_FLOPPY_FLAGS
},
/* disable these targets until they get supported
{
{
"lol",
0,
{
{ "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 },
{ "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 },
{ 0, 0, 0, 0 }
},
Common::EN_ANY,
Common::kPlatformPC98,
ADGF_NO_FLAGS
},
LOL_PC98_FLAGS
},
{
{
"lol",
@ -1051,7 +1033,7 @@ const KYRAGameDescription adGameDescs[] = {
ADGF_NO_FLAGS
},
LOL_PC98_SJIS_FLAGS
},*/
},
{
{
@ -1069,7 +1051,7 @@ const KYRAGameDescription adGameDescs[] = {
},
#endif // ENABLE_LOL
{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0) }
{ AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) }
};
const PlainGameDescriptor gameList[] = {

View File

@ -962,7 +962,7 @@ int GUI_LoK::controlsChangeMusic(Button *button) {
debugC(9, kDebugLevelGUI, "GUI_LoK::controlsChangeMusic()");
updateMenuButton(button);
_vm->_configMusic = ++_vm->_configMusic % ((_vm->gameFlags().platform == Common::kPlatformFMTowns || _vm->gameFlags().platform == Common::kPlatformPC98) ? 3 : 2);
_vm->_configMusic = ++_vm->_configMusic % (_vm->gameFlags().platform == Common::kPlatformFMTowns ? 3 : 2);
setupControls(_menu[5]);
return 0;
}

View File

@ -473,7 +473,7 @@ void LoLEngine::gui_drawLiveMagicBar(int x, int y, int curPoints, int unk, int m
int barHeight = (curPoints * h) / maxPoints;
if (barHeight < 1 && curPoints < 1)
if (barHeight < 1 && curPoints > 0)
barHeight = 1;
_screen->drawClippedLine(x - 1, y - h, x - 1, y, 1);
@ -1037,6 +1037,46 @@ int LoLEngine::clickedTurnRightArrow(Button *button) {
}
int LoLEngine::clickedAttackButton(Button *button) {
int c = button->data2Val2;
if (_characters[c].flags & 0x314C)
return 1;
int bl = calcNewBlockPosition(_currentBlock, _currentDirection);
if (_levelBlockProperties[bl].flags & 0x10) {
attackWall(0, 0);
return 1;
}
uint16 target = getNearestMonsterFromCharacter(c);
int s = 0;
for (int i = 0; i < 4; i++) {
if (!_characters[c].items[i])
continue;
runItemScript(c, _characters[c].items[i], 0x400, target, s);
runLevelScriptCustom(_currentBlock, 0x400, c, _characters[c].items[i], target, s);
s -= 10;
}
if (!s) {
runItemScript(c, 0, 0x400, target, s);
runLevelScriptCustom(_currentBlock, 0x400, c, 0, target, s);
}
s = _characters[c].weaponHit ? 4 : calcMonsterSkillLevel(c, 8) + 4;
// check for Zephyr ring
if (itemEquipped(c, 230))
s >>= 1;
_characters[c].flags |= 4;
gui_highlightPortraitFrame(c);
setCharacterUpdateEvent(c, 1, s, 1);
return 1;
}
@ -1074,7 +1114,7 @@ int LoLEngine::clickedMagicSubmenu(Button *button) {
// TODO
///
/*if (processSpellcast(c, _availableSpells[_selectedSpell], spellLevel)) {
setFaceFramesUnkArrays(c, 1, 8, 1);
setCharacterUpdateEvent(c, 1, 8, 1);
sub_718F(c, 2, spellLevel * spellLevel);
} else {*/
_characters[c].flags &= 0xfffb;
@ -1130,6 +1170,23 @@ int LoLEngine::clickedLiveMagicBarsLeft(Button *button) {
}
int LoLEngine::clickedPortraitEtcRight(Button *button) {
if (!_itemInHand)
return 1;
int flg = _itemProperties[_itemsInPlay[_itemInHand].itemPropertyIndex].flags;
int c = button->data2Val2;
if (flg & 1) {
if (!(_characters[c].flags & 8) || (flg & 0x20)) {
runItemScript(c, _itemInHand, 0x400, 0, 0);
runLevelScriptCustom(_currentBlock, 0x400, c, _itemInHand, 0, 0);
} else {
_txt->printMessage(2, getLangString(0x402c), _characters[c].name);
}
return 1;
}
_txt->printMessage(2, getLangString((flg & 8) ? 0x4029 : ((flg & 0x10) ? 0x402a : 0x402b)));
return 1;
}
@ -1389,8 +1446,10 @@ int LoLEngine::clickedWall(Button *button) {
int LoLEngine::clickedSequenceWindow(Button *button) {
runLevelScript(calcNewBlockPosition(_currentBlock, _currentDirection), 0x40);
if (!_seqTrigger || !posWithinRect(_mouseX, _mouseY, _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2))
if (!_seqTrigger || !posWithinRect(_mouseX, _mouseY, _seqWindowX1, _seqWindowY1, _seqWindowX2, _seqWindowY2)) {
_seqTrigger = 0;
removeInputTop();
}
return 1;
}
@ -1418,7 +1477,7 @@ int LoLEngine::clickedSceneThrowItem(Button *button) {
uint16 y = 0;
calcCoordinates(x, y, _currentBlock, 0x80, 0x80);
if (throwItem(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) {
if (launchObject(0, _itemInHand, x, y, 12, _currentDirection << 1, 6, _selectedCharacter, 0x3f)) {
snd_playSoundEffect(18, -1);
setHandItem(0);
}

View File

@ -181,14 +181,14 @@ int LoLEngine::makeItem(int itemType, int curFrame, int flags) {
void LoLEngine::placeMoveLevelItem(int itemIndex, int level, int block, int xOffs, int yOffs, int flyingHeight) {
calcCoordinates(_itemsInPlay[itemIndex].x, _itemsInPlay[itemIndex].y, block, xOffs, yOffs);
if (_itemsInPlay[itemIndex].blockPropertyIndex)
removeLevelItem(itemIndex, _itemsInPlay[itemIndex].blockPropertyIndex);
if (_itemsInPlay[itemIndex].block)
removeLevelItem(itemIndex, _itemsInPlay[itemIndex].block);
if (_currentLevel == level) {
setItemPosition(itemIndex, _itemsInPlay[itemIndex].x, _itemsInPlay[itemIndex].y, flyingHeight, 1);
} else {
_itemsInPlay[itemIndex].level = level;
_itemsInPlay[itemIndex].blockPropertyIndex = block;
_itemsInPlay[itemIndex].block = block;
_itemsInPlay[itemIndex].flyingHeight = flyingHeight;
_itemsInPlay[itemIndex].shpCurFrame_flg |= 0x4000;
}
@ -289,6 +289,24 @@ void LoLEngine::setHandItem(uint16 itemIndex) {
_screen->setMouseCursor(mouseOffs, mouseOffs, getItemIconShapePtr(itemIndex));
}
bool LoLEngine::itemEquipped(int charNum, uint16 itemType) {
if (charNum < 0 || charNum > 3)
return false;
if (!(_characters[charNum].flags & 1))
return false;
for (int i = 0; i < 11; i++) {
if (!_characters[charNum].items[i])
continue;
if (_itemsInPlay[_characters[charNum].items[i]].itemPropertyIndex == itemType)
return true;
}
return false;
}
void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b) {
if (!flyingHeight) {
x = (x & 0xffc0) | 0x40;
@ -298,7 +316,7 @@ void LoLEngine::setItemPosition(int item, uint16 x, uint16 y, int flyingHeight,
uint16 block = calcBlockIndex(x, y);
_itemsInPlay[item].x = x;
_itemsInPlay[item].y = y;
_itemsInPlay[item].blockPropertyIndex = block;
_itemsInPlay[item].block = block;
_itemsInPlay[item].flyingHeight = flyingHeight;
if (b)
@ -320,12 +338,12 @@ void LoLEngine::removeLevelItem(int item, int block) {
removeAssignedObjectFromBlock(&_levelBlockProperties[block], item);
removeDrawObjectFromBlock(&_levelBlockProperties[block], item);
runLevelScriptCustom(block, 0x100, -1, item, 0, 0);
_itemsInPlay[item].blockPropertyIndex = 0;
_itemsInPlay[item].block = 0;
_itemsInPlay[item].level = 0;
}
bool LoLEngine::throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c) {
int sp = checkDrawObjectSpace(_partyPosX, _partyPosX, x, y);
bool LoLEngine::launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c) {
int sp = checkDrawObjectSpace(_partyPosX, _partyPosX, startX, startY);
FlyingObject *t = _flyingObjects;
int slot = -1;
int i = 0;
@ -348,31 +366,31 @@ bool LoLEngine::throwItem(int a, int item, int x, int y, int flyingHeight, int d
i = slot;
t = &_flyingObjects[i];
endObjectFlight(t, x, y, 8);
endObjectFlight(t, startX, startY, 8);
}
if (i == 8)
return false;
t->enable = 1;
t->a = a;
t->objectType = objectType;
t->item = item;
t->x = x;
t->y = y;
t->x = startX;
t->y = startY;
t->flyingHeight = flyingHeight;
t->direction = direction;
t->distance = 255;
t->charNum = charNum;
t->attackerId = attackerId;
t->flags = 7;
t->wallFlags = 2;
t->c = c;
if (charNum != -1) {
if (charNum & 0x8000) {
if (attackerId != -1) {
if (attackerId & 0x8000) {
t->flags &= 0xfd;
} else {
t->flags &= 0xfb;
increaseExperience(charNum, 1, 2);
increaseExperience(attackerId, 1, 2);
}
}
@ -393,7 +411,7 @@ void LoLEngine::endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextB
cy = t->y;
}
if (t->a == 0 || t->a == 1) {
if (t->objectType == 0 || t->objectType == 1) {
objectFlightProcessHits(t, cx, cy, objectOnNextBlock);
t->x = (cx & 0xffc0) | 0x40;
t->y = (cy & 0xffc0) | 0x40;
@ -416,9 +434,9 @@ void LoLEngine::processObjectFlight(FlyingObject *t, int x, int y) {
}
void LoLEngine::updateObjectFlightPosition(FlyingObject *t) {
if (t->a == 0) {
if (t->objectType == 0) {
setItemPosition(t->item, t->x, t->y, t->flyingHeight, (t->flyingHeight == 0) ? 1 : 0);
} else if (t->a == 1) {
} else if (t->objectType == 1) {
if (t->flyingHeight == 0) {
deleteItem(t->item);
checkSceneUpdateNeed(calcBlockIndex(t->x, t->y));
@ -432,23 +450,23 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
uint16 r = 0;
if (objectOnNextBlock == 1) {
runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].blockPropertyIndex, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
runLevelScriptCustom(calcNewBlockPosition(_itemsInPlay[t->item].block, t->direction >> 1), 0x8000, -1, t->item, 0, 0);
return;
} else if (objectOnNextBlock == 2) {
if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) {
int o = _levelBlockProperties[_itemsInPlay[t->item].blockPropertyIndex].assignedObjects;
int o = _levelBlockProperties[_itemsInPlay[t->item].block].assignedObjects;
while (o & 0x8000) {
ItemInPlay *i = findObject(o);
o = i->nextAssignedObject;
runItemScript(t->charNum, t->item, 0x8000, o, 0);
runItemScript(t->attackerId, t->item, 0x8000, o, 0);
}
return;
} else {
r = getClosestMonster(x, y);
r = getNearestMonsterFromPos(x, y);
}
} else if (objectOnNextBlock == 4) {
@ -456,19 +474,19 @@ void LoLEngine::objectFlightProcessHits(FlyingObject *t, int x, int y, int objec
if (_itemProperties[_itemsInPlay[t->item].itemPropertyIndex].flags & 0x4000) {
for (int i = 0; i < 4; i++) {
if (_characters[i].flags & 1)
runItemScript(t->charNum, t->item, 0x8000, i, 0);
runItemScript(t->attackerId, t->item, 0x8000, i, 0);
}
return;
} else {
r = getClosestPartyMember(x, y);
r = getNearestPartyMemberFromPos(x, y);
}
}
runItemScript(t->charNum, t->item, 0x8000, r, 0);
runItemScript(t->attackerId, t->item, 0x8000, r, 0);
}
void LoLEngine::updateFlyingObjects(FlyingObject *t) {
void LoLEngine::updateFlyingObject(FlyingObject *t) {
int x = 0;
int y = 0;
getNextStepCoords(t->x, t->y, x, y, t->direction);

View File

@ -56,6 +56,7 @@ struct GameFlags {
bool useAltShapeHeader : 1; // alternative shape header (uses 2 bytes more, those are unused though)
bool isTalkie : 1;
bool useHiResOverlay : 1;
bool use16ColorMode : 1;
bool useDigSound : 1;
bool useInstallerPackage : 1;
@ -70,10 +71,11 @@ enum {
};
struct AudioDataStruct {
const char * const *_fileList;
int _fileListLen;
const void * _cdaTracks;
int _cdaNumTracks;
const char *const *fileList;
int fileListLen;
const void *cdaTracks;
int cdaNumTracks;
int extraOffset;
};
// TODO: this is just the start of makeing the debug output of the kyra engine a bit more useable

File diff suppressed because it is too large Load Diff

View File

@ -50,18 +50,11 @@ struct LoLCharacter {
int16 id;
uint8 curFaceFrame;
uint8 defaultFaceFrame;
uint8 field_12;
uint8 screamSfx;
const uint16 *defaultModifiers;
uint16 itemsMight[8];
uint16 field_27[2];
uint8 field_2B;
uint16 field_2C;
uint16 field_2E;
uint16 field_30;
uint16 field_32;
uint16 field_34;
uint8 field_36;
uint16 itemsProtection;
uint16 protectionAgainstItems[8];
uint16 itemProtection;
int16 hitPointsCur;
uint16 hitPointsMax;
int16 magicPointsCur;
@ -78,8 +71,8 @@ struct LoLCharacter {
uint8 skillLevels[3];
uint8 skillModifiers[3];
int32 experiencePts[3];
uint8 arrayUnk2[5];
uint8 arrayUnk1[5];
uint8 characterUpdateEvents[5];
uint8 characterUpdateDelay[5];
};
struct SpellProperty {
@ -100,17 +93,22 @@ struct LevelBlockProperty {
struct MonsterProperty {
uint8 shapeIndex;
uint8 maxWidth;
uint16 fightingStats[10];
uint16 unk2[8];
uint16 unk3[8];
uint16 fightingStats[9];
uint16 itemsMight[8];
uint16 protectionAgainstItems[8];
uint16 itemProtection;
uint16 might;
uint16 hitPoints;
uint8 speedTotalWaitTicks;
uint8 skillLevel;
uint16 flags;
uint16 unk5;
uint16 unk6[5];
uint8 unk7[4];
uint16 numDistAttacks;
uint16 numDistWeapons;
uint16 distWeapons[3];
uint8 attackSkillChance;
uint8 attackSkillType;
uint8 defenseSkillChance;
uint8 defenseSkillType;
uint8 sounds[3];
};
@ -118,15 +116,15 @@ struct MonsterInPlay {
uint16 nextAssignedObject;
uint16 nextDrawObject;
uint8 flyingHeight;
uint16 blockPropertyIndex;
uint16 block;
uint16 x;
uint16 y;
int8 shiftStep;
uint16 destX;
uint16 destY;
uint8 destDirection;
uint8 anon8;
uint8 anonh;
int8 hitOffsX;
int8 hitOffsY;
uint8 currentSubFrame;
uint8 mode;
@ -135,15 +133,15 @@ struct MonsterInPlay {
uint8 direction;
uint8 facing;
uint16 flags;
uint8 field_1B;
uint8 field_1C;
int16 might;
uint16 damageReceived;
//uint8 field_1C;
int16 hitPoints;
uint8 speedTick;
uint8 type;
MonsterProperty *properties;
uint8 field_25;
uint8 field_26;
uint8 field_27;
uint8 numDistAttacks;
uint8 curDistWeapon;
int8 distAttackTick;
uint16 assignedItems;
uint8 field_2A[4];
};
@ -152,15 +150,15 @@ struct ItemInPlay {
uint16 nextAssignedObject;
uint16 nextDrawObject;
uint8 flyingHeight;
uint16 blockPropertyIndex;
uint16 block;
uint16 x;
uint16 y;
int8 level;
uint16 itemPropertyIndex;
uint16 shpCurFrame_flg;
uint8 destDirection;
uint8 anon8;
uint8 anonh;
int8 hitOffsX;
int8 hitOffsY;
uint8 currentSubFrame;
};
@ -213,8 +211,8 @@ struct OpenDoorState {
struct FlyingObject {
uint8 enable;
uint8 a;
uint16 charNum;
uint8 objectType;
uint16 attackerId;
uint16 item;
uint16 x;
uint16 y;
@ -324,6 +322,8 @@ private:
int getCharSelection();
int selectionCharAccept();
void showStarcraftLogo();
int _charSelection;
int _charSelectionInfoResult;
@ -354,16 +354,17 @@ private:
void timerProcessDoors(int timerNum);
void timerProcessMonsters(int timerNum);
void timerSub3(int timerNum);
void timerSpecialCharacterUpdate(int timerNum);
void timerProcessFlyingObjects(int timerNum);
void timerRunSceneAnimScript(int timerNum);
void timerSub6(int timerNum);
void timerRegeneratePoints(int timerNum);
void timerUpdatePortraitAnimations(int skipUpdate);
void timerUpdateLampState(int timerNum);
void timerFadeMessageText(int timerNum);
static const uint8 _clock2Timers[];
static const uint8 _numClock2Timers;
int _timer3Para;
// sound
void loadTalkFile(int index);
@ -373,6 +374,7 @@ private:
void snd_stopSpeech(bool setFlag);
void snd_playSoundEffect(int track, int volume);
void snd_processEnvironmentalSoundEffect(int soundId, int block);
void snd_queueEnvironmentalSoundEffect(int soundId, int block);
void snd_loadSoundFile(int track);
int snd_playTrack(int track);
int snd_stopMusic();
@ -387,7 +389,11 @@ private:
char _curMusicFileExt;
int _environmentSfx;
int _environmentSfxVol;
int _environmentSfxDistThreshold;
int _envSfxDistThreshold;
bool _envSfxUseQueue;
int _envSfxNumTracksInQueue;
uint16 _envSfxQueuedTracks[10];
uint16 _envSfxQueuedBlocks[10];
int _nextSpeechId;
int _nextSpeaker;
@ -405,8 +411,8 @@ private:
int _ingameGMSoundIndexSize;
const uint8 *_ingameMT32SoundIndex;
int _ingameMT32SoundIndexSize;
/*const uint8 *_ingameADLSoundIndex;
int _ingameADLSoundIndexSize;*/
AudioDataStruct _soundData[3];
// gui
void gui_drawPlayField();
@ -597,15 +603,18 @@ private:
int olol_fadeSequencePalette(EMCState *script);
int olol_redrawPlayfield(EMCState *script);
int olol_loadNewLevel(EMCState *script);
int olol_getNearestMonsterFromCharacter(EMCState *script);
int olol_dummy0(EMCState *script);
int olol_loadMonsterProperties(EMCState *script);
int olol_battleHitSkillTest(EMCState *script);
int olol_inflictDamage(EMCState *script);
int olol_moveMonster(EMCState *script);
int olol_dialogueBox(EMCState *script);
int olol_giveTakeMoney(EMCState *script);
int olol_checkMoney(EMCState *script);
int olol_setScriptTimer(EMCState *script);
int olol_createHandItem(EMCState *script);
int olol_playAttackSound(EMCState *script);
int olol_characterJoinsParty(EMCState *script);
int olol_loadTimScript(EMCState *script);
int olol_runTimScript(EMCState *script);
@ -619,18 +628,23 @@ private:
int olol_processDialogue(EMCState *script);
int olol_stopTimScript(EMCState *script);
int olol_getWallFlags(EMCState *script);
int olol_changeMonsterSettings(EMCState *script);
int olol_changeMonsterStat(EMCState *script);
int olol_getMonsterStat(EMCState *script);
int olol_playCharacterScriptChat(EMCState *script);
int olol_update(EMCState *script);
int olol_healCharacter(EMCState *script);
int olol_drawExitButton(EMCState *script);
int olol_loadSoundFile(EMCState *script);
int olol_playMusicTrack(EMCState *script);
int olol_countBlockItems(EMCState *script);
int olol_stopCharacterSpeech(EMCState *script);
int olol_setPaletteBrightness(EMCState *script);
int olol_calcInflictableDamage(EMCState *script);
int olol_getInflictedDamage(EMCState *script);
int olol_checkForCertainPartyMember(EMCState *script);
int olol_printMessage(EMCState *script);
int olol_deleteLevelItem(EMCState *script);
int olol_calcInflictableDamagePerItem(EMCState *script);
int olol_objectLeavesLevel(EMCState *script);
int olol_playDialogueTalkText(EMCState *script);
int olol_checkMonsterTypeHostility(EMCState *script);
@ -638,7 +652,7 @@ private:
int olol_dummy1(EMCState *script);
int olol_suspendMonster(EMCState *script);
int olol_setDoorState(EMCState *script);
int olol_processButtonClick(EMCState *script);
int olol_resetTimDialogueState(EMCState *script);
int olol_savePage5(EMCState *script);
int olol_restorePage5(EMCState *script);
int olol_initDialogueSequence(EMCState *script);
@ -699,6 +713,7 @@ private:
// Maybe we can someday reduce the size.
char *getLangString(uint16 id);
uint8 *getTableEntry(uint8 *buffer, uint16 id);
void decodeSjis(const char *src, char *dst);
static const char * const _languageExt[];
@ -728,8 +743,6 @@ private:
int _numThrownShapes;
uint8 **_effectShapes;
int _numEffectShapes;
uint8 **_fireballShapes;
int _numFireballShapes;
const int8 *_gameShapeMap;
int _gameShapeMapSize;
@ -740,8 +753,8 @@ private:
// characters
bool addCharacter(int id);
void setFaceFrames(int charNum, int defaultFrame, int unk2, int redraw);
void setFaceFramesUnkArrays(int charNum, int unk1, int unk2, int unk3);
void setTemporaryFaceFrame(int charNum, int frame, int updateDelay, int redraw);
void setCharacterUpdateEvent(int charNum, int updateType, int updateDelay, int overwrite);
int countActiveCharacters();
void loadCharFaceShapes(int charNum, int id);
void calcCharPortraitXpos();
@ -756,7 +769,9 @@ private:
int calculateCharacterStats(int charNum, int index);
int calculateProtection(int index);
void setCharacterMagicOrHitPoints(int charNum, int type, int points, int mode);
void increaseExperience(int charNum, int skill, uint32 points);
void increaseCharacterHitpoints(int charNum, int points, bool unk);
LoLCharacter *_characters;
uint16 _activeCharsXpos[3];
@ -1023,15 +1038,16 @@ private:
ItemInPlay *findObject(uint16 index);
void runItemScript(int charNum, int item, int sub, int next, int reg4);
void setHandItem(uint16 itemIndex);
bool itemEquipped(int charNum, uint16 itemType);
void setItemPosition(int item, uint16 x, uint16 y, int flyingHeight, int b);
void removeLevelItem(int item, int block);
bool throwItem(int a, int item, int x, int y, int flyingHeight, int direction, int, int charNum, int c);
bool launchObject(int objectType, int item, int startX, int startY, int flyingHeight, int direction, int, int attackerId, int c);
void endObjectFlight(FlyingObject *t, int x, int y, int objectOnNextBlock);
void processObjectFlight(FlyingObject *t, int x, int y);
void updateObjectFlightPosition(FlyingObject *t);
void objectFlightProcessHits(FlyingObject *t, int x, int y, int objectOnNextBlock);
void updateFlyingObjects(FlyingObject *t);
void updateFlyingObject(FlyingObject *t);
void assignItemToBlock(uint16 *assignedBlockObjects, int id);
int checkDrawObjectSpace(int itemX, int itemY, int partyX, int partyY);
@ -1088,6 +1104,9 @@ private:
int calcMonsterSkillLevel(int id, int a);
bool checkBlockOccupiedByParty(int x, int y, int testFlag);
const uint16 *getCharacterOrMonsterStats(int id);
uint16 *getCharacterOrMonsterItemsMight(int id);
uint16 *getCharacterOrMonsterProtectionAgainstItems(int id);
void drawBlockObjects(int blockArrayIndex);
void drawMonster(uint16 id);
int getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags);
@ -1107,7 +1126,7 @@ private:
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 checkForPossibleDistanceAttack(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);
@ -1143,25 +1162,16 @@ private:
uint8 getRandomNumberSpecial();
uint8 _compassBroken;
uint8 _unkBt2;
uint8 _drainMagic;
uint16 _unkWordArraySize8[8];
uint8 *_pageBuffer1;
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);
void processMagicHeal(int charNum, int points);
bool notEnoughMagic(int charNum, int spellNum, int spellLevel);
int8 _availableSpells[7];
int _selectedSpell;
@ -1170,17 +1180,46 @@ private:
int _subMenuIndex;
uint16 _unkIceSHpFlag;
// unneeded
void setWalkspeed(uint8) {}
void removeHandItem() {}
bool lineIsPassable(int, int) { return false; }
uint8 *_healOverlay;
// save
Common::Error loadGameState(int slot) { return Common::kNoError; }
Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) { return Common::kNoError; }
uint8 **_fireballShapes;
int _numFireballShapes;
uint8 **_healShapes;
int _numHealShapes;
uint8 **_healiShapes;
int _numHealiShapes;
void generateTempData();
LevelTempData *_lvlTempData[28];
const uint8 *_healShapeFrames;
int _healShapeFramesSize;
// fight
int battleHitSkillTest(int16 attacker, int16 target, int skill);
int calcInflictableDamage(int16 attacker, int16 target, int hitType);
int inflictDamage(int16 target, int damage, int16 attacker, int skill, int deathFlag);
void characterHitpointsZero(int16 charNum, int a);
void resetCharacterState(LoLCharacter *c, int first, int last);
int calcInflictableDamagePerItem(int16 attacker, int16 target, uint16 itemMight, int index, int hitType);
void checkForPartyDeath();
void applyMonsterAttackSkill(MonsterInPlay *monster, int16 target, int16 damage);
void applyMonsterDefenseSkill(MonsterInPlay *monster, int16 attacker, int deathFlag, int skill, int damage);
int removeCharacterItem(int charNum, int itemFlags);
bool paralyzePoisonCharacter(int charNum, int typeFlag, int immunityFlags, int hitChance, int redraw);
void paralyzePoisonAllCharacters(int typeFlag, int immunityFlags, int hitChance);
void stunCharacter(int charNum);
void level11specialUnk();
void distObj1Sub(int a, int b, int c, int d);
void launchMagicViper();
void attackWall(int a, int b);
uint16 getNearestMonsterFromCharacter(int charNum);
uint16 getNearestMonsterFromCharacterForBlock(int block, int charNum);
uint16 getNearestMonsterFromPos(int x, int y);
uint16 getNearestPartyMemberFromPos(int x, int y);
int _partyDeathFlag;
// magic atlas
void displayAutomap();
@ -1211,6 +1250,18 @@ private:
uint8 _automapTopLeftY;
static const int8 _mapCoords[12][4];
bool _mapUpdateNeeded;
// unneeded
void setWalkspeed(uint8) {}
void removeHandItem() {}
bool lineIsPassable(int, int) { return false; }
// save
Common::Error loadGameState(int slot) { return Common::kNoError; }
Common::Error saveGameState(int slot, const char *saveName, const Graphics::Surface *thumbnail) { return Common::kNoError; }
void generateTempData();
LevelTempData *_lvlTempData[28];
};
} // end of namespace Kyra

View File

@ -286,6 +286,8 @@ enum kKyraResources {
lolMapCursorOvl,
lolMapStringId,
//lolMapPal,
lolHealShapeFrames,
#endif // ENABLE_LOL
kMaxResIDs

View File

@ -163,7 +163,7 @@ Common::Error KyraEngine_LoK::loadGameState(int slot) {
// it wasn't made sure that _curSfxFile was initialized
// so if it's out of bounds we just set it to 0.
if (_flags.platform == Common::kPlatformFMTowns || _flags.platform == Common::kPlatformPC98) {
if (_curSfxFile >= _soundData->_fileListLen || _curSfxFile < 0)
if (_curSfxFile >= _soundData->fileListLen || _curSfxFile < 0)
_curSfxFile = 0;
_sound->loadSoundFile(_curSfxFile);
}

View File

@ -105,9 +105,9 @@ void LoLEngine::addLevelItems() {
if (_itemsInPlay[i].level != _currentLevel)
continue;
assignBlockObject(&_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].assignedObjects, i);
assignBlockObject(&_levelBlockProperties[_itemsInPlay[i].block].assignedObjects, i);
_levelBlockProperties[_itemsInPlay[i].blockPropertyIndex].direction = 5;
_levelBlockProperties[_itemsInPlay[i].block].direction = 5;
_itemsInPlay[i].nextDrawObject = 0;
}
}
@ -259,8 +259,8 @@ void LoLEngine::restoreBlockTempData(int index) {
}
for (int i = 0; i < 30; i++) {
if (_monsters[i].blockPropertyIndex) {
_monsters[i].blockPropertyIndex = 0;
if (_monsters[i].block) {
_monsters[i].block = 0;
_monsters[i].properties = &_monsterProperties[_monsters[i].type];
placeMonster(&_monsters[i], _monsters[i].x, _monsters[i].y);
}
@ -276,14 +276,14 @@ void LoLEngine::restoreTempDataAdjustMonsterStrength(int index) {
uint16 d = (_monsterModifiers[_lvlTempData[index]->monsterDifficulty] << 8) / _monsterModifiers[_monsterDifficulty];
for (int i = 0; i < 30; i++) {
if (_monsters[i].mode >= 14 || _monsters[i].blockPropertyIndex == 0 || _monsters[i].might <= 0)
if (_monsters[i].mode >= 14 || _monsters[i].block == 0 || _monsters[i].hitPoints <= 0)
continue;
_monsters[i].might = (d * _monsters[i].might) >> 8;
_monsters[i].hitPoints = (d * _monsters[i].hitPoints) >> 8;
if (_monsterDifficulty < _lvlTempData[index]->monsterDifficulty)
_monsters[i].might++;
if (_monsters[i].might == 0)
_monsters[i].might = 1;
_monsters[i].hitPoints++;
if (_monsters[i].hitPoints == 0)
_monsters[i].hitPoints = 1;
}
}
@ -470,7 +470,7 @@ void LoLEngine::resetItems(int flag) {
ItemInPlay *it = &_itemsInPlay[id];
it->level = _currentLevel;
it->blockPropertyIndex = i;
it->block = i;
if (r)
r->nextAssignedObject = 0;
}

View File

@ -73,6 +73,8 @@ bool Screen::init() {
memset(_sjisOverlayPtrs, 0, sizeof(_sjisOverlayPtrs));
_useOverlays = false;
_useSJIS = false;
_use16ColorMode = _vm->gameFlags().use16ColorMode;
_sjisTempPage = _sjisFontData = 0;
if (_vm->gameFlags().useHiResOverlay) {
@ -432,11 +434,13 @@ void Screen::getFadeParams(const uint8 *palette, int delay, int &delayInc, int &
int Screen::fadePalStep(const uint8 *palette, int diff) {
debugC(9, kDebugLevelScreen, "Screen::fadePalStep(%p, %d)", (const void *)palette, diff);
const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : (_use16ColorMode ? 16 : 256)) * 3;
uint8 fadePal[768];
memcpy(fadePal, _screenPalette, 768);
memcpy(fadePal, _screenPalette, colors);
bool needRefresh = false;
const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256) * 3;
for (int i = 0; i < colors; ++i) {
int c1 = palette[i];
int c2 = fadePal[i];
@ -495,17 +499,35 @@ void Screen::setScreenPalette(const uint8 *palData) {
debugC(9, kDebugLevelScreen, "Screen::setScreenPalette(%p)", (const void *)palData);
const int colors = (_vm->gameFlags().platform == Common::kPlatformAmiga ? 32 : 256);
uint8 screenPal[256 * 4];
if (palData != _screenPalette)
memcpy(_screenPalette, palData, colors*3);
uint8 screenPal[256 * 4];
for (int i = 0; i < colors; ++i) {
screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3);
screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3);
screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3);
screenPal[4 * i + 3] = 0;
palData += 3;
if (_use16ColorMode && _vm->gameFlags().platform == Common::kPlatformPC98) {
for (int l = 0; l < 1024; l += 64) {
const uint8 *tp = palData;
for (int i = 0; i < 16; ++i) {
screenPal[l + 4 * i + 0] = palData[1];
screenPal[l + 4 * i + 1] = palData[0];
screenPal[l + 4 * i + 2] = palData[2];
screenPal[l + 4 * i + 3] = 0;
palData += 3;
}
palData = tp;
}
} else {
if (palData != _screenPalette)
memcpy(_screenPalette, palData, colors*3);
for (int i = 0; i < colors; ++i) {
screenPal[4 * i + 0] = (palData[0] << 2) | (palData[0] & 3);
screenPal[4 * i + 1] = (palData[1] << 2) | (palData[1] & 3);
screenPal[4 * i + 2] = (palData[2] << 2) | (palData[2] & 3);
screenPal[4 * i + 3] = 0;
palData += 3;
}
}
_system->setPalette(screenPal, 0, colors);
}
@ -1242,7 +1264,9 @@ void Screen::drawShape(uint8 pageNum, const uint8 *shapeData, int x, int y, int
&Screen::drawShapePlotType13, // used by Kyra 1
&Screen::drawShapePlotType14, // used by Kyra 1 (invisibility)
&Screen::drawShapePlotType11_15, // used by Kyra 1 (invisibility)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0,
&Screen::drawShapePlotType20, // used by LoL (heal spell effect)
0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
&Screen::drawShapePlotType33, // used by LoL (blood spots on the floor)
0, 0, 0,
@ -1683,7 +1707,6 @@ void Screen::drawShapePlotType0(uint8 *dst, uint8 cmd) {
}
void Screen::drawShapePlotType1(uint8 *dst, uint8 cmd) {
// uint32 relOffs = dst - _dsDstPage;
for (int i = 0; i < _dsTableLoopCount; ++i)
cmd = _dsTable[cmd];
@ -1705,7 +1728,6 @@ void Screen::drawShapePlotType4(uint8 *dst, uint8 cmd) {
}
void Screen::drawShapePlotType5(uint8 *dst, uint8 cmd) {
// uint32 relOffs = dst - _dsDstPage;
cmd = _dsTable2[cmd];
for (int i = 0; i < _dsTableLoopCount; ++i)
cmd = _dsTable[cmd];
@ -1812,6 +1834,15 @@ void Screen::drawShapePlotType14(uint8 *dst, uint8 cmd) {
*dst = cmd;
}
void Screen::drawShapePlotType20(uint8 *dst, uint8 cmd) {
cmd = _dsTable2[cmd];
uint8 tOffs = _dsTable3[cmd];
if (!(tOffs & 0x80))
cmd = _dsTable4[tOffs << 8 | *dst];
*dst = cmd;
}
void Screen::drawShapePlotType33(uint8 *dst, uint8 cmd) {
if (cmd == 255) {
*dst = _dsTable5[*dst];
@ -2822,6 +2853,9 @@ void Screen::loadPalette(const byte *data, uint8 *palData, int bytes) {
palData[0] = (col & 0xF) << 2; col >>= 4;
palData += 3;
}
} else if (_use16ColorMode) {
for (int i = 0; i < bytes; ++i)
palData[i] = ((data[i] & 0xF) << 4) | (data[i] & 0xF0);
} else {
memcpy(palData, data, bytes);
}

View File

@ -271,6 +271,7 @@ protected:
bool _useOverlays;
bool _useSJIS;
bool _use16ColorMode;
uint8 *_sjisFontData;
uint8 *_sjisTempPage;
@ -328,6 +329,7 @@ protected:
void drawShapePlotType12(uint8 *dst, uint8 cmd);
void drawShapePlotType13(uint8 *dst, uint8 cmd);
void drawShapePlotType14(uint8 *dst, uint8 cmd);
void drawShapePlotType20(uint8 *dst, uint8 cmd);
void drawShapePlotType33(uint8 *dst, uint8 cmd);
void drawShapePlotType37(uint8 *dst, uint8 cmd);
void drawShapePlotType48(uint8 *dst, uint8 cmd);

View File

@ -32,9 +32,6 @@
namespace Kyra {
Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system), _vm(vm) {
_customDimTable = new ScreenDim*[_screenDimTableCount];
memset(_customDimTable, 0, sizeof(ScreenDim*) * _screenDimTableCount);
_paletteOverlay1 = new uint8[0x100];
_paletteOverlay2 = new uint8[0x100];
_grayOverlay = new uint8[0x100];
@ -48,7 +45,7 @@ Screen_LoL::Screen_LoL(LoLEngine *vm, OSystem *system) : Screen_v2(vm, system),
_fadeFlag = 2;
_curDimIndex = 0;
_mapDimX = _mapDimY = _mapDimW = _mapDimH = _mapDimDstX = _mapBlockWidth = _mapDimDstY = _mapBlockHeight = _mapDimU5 = _mapDimU6 = _mapBlockWidth2 = _mapDimU8 = 0;
_internDimX = _internDimY = _internDimW = _internDimH = _internDimDstX = _internBlockWidth = _internDimDstY = _internBlockHeight = _internDimU5 = _internDimU6 = _internBlockWidth2 = _internDimU8 = 0;
}
Screen_LoL::~Screen_LoL() {
@ -64,6 +61,17 @@ Screen_LoL::~Screen_LoL() {
delete[] _grayOverlay;
}
bool Screen_LoL::init() {
if (Screen::init()) {
_screenDimTable = _use16ColorMode ? _screenDimTable16C : _screenDimTable256C;
_customDimTable = new ScreenDim*[_screenDimTableCount];
memset(_customDimTable, 0, sizeof(ScreenDim*) * _screenDimTableCount);
return true;
}
return false;
}
void Screen_LoL::setScreenDim(int dim) {
debugC(9, kDebugLevelScreen, "Screen_LoL::setScreenDim(%d)", dim);
assert(dim < _screenDimTableCount);
@ -525,23 +533,23 @@ void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2,
return;
const ScreenDim *cdim = getScreenDim(dim);
_mapDimX = cdim->sx << 3;
_mapDimY = cdim->sy;
_mapDimW = cdim->w << 3;
_mapDimH = cdim->h;
_internDimX = cdim->sx << 3;
_internDimY = cdim->sy;
_internDimW = cdim->w << 3;
_internDimH = cdim->h;
calcMapBoundaries(x2, y2, w, h);
if (_mapBlockWidth == -1)
if (_internBlockWidth == -1)
return;
uint8 *src = getPagePtr(page1) + y1 * 320 + x1;
uint8 *dst = getPagePtr(page2) + (_mapDimDstY + _mapDimY) * 320;
uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320;
for (int i = 0; i < _mapBlockHeight; i++) {
uint8 *s = src + _mapDimU5;
uint8 *d = dst + (_mapDimDstX + _mapDimX);
for (int i = 0; i < _internBlockHeight; i++) {
uint8 *s = src + _internDimU5;
uint8 *d = dst + (_internDimDstX + _internDimX);
for (int ii = 0; ii < _mapBlockWidth; ii++) {
for (int ii = 0; ii < _internBlockWidth; ii++) {
uint8 p = ovl[*s++];
if (p)
*d = p;
@ -552,60 +560,97 @@ void Screen_LoL::copyBlockSpecial(int page1, int x1, int y1, int page2, int x2,
src += 320;
}
addDirtyRect(_mapDimDstX + _mapDimX, _mapDimDstY + _mapDimY, _mapBlockWidth, _mapBlockHeight);
addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight);
}
void Screen_LoL::applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl) {
if (!w || !h || !ovl)
return;
const ScreenDim *cdim = getScreenDim(dim);
_internDimX = cdim->sx << 3;
_internDimY = cdim->sy;
_internDimW = cdim->w << 3;
_internDimH = cdim->h;
calcMapBoundaries(x2, y2, w, h);
if (_internBlockWidth == -1)
return;
uint8 *src = getPagePtr(page1) + y1 * 320 + x1;
uint8 *dst = getPagePtr(page2) + (_internDimDstY + _internDimY) * 320;
for (int i = 0; i < _internBlockHeight; i++) {
uint8 *s = src + _internDimU5;
uint8 *d = dst + (_internDimDstX + _internDimX);
if (flag)
d += (i >> 1);
for (int ii = 0; ii < _internBlockWidth; ii++) {
if (*s++)
*d = ovl[*d];
d++;
}
dst += 320;
src += 320;
}
addDirtyRect(_internDimDstX + _internDimX, _internDimDstY + _internDimY, _internBlockWidth, _internBlockHeight);
}
void Screen_LoL::calcMapBoundaries(int dstX, int dstY, int width, int height) {
_mapBlockWidth = _mapBlockWidth2 = width;
_mapBlockHeight = height;
_mapDimDstX = dstX;
_mapDimDstY = dstY;
_internBlockWidth = _internBlockWidth2 = width;
_internBlockHeight = height;
_internDimDstX = dstX;
_internDimDstY = dstY;
_mapDimU5 = _mapDimU6 = _mapDimU8 = 0;
_internDimU5 = _internDimU6 = _internDimU8 = 0;
int t = _mapDimDstX + _mapBlockWidth;
int t = _internDimDstX + _internBlockWidth;
if (t <= 0) {
_mapBlockWidth = _mapBlockHeight = -1;
_internBlockWidth = _internBlockHeight = -1;
return;
}
if (t <= _mapDimDstX) {
_mapDimU5 = _mapBlockWidth - t;
_mapBlockWidth = t;
_mapDimDstX = 0;
if (t <= _internDimDstX) {
_internDimU5 = _internBlockWidth - t;
_internBlockWidth = t;
_internDimDstX = 0;
}
t = _mapDimW - _mapDimDstX;
t = _internDimW - _internDimDstX;
if (t <= 0) {
_mapBlockWidth = _mapBlockHeight = -1;
_internBlockWidth = _internBlockHeight = -1;
return;
}
if (t <= _mapBlockWidth)
_mapBlockWidth = t;
if (t <= _internBlockWidth)
_internBlockWidth = t;
_mapBlockWidth2 -= _mapBlockWidth;
_internBlockWidth2 -= _internBlockWidth;
t = _mapDimDstY + _mapBlockHeight;
t = _internDimDstY + _internBlockHeight;
if (t <= 0) {
_mapBlockWidth = _mapBlockHeight = -1;
_internBlockWidth = _internBlockHeight = -1;
return;
}
if (t <= _mapDimDstY) {
_mapDimU6 = _mapBlockHeight - t;
_mapBlockHeight = t;
_mapDimDstY = 0;
if (t <= _internDimDstY) {
_internDimU6 = _internBlockHeight - t;
_internBlockHeight = t;
_internDimDstY = 0;
}
t = _mapDimH - _mapDimDstY;
t = _internDimH - _internDimDstY;
if (t <= 0) {
_mapBlockWidth = _mapBlockHeight = -1;
_internBlockWidth = _internBlockHeight = -1;
return;
}
if (t <= _mapBlockHeight)
_mapBlockHeight = t;
if (t <= _internBlockHeight)
_internBlockHeight = t;
}
void Screen_LoL::fadeToBlack(int delay, const UpdateFunctor *upFunc) {

View File

@ -39,6 +39,8 @@ public:
Screen_LoL(LoLEngine *vm, OSystem *system);
~Screen_LoL();
bool init();
void setScreenDim(int dim);
const ScreenDim *getScreenDim(int dim);
int curDimIndex() { return _curDimIndex; }
@ -60,11 +62,6 @@ public:
void smoothScrollTurnStep2(int srcPage1Num, int srcPage2Num, int dstPageNum);
void smoothScrollTurnStep3(int srcPage1Num, int srcPage2Num, int dstPageNum);
// magic atlas
// This method basically works like copyRegion, but the pixels
// copied also have a palette overlay applied to them.
void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
// palette stuff
void fadeToBlack(int delay=0x54, const UpdateFunctor *upFunc = 0);
void loadSpecialColours(uint8 *destPalette);
@ -75,6 +72,9 @@ public:
uint8 *generateLevelOverlay(const uint8 *srcPal, uint8 *ovl, int opColor, int weight);
uint8 *getLevelOverlay(int index) { return _levelOverlays[index]; }
void copyBlockSpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, uint8 *ovl);
void applyOverlaySpecial(int page1, int x1, int y1, int page2, int x2, int y2, int w, int h, int dim, int flag, uint8 *ovl);
uint8 getShapePaletteSize(const uint8 *shp);
uint8 *_paletteOverlay1;
@ -85,9 +85,12 @@ public:
private:
LoLEngine *_vm;
static const ScreenDim _screenDimTable[];
const ScreenDim *_screenDimTable;
static const int _screenDimTableCount;
static const ScreenDim _screenDimTable256C[];
static const ScreenDim _screenDimTable16C[];
ScreenDim **_customDimTable;
int _curDimIndex;
@ -96,18 +99,18 @@ private:
// magic atlas
void calcMapBoundaries(int dstX, int dstY, int c, int d);
int _mapDimX;
int _mapDimY;
int _mapDimW;
int _mapDimH;
int _mapDimDstX;
int _mapBlockWidth;
int _mapDimDstY;
int _mapBlockHeight;
int _mapDimU5;
int _mapDimU6;
int _mapBlockWidth2;
int _mapDimU8;
int _internDimX;
int _internDimY;
int _internDimW;
int _internDimH;
int _internDimDstX;
int _internBlockWidth;
int _internDimDstY;
int _internBlockHeight;
int _internDimU5;
int _internDimU6;
int _internBlockWidth2;
int _internDimU8;
};
} // end of namespace Kyra

View File

@ -119,7 +119,8 @@ void Screen_v2::getFadeParams(const uint8 *palette, int delay, int &delayInc, in
int maxDiff = 0;
diff = 0;
for (int i = 0; i < 768; ++i) {
int len = _use16ColorMode ? 48 : 768;
for (int i = 0; i < len; ++i) {
diff = ABS(palette[i] - _screenPalette[i]);
maxDiff = MAX(maxDiff, diff);
}

View File

@ -231,7 +231,7 @@ int LoLEngine::olol_getItemPara(EMCState *script) {
switch (stackPos(1)) {
case 0:
return i->blockPropertyIndex;
return i->block;
case 1:
return i->x;
case 2:
@ -298,7 +298,7 @@ int LoLEngine::olol_getCharacterStat(EMCState *script) {
return c->magicPointsMax;
case 9:
return c->itemsProtection;
return c->itemProtection;
case 10:
return c->items[d];
@ -307,7 +307,7 @@ int LoLEngine::olol_getCharacterStat(EMCState *script) {
return c->skillLevels[d] + c->skillModifiers[d];
case 12:
return c->field_27[d];
return c->protectionAgainstItems[d];
case 13:
return (d & 0x80) ? c->itemsMight[7] : c->itemsMight[d];
@ -341,7 +341,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 5:
//// TODO
setCharacterMagicOrHitPoints(stackPos(0), 0, e, 0);
break;
case 6:
@ -349,7 +349,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 7:
//// TODO
setCharacterMagicOrHitPoints(stackPos(0), 1, e, 0);
break;
case 8:
@ -357,7 +357,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 9:
c->itemsProtection = e;
c->itemProtection = e;
break;
case 10:
@ -369,7 +369,7 @@ int LoLEngine::olol_setCharacterStat(EMCState *script) {
break;
case 12:
c->field_27[d] = e;
c->protectionAgainstItems[d] = e;
break;
case 13:
@ -577,7 +577,7 @@ int LoLEngine::olol_getGlobalVar(EMCState *script) {
case 11:
return _compassBroken;
case 12:
return _unkBt2;
return _drainMagic;
case 13:
return _speechFlag;
default:
@ -651,7 +651,7 @@ int LoLEngine::olol_setGlobalVar(EMCState *script) {
break;
case 12:
_unkBt2 = a & 0xff;
_drainMagic = a & 0xff;
break;
default:
@ -708,7 +708,7 @@ int LoLEngine::olol_initMonster(EMCState *script) {
for (uint8 i = 0; i < 30; i++) {
MonsterInPlay *l = &_monsters[i];
if (l->might || l->mode == 13)
if (l->hitPoints || l->mode == 13)
continue;
memset(l, 0, sizeof(MonsterInPlay));
@ -719,13 +719,13 @@ 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[_monsterDifficulty]) >> 8;
l->hitPoints = (l->properties->hitPoints * _monsterModifiers[_monsterDifficulty]) >> 8;
if (_currentLevel == 12 && l->type == 2)
l->might = (l->might * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
l->hitPoints = (l->hitPoints * (_rnd.getRandomNumberRng(1, 128) + 192)) >> 8;
l->field_25 = l->properties->unk6[0];
l->field_27 = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1;
l->numDistAttacks = l->properties->numDistAttacks;
l->distAttackTick = _rnd.getRandomNumberRng(1, calcMonsterSkillLevel(l->id | 0x8000, 8)) - 1;
l->flyingHeight = 2;
l->flags = stackPos(5);
l->assignedItems = 0;
@ -740,7 +740,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->block);
return i;
}
@ -779,7 +779,7 @@ int LoLEngine::olol_loadNewLevel(EMCState *script) {
disableSysTimer(2);
for (int i = 0; i < 8; i++) {
if (!_flyingObjects[i].enable || _flyingObjects[i].a)
if (!_flyingObjects[i].enable || _flyingObjects[i].objectType)
continue;
endObjectFlight(&_flyingObjects[i], _flyingObjects[i].x, _flyingObjects[i].y, 1);
}
@ -800,6 +800,11 @@ int LoLEngine::olol_loadNewLevel(EMCState *script) {
return 1;
}
int LoLEngine::olol_getNearestMonsterFromCharacter(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getNearestMonsterFromCharacter(%p) (%d)", (const void *)script, stackPos(0));
return getNearestMonsterFromCharacter(stackPos(0));
}
int LoLEngine::olol_dummy0(EMCState *script) {
return 0;
}
@ -835,15 +840,14 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
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->itemsMight[i] = stackPos(9 + i);
l->protectionAgainstItems[i] = (stackPos(17 + i) << 8) / 100;
}
l->itemProtection = stackPos(25);
l->might = stackPos(26);
l->hitPoints = stackPos(26);
l->speedTotalWaitTicks = 1;
l->flags = stackPos(27);
l->unk5 = stackPos(28);
@ -851,13 +855,15 @@ int LoLEngine::olol_loadMonsterProperties(EMCState *script) {
l->unk5 = stackPos(29);
//
for (int i = 0; i < 5; i++)
l->unk6[i] = stackPos(30 + i);
l->numDistAttacks = stackPos(30);
l->numDistWeapons = stackPos(31);
for (int i = 0; i < 3; i++)
l->distWeapons[i] = stackPos(32 + i);
for (int i = 0; i < 2; i++) {
l->unk7[i] = stackPos(35 + i);
l->unk7[i + 2] = stackPos(37 + i);
}
l->attackSkillChance = stackPos(35);
l->attackSkillType = stackPos(36);
l->defenseSkillChance = stackPos(37);
l->defenseSkillType = stackPos(38);
for (int i = 0; i < 3; i++)
l->sounds[i] = stackPos(39 + i);
@ -870,6 +876,18 @@ int LoLEngine::olol_battleHitSkillTest(EMCState *script) {
return battleHitSkillTest(stackPos(0), stackPos(1), stackPos(2));
}
int LoLEngine::olol_inflictDamage(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_inflictDamage(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
if (stackPos(0) == -1) {
for (int i = 0; i < 4; i++)
inflictDamage(i, stackPos(1), stackPos(2), stackPos(3), stackPos(4));
} else {
inflictDamage(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
}
return 1;
}
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)];
@ -930,6 +948,20 @@ int LoLEngine::olol_createHandItem(EMCState *script) {
return 1;
}
int LoLEngine::olol_playAttackSound(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playAttackSound(%p) (%d)", (const void *)script, stackPos(0));
static const uint8 sounds[] = { 12, 62, 63 };
int d = stackPos(0);
if ((d < 70 || d > 74) && (d < 81 || d > 89) && (d < 93 || d > 97) && (d < 102 || d > 106))
snd_playSoundEffect(sounds[_itemProperties[d].skill & 3], -1);
else
snd_playSoundEffect(12, -1);
return 1;
}
int LoLEngine::olol_characterJoinsParty(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_characterJoinsParty(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
@ -1043,8 +1075,8 @@ int LoLEngine::olol_getWallFlags(EMCState *script) {
return _wllWallFlags[_levelBlockProperties[stackPos(0)].walls[stackPos(1) & 3]];
}
int LoLEngine::olol_changeMonsterSettings(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_changeMonsterSettings(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
int LoLEngine::olol_changeMonsterStat(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_changeMonsterStat(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
if (stackPos(0) == -1)
return 1;
@ -1060,7 +1092,7 @@ int LoLEngine::olol_changeMonsterSettings(EMCState *script) {
break;
case 1:
m->might = d;
m->hitPoints = d;
break;
case 2:
@ -1084,6 +1116,39 @@ int LoLEngine::olol_changeMonsterSettings(EMCState *script) {
return 1;
}
int LoLEngine::olol_getMonsterStat(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getMonsterStat(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
if (stackPos(0) == -1)
return 0;
MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
int d = stackPos(1);
switch (d) {
case 0:
return m->mode;
case 1:
return m->hitPoints;
case 2:
return m->block;
case 3:
return m->facing;
case 4:
return m->type;
case 5:
return m->properties->hitPoints;
case 6:
return m->flags;
case 7:
return m->properties->flags;
case 8:
return _monsterUnk[m->properties->shapeIndex];
default:
break;
}
return 0;
}
int LoLEngine::olol_playCharacterScriptChat(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_playCharacterScriptChat(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
@ -1098,6 +1163,18 @@ int LoLEngine::olol_update(EMCState *script) {
return 1;
}
int LoLEngine::olol_healCharacter(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_healCharacter(%p) (%d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3));
if (stackPos(3)) {
processMagicHeal(stackPos(0), stackPos(1));
} else {
increaseCharacterHitpoints(stackPos(0), stackPos(1), true);
if (stackPos(2))
gui_drawCharPortraitWithStats(stackPos(0));
}
return 1;
}
int LoLEngine::olol_drawExitButton(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_drawExitButton(%p) (%d, %d)", (const void *)script, stackPos(0), stackPos(1));
@ -1164,6 +1241,17 @@ int LoLEngine::olol_setPaletteBrightness(EMCState *script) {
return old;
}
int LoLEngine::olol_calcInflictableDamage(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcInflictableDamage(%p) (%d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2));
return calcInflictableDamage(stackPos(0), stackPos(1), stackPos(2));
}
int LoLEngine::olol_getInflictedDamage(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_getInflictedDamage(%p) (%d)", (const void *)script, stackPos(0));
int mx = stackPos(0);
return mx ? _rnd.getRandomNumberRng(2, mx) : 0;
}
int LoLEngine::olol_checkForCertainPartyMember(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_checkForCertainPartyMember(%p) (%d)", (const void *)script, stackPos(0));
for (int i = 0; i < 4; i++) {
@ -1186,14 +1274,19 @@ int LoLEngine::olol_printMessage(EMCState *script) {
int LoLEngine::olol_deleteLevelItem(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_deleteLevelItem(%p) (%d)", (const void *)script, stackPos(0));
if (_itemsInPlay[stackPos(0)].blockPropertyIndex)
removeLevelItem(stackPos(0), _itemsInPlay[stackPos(0)].blockPropertyIndex);
if (_itemsInPlay[stackPos(0)].block)
removeLevelItem(stackPos(0), _itemsInPlay[stackPos(0)].block);
deleteItem(stackPos(0));
return 1;
}
int LoLEngine::olol_calcInflictableDamagePerItem(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_calcInflictableDamagePerItem(%p) (%d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
return calcInflictableDamagePerItem(stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4));
}
int LoLEngine::olol_objectLeavesLevel(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_objectLeavesLevel(%p) (%d, %d, %d, %d, %d, %d)", (const void *)script, stackPos(0), stackPos(1), stackPos(2), stackPos(3), stackPos(4), stackPos(5));
int o = _levelBlockProperties[stackPos(0)].assignedObjects;
@ -1216,7 +1309,7 @@ int LoLEngine::olol_objectLeavesLevel(EMCState *script) {
MonsterInPlay *m = &_monsters[l];
setMonsterMode(m, 14);
checkSceneUpdateNeed(m->blockPropertyIndex);
checkSceneUpdateNeed(m->block);
placeMonster(m, 0, 0);
res = 1;
@ -1276,7 +1369,7 @@ int LoLEngine::olol_suspendMonster(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_suspendMonster(%p) (%d)", (const void *)script, stackPos(0));
MonsterInPlay *m = &_monsters[stackPos(0) & 0x7fff];
setMonsterMode(m, 14);
checkSceneUpdateNeed(m->blockPropertyIndex);
checkSceneUpdateNeed(m->block);
placeMonster(m, 0, 0);
return 1;
}
@ -1287,9 +1380,9 @@ int LoLEngine::olol_setDoorState(EMCState *script) {
return _emcDoorState;
}
int LoLEngine::olol_processButtonClick(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_processButtonClick(%p) (%d)", (const void *)script, stackPos(0));
_tim->forceDialogue(_activeTim[stackPos(0)]);
int LoLEngine::olol_resetTimDialogueState(EMCState *script) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::olol_resetTimDialogueState(%p) (%d)", (const void *)script, stackPos(0));
_tim->resetDialogueState(_activeTim[stackPos(0)]);
return 1;
}
@ -1433,7 +1526,7 @@ int LoLEngine::tlol_setupPaletteFade(const TIM *tim, const uint16 *param) {
int LoLEngine::tlol_loadPalette(const TIM *tim, const uint16 *param) {
debugC(3, kDebugLevelScriptFuncs, "LoLEngine::tlol_loadPalette(%p, %p) (%d)", (const void*)tim, (const void*)param, param[0]);
const char *palFile = (const char *)(tim->text + READ_LE_UINT16(tim->text + (param[0]<<1)));
_res->loadFileToBuf(palFile, _screen->getPalette(0), 768);
_screen->loadPalette(palFile, _screen->getPalette(0));
return 1;
}
@ -1747,13 +1840,13 @@ void LoLEngine::setupOpcodeTable() {
// 0x3C
Opcode(olol_loadNewLevel);
OpcodeUnImpl();
Opcode(olol_getNearestMonsterFromCharacter);
Opcode(olol_dummy0);
Opcode(olol_loadMonsterProperties);
// 0x40
Opcode(olol_battleHitSkillTest);
OpcodeUnImpl();
Opcode(olol_inflictDamage);
OpcodeUnImpl();
OpcodeUnImpl();
@ -1766,7 +1859,7 @@ void LoLEngine::setupOpcodeTable() {
// 0x48
Opcode(olol_setScriptTimer);
Opcode(olol_createHandItem);
OpcodeUnImpl();
Opcode(olol_playAttackSound);
Opcode(olol_characterJoinsParty);
// 0x4C
@ -1791,17 +1884,17 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_processDialogue);
Opcode(olol_stopTimScript);
Opcode(olol_getWallFlags);
Opcode(olol_changeMonsterSettings);
Opcode(olol_changeMonsterStat);
// 0x5C
OpcodeUnImpl();
Opcode(olol_getMonsterStat);
OpcodeUnImpl();
Opcode(olol_playCharacterScriptChat);
Opcode(olol_update);
// 0x60
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_healCharacter);
Opcode(olol_drawExitButton);
Opcode(olol_loadSoundFile);
@ -1818,14 +1911,14 @@ void LoLEngine::setupOpcodeTable() {
Opcode(olol_setPaletteBrightness);
// 0x6C
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_calcInflictableDamage);
Opcode(olol_getInflictedDamage);
Opcode(olol_checkForCertainPartyMember);
Opcode(olol_printMessage);
// 0x70
Opcode(olol_deleteLevelItem);
OpcodeUnImpl();
Opcode(olol_calcInflictableDamagePerItem);
OpcodeUnImpl();
OpcodeUnImpl();
@ -1857,7 +1950,7 @@ void LoLEngine::setupOpcodeTable() {
OpcodeUnImpl();
OpcodeUnImpl();
Opcode(olol_setDoorState);
Opcode(olol_processButtonClick);
Opcode(olol_resetTimDialogueState);
// 0x88
OpcodeUnImpl();

View File

@ -618,6 +618,8 @@ int TIMInterpreter::cmd_playVocFile(const uint16 *param) {
if (index < ARRAYSIZE(_vocFiles) && !_vocFiles[index].empty())
vm()->sound()->voicePlay(_vocFiles[index].c_str(), volume, true);
else if (index == 7 && !_vm->gameFlags().isTalkie)
vm()->sound()->playTrack(index);
else
vm()->sound()->playSoundEffect(index);
@ -1144,7 +1146,7 @@ uint16 TIMInterpreter_LoL::processDialogue() {
return res;
}
void TIMInterpreter_LoL::forceDialogue(TIM *tim) {
void TIMInterpreter_LoL::resetDialogueState(TIM *tim) {
if (!tim)
return;

View File

@ -145,7 +145,7 @@ public:
virtual void updateBackgroundAnimation(int animIndex) {}
virtual void playAnimationPart(int animIndex, int firstFrame, int lastFrame, int delay) {}
virtual void forceDialogue(TIM *tim) {}
virtual void resetDialogueState(TIM *tim) {}
int _drawPage2;
@ -231,7 +231,7 @@ public:
void drawDialogueBox(int numStr, const char *s1, const char *s2, const char *s3);
uint16 processDialogue();
void forceDialogue(TIM *tim);
void resetDialogueState(TIM *tim);
void setupBackgroundAnimationPart(int animIndex, int part, int firstFrame, int lastFrame, int cycles, int nextPart, int partDelay, int f, int sfxIndex, int sfxFrame);
void startBackgroundAnimation(int animIndex, int part);

View File

@ -88,6 +88,7 @@ void LoLEngine::setupPrologueData(bool load) {
memset(_selectionAnimTimers, 0, sizeof(_selectionAnimTimers));
memset(_screen->getPalette(1), 0, 768);
} else {
delete _chargenWSA; _chargenWSA = 0;
@ -114,6 +115,13 @@ void LoLEngine::setupPrologueData(bool load) {
_eventList.clear();
}
// We have three sound.dat files, one for the intro, one for the
// end sequence and one for ingame, each contained in a different
// PAK file. Therefore a new call to loadSoundFile() is required
// whenever the PAK file configuration changes.
if (_flags.platform == Common::kPlatformPC98)
_sound->loadSoundFile("sound.dat");
}
void LoLEngine::showIntro() {
@ -122,13 +130,16 @@ void LoLEngine::showIntro() {
_tim = new TIMInterpreter(this, _screen, _system);
assert(_tim);
if (_flags.platform == Common::kPlatformPC98)
showStarcraftLogo();
uint8 *pal = _screen->getPalette(0);
memset(pal, 0, 768);
_screen->setScreenPalette(pal);
_screen->clearPage(0);
_screen->clearPage(4);
_screen->clearPage(8);
_screen->clearPage(8);
TIM *intro = _tim->load("LOLINTRO.TIM", &_timIntroOpcodes);
@ -226,6 +237,9 @@ int LoLEngine::chooseCharacter() {
_screen->copyRegion(0, 0, 0, 0, 320, 200, 2, 0, Screen::CR_NO_P_CHECK);
_screen->_curPage = 0;
if (_flags.use16ColorMode)
_screen->loadPalette("LOL.NOL", _screen->getPalette(0));
_screen->fadePalette(_screen->getPalette(0), 30, 0);
bool kingIntro = true;
@ -571,6 +585,51 @@ int LoLEngine::selectionCharAccept() {
return -1;
}
void LoLEngine::showStarcraftLogo() {
WSAMovie_v2 *ci = new WSAMovie_v2(this, _screen);
assert(ci);
_screen->clearPage(0);
_screen->clearPage(2);
int endframe = ci->open("ci01.wsa", 0, _screen->_currentPalette);
if (!ci->opened()) {
delete ci;
return;
}
_screen->hideMouse();
ci->setX(32);
ci->setY(80);
ci->setDrawPage(2);
ci->displayFrame(0, 0);
_screen->copyPage(2, 0);
_screen->fadeFromBlack();
int inputFlag = 0;
for (int i = 0; i < endframe; i++) {
inputFlag = checkInput(0) & 0xff;
if (shouldQuit() || inputFlag)
break;
ci->displayFrame(i, 0);
_screen->copyPage(2, 0);
_screen->updateScreen();
delay(4 * _tickLength);
}
if (!(shouldQuit() || inputFlag)) {
_sound->voicePlay("star2");
while(_sound->voiceIsPlaying("star2") && !(shouldQuit() || inputFlag)) {
inputFlag = checkInput(0) & 0xff;
delay(_tickLength);
}
}
_screen->fadeToBlack();
_screen->showMouse();
_eventList.clear();
delete ci;
}
} // end of namespace Kyra
#endif // ENABLE_LOL

View File

@ -224,9 +224,11 @@ public:
*/
void voiceStop(const char *file = 0);
protected:
const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->_fileListLen) ? _soundDataList->_fileList[file] : ""; }
const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->_cdaTracks : 0; }
int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->_cdaNumTracks : 0; }
const char *fileListEntry(int file) const { return (_soundDataList != 0 && file >= 0 && file < _soundDataList->fileListLen) ? _soundDataList->fileList[file] : ""; }
int fileListLen() const { return _soundDataList->fileListLen; }
const void *cdaData() const { return _soundDataList != 0 ? _soundDataList->cdaTracks : 0; }
int cdaTrackNum() const { return _soundDataList != 0 ? _soundDataList->cdaNumTracks : 0; }
int extraOffset() const { return _soundDataList != 0 ? _soundDataList->extraOffset : 0; }
enum {
kNumChannelHandles = 4

View File

@ -2714,7 +2714,7 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0];
}
finOut /= 2;
finOut /= 4;
buffer[i << 1] += finOut;
buffer[(i << 1) + 1] += finOut;
}
@ -2887,7 +2887,7 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
finOut += _rhChan[ii].out;
}
finOut *= 7;
finOut *= 3;
buffer[i << 1] += finOut;
buffer[(i << 1) + 1] += finOut;
@ -3381,7 +3381,7 @@ void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) {
break;
};
int32 finOut = ((output * 7) / 2);
int32 finOut = ((output * 3) / ((_numChan + _numSSG - 3) / 3));
if (_chanInternal[i].enableLeft)
*leftSample += finOut;
@ -4064,8 +4064,7 @@ bool SoundPC98::init() {
}
void SoundPC98::playTrack(uint8 track) {
if (--track >= 56)
track -= 55;
track += extraOffset();
if (track == _lastTrack && _musicEnabled)
return;
@ -4074,6 +4073,10 @@ void SoundPC98::playTrack(uint8 track) {
char musicfile[13];
sprintf(musicfile, fileListEntry(0), track);
if (fileListLen() == 1)
sprintf(musicfile, fileListEntry(0), track);
else
strcpy(musicfile, fileListEntry(track));
delete[] _musicTrackData;
_musicTrackData = _vm->resource()->fileData(musicfile, 0);
if (_musicEnabled)
@ -4126,19 +4129,25 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() {
bool SoundTownsPC98_v2::init() {
_driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS);
_useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false;
_vm->checkCD();
// FIXME: While checking for 'track1.XXX(X)' looks like
// a good idea, we should definitely not be doing this
// here. Basically our filenaming scheme could change
// or we could add support for other audio formats. Also
// this misses the possibility that we play the tracks
// right off CD. So we should find another way to
// check if we have access to CD audio.
Resource *res = _vm->resource();
if (_musicEnabled &&
(res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla")))
_musicEnabled = 2;
if (_vm->gameFlags().platform == Common::kPlatformFMTowns) {
_vm->checkCD();
// FIXME: While checking for 'track1.XXX(X)' looks like
// a good idea, we should definitely not be doing this
// here. Basically our filenaming scheme could change
// or we could add support for other audio formats. Also
// this misses the possibility that we play the tracks
// right off CD. So we should find another way to
// check if we have access to CD audio.
Resource *res = _vm->resource();
if (_musicEnabled &&
(res->exists("track1.mp3") || res->exists("track1.ogg") || res->exists("track1.flac") || res->exists("track1.fla")))
_musicEnabled = 2;
_useFmSfx = false;
} else {
_useFmSfx = true;
}
return _driver->init();
}
@ -4153,6 +4162,8 @@ void SoundTownsPC98_v2::process() {
}
void SoundTownsPC98_v2::playTrack(uint8 track) {
track += extraOffset();
if (track == _lastTrack && _musicEnabled)
return;
@ -4171,7 +4182,10 @@ void SoundTownsPC98_v2::playTrack(uint8 track) {
beginFadeOut();
char musicfile[13];
sprintf(musicfile, fileListEntry(0), track);
if (fileListLen() == 1)
sprintf(musicfile, fileListEntry(0), track);
else
strcpy(musicfile, fileListEntry(track));
delete[] _musicTrackData;
_musicTrackData = _vm->resource()->fileData(musicfile, 0);
@ -4208,6 +4222,8 @@ void SoundTownsPC98_v2::beginFadeOut() {
int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool) {
static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
static const char patternHOF[] = "%s.PCM";
static const char patternLOL[] = "%s.VOC";
int h = 0;
if (_currentSFX) {
@ -4218,10 +4234,13 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, uint8, bool) {
}
char filename[13];
sprintf(filename, "%s.PCM", file);
const char *pattern = _vm->game() == GI_LOL ? patternLOL : patternHOF;
sprintf(filename, pattern, file);
uint8 *data = _vm->resource()->fileData(filename, 0);
uint8 *src = data;
if (!src)
return 0;
uint16 sfxRate = rates[READ_LE_UINT16(src)];
src += 2;

View File

@ -80,8 +80,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) {
uint8 *tmpPal2 = new uint8[256];
uint16 *tmpPal3 = new uint16[256];
memset (tmpPal1, 0, 64);
memset (tmpPal2, 0, 256);
memset (tmpPal3, 0xff, 512);
memset (tmpPal2, 0, 256);
for (int i = 0; i < 64; i++) {
tmpPal1[i] = *p;
@ -93,6 +92,7 @@ void LoLEngine::loadMonsterShapes(const char *file, int monsterIndex, int b) {
for (int i = 0; i < 16; i++) {
int pos = (monsterIndex << 4) + i;
memcpy(tmpPal2, _monsterShapes[pos] + 10, 256);
memset (tmpPal3, 0xff, 512);
uint8 numCol = *tmpPal2;
for (int ii = 0; ii < numCol; ii++) {
@ -152,7 +152,7 @@ int LoLEngine::deleteMonstersFromBlock(int block) {
cnt++;
setMonsterMode(m, 14);
checkSceneUpdateNeed(m->blockPropertyIndex);
checkSceneUpdateNeed(m->block);
placeMonster(m, 0, 0);
@ -184,14 +184,14 @@ void LoLEngine::setMonsterMode(MonsterInPlay *monster, int mode) {
monster->mode = mode;
monster->fightCurTick = 0;
if (mode == 14)
monster->might = 0;
monster->hitPoints = 0;
if (mode == 13 && (monster->flags & 0x20)) {
monster->mode = 0;
monsterDropItems(monster);
if (_currentLevel != 29)
setMonsterMode(monster, 14);
runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
if (monster->mode == 14)
placeMonster(monster, 0, 0);
}
@ -230,7 +230,7 @@ bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
return false;
for (int i = 0; i < 18; i++)
_visibleBlocks[i] = &_levelBlockProperties[(monster->blockPropertyIndex + _dscBlockIndex[dir + i]) & 0x3ff];
_visibleBlocks[i] = &_levelBlockProperties[(monster->block + _dscBlockIndex[dir + i]) & 0x3ff];
int16 fx1 = 0;
int16 fx2 = 0;
@ -241,8 +241,8 @@ bool LoLEngine::updateMonsterAdjustBlocks(MonsterInPlay *monster) {
void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
bool cont = true;
int t = monster->blockPropertyIndex;
if (monster->blockPropertyIndex) {
int t = monster->block;
if (monster->block) {
removeAssignedObjectFromBlock(&_levelBlockProperties[t], ((uint16)monster->id) | 0x8000);
_levelBlockProperties[t].direction = 5;
checkSceneUpdateNeed(t);
@ -250,7 +250,7 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
cont = false;
}
monster->blockPropertyIndex = calcBlockIndex(x, y);
monster->block = calcBlockIndex(x, y);
if (monster->x != x || monster->y != y) {
monster->x = x;
@ -258,26 +258,26 @@ void LoLEngine::placeMonster(MonsterInPlay *monster, uint16 x, uint16 y) {
monster->currentSubFrame = (++monster->currentSubFrame) & 3;
}
if (monster->blockPropertyIndex == 0)
if (monster->block == 0)
return;
assignMonsterToBlock(&_levelBlockProperties[monster->blockPropertyIndex].assignedObjects, ((uint16)monster->id) | 0x8000);
_levelBlockProperties[monster->blockPropertyIndex].direction = 5;
checkSceneUpdateNeed(monster->blockPropertyIndex);
assignMonsterToBlock(&_levelBlockProperties[monster->block].assignedObjects, ((uint16)monster->id) | 0x8000);
_levelBlockProperties[monster->block].direction = 5;
checkSceneUpdateNeed(monster->block);
if (monster->properties->sounds[0] == 0 || cont == false)
return;
if ((!(monster->properties->flags & 0x100) || ((monster->currentSubFrame & 1) == 0)) && monster->blockPropertyIndex == t)
if ((!(monster->properties->flags & 0x100) || ((monster->currentSubFrame & 1) == 0)) && monster->block == t)
return;
if (monster->blockPropertyIndex != t)
runLevelScriptCustom(monster->blockPropertyIndex, 0x800, -1, monster->id, 0, 0);
if (monster->block != t)
runLevelScriptCustom(monster->block, 0x800, -1, monster->id, 0, 0);
if (_updateFlags & 1)
return;
snd_processEnvironmentalSoundEffect(monster->properties->sounds[0], monster->blockPropertyIndex);
snd_processEnvironmentalSoundEffect(monster->properties->sounds[0], monster->block);
}
int LoLEngine::calcMonsterDirection(uint16 x1, uint16 y1, uint16 x2, uint16 y2) {
@ -319,7 +319,7 @@ void LoLEngine::setMonsterDirection(MonsterInPlay *monster, int dir) {
if (!(dir & 1) || ((monster->direction - (monster->facing << 1)) >= 2))
monster->facing = monster->direction >> 1;
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
}
void LoLEngine::monsterDropItems(MonsterInPlay *monster) {
@ -651,45 +651,45 @@ void LoLEngine::drawMonster(uint16 id) {
}
}
if (!m->field_1B)
if (!m->damageReceived)
return;
int dW = _screen->getShapeScaledWidth(shp, _dmScaleW) >> 1;
int dH = _screen->getShapeScaledHeight(shp, _dmScaleH) >> 1;
int a = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->might / (m->field_1B & 0x7fff));
int bloodAmount = (m->mode == 13) ? (m->fightCurTick << 1) : (m->properties->hitPoints / (m->damageReceived & 0x7fff));
shp = _gameShapes[6];
int cF = m->properties->flags & 0xc000;
if (cF == 0x4000)
cF = 63;
else if (cF == 0x8000)
cF = 15;
else if (cF == 0xc000)
cF = 74;
int bloodType = m->properties->flags & 0xc000;
if (bloodType == 0x4000)
bloodType = 63;
else if (bloodType == 0x8000)
bloodType = 15;
else if (bloodType == 0xc000)
bloodType = 74;
else
cF = 0;
bloodType = 0;
uint8 *tbl = new uint8[256];
if (cF) {
if (bloodType) {
for (int i = 0; i < 256; i++) {
tbl[i] = i;
if (i < 2 || i > 7)
continue;
tbl[i] += cF;
tbl[i] += bloodType;
}
}
dW += m->anon8;
dH += m->anonh;
dW += m->hitOffsX;
dH += m->hitOffsY;
a = CLIP(a, 1, 4);
bloodAmount = CLIP(bloodAmount, 1, 4);
int sW = _dmScaleW / a;
int sH = _dmScaleH / a;
int sW = _dmScaleW / bloodAmount;
int sH = _dmScaleH / bloodAmount;
_screen->drawShape(_sceneDrawPage1, shp, _shpDmX + dW, _shpDmY + dH, 13, 0x124, tbl, cF ? 1 : 0, sW, sH);
_screen->drawShape(_sceneDrawPage1, shp, _shpDmX + dW, _shpDmY + dH, 13, 0x124, tbl, bloodType ? 1 : 0, sW, sH);
delete[] tbl;
}
@ -698,14 +698,14 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
switch (_monsterUnk[m->properties->shapeIndex]) {
case 0:
if (dirFlags) {
return (m->properties->fightingStats[0] & 0xff) == 13 ? -1 : (dirFlags + m->currentSubFrame);
return (m->mode == 13) ? -1 : (dirFlags + m->currentSubFrame);
} else {
if (m->field_1B)
if (m->damageReceived)
return 12;
switch (m->mode - 5) {
case 0:
return m->field_1B ? 12 : ((m->properties->flags & 4) ? 13 : 0);
return (m->properties->flags & 4) ? 13 : 0;
case 3:
return (m->fightCurTick + 13);
case 6:
@ -713,7 +713,7 @@ int LoLEngine::getMonsterCurFrame(MonsterInPlay *m, uint16 dirFlags) {
case 8:
return -1;
default:
return m->field_1B ? 12 : m->currentSubFrame;
return m->currentSubFrame;
}
}
break;
@ -1013,9 +1013,9 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
monster->speedTick = 0;
if (monster->properties->flags & 0x40) {
monster->might += _rnd.getRandomNumberRng(1, 8);
if (monster->might > monster->properties->might)
monster->might = monster->properties->might;
monster->hitPoints += _rnd.getRandomNumberRng(1, 8);
if (monster->hitPoints > monster->properties->hitPoints)
monster->hitPoints = monster->properties->hitPoints;
}
if (monster->flags & 8) {
@ -1036,7 +1036,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
if ((monster->mode != 11) && (monster->mode != 14)) {
if (!(getRandomNumberSpecial() & 3)) {
monster->shiftStep = (++monster->shiftStep) & 0x0f;
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
}
}
@ -1062,7 +1062,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
if (updateMonsterAdjustBlocks(monster))
setMonsterMode(monster, 7);
for (int i = 0; i < 4; i++) {
if (calcNewBlockPosition(monster->blockPropertyIndex, i) == _currentBlock)
if (calcNewBlockPosition(monster->block, i) == _currentBlock)
setMonsterMode(monster, 7);
}
break;
@ -1096,7 +1096,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
// monster can't change mode before arriving at destination and/or attacking the party
if (!chasePartyWithDistanceAttacks(monster))
chasePartyWithCloseAttacks(monster);
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
break;
case 8:
@ -1105,7 +1105,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
setMonsterMode(monster, 5);
monster->fightCurTick = (int8) ((((8 << 8) / monster->properties->fightingStats[4]) * _monsterModifiers[6 + _monsterDifficulty]) >> 8);
}
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
break;
case 9:
@ -1119,7 +1119,7 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
break;
case 12:
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
if (++monster->fightCurTick > 13)
runLevelScriptCustom(0x404, -1, monster->id, monster->id, 0, 0);
break;
@ -1128,23 +1128,23 @@ void LoLEngine::updateMonster(MonsterInPlay *monster) {
// monster death
if (++monster->fightCurTick > 2)
killMonster(monster);
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
break;
case 14:
monster->field_1B = 0;
monster->damageReceived = 0;
break;
default:
break;
}
if (monster->field_1B) {
if (monster->field_1B & 0x8000)
monster->field_1B &= 0x7fff;
if (monster->damageReceived) {
if (monster->damageReceived & 0x8000)
monster->damageReceived &= 0x7fff;
else
monster->field_1B = 0;
checkSceneUpdateNeed(monster->blockPropertyIndex);
monster->damageReceived = 0;
checkSceneUpdateNeed(monster->block);
}
monster->flags &= 0xffef;
@ -1174,10 +1174,10 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
setMonsterDirection(monster, _monsterLastWalkDirection);
} else {
setMonsterDirection(monster, s);
if (monster->field_25) {
if (getMonsterDistance(monster->blockPropertyIndex, _currentBlock) >= 2) {
if (walkMonster_s3(monster->blockPropertyIndex, monster->direction, 3, _currentBlock) != 5) {
if (monster->field_27)
if (monster->numDistAttacks) {
if (getMonsterDistance(monster->block, _currentBlock) >= 2) {
if (checkForPossibleDistanceAttack(monster->block, monster->direction, 3, _currentBlock) != 5) {
if (monster->distAttackTick)
return;
}
}
@ -1192,9 +1192,80 @@ void LoLEngine::walkMonster(MonsterInPlay *monster) {
}
bool LoLEngine::chasePartyWithDistanceAttacks(MonsterInPlay *monster) {
if (!monster->field_25)
if (!monster->numDistAttacks)
return false;
if (monster->distAttackTick > 0) {
monster->distAttackTick--;
return false;
}
int dir = checkForPossibleDistanceAttack(monster->block, monster->facing, 4, _currentBlock);
if (dir == 5)
return false;
int s = 0;
if (monster->flags & 0x10) {
s = monster->properties->numDistWeapons ? _rnd.getRandomNumberRng(1, monster->properties->numDistWeapons) : 0;
} else {
s = monster->curDistWeapon++;
if (monster->curDistWeapon == monster->properties->numDistWeapons)
monster->curDistWeapon = 0;
}
int flyingObject = monster->properties->distWeapons[s];
if (flyingObject & 0xc000) {
if (getMonsterDistance(monster->block, _currentBlock) > 1) {
int type = flyingObject & 0x4000 ? 0 : 1;
flyingObject = makeItem(flyingObject & 0x3fff, 0, 0);
if (flyingObject) {
if (!launchObject(type, flyingObject, monster->x, monster->y, 12, dir << 1, -1, monster->id | 0x8000, 0x3f))
deleteItem(flyingObject);
}
}
} else if (!(flyingObject & 0x2000)) {
if (getMonsterDistance(monster->block, _currentBlock) > 1)
return false;
if (flyingObject == 1) {
snd_playSoundEffect(147, -1);
distObj1Sub(10, 2, 2, 1);
for (int i = 0; i < 4; i++) {
if (!(_characters[i].flags & 1))
continue;
int item = removeCharacterItem(i, 15);
if (item)
setItemPosition(item, _partyPosX, _partyPosY, 0, 1);
inflictDamage(i, 20, -1, 0, 2);
}
} else if (flyingObject == 3) {
// shriek
for (int i = 0; i < 30; i++) {
if (getMonsterDistance(monster->block, _monsters[i].block) < 7)
setMonsterMode(monster, 7);
}
_txt->printMessage(2, getLangString(0x401a));
} else if (flyingObject == 4) {
launchMagicViper();
} else {
return false;
}
}
if (monster->numDistAttacks != 255)
monster->numDistAttacks--;
monster->distAttackTick = (monster->properties->fightingStats[4] * 8) >> 8;
return true;
}
@ -1209,23 +1280,24 @@ void LoLEngine::chasePartyWithCloseAttacks(MonsterInPlay *monster) {
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);
int dst = getNearestPartyMemberFromPos(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);
int mx = calcInflictableDamage(m, dst, hit);
int dmg = mx ? _rnd.getRandomNumberRng(2, mx) : 0;
inflictDamage(dst, dmg, m, 0, 0);
applyMonsterAttackSkill(monster, dst, dmg);
}
setMonsterMode(monster, 8);
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
} else {
setMonsterDirection(monster, dir);
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
}
return;
}
@ -1308,24 +1380,26 @@ int LoLEngine::getMonsterDistance(uint16 block1, uint16 block2) {
return (dx << 1) + dy;
}
int LoLEngine::walkMonster_s3(uint16 monsterBlock, int direction, int distance, uint16 curBlock) {
int LoLEngine::checkForPossibleDistanceAttack(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))
if ((dir & 1) || (dir != direction << 1))
return 5;
if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) || ((monsterBlock & 0xffe0) != (curBlock & 0xffe0)))
if (((monsterBlock & 0x1f) != (curBlock & 0x1f)) && ((monsterBlock & 0xffe0) != (curBlock & 0xffe0)))
return 5;
if (distance < 0)
return 5;
int p = monsterBlock;
for (int i = 0; i < distance; i++) {
int p = calcNewBlockPosition(monsterBlock, direction);
p = calcNewBlockPosition(p, direction);
if (p == curBlock)
return direction;
@ -1373,7 +1447,7 @@ void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
if (monster->nextAssignedObject & 0x8000) {
r = true;
} else {
uint16 id = _levelBlockProperties[monster->blockPropertyIndex].assignedObjects;
uint16 id = _levelBlockProperties[monster->block].assignedObjects;
id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
if (id != monster->id) {
@ -1381,7 +1455,7 @@ void LoLEngine::rearrangeAttackingMonster(MonsterInPlay *monster) {
} else {
for (int i = 0; i < 3; i++) {
t = (t + 1) & 3;
id = _levelBlockProperties[calcNewBlockPosition(monster->blockPropertyIndex, t)].assignedObjects;
id = _levelBlockProperties[calcNewBlockPosition(monster->block, t)].assignedObjects;
id = (id & 0x8000) ? (id & 0x7fff) : 0xffff;
if (id != 0xffff)
r = true;
@ -1465,12 +1539,12 @@ void LoLEngine::moveStrayingMonster(MonsterInPlay *monster) {
void LoLEngine::killMonster(MonsterInPlay *monster) {
setMonsterMode(monster, 14);
monsterDropItems(monster);
checkSceneUpdateNeed(monster->blockPropertyIndex);
checkSceneUpdateNeed(monster->block);
uint8 w = _levelBlockProperties[monster->blockPropertyIndex].walls[0];
uint8 f = _levelBlockProperties[monster->blockPropertyIndex].flags;
uint8 w = _levelBlockProperties[monster->block].walls[0];
uint8 f = _levelBlockProperties[monster->block].flags;
if (_wllVmpMap[w] == 0 && _wllShapeMap[w] == 0 && !(f & 0x40) && !(monster->properties->flags & 0x1000))
_levelBlockProperties[monster->blockPropertyIndex].flags |= 0x80;
_levelBlockProperties[monster->block].flags |= 0x80;
placeMonster(monster, 0, 0);
}

View File

@ -44,7 +44,7 @@
namespace Kyra {
#define RESFILE_VERSION 44
#define RESFILE_VERSION 45
namespace {
bool checkKyraDat(Common::SeekableReadStream *file) {
@ -449,6 +449,8 @@ bool StaticResource::init() {
{ lolMapStringId, kLolRawDataBe16, "MAPSTRID.LST" },
//{ lolMapPal, kRawData, "MAP.PAL" },
{ lolHealShapeFrames, kRawData, "MHEAL.SHP" },
{ 0, 0, 0 }
};
#endif // ENABLE_LOL
@ -992,20 +994,13 @@ bool StaticResource::loadCharData(const char *filename, void *&ptr, int &size) {
t->id = file->readSint16LE();
t->curFaceFrame = file->readByte();
t->defaultFaceFrame = file->readByte();
t->field_12 = file->readByte();
t->screamSfx = file->readByte();
file->readUint32LE();
for (int ii = 0; ii < 8; ii++)
t->itemsMight[ii] = file->readUint16LE();
for (int ii = 0; ii < 2; ii++)
t->field_27[ii] = file->readUint16LE();
t->field_2B = file->readByte();
t->field_2C = file->readUint16LE();
t->field_2E = file->readUint16LE();
t->field_30 = file->readUint16LE();
t->field_32 = file->readUint16LE();
t->field_34 = file->readUint16LE();
t->field_36 = file->readByte();
t->itemsProtection = file->readUint16LE();
for (int ii = 0; ii < 8; ii++)
t->protectionAgainstItems[ii] = file->readUint16LE();
t->itemProtection = file->readUint16LE();
t->hitPointsCur = file->readSint16LE();;
t->hitPointsMax = file->readUint16LE();;
t->magicPointsCur = file->readSint16LE();;
@ -1027,9 +1022,9 @@ bool StaticResource::loadCharData(const char *filename, void *&ptr, int &size) {
for (int ii = 0; ii < 3; ii++)
t->experiencePts[ii] = file->readUint32LE();
for (int ii = 0; ii < 5; ii++)
t->arrayUnk2[ii] = file->readByte();
t->characterUpdateEvents[ii] = file->readByte();
for (int ii = 0; ii < 5; ii++)
t->arrayUnk1[ii] = file->readByte();
t->characterUpdateDelay[ii] = file->readByte();
};
ptr = charData;
@ -1430,47 +1425,28 @@ void KyraEngine_LoK::initStaticResource() {
// FIXME: It seems Kyra1 MAC CD includes AdLib and MIDI music and sfx, thus we enable
// support for those for now. (Based on patch #2767489 "Support for Mac Kyrandia 1 CD" by satz).
memset(_soundData, 0, sizeof(_soundData));
if (_flags.platform == Common::kPlatformPC || _flags.platform == Common::kPlatformMacintosh) {
_soundData[0]._fileList = _soundFilesIntro;
_soundData[0]._fileListLen = _soundFilesIntroSize;
_soundData[0]._cdaTracks = 0;
_soundData[0]._cdaNumTracks = 0;
_soundData[1]._fileList = _soundFiles;
_soundData[1]._fileListLen = _soundFilesSize;
_soundData[1]._cdaTracks = 0;
_soundData[1]._cdaNumTracks = 0;
_soundData[2]._fileList = 0;
_soundData[2]._fileListLen = 0;
_soundData[2]._cdaTracks = 0;
_soundData[2]._cdaNumTracks = 0;
_soundData[0].fileList = _soundFilesIntro;
_soundData[0].fileListLen = _soundFilesIntroSize;
_soundData[1].fileList = _soundFiles;
_soundData[1].fileListLen = _soundFilesSize;
} else if (_flags.platform == Common::kPlatformFMTowns) {
_soundData[0]._fileList = _soundFiles;
_soundData[0]._fileListLen = _soundFilesSize;
_soundData[0]._cdaTracks = _cdaTrackTable;
_soundData[0]._cdaNumTracks = _cdaTrackTableSize;
_soundData[1]._fileList = _soundFiles;
_soundData[1]._fileListLen = _soundFilesSize;
_soundData[1]._cdaTracks = _cdaTrackTable;
_soundData[1]._cdaNumTracks = _cdaTrackTableSize;
_soundData[2]._fileList = 0;
_soundData[2]._fileListLen = 0;
_soundData[2]._cdaTracks = 0;
_soundData[2]._cdaNumTracks = 0;
_soundData[0].fileList = _soundFiles;
_soundData[0].fileListLen = _soundFilesSize;
_soundData[0].cdaTracks = _cdaTrackTable;
_soundData[0].cdaNumTracks = _cdaTrackTableSize;
_soundData[1].fileList = _soundFiles;
_soundData[1].fileListLen = _soundFilesSize;
_soundData[1].cdaTracks = _cdaTrackTable;
_soundData[1].cdaNumTracks = _cdaTrackTableSize;
} else if (_flags.platform == Common::kPlatformPC98) {
_soundData[0]._fileList = tIntro98;
_soundData[0]._fileListLen = 1;
_soundData[0]._cdaTracks = 0;
_soundData[0]._cdaNumTracks = 0;
_soundData[1]._fileList = tIngame98;
_soundData[1]._fileListLen = 1;
_soundData[1]._cdaTracks = 0;
_soundData[1]._cdaNumTracks = 0;
_soundData[2]._fileList = 0;
_soundData[2]._fileListLen = 0;
_soundData[2]._cdaTracks = 0;
_soundData[2]._cdaNumTracks = 0;
} else {
memset(_soundData, 0, sizeof(_soundData));
_soundData[0].fileList = tIntro98;
_soundData[0].fileListLen = 1;
_soundData[0].extraOffset = -56;
_soundData[1].fileList = tIngame98;
_soundData[1].fileListLen = 1;
_soundData[1].extraOffset = -1;
}
}
@ -1673,45 +1649,34 @@ void KyraEngine_HoF::initStaticResource() {
static const char *pc98MusicFileListFinale[] = { "finale%d.86" };
static const char *pc98MusicFileListIngame[] = { "km%02d.86" };
memset(_soundData, 0, sizeof(_soundData));
if (_flags.platform == Common::kPlatformPC) {
_soundData[0]._fileList = _musicFileListIntro;
_soundData[0]._fileListLen = _musicFileListIntroSize;
_soundData[0]._cdaTracks = 0;
_soundData[0]._cdaNumTracks = 0;
_soundData[1]._fileList = _musicFileListIngame;
_soundData[1]._fileListLen = _musicFileListIngameSize;
_soundData[1]._cdaTracks = 0;
_soundData[1]._cdaNumTracks = 0;
_soundData[2]._fileList = _musicFileListFinale;
_soundData[2]._fileListLen = _musicFileListIntroSize;
_soundData[2]._cdaTracks = 0;
_soundData[2]._cdaNumTracks = 0;
_soundData[0].fileList = _musicFileListIntro;
_soundData[0].fileListLen = _musicFileListIntroSize;
_soundData[1].fileList = _musicFileListIngame;
_soundData[1].fileListLen = _musicFileListIngameSize;
_soundData[2].fileList = _musicFileListFinale;
_soundData[2].fileListLen = _musicFileListIntroSize;
} else if (_flags.platform == Common::kPlatformFMTowns) {
_soundData[0]._fileList = fmtMusicFileListIntro;
_soundData[0]._fileListLen = 1;
_soundData[0]._cdaTracks = _cdaTrackTableIntro;
_soundData[0]._cdaNumTracks = _cdaTrackTableIntroSize >> 1;
_soundData[1]._fileList = fmtMusicFileListIngame;
_soundData[1]._fileListLen = 1;
_soundData[1]._cdaTracks = _cdaTrackTableIngame;
_soundData[1]._cdaNumTracks = _cdaTrackTableIngameSize >> 1;
_soundData[2]._fileList = fmtMusicFileListFinale;
_soundData[2]._fileListLen = 1;
_soundData[2]._cdaTracks = _cdaTrackTableFinale;
_soundData[2]._cdaNumTracks = _cdaTrackTableFinaleSize >> 1;
_soundData[0].fileList = fmtMusicFileListIntro;
_soundData[0].fileListLen = 1;
_soundData[0].cdaTracks = _cdaTrackTableIntro;
_soundData[0].cdaNumTracks = _cdaTrackTableIntroSize >> 1;
_soundData[1].fileList = fmtMusicFileListIngame;
_soundData[1].fileListLen = 1;
_soundData[1].cdaTracks = _cdaTrackTableIngame;
_soundData[1].cdaNumTracks = _cdaTrackTableIngameSize >> 1;
_soundData[2].fileList = fmtMusicFileListFinale;
_soundData[2].fileListLen = 1;
_soundData[2].cdaTracks = _cdaTrackTableFinale;
_soundData[2].cdaNumTracks = _cdaTrackTableFinaleSize >> 1;
} else if (_flags.platform == Common::kPlatformPC98) {
_soundData[0]._fileList = pc98MusicFileListIntro;
_soundData[0]._fileListLen = 1;
_soundData[0]._cdaTracks = 0;
_soundData[0]._cdaNumTracks = 0;
_soundData[1]._fileList = pc98MusicFileListIngame;
_soundData[1]._fileListLen = 1;
_soundData[1]._cdaTracks = 0;
_soundData[1]._cdaNumTracks = 0;
_soundData[2]._fileList = pc98MusicFileListFinale;
_soundData[2]._fileListLen = 1;
_soundData[2]._cdaTracks = 0;
_soundData[2]._cdaNumTracks = 0;
_soundData[0].fileList = pc98MusicFileListIntro;
_soundData[0].fileListLen = 1;
_soundData[1].fileList = pc98MusicFileListIngame;
_soundData[1].fileListLen = 1;
_soundData[2].fileList = pc98MusicFileListFinale;
_soundData[2].fileListLen = 1;
}
// setup sequence data
@ -1884,10 +1849,33 @@ void LoLEngine::initStaticResource() {
memcpy (_mapCursorOverlay, tmp, tmpSize);
_staticres->unloadId(lolMapCursorOvl);
/*tmp = _staticres->loadRawData(lolMapPal, tmpSize);
_screen->_automapPal = new uint8[tmpSize];
memcpy (_screen->_automapPal, tmp, tmpSize);
_staticres->unloadId(lolMapPal);*/
_healShapeFrames = _staticres->loadRawData(lolHealShapeFrames, _healShapeFramesSize);
// assign music data
static const char *pcMusicFileListIntro[] = { "LOREINTR" };
static const char *pcMusicFileListFinale[] = { "LOREFINL" };
static const char *pcMusicFileListIngame[] = { "LORE%02d%c" };
static const char *pc98MusicFileListIntro[] = { 0, "lore84.86", "lore82.86", 0, 0, 0, "lore83.86", "lore81.86" };
static const char *pc98MusicFileListFinale[] = { "lore%02d.86" };
static const char *pc98MusicFileListIngame[] = { "lore%02d.86" };
memset(_soundData, 0, sizeof(_soundData));
if (_flags.platform == Common::kPlatformPC) {
_soundData[0].fileList = pcMusicFileListIntro;
_soundData[0].fileListLen = 1;
_soundData[1].fileList = pcMusicFileListIngame;
_soundData[1].fileListLen = 1;
_soundData[2].fileList = pcMusicFileListFinale;
_soundData[3].fileListLen = 1;
} else if (_flags.platform == Common::kPlatformPC98) {
_soundData[0].fileList = pc98MusicFileListIntro;
_soundData[0].fileListLen = ARRAYSIZE(pc98MusicFileListIntro);
_soundData[1].fileList = pc98MusicFileListIngame;
_soundData[1].fileListLen = 1;
_soundData[2].fileList = pc98MusicFileListFinale;
_soundData[2].fileListLen = ARRAYSIZE(pc98MusicFileListFinale);;
}
}
void LoLEngine::assignButtonCallback(Button *button, int index) {
@ -2949,7 +2937,7 @@ const int8 KyraEngine_MR::_albumWSAY[] = {
// lands of lore static res
#ifdef ENABLE_LOL
const ScreenDim Screen_LoL::_screenDimTable[] = {
const ScreenDim Screen_LoL::_screenDimTable256C[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0xC7, 0xCF, 0x00, 0x00 }, // Taken from Intro
{ 0x08, 0x48, 0x18, 0x38, 0xFE, 0x01, 0x00, 0x00 },
{ 0x0E, 0x00, 0x16, 0x78, 0xFE, 0x01, 0x00, 0x00 },
@ -2966,7 +2954,24 @@ const ScreenDim Screen_LoL::_screenDimTable[] = {
{ 0x0B, 0x8C, 0x10, 0x23, 0x3D, 0x01, 0x00, 0x00 } // Main menu box (3 entries, floppy version only)
};
const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable);
const ScreenDim Screen_LoL::_screenDimTable16C[] = {
{ 0x00, 0x00, 0x28, 0xC8, 0x33, 0x44, 0x00, 0x00 }, // Taken from Intro
{ 0x08, 0x48, 0x18, 0x38, 0x33, 0x44, 0x00, 0x00 },
{ 0x0E, 0x00, 0x16, 0x78, 0x33, 0x44, 0x00, 0x00 },
{ 0x0B, 0x7B, 0x1C, 0x12, 0x33, 0x11, 0x00, 0x00 },
{ 0x0B, 0x7B, 0x1C, 0x2D, 0x33, 0x11, 0x00, 0x00 },
{ 0x55, 0x7B, 0xE9, 0x37, 0x33, 0x11, 0x00, 0x00 },
{ 0x0B, 0x8C, 0x10, 0x2B, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (4 entries)
{ 0x04, 0x59, 0x20, 0x3C, 0x00, 0x00, 0x00, 0x00 },
{ 0x05, 0x6E, 0x1E, 0x0C, 0x33, 0x44, 0x00, 0x00 },
{ 0x07, 0x19, 0x1A, 0x97, 0x00, 0x00, 0x00, 0x00 },
{ 0x03, 0x1E, 0x22, 0x8C, 0x00, 0x00, 0x00, 0x00 },
{ 0x02, 0x48, 0x24, 0x34, 0x00, 0x00, 0x00, 0x00 },
{ 0x0B, 0x8C, 0x10, 0x33, 0x33, 0x44, 0x00, 0x00 }, // Main menu box (5 entries, not used here)
{ 0x0B, 0x8C, 0x10, 0x23, 0x33, 0x44, 0x00, 0x00 } // Main menu box (3 entries)
};
const int Screen_LoL::_screenDimTableCount = ARRAYSIZE(Screen_LoL::_screenDimTable256C);
const char * const LoLEngine::_languageExt[] = {
"ENG",

View File

@ -232,7 +232,7 @@ void TimerManager::pauseSingleTimer(uint8 id, bool p) {
timer->enabled &= (~2);
timer->lastUpdate += elapsedTime;
timer->nextRun += elapsedTime;
resync();
resetNextRun();
timer->pauseStartTime = 0;
}
}

View File

@ -40,12 +40,12 @@ void LoLEngine::setupTimers() {
_timer->addTimer(0x10, TimerV2(timerProcessMonsters), 6, true);
_timer->addTimer(0x11, TimerV2(timerProcessMonsters), 6, true);
_timer->setNextRun(0x11, _system->getMillis() + 3 * _tickLength);
_timer->addTimer(3, TimerV2(timerSub3), 15, true);
_timer->addTimer(3, TimerV2(timerSpecialCharacterUpdate), 15, true);
_timer->addTimer(4, TimerV2(timerProcessFlyingObjects), 1, true);
_timer->addTimer(0x50, TimerV2(timerRunSceneAnimScript), 0, false);
_timer->addTimer(0x51, TimerV2(timerRunSceneAnimScript), 0, false);
_timer->addTimer(0x52, TimerV2(timerRunSceneAnimScript), 0, false);
_timer->addTimer(8, TimerV2(timerSub6), 1200, true);
_timer->addTimer(8, TimerV2(timerRegeneratePoints), 1200, true);
_timer->addTimer(9, TimerV2(timerUpdatePortraitAnimations), 10, true);
_timer->addTimer(10, TimerV2(timerUpdateLampState), 360, true);
_timer->addTimer(11, TimerV2(timerFadeMessageText), 360, false);
@ -104,22 +104,101 @@ void LoLEngine::timerProcessDoors(int timerNum) {
}
void LoLEngine::timerProcessMonsters(int timerNum) {
// if (!_updateMonsters)
// return;
for (int i = timerNum & 0x0f; i < 30; i += 2)
updateMonster(&_monsters[i]);
}
void LoLEngine::timerSub3(int timerNum) {
void LoLEngine::timerSpecialCharacterUpdate(int timerNum) {
int v = 0;
for (int i = 0; i < 4; i++) {
if (!(_characters[i].flags & 1))
continue;
for (int ii = 0; ii < 5; ii++) {
if (!(_characters[i].characterUpdateEvents[ii]))
continue;
if (--_characters[i].characterUpdateDelay[ii] > 0) {
if (_characters[i].characterUpdateDelay[ii] > v)
v = _characters[i].characterUpdateDelay[ii];
continue;
}
switch (_characters[i].characterUpdateEvents[ii] - 1) {
case 0:
if (_characters[i].weaponHit) {
_characters[i].weaponHit = 0;
_characters[i].characterUpdateDelay[ii] = calcMonsterSkillLevel(i, 6);
if (_characters[i].characterUpdateDelay[ii] > v)
v = _characters[i].characterUpdateDelay[ii];
} else {
_characters[i].flags &= 0xfffb;
}
gui_drawCharPortraitWithStats(i);
break;
case 1:
_characters[i].damageSuffered = 0;
gui_drawCharPortraitWithStats(i);
break;
case 2:
_characters[i].flags &= 0xffbf;
gui_drawCharPortraitWithStats(i);
break;
case 3:
v = _rnd.getRandomNumberRng(1, 2);
if (inflictDamage(i, v, 0x8000, 0, 0x80)) {
_txt->printMessage(2, getLangString(0x4022), _characters[i].name);
_characters[i].characterUpdateDelay[ii] = 10;
if (_characters[i].characterUpdateDelay[ii] > v)
v = _characters[i].characterUpdateDelay[ii];
}
break;
case 4:
_characters[i].flags &= 0xfeff;
_txt->printMessage(0, getLangString(0x4027), _characters[i].name);
gui_drawCharPortraitWithStats(i);
break;
case 5:
setTemporaryFaceFrame(i, 0, 0, 1);
break;
case 6:
_characters[i].flags &= 0xefff;
gui_drawCharPortraitWithStats(i);
break;
case 7:
level11specialUnk();
break;
default:
break;
}
if (_characters[i].characterUpdateDelay[ii] <= 0)
_characters[i].characterUpdateEvents[ii] = 0;
}
}
if (v) {
_timer->enable(3);
_timer3Para = v * 15;
} else {
_timer->disable(3);
}
}
void LoLEngine::timerProcessFlyingObjects(int timerNum) {
for (int i = 0; i < 8; i++) {
if (!_flyingObjects[i].enable)
continue;
updateFlyingObjects(&_flyingObjects[i]);
updateFlyingObject(&_flyingObjects[i]);
}
}
@ -127,8 +206,24 @@ void LoLEngine::timerRunSceneAnimScript(int timerNum) {
runLevelScript(0x401 + (timerNum & 0x0f), -1);
}
void LoLEngine::timerSub6(int timerNum) {
void LoLEngine::timerRegeneratePoints(int timerNum) {
for (int i = 0; i < 4; i++) {
if (!(_characters[i].flags & 1))
continue;
// check for Duble ring
int hInc = (_characters[i].flags & 8) ? 0 : (itemEquipped(i, 228) ? 4 : 1);
// check for Talba ring
int mInc = _drainMagic ? ((_characters[i].magicPointsMax >> 5) * -1) :
((_characters[i].flags & 8) ? 0 : (itemEquipped(i, 227) ? (_characters[i].magicPointsMax / 10) : 1));
_characters[i].magicPointsCur = CLIP<int16>(_characters[i].magicPointsCur + mInc, 0, _characters[i].magicPointsMax);
if (!(_characters[i].flags & 0x80))
increaseCharacterHitpoints(i, hInc, false);
gui_drawCharPortraitWithStats(i);
}
}
void LoLEngine::timerUpdatePortraitAnimations(int skipUpdate) {

View File

@ -372,11 +372,20 @@ int WSAMovie_v2::open(const char *filename, int unk1, uint8 *palBuf) {
offsPal = 0x300;
_flags |= WF_HAS_PALETTE;
if (palBuf)
memcpy(palBuf, wsaData + 8 + ((_numFrames << 2) & 0xFFFF), 0x300);
_vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x300);
}
if (flags & 2)
if (flags & 2) {
if (_vm->gameFlags().use16ColorMode) {
offsPal = 0x30;
_flags |= WF_HAS_PALETTE;
if (palBuf)
_vm->screen()->loadPalette(wsaData + 8 + ((_numFrames << 2) & 0xFFFF), palBuf, 0x30);
}
_flags |= WF_XOR;
}
if (!(unk1 & 2)) {
_flags |= WF_OFFSCREEN_DECODE;

View File

@ -31,7 +31,7 @@
#include "md5.h"
enum {
kKyraDatVersion = 44,
kKyraDatVersion = 45,
kIndexSize = 12
};
@ -341,6 +341,8 @@ const ExtractFilename extractFilenames[] = {
{ lolMapStringId, lolTypeRaw16, "MAPSTRID.LST" },
//{ lolMapPal, kTypeRawData, "MAP.PAL" },
{ lolHealShapeFrames, kTypeRawData, "MHEAL.SHP" },
{ -1, 0, 0 }
};

View File

@ -251,6 +251,8 @@ enum kExtractID {
lolMapStringId,
//lolMapPal,
lolHealShapeFrames,
kMaxResIDs
};

View File

@ -74,6 +74,8 @@ const ExtractEntry lolCDFile2[] = {
{ lolMapStringId, 0x000287D0, 0x0002880C },
//{ lolMapPal, 0x0001D9C0, 0x0001DBC0 },
{ lolHealShapeFrames, 0x000297D0, 0x00029820 },
{ -1, 0, 0 }
};

View File

@ -557,6 +557,8 @@ const int lolCDFile2Need[] = {
lolMapStringId,
//lolMapPal,
lolHealShapeFrames,
-1
};