1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef KYRA_EOBCOMMON_H 24 #define KYRA_EOBCOMMON_H 25 26 #if defined(ENABLE_EOB) || defined(ENABLE_LOL) 27 #include "kyra/engine/kyra_rpg.h" 28 #endif // (ENABLE_EOB || ENABLE_LOL) 29 30 #ifdef ENABLE_EOB 31 32 namespace Kyra { 33 34 struct DarkMoonShapeDef { 35 int16 index; 36 uint8 x, y, w, h; 37 }; 38 39 struct CreatePartyModButton { 40 uint8 encodeLabelX; 41 uint8 encodeLabelY; 42 uint8 labelW; 43 uint8 labelH; 44 uint8 labelX; 45 uint8 labelY; 46 uint8 bodyIndex; 47 uint8 destX; 48 uint8 destY; 49 }; 50 51 struct EoBRect8 { 52 uint8 x; 53 uint8 y; 54 uint8 w; 55 uint8 h; 56 }; 57 58 struct EoBChargenButtonDef { 59 uint8 x; 60 uint8 y; 61 uint8 w; 62 uint8 h; 63 uint8 keyCode; 64 }; 65 66 struct EoBGuiButtonDef { 67 uint16 keyCode; 68 uint16 keyCode2; 69 uint16 flags; 70 uint16 x; 71 uint8 y; 72 uint16 w; 73 uint8 h; 74 uint16 arg; 75 }; 76 77 struct EoBCharacter { 78 uint8 id; 79 uint8 flags; 80 char name[21]; 81 int8 strengthCur; 82 int8 strengthMax; 83 int8 strengthExtCur; 84 int8 strengthExtMax; 85 int8 intelligenceCur; 86 int8 intelligenceMax; 87 int8 wisdomCur; 88 int8 wisdomMax; 89 int8 dexterityCur; 90 int8 dexterityMax; 91 int8 constitutionCur; 92 int8 constitutionMax; 93 int8 charismaCur; 94 int8 charismaMax; 95 int16 hitPointsCur; 96 int16 hitPointsMax; 97 int8 armorClass; 98 uint8 disabledSlots; 99 uint8 raceSex; 100 uint8 cClass; 101 uint8 alignment; 102 int8 portrait; 103 uint8 food; 104 uint8 level[3]; 105 uint32 experience[3]; 106 uint8 *faceShape; 107 108 int8 mageSpells[80]; 109 int8 clericSpells[80]; 110 uint32 mageSpellsAvailableFlags; 111 112 Item inventory[27]; 113 uint32 timers[10]; 114 int8 events[10]; 115 uint8 effectsRemainder[4]; 116 uint32 effectFlags; 117 uint8 damageTaken; 118 int8 slotStatus[5]; 119 }; 120 121 struct EoBItem { 122 uint8 nameUnid; 123 uint8 nameId; 124 uint8 flags; 125 int8 icon; 126 int8 type; 127 int8 pos; 128 int16 block; 129 Item next; 130 Item prev; 131 uint8 level; 132 int8 value; 133 }; 134 135 struct EoBItemType { 136 uint16 invFlags; 137 uint16 handFlags; 138 int8 armorClass; 139 int8 allowedClasses; 140 int8 requiredHands; 141 int8 dmgNumDiceS; 142 int8 dmgNumPipsS; 143 int8 dmgIncS; 144 int8 dmgNumDiceL; 145 int8 dmgNumPipsL; 146 int8 dmgIncL; 147 uint8 unk1; 148 uint16 extraProperties; 149 }; 150 151 struct SpriteDecoration { 152 uint8 *shp; 153 int16 x; 154 int16 y; 155 }; 156 157 struct EoBMonsterProperty { 158 int8 armorClass; 159 int8 hitChance; 160 int8 level; 161 uint8 hpDcTimes; 162 uint8 hpDcPips; 163 uint8 hpDcBase; 164 uint8 attacksPerRound; 165 struct DmgDc { 166 uint8 times; 167 uint8 pips; 168 int8 base; 169 } dmgDc[3]; 170 uint16 immunityFlags; 171 uint32 capsFlags; 172 uint32 typeFlags; 173 int32 experience; 174 175 uint8 u30; 176 int8 sound1; 177 int8 sound2; 178 uint8 numRemoteAttacks; 179 uint8 remoteWeaponChangeMode; 180 uint8 numRemoteWeapons; 181 182 int8 remoteWeapons[5]; 183 184 int8 tuResist; 185 uint8 dmgModifierEvade; 186 187 uint8 decorations[3]; 188 }; 189 190 struct EoBMonsterInPlay { 191 uint8 type; 192 uint8 unit; 193 uint16 block; 194 uint8 pos; 195 int8 dir; 196 uint8 animStep; 197 uint8 shpIndex; 198 int8 mode; 199 int8 stray; 200 int8 curAttackFrame; 201 int8 spellStatusLeft; 202 int16 hitPointsMax; 203 int16 hitPointsCur; 204 uint16 dest; 205 uint16 randItem; 206 uint16 fixedItem; 207 uint8 flags; 208 uint8 idleAnimState; 209 uint8 curRemoteWeapon; 210 uint8 numRemoteAttacks; 211 int8 palette; 212 uint8 directionChanged; 213 uint8 stepsTillRemoteAttack; 214 uint8 sub; 215 }; 216 217 struct ScriptTimer { 218 uint16 func; 219 uint16 ticks; 220 uint32 next; 221 }; 222 223 struct EoBMenuDef { 224 int8 titleStrId; 225 uint8 dim; 226 uint8 firstButtonStrId; 227 int8 numButtons; 228 int8 titleCol; 229 }; 230 struct EoBMenuButtonDef { 231 int8 labelId; 232 int16 x; 233 int8 y; 234 uint8 width; 235 uint8 height; 236 int16 keyCode; 237 int16 flags; 238 }; 239 240 class EoBInfProcessor; 241 242 class EoBCoreEngine : public KyraRpgEngine { 243 friend class TextDisplayer_rpg; 244 friend class GUI_EoB; 245 friend class Debugger_EoB; 246 friend class EoBInfProcessor; 247 friend class DarkmoonSequenceHelper; 248 friend class CharacterGenerator; 249 friend class TransferPartyWiz; 250 public: 251 EoBCoreEngine(OSystem *system, const GameFlags &flags); 252 virtual ~EoBCoreEngine(); 253 254 virtual void initKeymap(); 255 screen()256 Screen *screen() { return _screen; } gui()257 GUI *gui() const { return _gui; } 258 259 protected: 260 // Startup 261 virtual Common::Error init(); 262 Common::Error go(); 263 264 // Main Menu, Intro, Finale 265 virtual int mainMenu() = 0; seq_xdeath()266 virtual void seq_xdeath() {} 267 virtual void seq_playFinale() = 0; 268 bool _playFinale; 269 270 //Init, config 271 void loadItemsAndDecorationsShapes(); 272 void releaseItemsAndDecorationsShapes(); 273 274 void initButtonData(); 275 void initMenus(); 276 void initStaticResource(); 277 virtual void initSpells(); 278 279 void registerDefaultSettings(); 280 void readSettings(); 281 void writeSettings(); 282 283 const uint8 **_largeItemShapes; 284 const uint8 **_smallItemShapes; 285 const uint8 **_thrownItemShapes; 286 const uint8 **_largeItemShapesScl[3]; 287 const uint8 **_smallItemShapesScl[3]; 288 const uint8 **_thrownItemShapesScl[3]; 289 const int _numLargeItemShapes; 290 const int _numSmallItemShapes; 291 const int _numThrownItemShapes; 292 const int _numItemIconShapes; 293 294 const uint8 **_spellShapes; 295 const uint8 **_firebeamShapes; 296 const uint8 *_redSplatShape; 297 const uint8 *_greenSplatShape; 298 const uint8 **_wallOfForceShapes; 299 const uint8 **_teleporterShapes; 300 const uint8 **_sparkShapes; 301 const uint8 *_deadCharShape; 302 const uint8 *_disabledCharGrid; 303 const uint8 *_blackBoxSmallGrid; 304 const uint8 *_weaponSlotGrid; 305 const uint8 *_blackBoxWideGrid; 306 const uint8 *_lightningColumnShape; 307 308 uint8 *_itemsOverlay; 309 static const uint8 _itemsOverlayCGA[]; 310 311 static const uint8 _teleporterShapeDefs[]; 312 static const uint8 _wallOfForceShapeDefs[]; 313 314 const char *const *_mainMenuStrings; 315 316 // Main loop 317 virtual void startupNew(); 318 virtual void startupLoad() = 0; 319 void runLoop(); update()320 void update() { screen()->updateScreen(); } 321 bool checkPartyStatus(bool handleDeath); 322 323 bool _runFlag; 324 325 // Character generation / party transfer 326 bool startCharacterGeneration(); 327 bool startPartyTransfer(); 328 329 uint8 **_faceShapes; 330 331 static const int8 _characterClassType[]; 332 static const uint8 _hpIncrPerLevel[]; 333 static const uint8 _numLevelsPerClass[]; 334 static const int16 _hpConstModifiers[]; 335 static const uint8 _charClassModifier[]; 336 337 const uint8 *_classModifierFlags; 338 339 // timers 340 void setupTimers(); 341 virtual void enableSysTimer(int sysTimer); 342 virtual void disableSysTimer(int sysTimer); 343 void setCharEventTimer(int charIndex, uint32 countdown, int evnt, int updateExistingTimer); 344 void deleteCharEventTimer(int charIndex, int evnt); 345 void setupCharacterTimers(); 346 void advanceTimers(uint32 millis); 347 348 void timerProcessMonsters(int timerNum); 349 void timerSpecialCharacterUpdate(int timerNum); 350 void timerProcessFlyingObjects(int timerNum); 351 void timerProcessCharacterExchange(int timerNum); 352 void timerUpdateTeleporters(int timerNum); 353 void timerUpdateFoodStatus(int timerNum); 354 void timerUpdateMonsterIdleAnim(int timerNum); 355 getClock2Timer(int index)356 uint8 getClock2Timer(int index) { return index < _numClock2Timers ? _clock2Timers[index] : 0; } getNumClock2Timers()357 uint8 getNumClock2Timers() { return _numClock2Timers; } 358 359 static const uint8 _clock2Timers[]; 360 static const uint8 _numClock2Timers; 361 362 uint32 _disableElapsedTime; 363 uint32 _restPartyElapsedTime; 364 365 // Mouse 366 void setHandItem(Item itemIndex); 367 368 // Characters 369 int getDexterityArmorClassModifier(int dexterity); 370 int generateCharacterHitpointsByLevel(int charIndex, int levelIndex); 371 int getClassAndConstHitpointsModifier(int cclass, int constitution); 372 int getCharacterClassType(int cclass, int levelIndex); 373 int getModifiedHpLimits(int hpModifier, int constModifier, int level, bool mode); 374 Common::String getCharStrength(int str, int strExt); 375 int testCharacter(int16 index, int flags); 376 int getNextValidCharIndex(int curCharIndex, int searchStep); 377 378 void recalcArmorClass(int index); 379 int validateWeaponSlotItem(int index, int slot); 380 381 int getClericPaladinLevel(int index); 382 int getMageLevel(int index); 383 int getCharacterLevelIndex(int type, int cClass); 384 385 int countCharactersWithSpecificItems(int16 itemType, int16 itemValue); 386 int checkInventoryForItem(int character, int16 itemType, int16 itemValue); 387 void modifyCharacterHitpoints(int character, int16 points); 388 void neutralizePoison(int character); 389 390 void npcSequence(int npcIndex); 391 virtual void drawNpcScene(int npcIndex) = 0; 392 virtual void runNpcDialogue(int npcIndex) = 0; 393 void initNpc(int npcIndex); 394 int npcJoinDialogue(int npcIndex, int queryJoinTextId, int confirmJoinTextId, int noJoinTextId); 395 int prepareForNewPartyMember(int16 itemType, int16 itemValue); 396 void dropCharacter(int charIndex); 397 void removeCharacterFromParty(int charIndex); 398 void exchangeCharacters(int charIndex1, int charIndex2); 399 400 void increasePartyExperience(int16 points); 401 void increaseCharacterExperience(int charIndex, int32 points); 402 uint32 getRequiredExperience(int cClass, int levelIndex, int level); 403 void increaseCharacterLevel(int charIndex, int levelIndex); 404 405 void setWeaponSlotStatus(int charIndex, int mode, int slot); 406 407 EoBCharacter *_characters; 408 Common::String _strenghtStr; 409 int _castScrollSlot; 410 int _exchangeCharacterId; 411 412 const char *const *_levelGainStrings; 413 const uint32 *_expRequirementTables[6]; 414 415 const uint8 *_saveThrowTables[6]; 416 const uint8 *_saveThrowLevelIndex; 417 const uint8 *_saveThrowModDiv; 418 const uint8 *_saveThrowModExt; 419 420 const EoBCharacter *_npcPreset; 421 int _npcSequenceSub; 422 bool _partyResting; 423 bool _loading; 424 425 // Items 426 void loadItemDefs(); 427 Item duplicateItem(Item itemIndex); 428 void setItemPosition(Item *itemQueue, int block, Item item, int pos); 429 Item createItemOnCurrentBlock(Item itemIndex); 430 void createInventoryItem(EoBCharacter *c, Item itemIndex, int16 itemValue, int preferedInventorySlot); 431 int deleteInventoryItem(int charIndex, int slot); 432 void deleteBlockItem(uint16 block, int type); 433 int validateInventorySlotForItem(Item item, int charIndex, int slot); 434 int stripPartyItems(int16 itemType, int16 itemValue, int handleValueMode, int numItems); 435 bool deletePartyItems(int16 itemType, int16 itemValue); 436 virtual void updateUsedCharacterHandItem(int charIndex, int slot) = 0; 437 int itemUsableByCharacter(int charIndex, Item item); 438 int countQueuedItems(Item itemQueue, int16 id, int16 type, int count, int includeFlyingItems); 439 int getQueuedItem(Item *items, int pos, int id); 440 void printFullItemName(Item item); 441 void identifyQueuedItems(Item itemQueue); 442 void drawItemIconShape(int pageNum, Item itemId, int x, int y); 443 bool isMagicEffectItem(Item itemIndex); 444 bool checkInventoryForRings(int charIndex, int itemValue); 445 void eatItemInHand(int charIndex); 446 447 bool launchObject(int charIndex, Item item, uint16 startBlock, int startPos, int dir, int type); 448 void launchMagicObject(int charIndex, int type, uint16 startBlock, int startPos, int dir); 449 bool updateObjectFlight(EoBFlyingObject *fo, int block, int pos); 450 bool updateFlyingObjectHitTest(EoBFlyingObject *fo, int block, int pos); 451 void explodeObject(EoBFlyingObject *fo, int block, Item item); 452 void endObjectFlight(EoBFlyingObject *fo); 453 void checkFlyingObjects(); 454 455 void reloadWeaponSlot(int charIndex, int slotIndex, int itemType, int arrowOrDagger); 456 457 EoBItem *_items; 458 uint16 _numItems; 459 EoBItemType *_itemTypes; 460 char **_itemNames; 461 uint16 _numItemNames; 462 uint32 _partyEffectFlags; 463 Item _lastUsedItem; 464 465 const uint16 *_slotValidationFlags; 466 const int8 *_projectileWeaponAmmoTypes; 467 const uint8 *_wandTypes; 468 469 EoBFlyingObject *_flyingObjects; 470 const uint8 *_drawObjPosIndex; 471 const uint8 *_flightObjFlipIndex; 472 const int8 *_flightObjShpMap; 473 const int8 *_flightObjSclIndex; 474 475 const uint8 *_expObjectTlMode; 476 const uint8 *_expObjectTblIndex; 477 const uint8 *_expObjectShpStart; 478 const uint8 *_expObjectAnimTbl1; 479 int _expObjectAnimTbl1Size; 480 const uint8 *_expObjectAnimTbl2; 481 int _expObjectAnimTbl2Size; 482 const uint8 *_expObjectAnimTbl3; 483 int _expObjectAnimTbl3Size; 484 485 const char *const *_ascii2SjisTables; 486 const char *const *_ascii2SjisTables2; 487 488 // Monsters 489 void loadMonsterShapes(const char *filename, int monsterIndex, bool hasDecorations, int encodeTableIndex); 490 void releaseMonsterShapes(int first, int num); 491 uint8 *loadTownsShape(Common::SeekableReadStream *stream); generateMonsterPalettes(const char * file,int16 monsterIndex)492 virtual void generateMonsterPalettes(const char *file, int16 monsterIndex) {} loadMonsterDecoration(Common::SeekableReadStream * stream,int16 monsterIndex)493 virtual void loadMonsterDecoration(Common::SeekableReadStream *stream, int16 monsterIndex) {} loadMonsterProperties(const uint8 * data)494 virtual const uint8 *loadMonsterProperties(const uint8 *data) { return 0; } 495 const uint8 *loadActiveMonsterData(const uint8 *data, int level); 496 void initMonster(int index, int unit, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int i, int randItem, int fixedItem); 497 void placeMonster(EoBMonsterInPlay *m, uint16 block, int dir); 498 virtual void replaceMonster(int b, uint16 block, int pos, int dir, int type, int shpIndex, int mode, int h2, int randItem, int fixedItem) = 0; 499 void killMonster(EoBMonsterInPlay *m, bool giveExperience); 500 virtual bool killMonsterExtra(EoBMonsterInPlay *m) = 0; 501 int countSpecificMonsters(int type); 502 void updateAttackingMonsterFlags(); 503 504 const int8 *getMonstersOnBlockPositions(uint16 block); 505 int getClosestMonster(int charIndex, int block); 506 507 bool blockHasMonsters(uint16 block); 508 bool isMonsterOnPos(EoBMonsterInPlay *m, uint16 block, int pos, int checkPos4); 509 const int16 *findBlockMonsters(uint16 block, int pos, int dir, int blockDamage, int singleTargetCheckAdjacent); 510 511 void drawBlockObject(int flipped, int page, const uint8 *shape, int x, int y, int sd, uint8 *ovl = 0); 512 void drawMonsterShape(const uint8 *shape, int x, int y, int flipped, int flags, int palIndex); 513 void flashMonsterShape(EoBMonsterInPlay *m); 514 void updateAllMonsterShapes(); 515 void drawBlockItems(int index); 516 void drawDoor(int index); 517 virtual void drawDoorIntern(int type, int index, int x, int y, int w, int wall, int mDim, int16 y1, int16 y2) = 0; 518 void drawMonsters(int index); 519 void drawWallOfForce(int index); 520 void drawFlyingObjects(int index); 521 void drawTeleporter(int index); 522 523 void updateMonsters(int unit); 524 void updateMonsterDest(EoBMonsterInPlay *m); 525 void updateMonsterAttackMode(EoBMonsterInPlay *m); 526 void updateAllMonsterDests(); 527 void turnFriendlyMonstersHostile(); 528 int getNextMonsterDirection(int curBlock, int destBlock); 529 int getNextMonsterPos(EoBMonsterInPlay *m, int block); 530 int findFreeMonsterPos(int block, int size); 531 void updateMoveMonster(EoBMonsterInPlay *m); 532 bool updateMonsterTryDistanceAttack(EoBMonsterInPlay *m); 533 bool updateMonsterTryCloseAttack(EoBMonsterInPlay *m, int block); 534 void walkMonster(EoBMonsterInPlay *m, int destBlock); 535 bool walkMonsterNextStep(EoBMonsterInPlay *m, int destBlock, int direction); 536 void updateMonsterFollowPath(EoBMonsterInPlay *m, int turnSteps); 537 void updateMonstersStraying(EoBMonsterInPlay *m, int a); 538 void updateMonstersSpellStatus(EoBMonsterInPlay *m); 539 void setBlockMonsterDirection(int block, int dir); 540 541 uint8 *_monsterFlashOverlay; 542 uint8 *_monsterStoneOverlay; 543 544 SpriteDecoration *_monsterDecorations; 545 EoBMonsterProperty *_monsterProps; 546 547 EoBMonsterInPlay *_monsters; 548 549 const int8 *_monsterStepTable0; 550 const int8 *_monsterStepTable1; 551 const int8 *_monsterStepTable2; 552 const int8 *_monsterStepTable3; 553 const uint8 *_monsterCloseAttPosTable1; 554 const uint8 *_monsterCloseAttPosTable2; 555 const int8 *_monsterCloseAttUnkTable; 556 const uint8 *_monsterCloseAttChkTable1; 557 const uint8 *_monsterCloseAttChkTable2; 558 const uint8 *_monsterCloseAttDstTable1; 559 const uint8 *_monsterCloseAttDstTable2; 560 561 const uint8 *_monsterProximityTable; 562 const uint8 *_findBlockMonstersTable; 563 const char *const *_monsterDustStrings; 564 565 const uint8 *_enemyMageSpellList; 566 const uint8 *_enemyMageSfx; 567 const uint8 *_beholderSpellList; 568 const uint8 *_beholderSfx; 569 const char *const *_monsterSpecAttStrings; 570 571 const int8 *_monsterFrmOffsTable1; 572 const int8 *_monsterFrmOffsTable2; 573 574 const uint16 *_encodeMonsterShpTable; 575 const uint8 _teleporterWallId; 576 577 const int16 *_wallOfForceDsX; 578 const uint8 *_wallOfForceDsY; 579 const uint8 *_wallOfForceDsNumW; 580 const uint8 *_wallOfForceDsNumH; 581 const uint8 *_wallOfForceShpId; 582 583 const int8 *_monsterDirChangeTable; 584 585 // Level 586 void loadLevel(int level, int sub); 587 void readLevelFileData(int level); 588 Common::String initLevelData(int sub); 589 void addLevelItems(); 590 void loadVcnData(const char *file, const uint8 *cgaMapping); 591 void loadBlockProperties(const char *mazFile); 592 const uint8 *getBlockFileData(int levelIndex = 0); 593 Common::String getBlockFileName(int levelIndex, int sub); 594 const uint8 *getBlockFileData(const char *mazFile); 595 void loadDecorations(const char *cpsFile, const char *decFile); 596 void assignWallsAndDecorations(int wallIndex, int vmpIndex, int decDataIndex, int specialType, int flags); 597 void releaseDecorations(); 598 void releaseDoorShapes(); 599 void toggleWallState(int wall, int flags); 600 virtual void loadDoorShapes(int doorType1, int shapeId1, int doorType2, int shapeId2) = 0; 601 virtual const uint8 *loadDoorShapes(const char *filename, int doorIndex, const uint8 *shapeDefs) = 0; 602 603 void drawScene(int refresh); 604 void drawSceneShapes(int start = 0); 605 void drawDecorations(int index); 606 607 int calcNewBlockPositionAndTestPassability(uint16 curBlock, uint16 direction); 608 void notifyBlockNotPassable(); 609 void moveParty(uint16 block); 610 611 int clickedDoorSwitch(uint16 block, uint16 direction); 612 int clickedDoorPry(uint16 block, uint16 direction); 613 int clickedDoorNoPry(uint16 block, uint16 direction); 614 int clickedNiche(uint16 block, uint16 direction); 615 616 int specialWallAction(int block, int direction); 617 618 void openDoor(int block); 619 void closeDoor(int block); 620 621 int16 _doorType[2]; 622 int16 _noDoorSwitch[2]; 623 624 EoBRect8 *_levelDecorationRects; 625 SpriteDecoration *_doorSwitches; 626 627 int8 _currentSub; 628 Common::String _curGfxFile; 629 Common::String _curBlockFile; 630 631 uint32 _drawSceneTimer; 632 uint32 _flashShapeTimer; 633 uint32 _envAudioTimer; 634 uint16 _teleporterPulse; 635 636 Common::Array<const int16 *> _dscWallMapping; 637 const int16 *_dscShapeCoords; 638 639 const uint8 *_dscItemPosIndex; 640 const int16 *_dscItemShpX; 641 const uint8 *_dscItemScaleIndex; 642 const uint8 *_dscItemTileIndex; 643 const uint8 *_dscItemShapeMap; 644 645 const uint8 *_dscDoorScaleMult1; 646 const uint8 *_dscDoorScaleMult2; 647 const uint8 *_dscDoorScaleMult3; 648 const uint8 *_dscDoorY1; 649 const uint8 *_dscDoorXE; 650 651 uint8 *_greenFadingTable; 652 uint8 *_blueFadingTable; 653 uint8 *_lightBlueFadingTable; 654 uint8 *_blackFadingTable; 655 uint8 *_greyFadingTable; 656 657 const uint8 *_wllFlagPreset; 658 int _wllFlagPresetSize; 659 const uint8 *_teleporterShapeCoords; 660 const int8 *_portalSeq; 661 662 // Script 663 void runLevelScript(int block, int flags); 664 void setScriptFlags(uint32 flags); 665 void clearScriptFlags(uint32 flags); 666 bool checkScriptFlags(uint32 flags); 667 668 const uint8 *initScriptTimers(const uint8 *pos); 669 void updateScriptTimers(); updateScriptTimersExtra()670 virtual void updateScriptTimersExtra() {} 671 672 EoBInfProcessor *_inf; 673 int _stepCounter; 674 int _stepsUntilScriptCall; 675 ScriptTimer _scriptTimers[5]; 676 int _scriptTimersCount; 677 uint8 _scriptTimersMode; 678 679 // Gui 680 void gui_drawPlayField(bool refresh); 681 void gui_restorePlayField(); 682 void gui_drawAllCharPortraitsWithStats(); 683 void gui_drawCharPortraitWithStats(int index); 684 void gui_drawFaceShape(int index); 685 void gui_drawWeaponSlot(int charIndex, int slot); 686 void gui_drawWeaponSlotStatus(int x, int y, int status); 687 void gui_drawHitpoints(int index); 688 void gui_drawFoodStatusGraph(int index); 689 void gui_drawHorizontalBarGraph(int x, int y, int w, int h, int32 curVal, int32 maxVal, int col1, int col2); 690 void gui_drawCharPortraitStatusFrame(int index); 691 void gui_drawInventoryItem(int slot, int redraw, int pageNum); 692 void gui_drawCompass(bool force); 693 void gui_drawDialogueBox(); 694 void gui_drawSpellbook(); 695 void gui_drawSpellbookScrollArrow(int x, int y, int direction); 696 void gui_updateSlotAfterScrollUse(); 697 void gui_updateControls(); 698 void gui_toggleButtons(); 699 void gui_setPlayFieldButtons(); 700 void gui_setInventoryButtons(); 701 void gui_setStatsListButtons(); 702 void gui_setSwapCharacterButtons(); 703 void gui_setCastOnWhomButtons(); 704 void gui_initButton(int index, int x = -1, int y = -1, int val = -1); 705 Button *gui_getButton(Button *buttonList, int index); 706 707 int clickedInventoryNextPage(Button *button); 708 int clickedPortraitRestore(Button *button); 709 int clickedCharPortraitDefault(Button *button); 710 int clickedCamp(Button *button); 711 int clickedSceneDropPickupItem(Button *button); 712 int clickedCharPortrait2(Button *button); 713 int clickedWeaponSlot(Button *button); 714 int clickedCharNameLabelRight(Button *button); 715 int clickedInventorySlot(Button *button); 716 int clickedEatItem(Button *button); 717 int clickedInventoryPrevChar(Button *button); 718 int clickedInventoryNextChar(Button *button); 719 int clickedSpellbookTab(Button *button); 720 int clickedSpellbookList(Button *button); 721 int clickedCastSpellOnCharacter(Button *button); 722 int clickedUpArrow(Button *button); 723 int clickedDownArrow(Button *button); 724 int clickedLeftArrow(Button *button); 725 int clickedRightArrow(Button *button); 726 int clickedTurnLeftArrow(Button *button); 727 int clickedTurnRightArrow(Button *button); 728 int clickedAbortCharSwitch(Button *button); 729 int clickedSceneThrowItem(Button *button); 730 int clickedSceneSpecial(Button *button); 731 int clickedSpellbookAbort(Button *button); 732 int clickedSpellbookScroll(Button *button); 733 int clickedUnk(Button *button); 734 735 void gui_processCharPortraitClick(int index); 736 void gui_processWeaponSlotClickLeft(int charIndex, int slotIndex); 737 void gui_processWeaponSlotClickRight(int charIndex, int slotIndex); 738 void gui_processInventorySlotClick(int slot); 739 740 static const uint8 _buttonList1[]; 741 int _buttonList1Size; 742 static const uint8 _buttonList2[]; 743 int _buttonList2Size; 744 static const uint8 _buttonList3[]; 745 int _buttonList3Size; 746 static const uint8 _buttonList4[]; 747 int _buttonList4Size; 748 static const uint8 _buttonList5[]; 749 int _buttonList5Size; 750 static const uint8 _buttonList6[]; 751 int _buttonList6Size; 752 static const uint8 _buttonList7[]; 753 int _buttonList7Size; 754 static const uint8 _buttonList8[]; 755 int _buttonList8Size; 756 757 EoBGuiButtonDef *_buttonDefs; 758 759 const char *const *_characterGuiStringsHp; 760 const char *const *_characterGuiStringsWp; 761 const char *const *_characterGuiStringsWr; 762 const char *const *_characterGuiStringsSt; 763 const char *const *_characterGuiStringsIn; 764 765 const char *const *_characterStatusStrings7; 766 const char *const *_characterStatusStrings8; 767 const char *const *_characterStatusStrings9; 768 const char *const *_characterStatusStrings12; 769 const char *const *_characterStatusStrings13; 770 771 const uint16 *_inventorySlotsX; 772 const uint8 *_inventorySlotsY; 773 const uint8 **_compassShapes; 774 uint8 _charExchangeSwap; 775 bool _configHpBarGraphs; 776 bool _configMouseBtSwap; 777 778 Graphics::Surface _thumbNail; 779 780 // text 781 void setupDialogueButtons(int presetfirst, int numStr, va_list &args); 782 void initDialogueSequence(); 783 void restoreAfterDialogueSequence(); 784 void drawSequenceBitmap(const char *file, int destRect, int x1, int y1, int flags); 785 int runDialogue(int dialogueTextId, int numStr, ...); 786 787 char _dialogueLastBitmap[13]; 788 int _moveCounter; 789 790 const char *const *_chargenStatStrings; 791 const char *const *_chargenRaceSexStrings; 792 const char *const *_chargenClassStrings; 793 const char *const *_chargenAlignmentStrings; 794 795 const char *const *_pryDoorStrings; 796 const char *const *_warningStrings; 797 798 const char *const *_ripItemStrings; 799 const char *const *_cursedString; 800 const char *const *_enchantedString; 801 const char *const *_magicObjectStrings; 802 const char *const *_magicObjectString5; 803 const char *const *_patternSuffix; 804 const char *const *_patternGrFix1; 805 const char *const *_patternGrFix2; 806 const char *const *_validateArmorString; 807 const char *const *_validateCursedString; 808 const char *const *_validateNoDropString; 809 const char *const *_potionStrings; 810 const char *const *_wandStrings; 811 const char *const *_itemMisuseStrings; 812 813 const char *const *_suffixStringsRings; 814 const char *const *_suffixStringsPotions; 815 const char *const *_suffixStringsWands; 816 817 const char *const *_takenStrings; 818 const char *const *_potionEffectStrings; 819 820 const char *const *_yesNoStrings; 821 const char *const *_npcMaxStrings; 822 const char *const *_okStrings; 823 const char *const *_npcJoinStrings; 824 const char *const *_cancelStrings; 825 const char *const *_abortStrings; 826 827 // Rest party 828 void restParty_displayWarning(const char *str); 829 bool restParty_updateMonsters(); 830 int restParty_getCharacterWithLowestHp(); 831 bool restParty_checkHealSpells(int charIndex); 832 bool restParty_checkSpellsToLearn(); restParty_npc()833 virtual void restParty_npc() {} 834 virtual bool restParty_extraAbortCondition(); 835 836 // misc 837 void delay(uint32 millis, bool doUpdate = false, bool isMainLoop = false); 838 839 void displayParchment(int id); 840 int countResurrectionCandidates(); 841 842 void seq_portal(); 843 bool checkPassword(); 844 845 Common::String convertAsciiToSjis(Common::String str); 846 847 virtual int resurrectionSelectDialogue() = 0; useHorn(int charIndex,int weaponSlot)848 virtual void useHorn(int charIndex, int weaponSlot) {} 849 virtual bool checkPartyStatusExtra() = 0; drawLightningColumn()850 virtual void drawLightningColumn() {} charSelectDialogue()851 virtual int charSelectDialogue() { return -1; } characterLevelGain(int charIndex)852 virtual void characterLevelGain(int charIndex) {} 853 854 Common::Error loadGameState(int slot); 855 Common::Error saveGameStateIntern(int slot, const char *saveName, const Graphics::Surface *thumbnail); 856 857 const uint8 *_cgaMappingDefault; 858 const uint8 *_cgaMappingAlt; 859 const uint8 *_cgaMappingInv; 860 const uint8 *_cgaMappingItemsL; 861 const uint8 *_cgaMappingItemsS; 862 const uint8 *_cgaMappingThrown; 863 const uint8 *_cgaMappingIcons; 864 const uint8 *_cgaMappingDeco; 865 const uint8 *_cgaMappingLevel[5]; 866 const uint8 *_cgaLevelMappingIndex; 867 868 bool _enableHiResDithering; 869 870 // Default parameters will import all present original save files and push them to the top of the save dialog. 871 bool importOriginalSaveFile(int destSlot, const char *sourceFile = 0); 872 Common::String readOriginalSaveFile(Common::String &file); 873 bool saveAsOriginalSaveFile(int slot = -1); 874 875 void *generateMonsterTempData(LevelTempData *tmp); 876 void restoreMonsterTempData(LevelTempData *tmp); 877 void releaseMonsterTempData(LevelTempData *tmp); 878 void *generateWallOfForceTempData(LevelTempData *tmp); 879 void restoreWallOfForceTempData(LevelTempData *tmp); 880 void releaseWallOfForceTempData(LevelTempData *tmp); 881 882 const char *const *_saveLoadStrings; 883 884 const uint8 *_mnDef; 885 const char *const *_mnWord; 886 const char *const *_mnPrompt; 887 int _mnNumWord; 888 889 int _rrCount; 890 const char *_rrNames[10]; 891 int8 _rrId[10]; 892 893 bool _allowSkip; 894 bool _allowImport; 895 896 Screen_EoB *_screen; 897 GUI_EoB *_gui; 898 899 // fight 900 void useSlotWeapon(int charIndex, int slotIndex, Item item); 901 int closeDistanceAttack(int charIndex, Item item); 902 int thrownAttack(int charIndex, int slotIndex, Item item); 903 int projectileWeaponAttack(int charIndex, Item item); 904 905 void inflictMonsterDamage(EoBMonsterInPlay *m, int damage, bool giveExperience); 906 void calcAndInflictMonsterDamage(EoBMonsterInPlay *m, int times, int pips, int offs, int flags, int savingThrowType, int savingThrowEffect); 907 void calcAndInflictCharacterDamage(int charIndex, int times, int itemOrPips, int useStrModifierOrBase, int flags, int savingThrowType, int savingThrowEffect); 908 int calcCharacterDamage(int charIndex, int times, int itemOrPips, int useStrModifierOrBase, int flags, int savingThrowType, int damageType); 909 void inflictCharacterDamage(int charIndex, int damage); 910 911 bool characterAttackHitTest(int charIndex, int monsterIndex, int item, int attackType); 912 bool monsterAttackHitTest(EoBMonsterInPlay *m, int charIndex); 913 bool flyingObjectMonsterHit(EoBFlyingObject *fo, int monsterIndex); 914 bool flyingObjectPartyHit(EoBFlyingObject *fo); 915 916 void monsterCloseAttack(EoBMonsterInPlay *m); 917 void monsterSpellCast(EoBMonsterInPlay *m, int type); 918 void statusAttack(int charIndex, int attackStatusFlags, const char *attackStatusString, int savingThrowType, uint32 effectDuration, int restoreEvent, int noRefresh); 919 920 int calcMonsterDamage(EoBMonsterInPlay *m, int times, int pips, int offs, int flags, int savingThrowType, int savingThrowEffect); 921 int calcDamageModifers(int charIndex, EoBMonsterInPlay *m, int item, int itemType, int useStrModifier); 922 bool trySavingThrow(void *target, int hpModifier, int level, int type, int race); 923 bool specialAttackSavingThrow(int charIndex, int type); 924 int getSaveThrowModifier(int hpModifier, int level, int type); 925 bool calcDamageCheckItemType(int itemType); 926 int savingThrowReduceDamage(int savingThrowEffect, int damage); 927 bool tryMonsterAttackEvasion(EoBMonsterInPlay *m); 928 int getStrHitChanceModifier(int charIndex); 929 int getStrDamageModifier(int charIndex); 930 int getDexHitChanceModifier(int charIndex); 931 int getMonsterAcHitChanceModifier(int charIndex, int monsterAc); 932 void explodeMonster(EoBMonsterInPlay *m); 933 934 int _dstMonsterIndex; 935 bool _preventMonsterFlash; 936 int16 _foundMonstersArray[5]; 937 int8 _monsterBlockPosArray[6]; 938 const uint8 *_monsterAcHitChanceTable1; 939 const uint8 *_monsterAcHitChanceTable2; 940 941 // magic 942 void useMagicBookOrSymbol(int charIndex, int type); 943 void useMagicScroll(int charIndex, int type, int weaponSlot); 944 void usePotion(int charIndex, int weaponSlot); 945 void useWand(int charIndex, int weaponSlot); 946 turnUndeadAuto()947 virtual void turnUndeadAuto() {} 948 virtual void turnUndeadAutoHit() = 0; 949 950 void castSpell(int spell, int weaponSlot); 951 void removeCharacterEffect(int spell, int charIndex, int showWarning); 952 void removeAllCharacterEffects(int charIndex); 953 void castOnWhomDialogue(); 954 void startSpell(int spell); 955 956 void sparkEffectDefensive(int charIndex); 957 void sparkEffectOffensive(); 958 void setSpellEventTimer(int spell, int timerBaseFactor, int timerLength, int timerLevelFactor, int updateExistingTimer); 959 void sortCharacterSpellList(int charIndex); 960 961 bool magicObjectDamageHit(EoBFlyingObject *fo, int dcTimes, int dcPips, int dcOffs, int level); 962 bool magicObjectStatusHit(EoBMonsterInPlay *m, int type, bool tryEvade, int mod); 963 bool turnUndeadHit(EoBMonsterInPlay *m, int hitChance, int casterLevel); 964 void causeWounds(int dcTimes, int dcPips, int dcOffs); 965 966 int getMagicWeaponSlot(int charIndex); 967 int createMagicWeaponType(int invFlags, int handFlags, int armorClass, int allowedClasses, int dmgNum, int dmgPips, int dmgInc, int extraProps); 968 Item createMagicWeaponItem(int flags, int icon, int value, int type); 969 void removeMagicWeaponItem(Item item); 970 971 void updateWallOfForceTimers(); 972 void destroyWallOfForce(int index); 973 974 int findSingleSpellTarget(int dist); 975 976 int findFirstCharacterSpellTarget(); 977 int findNextCharacterSpellTarget(int curCharIndex); 978 int charDeathSavingThrow(int charIndex, int div); 979 980 void printWarning(const char *str); 981 void printNoEffectWarning(); 982 spellCallback_start_empty()983 void spellCallback_start_empty() {} spellCallback_end_empty(void *)984 bool spellCallback_end_empty(void *) { return true; } 985 void spellCallback_start_armor(); 986 void spellCallback_start_burningHands(); 987 void spellCallback_start_detectMagic(); 988 bool spellCallback_end_detectMagic(void *); 989 void spellCallback_start_magicMissile(); 990 bool spellCallback_end_magicMissile(void *obj); 991 void spellCallback_start_shockingGrasp(); 992 bool spellCallback_end_shockingGraspFlameBlade(void *obj); 993 void spellCallback_start_improvedIdentify(); 994 void spellCallback_start_melfsAcidArrow(); 995 bool spellCallback_end_melfsAcidArrow(void *obj); 996 void spellCallback_start_dispelMagic(); 997 void spellCallback_start_fireball(); 998 bool spellCallback_end_fireball(void *obj); 999 void spellCallback_start_flameArrow(); 1000 bool spellCallback_end_flameArrow(void *obj); 1001 void spellCallback_start_holdPerson(); 1002 bool spellCallback_end_holdPerson(void *obj); 1003 void spellCallback_start_lightningBolt(); 1004 bool spellCallback_end_lightningBolt(void *obj); 1005 void spellCallback_start_vampiricTouch(); 1006 bool spellCallback_end_vampiricTouch(void *obj); 1007 void spellCallback_start_fear(); 1008 void spellCallback_start_iceStorm(); 1009 bool spellCallback_end_iceStorm(void *obj); 1010 void spellCallback_start_stoneSkin(); 1011 void spellCallback_start_removeCurse(); 1012 void spellCallback_start_coneOfCold(); 1013 void spellCallback_start_holdMonster(); 1014 bool spellCallback_end_holdMonster(void *obj); 1015 void spellCallback_start_wallOfForce(); 1016 void spellCallback_start_disintegrate(); 1017 void spellCallback_start_fleshToStone(); 1018 void spellCallback_start_stoneToFlesh(); 1019 void spellCallback_start_trueSeeing(); 1020 bool spellCallback_end_trueSeeing(void *); 1021 void spellCallback_start_slayLiving(); 1022 void spellCallback_start_powerWordStun(); 1023 void spellCallback_start_causeLightWounds(); 1024 void spellCallback_start_cureLightWounds(); 1025 void spellCallback_start_aid(); 1026 bool spellCallback_end_aid(void *obj); 1027 void spellCallback_start_flameBlade(); 1028 void spellCallback_start_slowPoison(); 1029 bool spellCallback_end_slowPoison(void *obj); 1030 void spellCallback_start_createFood(); 1031 void spellCallback_start_removeParalysis(); 1032 void spellCallback_start_causeSeriousWounds(); 1033 void spellCallback_start_cureSeriousWounds(); 1034 void spellCallback_start_neutralizePoison(); 1035 void spellCallback_start_causeCriticalWounds(); 1036 void spellCallback_start_cureCriticalWounds(); 1037 void spellCallback_start_flameStrike(); 1038 bool spellCallback_end_flameStrike(void *obj); 1039 void spellCallback_start_raiseDead(); 1040 void spellCallback_start_harm(); 1041 void spellCallback_start_heal(); 1042 void spellCallback_start_layOnHands(); 1043 void spellCallback_start_turnUndead(); 1044 bool spellCallback_end_monster_lightningBolt(void *obj); 1045 bool spellCallback_end_monster_fireball1(void *obj); 1046 bool spellCallback_end_monster_fireball2(void *obj); 1047 bool spellCallback_end_monster_deathSpell(void *obj); 1048 bool spellCallback_end_monster_disintegrate(void *obj); 1049 bool spellCallback_end_monster_causeCriticalWounds(void *obj); 1050 bool spellCallback_end_monster_fleshToStone(void *obj); 1051 1052 int8 _openBookSpellLevel; 1053 int8 _openBookSpellSelectedItem; 1054 int8 _openBookSpellListOffset; 1055 uint8 _openBookChar; 1056 uint8 _openBookType; 1057 uint8 _openBookCharBackup; 1058 uint8 _openBookTypeBackup; 1059 uint8 _openBookCasterLevel; 1060 const char *const *_openBookSpellList; 1061 int8 *_openBookAvailableSpells; 1062 uint8 _activeSpellCharId; 1063 uint8 _activeSpellCharacterPos; 1064 int _activeSpell; 1065 int _characterSpellTarget; 1066 bool _returnAfterSpellCallback; 1067 1068 typedef void (EoBCoreEngine::*SpellStartCallback)(); 1069 typedef bool (EoBCoreEngine::*SpellEndCallback)(void *obj); 1070 1071 struct EoBSpell { 1072 const char *name; 1073 SpellStartCallback startCallback; 1074 uint16 flags; 1075 const uint16 *timingPara; 1076 SpellEndCallback endCallback; 1077 uint8 sound; 1078 uint32 effectFlags; 1079 uint16 damageFlags; 1080 }; 1081 1082 EoBSpell *_spells; 1083 int _numSpells; 1084 1085 struct WallOfForce { 1086 uint16 block; 1087 uint32 duration; 1088 }; 1089 1090 WallOfForce *_wallsOfForce; 1091 1092 const char *const *_bookNumbers; 1093 const char *const *_mageSpellList; 1094 int _mageSpellListSize; 1095 int _clericSpellOffset; 1096 const char *const *_clericSpellList; 1097 const char *const *_spellNames; 1098 const char *const *_magicStrings1; 1099 const char *const *_magicStrings2; 1100 const char *const *_magicStrings3; 1101 const char *const *_magicStrings4; 1102 const char *const *_magicStrings6; 1103 const char *const *_magicStrings7; 1104 const char *const *_magicStrings8; 1105 const char *const *_magicStrings9; 1106 1107 uint8 *_spellAnimBuffer; 1108 1109 const uint8 *_sparkEffectDefSteps; 1110 const uint8 *_sparkEffectDefSubSteps; 1111 const uint8 *_sparkEffectDefShift; 1112 const uint8 *_sparkEffectDefAdd; 1113 const uint8 *_sparkEffectDefX; 1114 const uint8 *_sparkEffectDefY; 1115 const uint32 *_sparkEffectOfFlags1; 1116 const uint32 *_sparkEffectOfFlags2; 1117 const uint8 *_sparkEffectOfShift; 1118 const uint8 *_sparkEffectOfX; 1119 const uint8 *_sparkEffectOfY; 1120 1121 const uint8 *_magicFlightObjectProperties; 1122 const uint8 *_turnUndeadEffect; 1123 const uint8 *_burningHandsDest; 1124 const int8 *_coneOfColdDest1; 1125 const int8 *_coneOfColdDest2; 1126 const int8 *_coneOfColdDest3; 1127 const int8 *_coneOfColdDest4; 1128 const uint8 *_coneOfColdGfxTbl; 1129 int _coneOfColdGfxTblSize; 1130 1131 // Menu 1132 EoBMenuDef *_menuDefs; 1133 const EoBMenuButtonDef *_menuButtonDefs; 1134 1135 bool _configMouse; 1136 bool _config2431; 1137 1138 const char *const *_menuStringsMain; 1139 const char *const *_menuStringsSaveLoad; 1140 const char *const *_menuStringsOnOff; 1141 const char *const *_menuStringsSpells; 1142 const char *const *_menuStringsRest; 1143 const char *const *_menuStringsDrop; 1144 const char *const *_menuStringsExit; 1145 const char *const *_menuStringsStarve; 1146 const char *const *_menuStringsScribe; 1147 const char *const *_menuStringsDrop2; 1148 const char *const *_menuStringsHead; 1149 const char *const *_menuStringsPoison; 1150 const char *const *_menuStringsMgc; 1151 const char *const *_menuStringsPrefs; 1152 const char *const *_menuStringsRest2; 1153 const char *const *_menuStringsRest3; 1154 const char *const *_menuStringsRest4; 1155 const char *const *_menuStringsDefeat; 1156 const char *_errorSlotEmptyString; 1157 const char *_errorSlotNoNameString; 1158 const char *_menuOkString; 1159 const char *const *_2431Strings; 1160 const char *const *_katakanaLines; 1161 const char *const *_katakanaSelectStrings; 1162 const char *const *_menuStringsTransfer; 1163 const char *const *_transferStringsScummVM; 1164 const char *const *_menuStringsSpec; 1165 const char *const *_menuStringsSpellNo; 1166 const char *const *_menuYesNoStrings; 1167 const char *const *_saveNamePatterns; 1168 1169 const uint8 *_spellLevelsMage; 1170 int _spellLevelsMageSize; 1171 const uint8 *_spellLevelsCleric; 1172 int _spellLevelsClericSize; 1173 const uint8 *_numSpellsCleric; 1174 const uint8 *_numSpellsWisAdj; 1175 const uint8 *_numSpellsPal; 1176 const uint8 *_numSpellsMage; 1177 1178 // sound 1179 void snd_playSong(int id); 1180 void snd_playSoundEffect(int id, int volume=0xFF); 1181 void snd_stopSound(); 1182 void snd_fadeOut(int del = 160); 1183 virtual void snd_loadAmigaSounds(int level, int sub) = 0; 1184 1185 const char **_amigaSoundMap; 1186 const char *const *_amigaLevelSoundList1; 1187 const char *const *_amigaLevelSoundList2; 1188 1189 int _amigaCurSoundFile; 1190 1191 // keymap 1192 static const char *const kKeymapName; 1193 }; 1194 1195 } // End of namespace Kyra 1196 1197 #endif // ENABLE_EOB 1198 1199 #endif 1200