diff options
-rw-r--r-- | devtools/create_kyradat/create_kyradat.cpp | 12 | ||||
-rw-r--r-- | devtools/create_kyradat/create_kyradat.h | 4 | ||||
-rw-r--r-- | devtools/create_kyradat/games.cpp | 4 | ||||
-rw-r--r-- | devtools/create_kyradat/tables.cpp | 8 | ||||
-rw-r--r-- | engines/kyra/eob1.cpp | 8 | ||||
-rw-r--r-- | engines/kyra/eobcommon.cpp | 18 | ||||
-rw-r--r-- | engines/kyra/eobcommon.h | 67 | ||||
-rw-r--r-- | engines/kyra/items_eob.cpp | 6 | ||||
-rw-r--r-- | engines/kyra/magic_eob.cpp | 243 | ||||
-rw-r--r-- | engines/kyra/resource.h | 4 | ||||
-rw-r--r-- | engines/kyra/sprites_eob.cpp | 6 | ||||
-rw-r--r-- | engines/kyra/staticres_eob.cpp | 13 |
12 files changed, 277 insertions, 116 deletions
diff --git a/devtools/create_kyradat/create_kyradat.cpp b/devtools/create_kyradat/create_kyradat.cpp index d5fc803f8f..8bd5baeb2a 100644 --- a/devtools/create_kyradat/create_kyradat.cpp +++ b/devtools/create_kyradat/create_kyradat.cpp @@ -413,8 +413,8 @@ const ExtractFilename extractFilenames[] = { { kEob1MonsterProperties, kTypeRawData, false }, { kEob1EnemyMageSpellList, kTypeRawData, false }, { kEob1EnemyMageSfx, kTypeRawData, false }, - { kEob1MonsterDistAttType17, kTypeRawData, false }, - { kEob1MonsterDistAttSfx17, kTypeRawData, false }, + { kEob1BeholderSpellList, kTypeRawData, false }, + { kEob1BeholderSfx, kTypeRawData, false }, { kEob1TurnUndeadString, kTypeStringList, true }, { kEob1NpcShpData, kTypeRawData, false }, @@ -1656,10 +1656,10 @@ const char *getIdString(const int id) { return "kEob1EnemyMageSpellList"; case kEob1EnemyMageSfx: return "kEob1EnemyMageSfx"; - case kEob1MonsterDistAttType17: - return "kEob1MonsterDistAttType17"; - case kEob1MonsterDistAttSfx17: - return "kEob1MonsterDistAttSfx17"; + case kEob1BeholderSpellList: + return "kEob1BeholderSpellList"; + case kEob1BeholderSfx: + return "kEob1BeholderSfx"; case kEob1TurnUndeadString: return "kEob1TurnUndeadString"; case kEob1NpcShpData: diff --git a/devtools/create_kyradat/create_kyradat.h b/devtools/create_kyradat/create_kyradat.h index 75511b6a67..7cacbb5122 100644 --- a/devtools/create_kyradat/create_kyradat.h +++ b/devtools/create_kyradat/create_kyradat.h @@ -414,8 +414,8 @@ enum kExtractID { kEob1EnemyMageSpellList, kEob1EnemyMageSfx, - kEob1MonsterDistAttType17, - kEob1MonsterDistAttSfx17, + kEob1BeholderSpellList, + kEob1BeholderSfx, kEob1TurnUndeadString, kEob1NpcShpData, diff --git a/devtools/create_kyradat/games.cpp b/devtools/create_kyradat/games.cpp index bfbab79ee8..31f6dd6300 100644 --- a/devtools/create_kyradat/games.cpp +++ b/devtools/create_kyradat/games.cpp @@ -1061,8 +1061,8 @@ const int eob1FloppyNeed[] = { kEob1MonsterProperties, kEob1EnemyMageSpellList, kEob1EnemyMageSfx, - kEob1MonsterDistAttType17, - kEob1MonsterDistAttSfx17, + kEob1BeholderSpellList, + kEob1BeholderSfx, kEob1TurnUndeadString, kEob1NpcShpData, diff --git a/devtools/create_kyradat/tables.cpp b/devtools/create_kyradat/tables.cpp index a30d248d28..d846372b77 100644 --- a/devtools/create_kyradat/tables.cpp +++ b/devtools/create_kyradat/tables.cpp @@ -2398,12 +2398,12 @@ const ExtractEntrySearchData kEob1EnemyMageSfxProvider[] = { EXTRACT_END_ENTRY }; -const ExtractEntrySearchData kEob1MonsterDistAttType17Provider[] = { +const ExtractEntrySearchData kEob1BeholderSpellListProvider[] = { { UNK_LANG, kPlatformPC, { 0x00000004, 0x00000079, { { 0x8E, 0x13, 0x54, 0x9D, 0x54, 0xF6, 0xC9, 0x6E, 0x10, 0xF1, 0xC0, 0xE9, 0x66, 0xDD, 0x95, 0xED } } } }, EXTRACT_END_ENTRY }; -const ExtractEntrySearchData kEob1MonsterDistAttSfx17Provider[] = { +const ExtractEntrySearchData kEob1BeholderSfxProvider[] = { { UNK_LANG, kPlatformPC, { 0x00000004, 0x000000F5, { { 0xA9, 0x90, 0x41, 0x0D, 0xB5, 0xE0, 0x28, 0xFD, 0x0A, 0xC3, 0xF9, 0xEC, 0xC8, 0x47, 0xC1, 0x57 } } } }, EXTRACT_END_ENTRY }; @@ -3872,8 +3872,8 @@ const ExtractEntry extractProviders[] = { { kEob1EnemyMageSpellList, kEob1EnemyMageSpellListProvider }, { kEob1EnemyMageSfx, kEob1EnemyMageSfxProvider }, - { kEob1MonsterDistAttType17, kEob1MonsterDistAttType17Provider }, - { kEob1MonsterDistAttSfx17, kEob1MonsterDistAttSfx17Provider }, + { kEob1BeholderSpellList, kEob1BeholderSpellListProvider }, + { kEob1BeholderSfx, kEob1BeholderSfxProvider }, { kEob1TurnUndeadString, kEob1TurnUndeadStringProvider }, { kEob1NpcShpData, kEob1NpcShpDataProvider }, diff --git a/engines/kyra/eob1.cpp b/engines/kyra/eob1.cpp index f48e850274..6491dfa135 100644 --- a/engines/kyra/eob1.cpp +++ b/engines/kyra/eob1.cpp @@ -78,7 +78,7 @@ Common::Error EobEngine::init() { _scriptTimersCount = 1; - //_wllWallFlags[132] = 0x1f; + _wllWallFlags[132] = 1; _wllWallFlags[133] = 1; return Common::kNoError; @@ -222,7 +222,9 @@ void EobEngine::runNpcDialogue(int npcIndex) { if (!checkScriptFlag(0x100000)) { if (deletePartyItems(6, -1)) { - TXT(28); + //_npcSequenceSub = 0; + //drawNpcScene(npcIndex); + TXT(28); createItemOnCurrentBlock(32); setScriptFlag(0x100000); r = 1; @@ -423,7 +425,7 @@ void EobEngine::drawDoorIntern(int type, int index, int x, int y, int w, int wal case 7: case 8: case 9: - y = _dscDoorY7[mDim] - _doorShapes[shapeIndex + 3][1]; + y = _dscDoorY3[mDim] - _doorShapes[shapeIndex + 3][1]; d1 = x - (_doorShapes[shapeIndex + 3][2] << 2); x -= (shp[2] << 2); drawBlockObject(0, 2, _doorShapes[shapeIndex + 3], d1, y, 5); diff --git a/engines/kyra/eobcommon.cpp b/engines/kyra/eobcommon.cpp index 5fc50f667b..b9406ff05d 100644 --- a/engines/kyra/eobcommon.cpp +++ b/engines/kyra/eobcommon.cpp @@ -57,8 +57,8 @@ EobCoreEngine::EobCoreEngine(OSystem *system, const GameFlags &flags) : LolEobBa _monsterDustStrings = 0; _enemyMageSpellList = 0; _enemyMageSfx = 0; - _monsterDistAttType17 = 0; - _monsterDistAttSfx17 = 0; + _beholderSpellList = 0; + _beholderSfx = 0; _faceShapes = 0; _characters = 0; @@ -853,8 +853,8 @@ void EobCoreEngine::recalcArmorClass(int index) { if (c->effectFlags & 0x4000) { int8 m1 = 5; - if (getCharacterClericPaladinLevel(index) > 5) - m1 += ((getCharacterClericPaladinLevel(index) - 5) / 3); + if (getClericPaladinLevel(index) > 5) + m1 += ((getClericPaladinLevel(index) - 5) / 3); if (c->armorClass > m1) c->armorClass = m1; @@ -893,7 +893,7 @@ int EobCoreEngine::validateWeaponSlotItem(int index, int slot) { return r; } -int EobCoreEngine::getCharacterClericPaladinLevel(int index) { +int EobCoreEngine::getClericPaladinLevel(int index) { if (_castScrollSlot) return 9; @@ -913,7 +913,7 @@ int EobCoreEngine::getCharacterClericPaladinLevel(int index) { return 1; } -int EobCoreEngine::getCharacterMageLevel(int index) { +int EobCoreEngine::getMageLevel(int index) { if (_castScrollSlot) return 9; @@ -1682,7 +1682,7 @@ int EobCoreEngine::closeDistanceAttack(int charIndex, Item item) { uint16 flg = 0x100; - if ((_flags.gameID == GI_EOB1 && _items[item].type > 51 && _items[item].type < 57) || (_flags.gameID == GI_EOB2 && isMagicWeapon(item))) + if (isMagicEffectItem(item)) flg |= 1; _dstMonsterIndex = r; @@ -1966,6 +1966,10 @@ void EobCoreEngine::monsterCloseAttack(EobMonsterInPlay *m) { if (!monsterAttackHitTest(m, c)) continue; dmg += rollDice(_monsterProps[m->type].dmgDc[ii].times, _monsterProps[m->type].dmgDc[ii].pips, _monsterProps[m->type].dmgDc[ii].base); + if (_characters[c].effectsRemainder[1]) { + if (--_characters[c].effectsRemainder[1]) + dmg = 0; + } } if (dmg > 0) { diff --git a/engines/kyra/eobcommon.h b/engines/kyra/eobcommon.h index 1b701cfeb3..867582864f 100644 --- a/engines/kyra/eobcommon.h +++ b/engines/kyra/eobcommon.h @@ -367,8 +367,9 @@ protected: void recalcArmorClass(int index); int validateWeaponSlotItem(int index, int slot); - int getCharacterClericPaladinLevel(int index); - int getCharacterMageLevel(int index); + + int getClericPaladinLevel(int index); + int getMageLevel(int index); int getCharacterLevelIndex(int type, int cClass); int countCharactersWithSpecificItems(int16 itemType, int16 itemValue); @@ -429,7 +430,7 @@ protected: void printFullItemName(Item item); void identifyQueuedItems(Item itemQueue); void drawItemIconShape(int pageNum, Item itemId, int x, int y); - bool isMagicWeapon(Item itemIndex); + bool isMagicEffectItem(Item itemIndex); bool checkInventoryForRings(int charIndex, int itemValue); void eatItemInHand(int charIndex); @@ -549,8 +550,8 @@ protected: const uint8 *_enemyMageSpellList; const uint8 *_enemyMageSfx; - const uint8 *_monsterDistAttType17; - const uint8 *_monsterDistAttSfx17; + const uint8 *_beholderSpellList; + const uint8 *_beholderSfx; const char *const *_monsterSpecAttStrings; const int8 *_monsterFrmOffsTable1; @@ -912,57 +913,63 @@ protected: bool magicObjectStatusHit(EobMonsterInPlay *m, int type, bool tryEvade, int mod); bool turnUndeadHit(EobMonsterInPlay *m, int hitChance, int casterLevel); + int getMagicWeaponSlot(int charIndex); + int createMagicWeaponType(int invFlags, int handFlags, int armorClass, int allowedClasses, int dmgNum, int dmgPips, int dmgInc, int extraProps); + Item createMagicWeaponItem(int flags, int icon, int value, int type); + void removeMagicWeaponItem(Item item); + int findSingleSpellTarget(int dist); void printWarning(const char *str); void printNoEffectWarning(); void spellCallback_start_empty() {} - bool spellCallback_end_empty(EobFlyingObject *fo) { return true; } + bool spellCallback_end_empty(void*) { return true; } void spellCallback_start_armor(); void spellCallback_start_burningHands(); void spellCallback_start_detectMagic(); - bool spellCallback_end_detectMagic(EobFlyingObject *fo); + bool spellCallback_end_detectMagic(void*); void spellCallback_start_magicMissile(); - bool spellCallback_end_magicMissile(EobFlyingObject *fo); + bool spellCallback_end_magicMissile(void *obj); void spellCallback_start_shockingGrasp(); - bool spellCallback_end_shockingGraspFlameBlade(EobFlyingObject *fo); + bool spellCallback_end_shockingGraspFlameBlade(void *obj); void spellCallback_start_improvedIdentify(); void spellCallback_start_melfsAcidArrow(); - bool spellCallback_end_melfsAcidArrow(EobFlyingObject *fo); + bool spellCallback_end_melfsAcidArrow(void *obj); void spellCallback_start_dispelMagic(); void spellCallback_start_fireball(); - bool spellCallback_end_fireball(EobFlyingObject *fo); + bool spellCallback_end_fireball(void *obj); void spellCallback_start_flameArrow(); - bool spellCallback_end_flameArrow(EobFlyingObject *fo); + bool spellCallback_end_flameArrow(void *obj); void spellCallback_start_holdPerson(); - bool spellCallback_end_holdPerson(EobFlyingObject *fo); + bool spellCallback_end_holdPerson(void *obj); void spellCallback_start_lightningBolt(); - bool spellCallback_end_lightningBolt(EobFlyingObject *fo); + bool spellCallback_end_lightningBolt(void *obj); void spellCallback_start_vampiricTouch(); - bool spellCallback_end_vampiricTouch(EobFlyingObject *fo); + bool spellCallback_end_vampiricTouch(void *obj); void spellCallback_start_fear(); void spellCallback_start_iceStorm(); - bool spellCallback_end_iceStorm(EobFlyingObject *fo); + bool spellCallback_end_iceStorm(void *obj); + void spellCallback_start_stoneSkin(); void spellCallback_start_removeCurse(); void spellCallback_start_coneOfCold(); void spellCallback_start_holdMonster(); - bool spellCallback_end_holdMonster(EobFlyingObject *fo); + bool spellCallback_end_holdMonster(void *obj); void spellCallback_start_wallOfForce(); void spellCallback_start_disintegrate(); void spellCallback_start_fleshToStone(); void spellCallback_start_stoneToFlesh(); void spellCallback_start_trueSeeing(); - bool spellCallback_end_trueSeeing(EobFlyingObject *fo); + bool spellCallback_end_trueSeeing(void*); void spellCallback_start_slayLiving(); void spellCallback_start_powerWordStun(); void spellCallback_start_causeLightWounds(); void spellCallback_start_cureLightWounds(); void spellCallback_start_aid(); - bool spellCallback_end_aid(EobFlyingObject *fo); + bool spellCallback_end_aid(void *obj); void spellCallback_start_flameBlade(); void spellCallback_start_slowPoison(); - bool spellCallback_end_slowPoison(EobFlyingObject *fo); + bool spellCallback_end_slowPoison(void *obj); void spellCallback_start_createFood(); void spellCallback_start_removeParalysis(); void spellCallback_start_causeSeriousWounds(); @@ -971,19 +978,19 @@ protected: void spellCallback_start_causeCriticalWounds(); void spellCallback_start_cureCriticalWounds(); void spellCallback_start_flameStrike(); - bool spellCallback_end_flameStrike(EobFlyingObject *fo); + bool spellCallback_end_flameStrike(void *obj); void spellCallback_start_raiseDead(); void spellCallback_start_harm(); void spellCallback_start_heal(); void spellCallback_start_layOnHands(); void spellCallback_start_turnUndead(); - bool spellCallback_end_kuotoaAttack(EobFlyingObject *fo); - bool spellCallback_end_unk1Passive(EobFlyingObject *fo); - bool spellCallback_end_unk2Passive(EobFlyingObject *fo); - bool spellCallback_end_deathSpellPassive(EobFlyingObject *fo); - bool spellCallback_end_disintegratePassive(EobFlyingObject *fo); - bool spellCallback_end_causeCriticalWoundsPassive(EobFlyingObject *fo); - bool spellCallback_end_fleshToStonePassive(EobFlyingObject *fo); + bool spellCallback_end_lightningBoltPassive(void *obj); + bool spellCallback_end_unk1Passive(void *obj); + bool spellCallback_end_unk2Passive(void *obj); + bool spellCallback_end_deathSpellPassive(void*); + bool spellCallback_end_disintegratePassive(void*); + bool spellCallback_end_causeCriticalWoundsPassive(void*); + bool spellCallback_end_fleshToStonePassive(void*); int8 _openBookSpellLevel; int8 _openBookSpellSelectedItem; @@ -997,11 +1004,11 @@ protected: int8 *_openBookAvailableSpells; uint8 _activeSpellCharId; uint8 _activeSpellCharacterPos; - uint8 _activeSpell; + int _activeSpell; bool _returnAfterSpellCallback; typedef void (EobCoreEngine::*SpellStartCallback)(); - typedef bool (EobCoreEngine::*SpellEndCallback)(EobFlyingObject *fo); + typedef bool (EobCoreEngine::*SpellEndCallback)(void *obj); struct EobSpell { const char *name; diff --git a/engines/kyra/items_eob.cpp b/engines/kyra/items_eob.cpp index e2d28703a8..a83207b565 100644 --- a/engines/kyra/items_eob.cpp +++ b/engines/kyra/items_eob.cpp @@ -208,7 +208,7 @@ int EobCoreEngine::validateInventorySlotForItem(Item item, int charIndex, int sl int itm = _characters[charIndex].inventory[slot]; int ex = _itemTypes[_items[itm].type].extraProperties & 0x7f; - if (slot < 2 && _items[itm].flags & 0x20 && ex > 0 && ex < 4) { + if (slot < 2 && (_items[itm].flags & 0x20) && ex > 0 && ex < 4) { if (_flags.gameID == GI_EOB2) _txt->printMessage(_validateCursedString[0], -1, _characters[charIndex].name); return 0; @@ -474,8 +474,8 @@ void EobCoreEngine::drawItemIconShape(int pageNum, Item itemId, int x, int y) { } } -bool EobCoreEngine::isMagicWeapon(Item itemIndex) { - return (_items[itemIndex].type > 10 && _items[itemIndex].type < 18); +bool EobCoreEngine::isMagicEffectItem(Item itemIndex) { + return (itemIndex > 10 && itemIndex < 18); } bool EobCoreEngine::checkInventoryForRings(int charIndex, int itemValue) { diff --git a/engines/kyra/magic_eob.cpp b/engines/kyra/magic_eob.cpp index d06e15b36f..88046fd3a5 100644 --- a/engines/kyra/magic_eob.cpp +++ b/engines/kyra/magic_eob.cpp @@ -192,7 +192,7 @@ void EobCoreEngine::castSpell(int spell, int weaponSlot) { return; } - if (isMagicWeapon(c->inventory[0]) || isMagicWeapon(c->inventory[1])) { + if (isMagicEffectItem(c->inventory[0]) || isMagicEffectItem(c->inventory[1])) { printWarning(_magicStrings1[3]); return; } @@ -239,7 +239,7 @@ void EobCoreEngine::removeCharacterEffect(int spell, int charIndex, int showWarn printWarning(Common::String::format(_magicStrings3[_flags.gameID == GI_EOB1 ? 3 : 2], c->name, s->name).c_str()); if (s->endCallback) - (this->*s->endCallback)(0); + (this->*s->endCallback)(c); if (s->flags & 1) c->effectFlags &= ~s->effectFlags; @@ -270,13 +270,15 @@ void EobCoreEngine::removeCharacterEffect(int spell, int charIndex, int showWarn void EobCoreEngine::removeAllCharacterEffects(int charIndex) { EobCharacter *c = &_characters[charIndex]; + c->effectFlags = 0; memset(c->effectsRemainder, 0, 4); for (int i = 0; i < 10; i++) { - if (c->events[i] < 0) + if (c->events[i] < 0) { removeCharacterEffect(-c->events[i], charIndex, 0); - c->timers[i] = 0; - c->events[i] = 0; + c->timers[i] = 0; + c->events[i] = 0; + } } setupCharacterTimers(); @@ -444,7 +446,7 @@ void EobCoreEngine::sparkEffectOffensive() { } void EobCoreEngine::setSpellEventTimer(int spell, int timerBaseFactor, int timerLength, int timerLevelFactor, int updateExistingTimer) { - int l = _openBookType == 1 ? getCharacterClericPaladinLevel(_openBookChar) : getCharacterMageLevel(_openBookChar); + int l = _openBookType == 1 ? getClericPaladinLevel(_openBookChar) : getMageLevel(_openBookChar); uint32 countdown = timerLength * timerBaseFactor + timerLength * l * timerLevelFactor; setCharEventTimer(_activeSpellCharId, countdown, -spell, updateExistingTimer); } @@ -632,6 +634,63 @@ bool EobCoreEngine::turnUndeadHit(EobMonsterInPlay *m, int hitChance, int caster return true; } +int EobCoreEngine::getMagicWeaponSlot(int charIndex) { + return _characters[charIndex].inventory[1] ? 0 : 1; +} + +int EobCoreEngine::createMagicWeaponType(int invFlags, int handFlags, int armorClass, int allowedClasses, int dmgNumDice, int dmgPips, int dmgInc, int extraProps) { + int i = 51; + for (; i < 57; i++) { + if (_itemTypes[i].armorClass == -30) + break; + } + + if (i == 57) + return -1; + + EobItemType *tp = &_itemTypes[i]; + tp->invFlags = invFlags; + tp->requiredHands = 0; + tp->handFlags = handFlags; + tp->armorClass = armorClass; + tp->allowedClasses = allowedClasses; + tp->dmgNumDiceL = tp->dmgNumDiceS = dmgNumDice; + tp->dmgNumPipsL = tp->dmgNumPipsL = dmgPips; + tp->dmgIncL = tp->dmgIncS = dmgInc; + tp->extraProperties = extraProps; + + return i; +} + +Item EobCoreEngine::createMagicWeaponItem(int flags, int icon, int value, int type) { + Item i = 11; + for (; i < 17; i++) { + if (_items[i].block == -2) + break; + } + + if (i == 17) + return -1; + + EobItem *itm = &_items[i]; + itm->flags = 0x20 | flags; + itm->icon = icon; + itm->value = value; + itm->type = type; + itm->pos = 0; + itm->block = 0; + itm->nameId = itm->nameUnid = 0; + itm->prev = itm->next = 0; + + return i; +} + +void EobCoreEngine::removeMagicWeaponItem(Item item) { + _itemTypes[_items[item].type].armorClass = -30; + _items[item].block = -2; + _items[item].level = -1; +} + int EobCoreEngine::findSingleSpellTarget(int dist) { uint16 bl = _currentBlock; int res = -1; @@ -658,7 +717,7 @@ void EobCoreEngine::printNoEffectWarning() { } void EobCoreEngine::spellCallback_start_armor() { - _characters[_activeSpellCharId].effectsRemainder[0] = getCharacterMageLevel(_openBookChar) + 8; + _characters[_activeSpellCharId].effectsRemainder[0] = getMageLevel(_openBookChar) + 8; if ((getDexterityArmorClassModifier(_characters[_activeSpellCharId].dexterityCur) + 6) >= _characters[_activeSpellCharId].armorClass) printWarning(Common::String::format(_magicStrings6[0], _characters[_activeSpellCharId].name).c_str()); } @@ -672,7 +731,7 @@ void EobCoreEngine::spellCallback_start_burningHands() { _screen->updateScreen(); delay(2 * _tickLength); - int cl = getCharacterMageLevel(_openBookChar); + int cl = getMageLevel(_openBookChar); int bl = calcNewBlockPosition(_currentBlock, _currentDirection); const int8 *pos = getMonstersOnBlockPositions(bl); @@ -692,10 +751,11 @@ void EobCoreEngine::spellCallback_start_burningHands() { } void EobCoreEngine::spellCallback_start_detectMagic() { - + setHandItem(_itemInHand); } -bool EobCoreEngine::spellCallback_end_detectMagic(EobFlyingObject*) { +bool EobCoreEngine::spellCallback_end_detectMagic(void*) { + setHandItem(_itemInHand); return true; } @@ -703,15 +763,33 @@ void EobCoreEngine::spellCallback_start_magicMissile() { launchMagicObject(_openBookChar, 0, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_magicMissile(EobFlyingObject *fo) { - return magicObjectDamageHit(fo, 1, 4, 1, (getCharacterMageLevel(fo->attackerId) - 1) >> 1); +bool EobCoreEngine::spellCallback_end_magicMissile(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; + return magicObjectDamageHit(fo, 1, 4, 1, (getMageLevel(fo->attackerId) - 1) >> 1); } void EobCoreEngine::spellCallback_start_shockingGrasp() { - + int t = createMagicWeaponType(0, 0, 0, 0x0f, 1, 8, getMageLevel(_openBookChar), 1); + Item i = (t != -1) ? createMagicWeaponItem(0x10, 82, 0, t) : -1; + if (t == -1 || i == -1) { + if (_flags.gameID == GI_EOB2) + printWarning(_magicStrings8[0]); + removeCharacterEffect(_activeSpell, _activeSpellCharId, 0); + deleteCharEventTimer(_activeSpellCharId, -_activeSpell); + _returnAfterSpellCallback = true; + } else { + _characters[_activeSpellCharId].inventory[getMagicWeaponSlot(_activeSpellCharId)] = i; + } } -bool EobCoreEngine::spellCallback_end_shockingGraspFlameBlade(EobFlyingObject*) { +bool EobCoreEngine::spellCallback_end_shockingGraspFlameBlade(void *obj) { + EobCharacter *c = (EobCharacter*)obj; + for (int i = 0; i < 2; i++) { + if (isMagicEffectItem(c->inventory[i])) { + removeMagicWeaponItem(c->inventory[i]); + c->inventory[i] = 0; + } + } return true; } @@ -723,36 +801,43 @@ void EobCoreEngine::spellCallback_start_melfsAcidArrow() { launchMagicObject(_openBookChar, 1, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_melfsAcidArrow(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_melfsAcidArrow(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; assert(fo); - return magicObjectDamageHit(fo, 2, 4, 0, getCharacterMageLevel(fo->attackerId) / 3); + return magicObjectDamageHit(fo, 2, 4, 0, getMageLevel(fo->attackerId) / 3); } void EobCoreEngine::spellCallback_start_dispelMagic() { - + for (int i = 0; i < 6; i++) { + if (testCharacter(i, 1)) + removeAllCharacterEffects(i); + } } void EobCoreEngine::spellCallback_start_fireball() { launchMagicObject(_openBookChar, 2, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_fireball(EobFlyingObject *fo) { - return magicObjectDamageHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId)); +bool EobCoreEngine::spellCallback_end_fireball(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; + return magicObjectDamageHit(fo, 1, 6, 0, getMageLevel(fo->attackerId)); } void EobCoreEngine::spellCallback_start_flameArrow() { launchMagicObject(_openBookChar, 3, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_flameArrow(EobFlyingObject *fo) { - return magicObjectDamageHit(fo, 5, 6, 0, getCharacterMageLevel(fo->attackerId)); +bool EobCoreEngine::spellCallback_end_flameArrow(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; + return magicObjectDamageHit(fo, 5, 6, 0, getMageLevel(fo->attackerId)); } void EobCoreEngine::spellCallback_start_holdPerson() { launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 4 : 3, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_holdPerson(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_holdPerson(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; bool res = false; if (_flags.gameID == GI_EOB2 && fo->curBlock == _currentBlock) { @@ -781,15 +866,30 @@ void EobCoreEngine::spellCallback_start_lightningBolt() { launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 5 : 4, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_lightningBolt(EobFlyingObject *fo) { - return magicObjectDamageHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId)); +bool EobCoreEngine::spellCallback_end_lightningBolt(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; + return magicObjectDamageHit(fo, 1, 6, 0, getMageLevel(fo->attackerId)); } void EobCoreEngine::spellCallback_start_vampiricTouch() { - + int t = createMagicWeaponType(0, 0, 0, 0x0f, getMageLevel(_openBookChar) >> 1, 6, 0, 1); + Item i = (t != -1) ? createMagicWeaponItem(0x18, 83, 0, t) : -1; + if (t == -1 || i == -1) { + if (_flags.gameID == GI_EOB2) + printWarning(_magicStrings8[0]); + removeCharacterEffect(_activeSpell, _activeSpellCharId, 0); + deleteCharEventTimer(_activeSpellCharId, -_activeSpell); + _returnAfterSpellCallback = true; + } else { + _characters[_activeSpellCharId].inventory[getMagicWeaponSlot(_activeSpellCharId)] = i; + } } -bool EobCoreEngine::spellCallback_end_vampiricTouch(EobFlyingObject*) { +bool EobCoreEngine::spellCallback_end_vampiricTouch(void *obj) { + EobCharacter *c = (EobCharacter*)obj; + if (c->hitPointsCur > c->hitPointsMax) + c->hitPointsCur = c->hitPointsMax; + spellCallback_end_shockingGraspFlameBlade(obj); return true; } @@ -806,24 +906,29 @@ void EobCoreEngine::spellCallback_start_iceStorm() { launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 6 : 5, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_iceStorm(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_iceStorm(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; static int8 blockAdv[] = { -32, 32, 1, -1 }; - bool res = magicObjectDamageHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId)); + bool res = magicObjectDamageHit(fo, 1, 6, 0, getMageLevel(fo->attackerId)); if (res) { for (int i = 0; i < 4; i++) { uint16 bl = fo->curBlock; fo->curBlock = (fo->curBlock + blockAdv[i]) & 0x3ff; - magicObjectDamageHit(fo, 1, 6, 0, getCharacterMageLevel(fo->attackerId)); + magicObjectDamageHit(fo, 1, 6, 0, getMageLevel(fo->attackerId)); fo->curBlock = bl; } } return res; } +void EobCoreEngine::spellCallback_start_stoneSkin() { + _characters[_activeSpellCharId].effectsRemainder[1] = (getMageLevel(_openBookChar) >> 1) + rollDice(1, 4); +} + void EobCoreEngine::spellCallback_start_removeCurse() { for (int i = 0; i < 27; i++) { Item itm = _characters[_activeSpellCharId].inventory[i]; - if (itm && (_items[itm].flags & 0x20) && !isMagicWeapon(itm)) + if (itm && (_items[itm].flags & 0x20) && !isMagicEffectItem(itm)) _items[itm].flags = (_items[itm].flags & ~0x20) | 0x40; } } @@ -831,7 +936,7 @@ void EobCoreEngine::spellCallback_start_removeCurse() { void EobCoreEngine::spellCallback_start_coneOfCold() { static const int8 *dirTables[] = { _coneOfColdDest1, _coneOfColdDest2, _coneOfColdDest3, _coneOfColdDest4 }; - int cl = getCharacterMageLevel(_openBookChar); + int cl = getMageLevel(_openBookChar); //drawConeOfColdEffect(150, 50, 10, 1, 100, _coneOfColdGfxTbl); const int8 *tbl = dirTables[_currentDirection]; @@ -849,7 +954,8 @@ void EobCoreEngine::spellCallback_start_holdMonster() { launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 7 : 6, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_holdMonster(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_holdMonster(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; bool res = false; for (const int16 *m = findBlockMonsters(fo->curBlock, fo->curPos, fo->direction, 1, 1); *m != -1; m++) res |= magicObjectStatusHit(&_monsters[*m], 1, true, 4); @@ -888,16 +994,17 @@ void EobCoreEngine::spellCallback_start_trueSeeing() { _wllVmpMap[46] = 0; } -bool EobCoreEngine::spellCallback_end_trueSeeing(EobFlyingObject*) { +bool EobCoreEngine::spellCallback_end_trueSeeing(void*) { _wllVmpMap[46] = 1; return true; } void EobCoreEngine::spellCallback_start_slayLiving() { int d = findSingleSpellTarget(2); - if (d != -1) + if (d != -1) { if (!magicObjectStatusHit(&_monsters[d], 3, true, 4)) inflictMonsterDamage(&_monsters[d], rollDice(2, 8, 1), true); + } } void EobCoreEngine::spellCallback_start_powerWordStun() { @@ -917,22 +1024,55 @@ void EobCoreEngine::spellCallback_start_cureLightWounds() { } void EobCoreEngine::spellCallback_start_aid() { + if (!testCharacter(_activeSpellCharId, 3)) { + printNoEffectWarning(); + } else if (_characters[_activeSpellCharId].effectsRemainder[3]) { + printWarning(Common::String::format(_magicStrings8[(_flags.gameID == GI_EOB1) ? 2 : 5], _characters[_activeSpellCharId].name).c_str()); + } else { + _characters[_activeSpellCharId].effectsRemainder[3] = rollDice(1, 8); + _characters[_activeSpellCharId].hitPointsCur += _characters[_activeSpellCharId].effectsRemainder[3]; + _characters[_activeSpellCharId].effectFlags |= 0x1000; + return; + } + removeCharacterEffect(_activeSpell, _activeSpellCharId, 0); + deleteCharEventTimer(_activeSpellCharId, -_activeSpell); } -bool EobCoreEngine::spellCallback_end_aid(EobFlyingObject*) { +bool EobCoreEngine::spellCallback_end_aid(void *obj) { + EobCharacter *c = (EobCharacter*)obj; + c->hitPointsCur -= c->effectsRemainder[3]; + c->effectsRemainder[3] = 0; + c->effectFlags &= ~0x1000; return true; } void EobCoreEngine::spellCallback_start_flameBlade() { - + int t = createMagicWeaponType(0, 0, 0, 0x0f, 1, 4, 4, 1); + Item i = (t != -1) ? createMagicWeaponItem(0, 84, 0, t) : -1; + if (t == -1 || i == -1) { + if (_flags.gameID == GI_EOB2) + printWarning(_magicStrings8[0]); + removeCharacterEffect(_activeSpell, _activeSpellCharId, 0); + deleteCharEventTimer(_activeSpellCharId, -_activeSpell); + _returnAfterSpellCallback = true; + } else { + _characters[_activeSpellCharId].inventory[getMagicWeaponSlot(_activeSpellCharId)] = i; + } } void EobCoreEngine::spellCallback_start_slowPoison() { - + if (_characters[_activeSpellCharId].flags & 2) { + _characters[_activeSpellCharId].effectFlags |= 0x2000; + setSpellEventTimer(_activeSpell, 1, 32760, 1, 1); + } else { + printNoEffectWarning(); + } } -bool EobCoreEngine::spellCallback_end_slowPoison(EobFlyingObject*) { +bool EobCoreEngine::spellCallback_end_slowPoison(void *obj) { + EobCharacter *c = (EobCharacter*)obj; + c->effectFlags &= ~0x2000; return true; } @@ -963,7 +1103,10 @@ void EobCoreEngine::spellCallback_start_cureSeriousWounds() { } void EobCoreEngine::spellCallback_start_neutralizePoison() { - + if (_characters[_activeSpellCharId].flags & 2) + neutralizePoison(_activeSpellCharId); + else + printNoEffectWarning(); } void EobCoreEngine::spellCallback_start_causeCriticalWounds() { @@ -978,7 +1121,8 @@ void EobCoreEngine::spellCallback_start_flameStrike() { launchMagicObject(_openBookChar, _flags.gameID == GI_EOB1 ? 8 : 7, _currentBlock, _activeSpellCharacterPos, _currentDirection); } -bool EobCoreEngine::spellCallback_end_flameStrike(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_flameStrike(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; return magicObjectDamageHit(fo, 6, 8, 0, 0); } @@ -1012,7 +1156,7 @@ void EobCoreEngine::spellCallback_start_turnUndead() { if (!(_levelBlockProperties[bl].flags & 7)) return; - int cl = _openBookCasterLevel ? _openBookCasterLevel : getCharacterClericPaladinLevel(_openBookChar); + int cl = _openBookCasterLevel ? _openBookCasterLevel : getClericPaladinLevel(_openBookChar); int r = rollDice(1, 20); bool hit = false; @@ -1033,11 +1177,13 @@ void EobCoreEngine::spellCallback_start_turnUndead() { _preventMonsterFlash = false; } -bool EobCoreEngine::spellCallback_end_kuotoaAttack(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_lightningBoltPassive(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; return magicObjectDamageHit(fo, 0, 0, 12, 1); } -bool EobCoreEngine::spellCallback_end_unk1Passive(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_unk1Passive(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; bool res = false; if (_partyEffectFlags & 0x20000) { res = magicObjectDamageHit(fo, 4, 10, 6, 0); @@ -1051,23 +1197,24 @@ bool EobCoreEngine::spellCallback_end_unk1Passive(EobFlyingObject *fo) { return res; } -bool EobCoreEngine::spellCallback_end_unk2Passive(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_unk2Passive(void *obj) { + EobFlyingObject *fo = (EobFlyingObject*)obj; return magicObjectDamageHit(fo, 0, 0, 18, 0); } -bool EobCoreEngine::spellCallback_end_deathSpellPassive(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_deathSpellPassive(void*) { return true; } -bool EobCoreEngine::spellCallback_end_disintegratePassive(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_disintegratePassive(void*) { return true; } -bool EobCoreEngine::spellCallback_end_causeCriticalWoundsPassive(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_causeCriticalWoundsPassive(void*) { return true; } -bool EobCoreEngine::spellCallback_end_fleshToStonePassive(EobFlyingObject *fo) { +bool EobCoreEngine::spellCallback_end_fleshToStonePassive(void*) { return true; } diff --git a/engines/kyra/resource.h b/engines/kyra/resource.h index a54ae6cd9a..b3a5aa3817 100644 --- a/engines/kyra/resource.h +++ b/engines/kyra/resource.h @@ -487,8 +487,8 @@ enum KyraResources { kEob1EnemyMageSpellList, kEob1EnemyMageSfx, - kEob1MonsterDistAttType17, - kEob1MonsterDistAttSfx17, + kEob1BeholderSpellList, + kEob1BeholderSfx, kEob1TurnUndeadString, diff --git a/engines/kyra/sprites_eob.cpp b/engines/kyra/sprites_eob.cpp index 945ccaca17..cb8ae51860 100644 --- a/engines/kyra/sprites_eob.cpp +++ b/engines/kyra/sprites_eob.cpp @@ -55,7 +55,7 @@ namespace Kyra { void EobCoreEngine::loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex) { Common::String s = filename; - if (GI_EOB1 && !scumm_stricmp(filename, "rust") || !scumm_stricmp(filename, "drider") || !scumm_stricmp(filename, "spider") || !scumm_stricmp(filename, "mantis") || !scumm_stricmp(filename, "xorn")) + if (GI_EOB1 && !scumm_stricmp(filename, "rust") || !scumm_stricmp(filename, "drider") || !scumm_stricmp(filename, "spider") || !scumm_stricmp(filename, "mantis") || !scumm_stricmp(filename, "xorn") || !scumm_stricmp(filename, "xanath")) s += "1"; _screen->loadShapeSetBitmap(s.c_str(), 3, 3); @@ -971,8 +971,8 @@ bool EobCoreEngine::updateMonsterTryDistanceAttack(EobMonsterInPlay *m) { } snd_processEnvironmentalSoundEffect(108, m->block); } else { - launchMagicObject(-1, _monsterDistAttType17[m->numRemoteAttacks], m->block, m->pos, m->dir); - snd_processEnvironmentalSoundEffect(_monsterDistAttSfx17[m->numRemoteAttacks], m->block); + launchMagicObject(-1, _beholderSpellList[d], m->block, m->pos, m->dir); + snd_processEnvironmentalSoundEffect(_beholderSfx[d], m->block); } break; default: diff --git a/engines/kyra/staticres_eob.cpp b/engines/kyra/staticres_eob.cpp index f30833cc08..b1ab606f5e 100644 --- a/engines/kyra/staticres_eob.cpp +++ b/engines/kyra/staticres_eob.cpp @@ -803,7 +803,7 @@ void EobCoreEngine::initSpells() { mp(2); // Vampiric Touch mpn; // Fear mpn; // Ice Storm - mp1n; // Stone Skin /// --- para required? + mp1n; // Stone Skin mp1n; // Cloud Kill /// mp2(4); // Improved Invisibility /// mp2n; // remove Curse /// @@ -881,7 +881,8 @@ void EobCoreEngine::initSpells() { sc(vampiricTouch); sc(fear); sc(iceStorm); - sc(empty); // EOB1: stone skin, EOB2: imp invisibility + sc1(stoneSkin); // stone skin + sc2(empty); // imp invisibility sc1(empty); // Cloudkill sc2(removeCurse); sc(coneOfCold); @@ -1004,7 +1005,7 @@ void EobCoreEngine::initSpells() { ec2(empty); ec(empty); ec2(empty); - ec1(kuotoaAttack); + ec1(lightningBoltPassive); ec2(unk1Passive); ec2(empty); ec2(unk2Passive); @@ -1072,8 +1073,8 @@ void EobEngine::initStaticResource() { _enemyMageSpellList = _staticres->loadRawData(kEob1EnemyMageSpellList, temp); _enemyMageSfx = _staticres->loadRawData(kEob1EnemyMageSfx, temp); - _monsterDistAttType17 = _staticres->loadRawData(kEob1MonsterDistAttType17, temp); - _monsterDistAttSfx17 = _staticres->loadRawData(kEob1MonsterDistAttSfx17, temp); + _beholderSpellList = _staticres->loadRawData(kEob1BeholderSpellList, temp); + _beholderSfx = _staticres->loadRawData(kEob1BeholderSfx, temp); _turnUndeadString = _staticres->loadStrings(kEob1TurnUndeadString, temp); @@ -1162,7 +1163,7 @@ void EobEngine::initSpells() { { 0x0488, 0x000000, 0x01 }, // vampiric touch { 0x0100, 0x000000, 0x00 }, // fear { 0x0100, 0x000000, 0x41 }, // ice storm - { 0x0000, 0x000000, 0x00 }, // STONE SKIN + { 0x0033, 0x000001, 0x00 }, // STONE SKIN { 0x0000, 0x000000, 0x00 }, // CLOUD KILL { 0x0100, 0x000000, 0x41 }, // cone of cold { 0x0100, 0x000000, 0x00 }, // hold monster |