aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devtools/create_kyradat/create_kyradat.cpp12
-rw-r--r--devtools/create_kyradat/create_kyradat.h4
-rw-r--r--devtools/create_kyradat/games.cpp4
-rw-r--r--devtools/create_kyradat/tables.cpp8
-rw-r--r--engines/kyra/eob1.cpp8
-rw-r--r--engines/kyra/eobcommon.cpp18
-rw-r--r--engines/kyra/eobcommon.h67
-rw-r--r--engines/kyra/items_eob.cpp6
-rw-r--r--engines/kyra/magic_eob.cpp243
-rw-r--r--engines/kyra/resource.h4
-rw-r--r--engines/kyra/sprites_eob.cpp6
-rw-r--r--engines/kyra/staticres_eob.cpp13
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