diff options
Diffstat (limited to 'engines/xeen/scripts.cpp')
-rw-r--r-- | engines/xeen/scripts.cpp | 548 |
1 files changed, 295 insertions, 253 deletions
diff --git a/engines/xeen/scripts.cpp b/engines/xeen/scripts.cpp index 8777cdc6e0..bc0b179d4c 100644 --- a/engines/xeen/scripts.cpp +++ b/engines/xeen/scripts.cpp @@ -21,7 +21,10 @@ */ #include "common/config-manager.h" +#include "common/textconsole.h" +#include "backends/audiocd/audiocd.h" #include "xeen/scripts.h" +#include "xeen/dialogs/dialogs_copy_protection.h" #include "xeen/dialogs/dialogs_input.h" #include "xeen/dialogs/dialogs_whowill.h" #include "xeen/dialogs/dialogs_query.h" @@ -138,7 +141,7 @@ int Scripts::checkEvents() { Party &party = *_vm->_party; Sound &sound = *_vm->_sound; Windows &windows = *_vm->_windows; - bool isDarkCc = files._isDarkCc; + int ccNum = files._ccNum; _refreshIcons = false; _itemType = 0; @@ -182,10 +185,10 @@ int Scripts::checkEvents() { for (eventIndex = 0; eventIndex < map._events.size() && !_vm->shouldExit(); ++eventIndex) { MazeEvent &event = map._events[eventIndex]; - if (event._position == _currentPos && party._mazeDirection != - (_currentPos.x | _currentPos.y) && event._line == _lineNum) { + if (event._position == _currentPos && event._line == _lineNum && + (party._mazeDirection | _currentPos.x | _currentPos.y)) { if (event._direction == party._mazeDirection || event._direction == DIR_ALL) { - _vm->_mode = MODE_RECORD_EVENTS; + _vm->_mode = MODE_SCRIPT_IN_PROGRESS; _scriptExecuted = true; doOpcode(event); break; @@ -209,24 +212,27 @@ int Scripts::checkEvents() { if (party._treasure._hasItems || party._treasure._gold || party._treasure._gems) party.giveTreasure(); - if (_animCounter > 0 && intf._objNumber) { - MazeObject &selectedObj = map._mobData._objects[intf._objNumber - 1]; + if (_animCounter > 0 && intf._objNumber != -1) { + MazeObject &selectedObj = map._mobData._objects[intf._objNumber]; - if (selectedObj._spriteId == (isDarkCc ? 15 : 16)) { - for (uint idx = 0; idx < 16; ++idx) { - MazeObject &obj = map._mobData._objects[idx]; - if (obj._spriteId == (isDarkCc ? 62 : 57)) { + if (selectedObj._spriteId == (ccNum ? 15 : 16)) { + // Treasure chests that were opened will be set to be in an open, empty state + for (uint idx = 0; idx < map._mobData._objectSprites.size(); ++idx) { + MonsterObjectData::SpriteResourceEntry &e = map._mobData._objectSprites[idx]; + if (e._spriteId == (ccNum ? 57 : 62)) { selectedObj._id = idx; - selectedObj._spriteId = isDarkCc ? 62 : 57; + selectedObj._spriteId = ccNum ? 57 : 62; + selectedObj._sprites = &e._sprites; break; } } } else if (selectedObj._spriteId == 73) { - for (uint idx = 0; idx < 16; ++idx) { - MazeObject &obj = map._mobData._objects[idx]; - if (obj._spriteId == 119) { + for (uint idx = 0; idx < map._mobData._objectSprites.size(); ++idx) { + MonsterObjectData::SpriteResourceEntry &e = map._mobData._objectSprites[idx]; + if (e._spriteId == 119) { selectedObj._id = idx; selectedObj._spriteId = 119; + selectedObj._sprites = &e._sprites; break; } } @@ -237,8 +243,17 @@ int Scripts::checkEvents() { _vm->_mode = oldMode; windows.closeAll(); - if (_scriptExecuted || !intf._objNumber || _dirFlag) { - if (_dirFlag && !_scriptExecuted && intf._objNumber && !map._currentIsEvent) { + if (g_vm->getIsCD() && g_system->getAudioCDManager()->isPlaying()) + // Stop any playing voice + g_system->getAudioCDManager()->stop(); + + if (g_vm->shouldExit()) + return g_vm->_gameMode; + + if (_scriptExecuted) + intf.clearEvents(); + if (_scriptExecuted || intf._objNumber == -1 || _dirFlag) { + if (_dirFlag && !_scriptExecuted && intf._objNumber != -1 && !map._currentIsEvent) { sound.playFX(21); } } else { @@ -269,69 +284,71 @@ int Scripts::checkEvents() { return _scriptResult; } -void Scripts::openGrate(int wallVal, int action) { +bool Scripts::openGrate(int wallVal, int action) { Combat &combat = *_vm->_combat; FileManager &files = *_vm->_files; Interface &intf = *_vm->_interface; Map &map = *_vm->_map; Party &party = *_vm->_party; Sound &sound = *_vm->_sound; - bool isDarkCc = files._isDarkCc; - - if ((wallVal != 13 || map._currentGrateUnlocked) && (!isDarkCc || wallVal != 9 || - map.mazeData()._wallKind != 2)) { - if (wallVal != 9 && !map._currentGrateUnlocked) { - int charIndex = WhoWill::show(_vm, 13, action, false) - 1; - if (charIndex < 0) { - intf.draw3d(true); - return; - } + int ccNum = files._ccNum; - // There is a 1 in 4 chance the character will receive damage - if (_vm->getRandomNumber(1, 4) == 1) { - combat.giveCharDamage(map.mazeData()._trapDamage, - (DamageType)_vm->getRandomNumber(0, 6), charIndex); - } + if (!((wallVal != 13 || map._currentGrateUnlocked) && (!ccNum || wallVal != 9 || + map.mazeData()._wallKind != 2))) + return false; - // Check whether character can unlock the door - Character &c = party._activeParty[charIndex]; - if ((c.getThievery() + _vm->getRandomNumber(1, 20)) < - map.mazeData()._difficulties._unlockDoor) - return; + if (wallVal != 9 && !map._currentGrateUnlocked) { + int charIndex = WhoWill::show(_vm, 13, action, false) - 1; + if (charIndex < 0) { + intf.draw3d(true); + return true; + } - c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel(); + // There is a 1 in 4 chance the character will receive damage + if (_vm->getRandomNumber(1, 4) == 1) { + combat.giveCharDamage(map.mazeData()._trapDamage, + (DamageType)_vm->getRandomNumber(0, 6), charIndex); } - // Flag the grate as unlocked, and the wall the grate is on - map.setCellSurfaceFlags(party._mazePosition, 0x80); - map.setWall(party._mazePosition, party._mazeDirection, wallVal); + // Check whether character can unlock the door + Character &c = party._activeParty[charIndex]; + if ((c.getThievery() + _vm->getRandomNumber(1, 20)) < + map.mazeData()._difficulties._unlockDoor) + return true; - // Set the grate as opened and the wall on the other side of the grate - Common::Point pt = party._mazePosition; - Direction dir = (Direction)((int)party._mazeDirection ^ 2); - switch (party._mazeDirection) { - case DIR_NORTH: - pt.y++; - break; - case DIR_EAST: - pt.x++; - break; - case DIR_SOUTH: - pt.y--; - break; - case DIR_WEST: - pt.x--; - break; - default: - break; - } + c._experience += map.mazeData()._difficulties._unlockDoor * c.getCurrentLevel(); + } - map.setCellSurfaceFlags(pt, 0x80); - map.setWall(pt, dir, wallVal); + // Flag the grate as unlocked, and the wall the grate is on + map.setCellSurfaceFlags(party._mazePosition, 0x80); + map.setWall(party._mazePosition, party._mazeDirection, wallVal); - sound.playFX(10); - intf.draw3d(true); + // Set the grate as opened and the wall on the other side of the grate + Common::Point pt = party._mazePosition; + Direction dir = (Direction)((int)party._mazeDirection ^ 2); + switch (party._mazeDirection) { + case DIR_NORTH: + pt.y++; + break; + case DIR_EAST: + pt.x++; + break; + case DIR_SOUTH: + pt.y--; + break; + case DIR_WEST: + pt.x--; + break; + default: + break; } + + map.setCellSurfaceFlags(pt, 0x80); + map.setWall(pt, dir, wallVal); + + sound.playFX(10); + intf.draw3d(true); + return true; } bool Scripts::doOpcode(MazeEvent &event) { @@ -373,7 +390,7 @@ bool Scripts::doOpcode(MazeEvent &event) { bool result = (this->*COMMAND_LIST[event._opcode])(params); if (result) // Move to next line - _lineNum = _vm->_party->_partyDead ? -1 : _lineNum + 1; + _lineNum = _vm->_party->_dead ? SCRIPT_ABORT : _lineNum + 1; return result; } @@ -465,7 +482,7 @@ bool Scripts::cmdTeleport(ParamsIterator ¶ms) { Sound &sound = *_vm->_sound; windows.closeAll(); - + bool restartFlag = _event->_opcode == OP_TeleportAndContinue; int mapId = params.readByte(); Common::Point pt; @@ -491,8 +508,7 @@ bool Scripts::cmdTeleport(ParamsIterator ¶ms) { party._stepped = true; if (mapId != party._mazeId) { - int spriteId = (intf._objNumber == 0) ? -1 : - map._mobData._objects[intf._objNumber - 1]._spriteId; + int spriteId = (intf._objNumber == -1) ? -1 : map._mobData._objects[intf._objNumber]._spriteId; switch (spriteId) { case 47: @@ -519,7 +535,7 @@ bool Scripts::cmdTeleport(ParamsIterator ¶ms) { if (restartFlag) { // Draw the new location and start any script at that location - intf.draw3d(true); + events.ipause(2); _lineNum = SCRIPT_RESET; return false; } else { @@ -592,7 +608,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator ¶ms) { Combat &combat = *_vm->_combat; Party &party = *_vm->_party; Windows &windows = *_vm->_windows; - int mode1, mode2, mode3, param2; + int mode1, mode2, mode3; uint32 val1, val2, val3; _refreshIcons = true; @@ -614,7 +630,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator ¶ms) { break; } - param2 = mode2 = params.readByte(); + mode2 = params.readByte(); switch (mode2) { case 16: case 34: @@ -707,7 +723,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator ¶ms) { if (_charIndex == 0 || _charIndex == 8) { for (uint idx = 0; idx < party._activeParty.size(); ++idx) { if (_charIndex == 0 || (_charIndex == 8 && (int)idx != combat._combatTarget)) { - party.giveTake(mode1, val1, mode2, val2, idx); + bool flag = party.giveTake(mode1, val1, mode2, val2, idx); switch (mode1) { case 8: @@ -715,7 +731,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator ¶ms) { // fall through case 21: case 66: - if (param2) { + if (flag) { switch (mode2) { case 82: mode1 = 0; @@ -728,13 +744,18 @@ bool Scripts::cmdTakeOrGive(ParamsIterator ¶ms) { case 100: case 101: case 106: - if (param2) + if (flag) continue; // Break out of character loop idx = party._activeParty.size(); break; + default: + break; } + } else { + // Break out of character loop + idx = party._activeParty.size(); } break; @@ -744,7 +765,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator ¶ms) { case 100: case 101: case 106: - if (param2) { + if (flag) { _lineNum = -1; return false; } @@ -766,7 +787,7 @@ bool Scripts::cmdTakeOrGive(ParamsIterator ¶ms) { case 100: case 101: case 106: - if (param2) + if (flag) continue; // Break out of character loop @@ -793,9 +814,9 @@ bool Scripts::cmdRemove(ParamsIterator ¶ms) { Interface &intf = *_vm->_interface; Map &map = *_vm->_map; - if (intf._objNumber) { + if (intf._objNumber != -1) { // Give the active object a completely way out of bounds position - MazeObject &obj = map._mobData._objects[intf._objNumber - 1]; + MazeObject &obj = map._mobData._objects[intf._objNumber]; obj._position = Common::Point(128, 128); } @@ -845,7 +866,7 @@ bool Scripts::cmdSpawn(ParamsIterator ¶ms) { } bool Scripts::cmdDoTownEvent(ParamsIterator ¶ms) { - _scriptResult = _vm->_locations->doAction((LocationAction)params.readByte()); + _scriptResult = _vm->_locations->doAction(params.readByte()); _vm->_party->_stepped = true; _refreshIcons = true; @@ -930,40 +951,46 @@ bool Scripts::cmdConfirmWord(ParamsIterator ¶ms) { int param2 = params.readByte(); int param3 = params.readByte(); - Common::String msg1 = param2 ? map._events._text[param2] : _message; - Common::String msg2; + Common::String expected2; + Common::String title; if (_event->_opcode == OP_ConfirmWord_2) { - msg2 = ""; + title = ""; } else if (param3) { - msg2 = map._events._text[param3]; + title = map._events._text[param3]; } else { - msg2 = Res.WHATS_THE_PASSWORD; + title = Res.WHATS_THE_PASSWORD; } - _mirrorId = StringInput::show(_vm, inputType, msg1, msg2, _event->_opcode); + if (!param2) { + expected2 = _message; + } else if (param2 < (int)map._events._text.size()) { + expected2 = map._events._text[param2]; + } + + _mirrorId = StringInput::show(_vm, inputType, expected2, title, _event->_opcode); if (_mirrorId) { - if (_mirrorId == 33 && files._isDarkCc) { + if (_mirrorId == 33 && files._ccNum) { doDarkSideEnding(); - } else if (_mirrorId == 34 && files._isDarkCc) { + } else if (_mirrorId == 34 && files._ccNum) { doWorldEnding(); - } else if (_mirrorId == 35 && files._isDarkCc && + } else if (_mirrorId == 35 && files._ccNum && _vm->getGameID() == GType_WorldOfXeen) { doCloudsEnding(); - } else if (_mirrorId == 40 && !files._isDarkCc) { + } else if (_mirrorId == 40 && !files._ccNum) { doCloudsEnding(); - } else if (_mirrorId == 60 && !files._isDarkCc) { + } else if (_mirrorId == 60 && !files._ccNum) { doDarkSideEnding(); - } else if (_mirrorId == 61 && !files._isDarkCc) { + } else if (_mirrorId == 61 && !files._ccNum) { doWorldEnding(); } else { - if (_mirrorId == 59 && !files._isDarkCc) { + if (_mirrorId == 59 && !files._ccNum) { for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { XeenItem &item = party._treasure._weapons[idx]; if (!item._id) { - item._id = 34; + item._id = XEEN_SLAYER_SWORD; item._material = 0; - item._bonusFlags = 0; + item._state.clear(); party._treasure._hasItems = true; return cmdExit(params); @@ -990,7 +1017,7 @@ bool Scripts::cmdDamage(ParamsIterator ¶ms) { int damage = params.readUint16LE(); DamageType damageType = (DamageType)params.readByte(); - combat.giveCharDamage(damage, damageType, _charIndex); + combat.giveCharDamage(damage, damageType, _charIndex - 1); return true; } @@ -1033,11 +1060,16 @@ bool Scripts::cmdCallEvent(ParamsIterator ¶ms) { } bool Scripts::cmdReturn(ParamsIterator ¶ms) { - StackEntry &se = _stack.top(); - _currentPos = se; - _lineNum = se.line; + if (_stack.empty()) { + // WORKAROUND: Some scripts in Swords of Xeen use cmdReturn as a substitute for cmdExit + return cmdExit(params); + } else { + StackEntry se = _stack.pop(); + _currentPos = se; + _lineNum = se.line; - return true; + return true; + } } bool Scripts::cmdSetVar(ParamsIterator ¶ms) { @@ -1114,17 +1146,17 @@ bool Scripts::cmdRndDamage(ParamsIterator ¶ms) { DamageType dmgType = (DamageType)params.readByte(); int max = params.readByte(); - combat.giveCharDamage(_vm->getRandomNumber(1, max), dmgType, _charIndex); + combat.giveCharDamage(_vm->getRandomNumber(1, max), dmgType, _charIndex - 1); return true; } bool Scripts::cmdMoveWallObj(ParamsIterator ¶ms) { Map &map = *_vm->_map; - int itemNum = params.readByte(); + int index = params.readByte(); int x = params.readShort(); int y = params.readShort(); - map._mobData._wallItems[itemNum]._position = Common::Point(x, y); + map._mobData._wallItems[index]._position = Common::Point(x, y); return true; } @@ -1203,14 +1235,25 @@ bool Scripts::cmdDisplayBottom(ParamsIterator ¶ms) { bool Scripts::cmdIfMapFlag(ParamsIterator ¶ms) { Map &map = *_vm->_map; - MazeMonster &monster = map._mobData._monsters[params.readByte()]; + int monsterNum = params.readByte(); + int lineNum = params.readByte(); - if (monster._position.x >= 32 || monster._position.y >= 32) { - _lineNum = params.readByte(); - return false; + if (monsterNum == 0xff) { + for (monsterNum = 0; monsterNum < (int)map._mobData._monsters.size(); ++monsterNum) { + MazeMonster &monster = map._mobData._monsters[monsterNum]; + + if ((uint)monster._position.x < 32 && (uint)monster._position.y < 32) + return true; + } + } else { + MazeMonster &monster = map._mobData._monsters[monsterNum]; + + if ((uint)monster._position.x < 32 && (uint)monster._position.y < 32) + return true; } - return true; + _lineNum = lineNum; + return false; } bool Scripts::cmdSelectRandomChar(ParamsIterator ¶ms) { @@ -1220,64 +1263,47 @@ bool Scripts::cmdSelectRandomChar(ParamsIterator ¶ms) { bool Scripts::cmdGiveEnchanted(ParamsIterator ¶ms) { Party &party = *_vm->_party; - + int itemOffset = _vm->getGameID() == GType_Swords ? 6 : 0; + XeenItem *item; + int invIndex; int id = params.readByte(); - int material = params.readByte(); - int flags = params.readByte(); - - if (id >= 35) { - if (id < 49) { - for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { - XeenItem &item = party._treasure._armor[idx]; - if (!item.empty()) { - item._id = id - 35; - item._material = material; - item._bonusFlags = flags; - party._treasure._hasItems = true; - break; - } - } - return true; - } else if (id < 60) { - for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { - XeenItem &item = party._treasure._accessories[idx]; - if (!item.empty()) { - item._id = id - 49; - item._material = material; - item._bonusFlags = flags; - party._treasure._hasItems = true; - break; - } - } + // Get category of item to add + ItemCategory cat = CATEGORY_WEAPON; + if (id < (35 + itemOffset)) { + } else if (id < (49 + itemOffset)) { + cat = CATEGORY_ARMOR; + id -= 35 + itemOffset; + } else if (id < (60 + itemOffset)) { + cat = CATEGORY_ACCESSORY; + id -= 49 + itemOffset; + } else if (id < (82 + itemOffset)) { + cat = CATEGORY_MISC; + id -= 60 + itemOffset; + } else { + party._questItems[id - (82 + itemOffset)]++; + } - return true; - } else if (id < 82) { - for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { - XeenItem &item = party._treasure._misc[idx]; - if (!item.empty()) { - item._id = id; - item._material = material; - item._bonusFlags = flags; - party._treasure._hasItems = true; - break; - } - } + // Check for an empty slot + for (invIndex = 0, item = party._treasure[cat]; invIndex < MAX_TREASURE_ITEMS && !item->empty(); ++invIndex, ++item) + ; - return true; - } else { - party._questItems[id - 82]++; - } - } + if (invIndex == MAX_TREASURE_ITEMS) { + // Treasure category entirely full. Should never happen + warning("Treasure category was completely filled up"); + } else { + party._treasure._hasItems = true; - for (int idx = 0; idx < MAX_TREASURE_ITEMS; ++idx) { - XeenItem &item = party._treasure._weapons[idx]; - if (!item.empty()) { - item._id = id; - item._material = material; - item._bonusFlags = flags; - party._treasure._hasItems = true; - break; + if (cat == CATEGORY_MISC) { + // Handling of misc items. Note that for them, id actually specifies the material field + item->_material = id; + item->_id = params.readByte(); + item->_state._counter = (item->_material == 10 || item->_material == 11) ? 1 : _vm->getRandomNumber(3, 10); + } else { + // Weapons, armor, and accessories + item->_id = id; + item->_material = params.readByte(); + item->_state = params.readByte(); } } @@ -1391,6 +1417,8 @@ bool Scripts::cmdFallToMap(ParamsIterator ¶ms) { } bool Scripts::cmdDisplayMain(ParamsIterator ¶ms) { + _windowIndex = 11; + display(false, 0); return true; } @@ -1415,7 +1443,7 @@ bool Scripts::cmdCutsceneEndDarkside(ParamsIterator ¶ms) { Party &party = *_vm->_party; _vm->_saves->_wonDarkSide = true; party._questItems[53] = 1; - party._darkSideEnd = true; + party._darkSideCompleted = true; party._mazeId = 29; party._mazeDirection = DIR_NORTH; party._mazePosition = Common::Point(25, 21); @@ -1436,24 +1464,55 @@ bool Scripts::cmdCutsceneEndWorld(ParamsIterator ¶ms) { g_vm->saveSettings(); _vm->_saves->_wonWorld = true; - _vm->_party->_worldEnd = true; + _vm->_party->_worldCompleted = true; doWorldEnding(); return false; } bool Scripts::cmdFlipWorld(ParamsIterator ¶ms) { - _vm->_map->_loadDarkSide = params.readByte() != 0; + _vm->_map->_loadCcNum = params.readByte(); + return true; +} + +bool Scripts::cmdPlayCD(ParamsIterator ¶ms) { + int trackNum = params.readByte(); + int start = params.readUint16LE(); + int finish = params.readUint16LE(); + debugC(3, kDebugScripts, "cmdPlayCD Track=%d start=%d finish=%d", trackNum, start, finish); + + if (_vm->_files->_ccNum && trackNum < 31) + trackNum += 30; + assert(trackNum <= 60); + + start = convertCDTime(start); + finish = convertCDTime(finish); + + g_system->getAudioCDManager()->play(trackNum, 1, start, finish - start, false, Audio::Mixer::kSpeechSoundType); return true; } -bool Scripts::cmdPlayCD(ParamsIterator ¶ms) { error("TODO"); } +#define CD_FRAME_RATE 75 +uint Scripts::convertCDTime(uint srcTime) { + // Times are encoded as MMSSCC - MM=Minutes, SS=Seconds, CC=Centiseconds (1/100th second) + uint mins = srcTime / 10000; + uint csec = srcTime % 10000; + return (mins * 6000 + csec) * CD_FRAME_RATE / 100; +} void Scripts::doCloudsEnding() { + g_vm->_party->_cloudsCompleted = true; doEnding("ENDGAME"); + + g_vm->_mode = MODE_INTERACTIVE; + g_vm->_saves->saveGame(); + + g_vm->_gameMode = GMODE_MENU; + g_vm->_mode = MODE_STARTUP; } void Scripts::doDarkSideEnding() { + g_vm->_party->_darkSideCompleted = true; doEnding("ENDGAME2"); } @@ -1487,56 +1546,56 @@ void Scripts::doEnding(const Common::String &endStr) { bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { FileManager &files = *_vm->_files; Party &party = *_vm->_party; - Character &ps = party._activeParty[charIndex]; + Character *ps = (charIndex == -1) ? nullptr : &party._activeParty[charIndex]; uint v = 0; switch (action) { case 3: // Player sex - v = (uint)ps._sex; + v = (uint)ps->_sex; break; case 4: // Player race - v = (uint)ps._race; + v = (uint)ps->_race; break; case 5: // Player class - v = (uint)ps._class; + v = (uint)ps->_class; break; case 8: // Current health points - v = (uint)ps._currentHp; + v = (uint)ps->_currentHp; break; case 9: // Current spell points - v = (uint)ps._currentSp; + v = (uint)ps->_currentSp; break; case 10: // Get armor class - v = (uint)ps.getArmorClass(false); + v = (uint)ps->getArmorClass(false); break; case 11: // Level bonus (extra beyond base) - v = ps._level._temporary; + v = ps->_level._temporary; break; case 12: // Current age, including unnatural aging - v = ps.getAge(false); + v = ps->getAge(false); break; case 13: assert(val < 18); - if (ps._skills[val]) + if (ps->_skills[val]) v = val; break; case 15: // Award assert(val < AWARDS_TOTAL); - if (ps.hasAward(val)) + if (ps->hasAward(val)) v = val; break; case 16: // Experience - v = ps._experience; + v = ps->_experience; break; case 17: // Party poison resistence @@ -1544,38 +1603,19 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { break; case 18: // Condition - assert(val < 16); - if (!ps._conditions[val] && !(val & 0x10)) - v = val; + assert(val <= NO_CONDITION); + v = (ps->_conditions[val] || val == NO_CONDITION) ? val : 0xffffffff; break; case 19: { // Can player cast a given spell - - // Get the type of character - int category; - switch (ps._class) { - case CLASS_KNIGHT: - case CLASS_ARCHER: - category = 0; - break; - case CLASS_PALADIN: - case CLASS_CLERIC: - category = 1; - break; - case CLASS_BARBARIAN: - case CLASS_DRUID: - category = 2; - break; - default: - category = 0; - break; - } + SpellsCategory category = ps->getSpellsCategory(); + assert(category != SPELLCAT_INVALID); // Check if the character class can cast the particular spell - for (int idx = 0; idx < 39; ++idx) { + for (int idx = 0; idx < SPELLS_PER_CLASS; ++idx) { if (Res.SPELLS_ALLOWED[category][idx] == (int)val) { // Can cast it. Check if the player has it in their spellbook - if (ps._spells[idx]) + if (ps->_spells[idx]) v = val; break; } @@ -1583,42 +1623,44 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { break; } case 20: - if (files._isDarkCc) + assert(val < 256); + if (files._ccNum && _vm->getGameID() != GType_Swords) val += 256; - assert(val < 512); v = party._gameFlags[val / 256][val % 256] ? val : 0xffffffff; break; - case 21: + case 21: { // Scans inventories for given item number + uint itemOffset = _vm->getGameID() == GType_Swords ? 6 : 0; v = 0xFFFFFFFF; - if (val < 82) { - for (int idx = 0; idx < 9; ++idx) { - if (val == 35) { - if (ps._weapons[idx]._id == val) { + if (val < (82 + itemOffset)) { + for (int idx = 0; idx < INV_ITEMS_TOTAL; ++idx) { + if (val < (35 + itemOffset)) { + if (ps->_weapons[idx]._id == val) { v = val; break; } - } else if (val < 49) { - if (ps._armor[idx]._id == (val - 35)) { + } else if (val < (49 + itemOffset)) { + if (ps->_armor[idx]._id == (val - 35)) { v = val; break; } - } else if (val < 60) { - if (ps._accessories[idx]._id == (val - 49)) { + } else if (val < (60 + itemOffset)) { + if (ps->_accessories[idx]._id == (val - (49 + itemOffset))) { v = val; break; } } else { - if (ps._misc[idx]._id == (val - 60)) { + if (ps->_misc[idx]._id == (val - (60 + itemOffset))) { v = val; break; } } } - } else if (party._questItems[val - 82]) { + } else if (party._questItems[val - (82 + itemOffset)]) { v = val; } break; + } case 25: // Returns number of minutes elapsed in the day (0-1440) v = party._minutes; @@ -1632,32 +1674,32 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { v = party._gems; break; case 37: - // Might bonus (extra beond base) - v = ps._might._temporary; + // Might bonus (extra beyond base) + v = ps->_might._temporary; break; case 38: // Intellect bonus (extra beyond base) - v = ps._intellect._temporary; + v = ps->_intellect._temporary; break; case 39: // Personality bonus (extra beyond base) - v = ps._personality._temporary; + v = ps->_personality._temporary; break; case 40: // Endurance bonus (extra beyond base) - v = ps._endurance._temporary; + v = ps->_endurance._temporary; break; case 41: // Speed bonus (extra beyond base) - v = ps._speed._temporary; + v = ps->_speed._temporary; break; case 42: // Accuracy bonus (extra beyond base) - v = ps._accuracy._temporary; + v = ps->_accuracy._temporary; break; case 43: // Luck bonus (extra beyond base) - v = ps._luck._temporary; + v = ps->_luck._temporary; break; case 44: v = YesNo::show(_vm, val); @@ -1665,83 +1707,83 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { break; case 45: // Might base (before bonus) - v = ps._might._permanent; + v = ps->_might._permanent; break; case 46: // Intellect base (before bonus) - v = ps._intellect._permanent; + v = ps->_intellect._permanent; break; case 47: // Personality base (before bonus) - v = ps._personality._permanent; + v = ps->_personality._permanent; break; case 48: // Endurance base (before bonus) - v = ps._endurance._permanent; + v = ps->_endurance._permanent; break; case 49: // Speed base (before bonus) - v = ps._speed._permanent; + v = ps->_speed._permanent; break; case 50: // Accuracy base (before bonus) - v = ps._accuracy._permanent; + v = ps->_accuracy._permanent; break; case 51: // Luck base (before bonus) - v = ps._luck._permanent; + v = ps->_luck._permanent; break; case 52: // Fire resistence (before bonus) - v = ps._fireResistence._permanent; + v = ps->_fireResistence._permanent; break; case 53: // Elecricity resistence (before bonus) - v = ps._electricityResistence._permanent; + v = ps->_electricityResistence._permanent; break; case 54: // Cold resistence (before bonus) - v = ps._coldResistence._permanent; + v = ps->_coldResistence._permanent; break; case 55: // Poison resistence (before bonus) - v = ps._poisonResistence._permanent; + v = ps->_poisonResistence._permanent; break; case 56: // Energy reistence (before bonus) - v = ps._energyResistence._permanent; + v = ps->_energyResistence._permanent; break; case 57: // Energy resistence (before bonus) - v = ps._magicResistence._permanent; + v = ps->_magicResistence._permanent; break; case 58: // Fire resistence (extra beyond base) - v = ps._fireResistence._temporary; + v = ps->_fireResistence._temporary; break; case 59: // Electricity resistence (extra beyond base) - v = ps._electricityResistence._temporary; + v = ps->_electricityResistence._temporary; break; case 60: // Cold resistence (extra beyond base) - v = ps._coldResistence._temporary; + v = ps->_coldResistence._temporary; break; case 61: // Poison resistence (extra beyod base) - v = ps._poisonResistence._temporary; + v = ps->_poisonResistence._temporary; break; case 62: // Energy resistence (extra beyond base) - v = ps._energyResistence._temporary; + v = ps->_energyResistence._temporary; break; case 63: // Magic resistence (extra beyond base) - v = ps._magicResistence._temporary; + v = ps->_magicResistence._temporary; break; case 64: // Level (before bonus) - v = ps._level._permanent; + v = ps->_level._permanent; break; case 65: // Total party food @@ -1772,19 +1814,19 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { break; case 77: // Armor class (extra beyond base) - v = ps._ACTemp; + v = ps->_ACTemp; break; case 78: - // Test whether current Hp is equal to or exceeds the max HP - v = ps._currentHp >= ps.getMaxHP() ? 1 : 0; + // Test whether current Hp exceeds max HP or not + v = ps->_currentHp <= ps->getMaxHP() ? 1 : 0; break; case 79: // Test for Wizard Eye being active v = party._wizardEyeActive ? 1 : 0; break; case 81: - // Test whether current Sp is equal to or exceeds the max SP - v = ps._currentSp >= ps.getMaxSP() ? 1 : 0; + // Test whether current Sp exceeds the max SP or not + v = ps->_currentSp <= ps->getMaxSP() ? 1 : 0; break; case 84: // Current facing direction @@ -1802,7 +1844,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { case 91: case 92: // Get a player stat - v = ps.getStat((Attribute)(action - 86), 0); + v = ps->getStat((Attribute)(action - 86), 0); break; case 93: // Current day of the week (10 days per week) @@ -1818,7 +1860,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { break; case 102: // Thievery skill - v = ps.getThievery(); + v = ps->getThievery(); break; case 103: // Get value of world flag @@ -1826,7 +1868,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { break; case 104: // Get value of quest flag - v = party._questFlags[files._isDarkCc][val] ? val : 0xffffffff; + v = party._questFlags[(_vm->getGameID() == GType_Swords ? 0 : files._ccNum * 30) + val] ? val : 0xffffffff; break; case 105: // Test number of Megacredits in party. Only used by King's Engineer in Castle Burlock @@ -1834,7 +1876,7 @@ bool Scripts::ifProc(int action, uint32 val, int mode, int charIndex) { break; case 107: // Get value of character flag - error("Unused"); + v = party._characterFlags[ps->_rosterId][val] ? val : 0xffffffff; break; default: break; @@ -1857,8 +1899,8 @@ bool Scripts::copyProtectionCheck() { if (!ConfMan.getBool("copy_protection")) return true; - // Currently not implemented - return true; + // Show the copy protection dialog + return CopyProtection::show(_vm); } void Scripts::display(bool justifyFlag, int var46) { |