1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
|
/*
* PROPRIETARY INFORMATION. This software is proprietary to POWDER
* Development, and is not to be reproduced, transmitted, or disclosed
* in any way without written permission.
*
* Produced by: Jeff Lait
*
* POWDER Development
*
* NAME: creature.h ( POWDER Library, C++ )
*
* COMMENTS:
* This provides the definition of all mob types. Individual
* instances are copied out of the main ROM table so they can store
* their non-static data.
*/
#ifndef __creature_h__
#define __creature_h__
#include "grammar.h"
#include "glbdef.h"
#include "intrinsic.h"
#include "mobref.h"
#include "name.h"
#include "speed.h"
#include "map.h"
class ITEM;
class SRAMSTREAM;
class MOB;
// One time mob initialization.
void mob_init();
// AI initialization, resetting, saving, loading
void ai_init();
void ai_reset();
// invoked by save/loadGlobal
void ai_save(SRAMSTREAM &os);
void ai_load(SRAMSTREAM &is);
//
// Used for the drag and drop menu system to go to and from u8 and
// our action/spell values.
// These are usually tied to actions, hence their presence here.
//
u8 action_packStripButton(ACTION_NAMES action);
u8 action_packStripButton(SPELL_NAMES spell);
void action_unpackStripButton(u8 value, ACTION_NAMES &action, SPELL_NAMES &spell);
// The grey value will be 0 if this sprite isn't useable, so should be grey
// to 256 for a fully charged sprite.
SPRITE_NAMES action_spriteFromStripButton(u8 value, int *grey = 0);
void action_indexToOverlayPos(int index, int &x, int &y);
// Kill counters.
extern u16 glbKillCount[NUM_MOBS];
// Inventory size...
#define MOBINV_WIDTH 12
#define MOBINV_HEIGHT 8
// AI State variables. These are volatile
#define AI_DIRTY_INVENTORY 0x8000
#define AI_HAS_THROWABLE 0x4000
#define AI_HAS_ATTACKWAND 0x2000
#define AI_HAS_EDIBLE 0x1000
#define AI_LAST_HIT_LOC 0x03ff
// AI FSM Modes. This is non-volatile.
#define AI_FSM_NORMAL 0
#define AI_FSM_ATTACK 1
#define AI_FSM_GUARD 2
#define AI_FSM_STAY 3
#define AI_FSM_JUSTBORN 4
// Intrinsic source flags
#define INTRINSIC_FROM_ITEM 1
#define INTRINSIC_FROM_PERMAMENT 2
#define INTRINSIC_FROM_TEMPORARY 4
class INTRINSIC_COUNTER
{
public:
#ifdef STRESS_TEST
~INTRINSIC_COUNTER()
{
// Verify that we are no longer referenced by anyone.
if (glbCurLevel)
glbCurLevel->verifyCounterGone(this);
}
#endif
INTRINSIC_NAMES myIntrinsic;
int myTurns;
INTRINSIC_COUNTER *myNext;
// Tracks who put this counter on!
MOBREF myInflictor;
};
// Instance of a mob.
// Do not make this virtual or you will have misunderstood the
// point of the exercise!
class MOB
{
private:
MOB(); // Create mobs with ::create please.
public:
~MOB();
// Resets all the mob counts, such as the number of creatures slain,
// etc.
static void init();
// Loads & saves the global state.
static void saveGlobal(SRAMSTREAM &os);
static void loadGlobal(SRAMSTREAM &is);
// The avatar is the special mob through which everything is viewed.
// It also gets the pronoun "you".
static MOB *getAvatar();
static void setAvatar(MOB *mob);
static void saveAvatar(SRAMSTREAM &os);
static void loadAvatar(SRAMSTREAM &is);
// Mobs can belong to lists...
MOB *getNext() { return myNext; }
void setNext(MOB *mob) { myNext = mob; }
bool isAvatar() const { return getAvatar() == this; }
static bool isAvatarOnFreshSquare() { return ourAvatarOnFreshSquare; }
static void setAvatarOnFreshSquare(bool fresh)
{ ourAvatarOnFreshSquare = fresh; }
// Are we currently polymorphed?
bool isPolymorphed() const { return !myBaseType.isNull(); }
// Returns the base creature type. This is what you are
// before polymorphing.
MOB *getBaseType() const { return myBaseType.getMob(); }
// Get our MOBREF. Pass by reference to minimize reconstruction.
// DO NOT USE THIS. Instead, use MOBREF.setMob(this), which has
// the advantage of dealing with the MOB * being null.
const MOBREF &getMobRef() const { return myOwnRef; }
// This alert tells us to invalidate any references to the given mob.
void alertMobGone(MOB *mob);
// This clears all the references on this mob as a result of it
// being unregistered from a map.
void clearReferences();
static MOB *create(MOB_NAMES definition);
// Equips self with an ascension worthy set of equipment/abilities.
void buildAscensionKit();
// Creates a new mob, possibly updating the avatar.
static MOB *load(SRAMSTREAM &is);
// Writes out mob data...
void save(SRAMSTREAM &os);
// Verifies our MOBREFs are valid.
// Reports 0 if nulls, ! if bad link.
bool verifyMob() const;
// Verifies that we don't see the given INTRINISC_COUNTER anywhere.
bool verifyCounterGone(INTRINSIC_COUNTER *counter) const;
// Chooses an NPC def given a threat level
static MOB_NAMES chooseNPC(int threatlevel);
// Creates an NPC given a threat level.
static MOB *createNPC(int threatlevel);
// Turn this mob into a unique.
// This should be done just after create!
void makeUnique();
// Is the mob physically capable of being on the given square.
// checksafety will prohibit squares that will damage the
// critter.
bool canMove(int nx, int ny, bool checkitem,
bool allowdoor = false,
bool checksafety = false) const;
// Checks if the mob can move through a diagonal passage. We
// prohibit kiddie-corner style moves. If dx and dy are not both
// non-zero, turns into a normal canMove.
// In case of diagonal, the orthogonal passages are only tested
// for MOVE flags, not for bolders, mobs, safety, etc.
bool canMoveDelta(int dx, int dy, bool checkitem,
bool allowdoor = false,
bool checksafety = false) const;
// This returns true if this is aware of mob. This means that:
// A) this cannot see, has telepathy, and mob has a mind.
// B) this can see, mob is visible, has los, and mob is lit
// C) this can see, can see invisible, mob is invisible, has los, and lit.
// D) if either party is in a pit, the distance is 1.
// E) both parties are same submerge state.
// F) not deaf, noiselevel of other critter is high enough
// G) has warning, other creature in range.
// The LOS check is skipped if checklos = false.
// If only sight is true, only sight checks are made.
bool canSense(const MOB *mob, bool checklos = true, bool onlysight = false) const;
// Returns *how* you can sense the given mob.
SENSE_NAMES getSenseType(const MOB *mob) const;
// This is the movement mask we currently can do, modified by items,
// etc.
MOVE_NAMES getMoveType() const;
int getX() const { return myX; }
int getY() const { return myY; }
int getDLevel() const { return myDLevel; }
void setDLevel(int d) { myDLevel = d; }
int getTile() const; // This is Upper left.
int getTileLL() const;
int getTileLR() const;
int getTileUR() const;
MOB_NAMES getDefinition() const { return (MOB_NAMES) myDefinition; }
void setOrigDefinition(MOB_NAMES origdefn) { myOrigDefinition = origdefn; }
// Changes our internal & original type. If reset, we wipe
// out our mp/hp type stats.
void changeDefinition(MOB_NAMES newdefn, bool reset);
MOBTYPE_NAMES getMobType() const { return (MOBTYPE_NAMES) glb_mobdefs[myDefinition].mobtype; }
const MOB_DEF &defn() const { return defn(getDefinition()); }
static const MOB_DEF &defn(MOB_NAMES mob) { return glb_mobdefs[mob]; }
int getHP() const { return myHP; }
int getMaxHP() const { return myMaxHP; }
void incrementMaxHP(int amount);
void setMinimalHP() { myHP = 1; }
void setMaximalHP() { myHP = myMaxHP; }
void forceHP(int hp) { myMaxHP = myHP = hp; }
int getHitDie() const { return myHitDie / 2; }
void incrementHitDie(int amount) { myHitDie += amount*2; }
int getExpLevel() const { return myExpLevel; }
int getMP() const { return myMP; }
int getMaxMP() const { return myMaxMP; }
void incrementMaxMP(int amount);
int getMagicDie() const { return myMagicDie / 2; }
void incrementMagicDie(int amount) { myMagicDie += amount*2; }
int getExp() const { return myExp; }
int getStrength() const
{ return glb_mobdefs[myDefinition].strength; }
int getSmarts() const
{ return glb_mobdefs[myDefinition].smarts; }
SIZE_NAMES getSize() const { return (SIZE_NAMES)
glb_mobdefs[myDefinition].size; }
// This gets the maximum AC of the creature.
int getAC() const;
// Computes the score, only really sensible for the avatar
int calcScore(bool haswon) const;
// This properly rolls the AC to find out what it is for this
// particular hit.
int rollAC(MOB *attacker) const;
MATERIAL_NAMES getMaterial() const
{ return (MATERIAL_NAMES) glb_mobdefs[myDefinition].material; }
bool hasBreathAttack() const;
ATTACK_NAMES getBreathAttack() const;
bool isBreathAttackCharged() const;
int getBreathRange() const;
const char *getBreathSubstance() const;
bool isTalkative() const;
void submergeItemEffects(SQUARE_NAMES tile);
bool hasItem(ITEM_NAMES def) const;
// This finds out if the mob emits light, and if so, how far.
bool isLight() const;
int getLightRadius() const;
// Determines if we are allowed to move on diagonals
// (obscure reference to diabolizing matrices)
bool canMoveDiabolically() const;
bool canResurrectFromCorpse() const;
bool isBoneless() const;
bool isBloodless() const;
void setAIFSM(int fsm) { myAIFSM = fsm; }
void setAITarget(MOB *mob) { myAITarget.setMob(mob); }
void clearAITarget() { myAITarget.setMob(0); }
MOB *getAITarget() const { return myAITarget.getMob(); }
// Returns the master of this mob. This is who the mob
// immediately reports to
MOB *getMaster() const;
// Returns true if this mob is at some level a slave of the given
// critter.
// You are not a slave to yourself.
bool isSlave(const MOB *owner) const;
// Makes this a slave of the given master.
void makeSlaveOf(const MOB *owner);
// Returns true if we have a common master.
bool hasCommonMaster(const MOB *other) const;
bool hasIntrinsic(INTRINSIC_NAMES intrinsic, bool allowitem=true) const;
// Return bit field showing all sources of the intrinsic
int intrinsicFromWhat(INTRINSIC_NAMES intrinsic) const;
// Return a string giving the identifier for the intrinsic source
const char *intrinsicFromWhatLetter(INTRINSIC_NAMES intrinsic) const;
// These just chain to the relevant intrinsic, but allow for
// more legible code.
bool hasSkill(SKILL_NAMES skill, bool allowitem=true, bool ignoreamnesia=false) const;
bool hasSpell(SPELL_NAMES spell, bool allowitem=true, bool ignoreamnesia=false) const;
// Rolls to see if the given skill meets its proc chance
bool skillProc(SKILL_NAMES skill) const;
// These determine if you have the necessary prereqs.
// If explain is true, the list of failed prereqs is given.
bool canLearnSkill(SKILL_NAMES skill, bool explain=false) const;
int getUsedSkillSlots() const;
int getFreeSkillSlots() const;
bool canLearnSpell(SPELL_NAMES spell, bool explain=false) const;
int getUsedSpellSlots() const;
int getFreeSpellSlots() const;
void clearDeathIntrinsics(bool silent);
bool canDigest(ITEM *item) const;
bool safeToDigest(ITEM *item) const;
bool canFly() const;
// Return true if anything we are wearing is made of that material.
bool isWearing(MATERIAL_NAMES material) const;
// Sorts our linked list invenroy to match the expected slot
// order
void sortInventoryBySlot();
// This sets the intrinsic permamently & instantly.
void setIntrinsic(INTRINSIC_NAMES intrinsic);
// Merges into our intrinsic all those in the given string
void mergeIntrinsicsFromString(const char *rawstr);
// This removes the intrinsic. It does so instantly & permamently.
void clearIntrinsic(INTRINSIC_NAMES intrinsic, bool silent=false);
// This sets the given intrinsic for the given number of turns.
// Turns are eaten every heartbeat.
// If the intrinsic is already on permamently, it doesn't affect
// anything.
// We are not guaranteed to return a counter.
// If quiet is set, we never announce the gain/loss
void setTimedIntrinsic(MOB *inflictor,
INTRINSIC_NAMES intrinsic, int turns,
bool quiet = false);
int getAttackBonus(const ATTACK_DEF *attack, ATTACKSTYLE_NAMES style);
// Returns the probability, 0..100 inclusive, that the second
// weapon should be allowed to proc.
// This is zero if there is no second weapon, etc.
int getSecondWeaponChance() const;
// This gets THIS mobs attitude towards APPRAISEE.
ATTITUDE_NAMES getAttitude(const MOB *appraisee) const;
AI_NAMES getAI() const
{ return (AI_NAMES) glb_mobdefs[myDefinition].ai; }
// Move the mob into the given tile, updating the gfx map &
// applying any relevant callbacks.
// Note the new mob x/y is not necessarily nx ny!
// Returns false if the creature is now dead.
bool move(int nx, int ny, bool interlevel = false);
// This runs all the every-turn things this mob should do. This will
// cause the mob to age, consume food, regain magic & hits, etc. This
// is often in the MOBs time frame, not the world time frame, so usually
// occurs before the mob's AI frame (so faster mobs consume faster)
// This returns true if the mob can still perform an action. It
// returns false if the mob's ai should be skipped (eg: the mob died)
bool doHeartbeat();
// This finds a random dx,dy pair for which canMove returns true.
// The move will not move into the owner.
void findRandomValidMove(int &dx, int &dy, MOB *owner);
// Determines if the creature is confused. It then will adjust
// the dx, dy, and dz values appropriately. It does the random
// chance to keep the original decision.
// Care must be taken to not end up with double jeopardy.
void applyConfusion(int &dx, int &dy);
void applyConfusionNoSelf(int &dx, int &dy);
void applyConfusion(int &dx, int &dy, int &dz);
// Returns number of foes that are melee adjacent,
// does not count friends, sleeping, or paralysed.
int calculateFoesSurrounding() const;
// Returns true if this mob should doAI on the given phase.
bool validMovePhase(PHASE_NAMES phase);
// This does the prequel actions prior to the creature getting its
// move. It's move would either be the user action or the doAI
// action.
// true is returned if the user should act, false if the prequel
// ate their action.
bool doMovePrequel();
// AI: All ai prefixed functions, along with doAI, are found in
// ai.cpp.
//
// This runs the AI script on this MOB, which will cause it to run
// some action or another.
void doAI();
// Returns true if we successfully move in the given direction.
// We will try and jump if possible.
// actionBump will be used, but blockers will be avoided.
// if target mob blocks, an attack will still be made.
// This can handle dx & dy both being non zero, in which case it
// picks one of them.
bool aiMoveInDirection(int dx, int dy, int distx, int disty,
MOB *target);
// Decays knowledge of us.
void aiDecayKnowledgeBase();
// Returns true if we know that the given target has a resistance
// to the element. This means we should likely not bother with
// an attack based on that element.
bool aiCanTargetResist(MOB *target, ELEMENT_NAMES element) const;
// Tries to note that the given target has the given intrinsic,
// internally tranforms into a call to CanResist.
void aiNoteThatTargetHasIntrinsic(MOB *target, INTRINSIC_NAMES intrinsic);
// Tries to note that the given target can resist the given element
void aiNoteThatTargetCanResist(MOB *target, ELEMENT_NAMES element);
// Internal function when we've passed the tests.
void aiTrulyNoteThatTargetCanResist(MOB *target, ELEMENT_NAMES element);
// Returns true if acted.
// Searches inventory for useful items and uses them.
bool aiUseInventory();
// Picks up whatever is on the ground.
bool aiBePackrat();
// Searches through one's invenotry for yummy stuff and eats it.
bool aiEatStuff();
// Tries to leave melee combat through teleportation, etc.
// Only does so if it decides it's unsafe (low hp, etc)
bool aiDoFleeMelee(MOB *target);
// Looks for any battle preperations it can do. Ie, casting
// buffs, etc.
// The dx, dy is the offset to our target.
bool aiDoBattlePrep(int diffx, int diffy);
// Heal, cure, etc.
bool aiDoUrgentMoves();
// Specific action ai:
// Attacks: These will attack in the given direction at the
// given range.
bool aiDoRangedAttack(int dx, int dy, int range);
bool aiDoThrownAttack(int dx, int dy, int range);
bool aiDoWandAttack(int dx, int dy, int range);
bool aiDoSpellAttack(int dx, int dy, int range);
// Heals: These attempt to restore health/cure poison.
bool aiDoHealSelf();
bool aiDoCurePoisonSelf();
// This attempts to immerse onself in water.
bool aiDoDouseSelf();
// Attempts to freeze the square I stand on
bool aiDoFreezeMySquare();
// Try to get off my current square onto a safe square
bool aiDoEscapeMySquare();
// This will attempt to stop stoning, provided we care about it.
bool aiDoStopStoningSelf();
// Specific AI behaviours:
// Mice run around with the right hand rule getting into mischief.
bool aiDoMouse();
// Testing functions.
bool aiIsItemCooler(ITEM *item, ITEMSLOT_NAMES slot);
bool aiIsItemThrowable(ITEM *item, MOB *target = 0) const;
bool aiIsItemZapAttack(ITEM *item) const;
bool aiIsPoisoned() const;
bool aiWillOpenDoors() const;
// Actions... This is where all the creature smarts go. At the
// root is the actionBump - this is a request by a creature to go
// in a certain direction. What it means is creature dependent...
// Actions return true if they consumed a timeslot, and false if
// they failed.
// All of the "action" prefixed functions can be found in action.cpp.
bool actionBump(int dx, int dy);
// The creature uses its breath attack in the given direction.
bool actionBreathe(int dx, int dy);
// Note all these callbacks take a MOBREF * inside data!
static bool meltRocksCBStatic(int x, int y, bool final, void *data);
// The attack is in ourEffectAttack.
static bool areaAttackCBStatic(int x, int y, bool final, void *data);
// Spell is in ourZapSpell.
static bool zapCallbackStatic(int x, int y, bool final, void *data);
// This tries to swap with a creature in the given direction.
bool actionSwap(int dx, int dy);
// Talk to someone or something
bool actionTalk(int dx, int dy);
// Puts the mob to sleep for 50 turns.
bool actionSleep();
// This tries to push on the given direction.
bool actionPush(int dx, int dy);
// This will move in the given direction. It does no intelligence
// checks!
bool actionWalk(int dx, int dy, bool spacewalk = false);
// This will jump in the given direction. This will move you
// two squares. It can jump over things, but not through walls.
// Destination must be visible and lit.
bool actionJump(int dx, int dy);
// Applies the magic door effect, only valid for avatars.
// Coords are absolute location of magical door.
bool actionMagicDoorEffect(int x, int y);
// This will try to open the object in the given direction.
bool actionOpen(int dx, int dy);
// THis will try to close the object.
bool actionClose(int dx, int dy);
// This causes this MOB to search the given square, spamming
// the appropriate discovery and revealling it to the world.
// It returns true if anything was found.
// The isaction controls if it was purposeful or not. This affects
// the probability in dark areas. Darkness penalty only applies
// to purposeful search attempts. (Finding stuff accidentally is
// bad, so should be encouraged :>)
bool searchSquare(int x, int y, bool isaction);
// This searches at the square we are now on.
bool actionSearch();
// This will attack what is in the given direction.
bool actionAttack(int dx, int dy, int multiplierbonus = 0);
// This handles attempts to climb things.
bool actionClimb();
bool actionClimbUp();
bool actionClimbDown();
bool actionDig(int dx, int dy, int dz, int range, bool magical);
// Picks up whats on the floor.
// The specified item is which item to pickup.
// Note that picking up an item may destroy it when it merges
// with a stack, newitem will be set to the resulting item.
bool actionPickUp(ITEM *item, ITEM **newitem = 0);
// Tries to drop the given item.
bool actionDrop(int ix, int iy);
// Sorts the inventory items.
bool actionSort();
// Tries to eat.
// This doubles as drinking.
bool actionEat(int ix, int iy);
// Tries to throw.
bool actionThrow(int ix, int iy, int dx, int dy, int dz);
// Throws a quivered item.
bool actionFire(int dx, int dy, int dz);
// Puts the specified object into the quiver.
bool actionQuiver(int ix, int iy);
// Verifies you can zap
bool ableToZap(int ix, int iy, int dx, int dy, int dz, bool quiet);
// Tries to zap.
bool actionZap(int ix, int iy, int dx, int dy, int dz);
// Tries to cast.
bool actionCast(SPELL_NAMES spell, int dx, int dy, int dz);
// Verifies if you can read.
bool ableToRead(int ix, int iy, bool quiet);
// Tries to read.
bool actionRead(int ix, int iy);
// The potion is what to dip into, the i() is what to dip.
bool actionDip(int potionx, int potiony, int ix, int iy);
// This will cause you to query the gods as to your current
// status.
bool actionPray();
// Take control of given mob, only really works for avatar.
bool actionPossess(MOB *mob, int duration);
// Removes our possession and returns ourself to our original
// body, provided it exists.
bool actionReleasePossession(bool systemshock = false);
// This will perform a random teleport, unless the creature has
// teleport control, in which case it will use its own AI (or
// user input) for the destination.
// allowcontrol will enable teleport control to be tested.
// givecontrol will grant the creature telecontrol for this action.
// Xloc and yloc give the teleport destination, if present.
bool actionTeleport(bool allowcontrol=true, bool givecontrol=false,
int xloc=-1, int yloc=-1);
bool actionForget(SPELL_NAMES spell, SKILL_NAMES skill);
// UPdates our tile according to what we are wearing.
void rebuildAppearance();
// Update our worn intrinsic according to what we have equipped.
void rebuildWornIntrinsic();
// Determines how well dressed the creature is.
// per god amounts optionally stored in dressiness. 0 is nothing
// nice, no consistent maximum.
void determineClassiness(int *dressiness = 0);
// Verifies you can equip the item.
bool ableToEquip(int ix, int iy, ITEMSLOT_NAMES slot, bool quiet);
// Tries to equip the item in the given inventory slot.
bool actionEquip(int ix, int iy, ITEMSLOT_NAMES slot, bool quiet=false);
// Verifies you can remove the item.
bool ableToDequip(ITEMSLOT_NAMES slot, bool quiet);
// Tries to take off the item in the given slot.
bool actionDequip(ITEMSLOT_NAMES slot, bool quiet = false);
// Returns the total skill the creature has with the given
// armour or weapon.
int getWeaponSkillLevel(const ITEM *weapon,
ATTACKSTYLE_NAMES attackstyle) const;
int getArmourSkillLevel(const ITEM *armour) const;
// This records that src tried to attack us.
// We may choose to disregard this if we feel it is friendly fire,
// or currently have someone we hate more.
void noteAttacker(MOB *src);
// Receptor functions...
// The attacking item may be null, in which case the mob attacks
// alone.
// These return false if the creature dies.
// The actuallyhit is set to true if any attack landed.
// It is NOT set to false otherwise!
bool receiveAttack(ATTACK_NAMES attack, MOB *src, ITEM *weapon,
ITEM *launcher,
ATTACKSTYLE_NAMES style,
bool *actuallyhit = 0, int multiplier = 0);
bool receiveAttack(const ATTACK_DEF *attack, MOB *src, ITEM *weapon,
ITEM *launcher,
ATTACKSTYLE_NAMES style,
bool *actuallyhit = 0, int multiplier = 0);
bool receiveDamage(ATTACK_NAMES attack, MOB *src,
ITEM *weapon,
ITEM *launcher,
ATTACKSTYLE_NAMES style,
int multiplier = 1,
int damage_reduction = 0);
bool receiveDamage(const ATTACK_DEF *attack, MOB *src,
ITEM *weapon,
ITEM *launcher,
ATTACKSTYLE_NAMES style,
int multiplier = 1,
int damage_reduction = 0);
void receiveDeathExp(int explevel);
void receiveExp(int exp);
// Clears all experience: Ouch!
void wipeExp();
// Enchant a random piece of armour by the given amounts.
// ITEMSLOT_NAMES -1 means a random armour piece.
void receiveArmourEnchant(ITEMSLOT_NAMES slot, int bonus, bool shudder);
// Enchant your weapon.
void receiveWeaponEnchant(int bonus, bool shudder);
// Curses random item that isn't already cursed, starting with
// your equipped items.
// onlyequip true will ensure only equipped items will be cursed.
// forceany prevents the code from preferring equipped items.
void receiveCurse(bool onlyequip, bool forceany);
// Uncurses random cursed item, starting with equipped items.
// Doall true means it will uncurse everything.
void receiveUncurse(bool doall);
// Only update HP through these methods to ensure consistent treatment
// vampiric heals prevent Tlosh from growing angry.
bool receiveHeal(int hp, MOB *src, bool vampiric = false);
bool receiveMana(int mp, MOB *src);
bool receiveCure();
bool receiveSlowPoison();
SPELL_NAMES findSpell(GOD_NAMES god, int *numspell = 0) const;
SKILL_NAMES findSkill(GOD_NAMES god, int *numskill = 0) const;
void learnSpell(SPELL_NAMES spell, int duration = -1);
void learnSkill(SKILL_NAMES skill, int duration = -1);
// Returns if we are able to cast the spell, ie have enough mana,
// have the right intrinsic, etc.
bool canCastSpell(SPELL_NAMES spell);
// Returns how close we are to casting the spell. 0 means
// not possible, 256 we can cast it this instant.
int spellCastability(SPELL_NAMES spell);
void gainLevel();
// Undo casting cost of the spell.
void cancelSpell(SPELL_NAMES spell);
//
// piety functions. These are implemented in piety.cpp.
// They control the implicity worship given to one or more gods
// by just about any action.
//
// Currently only the avatar triggers these, but theoritically
// that could be expanded.
//
void pietyGainLevel();
void pietyKill(MOB *mob, ATTACKSTYLE_NAMES style);
void pietyEat(ITEM *item, int foodval);
void pietyDress(INTRINSIC_NAMES intrinsic);
void pietyZapWand(ITEM *wand);
void pietySurrounded(int numenemy);
void pietyHeal(int amount, bool self, bool enemy, bool vampiric);
void pietyCastSpell(SPELL_NAMES spell);
void pietyCreateTrap();
void pietyFindSecret();
void pietyAttack(MOB *mob, const ATTACK_DEF *attack,
ATTACKSTYLE_NAMES style);
// You made the given amount of noise.
void pietyMakeNoise(int noise);
// You identified something.
void pietyIdentify(ITEM_NAMES itemdef);
// Broke an item
void pietyBreak(ITEM *item);
// Prints out a report of the current piety levels of all gods.
void pietyReport();
// Announces the whim of xom if you are following ><0|V|
void pietyAnnounceWhimOfXom();
// Runs the god AI to determine what to do with the poor player.
void pietyRungods();
// Used to actually apply piety points to a given god.
void pietyGrant(GOD_NAMES god, int amount, bool forbidden = false);
// Applied when one performs a forbidden action.
void pietyTransgress(GOD_NAMES god);
// Applied to use up some god points in doling out punishment.
void pietyPunish(GOD_NAMES god);
// Applied to use up some god points in doling out rewards.
void pietyBoon(GOD_NAMES god);
// Returns true if the player can benefit from the given boon.
bool pietyBoonValid(BOON_NAMES boon);
// What sort of crappy comment is this?
// "The string can take certain parameters..."
void reportMessage(const char *str) const;
inline void reportMessage(BUF buf) const
{ reportMessage(buf.buffer()); }
// This reports a message with mob specific connotations:
// %U means the mob itself.
// %u means the mob itself without any article.
// %i means the item identified at class level
// %R means the possessive of the mob. (full name!)
// %r means the possessive, pronoun.
// %A means the accusative of the mob.
// %p means the pronoun.
// %M? means the mob, using the same code as above.
// %I? means the item, using the same code as above.
// %I1? means the singular item, using the same code as above.
// <foo> means to conjugate foo with this mob.
// <I:..> and <M:..> conjugate respectively.
// %B1, %B2, refer to an ancillary buffer with a specific
// numbering order.
void formatAndReport(const char *str);
void formatAndReport(const char *str, const char *b1, const char *b2 = 0, const char *b3 = 0);
inline void formatAndReport(const char *str, BUF b1)
{ formatAndReport(str, b1.buffer()); }
void formatAndReport(const char *str, const MOB *mob, const char *b1 = 0, const char *b2 = 0, const char *b3 = 0);
inline void formatAndReport(const char *str, const MOB *mob, BUF b1)
{ formatAndReport(str, mob, b1.buffer()); }
void formatAndReport(const char *str, const ITEM *item, const char *b1 = 0, const char *b2 = 0, const char *b3 = 0);
inline void formatAndReport(const char *str, const ITEM *item, BUF b1)
{ formatAndReport(str, item, b1.buffer()); }
void formatAndReportExplicit(const char *str, const MOB *mob, const ITEM *item, const char *b1 = 0, const char *b2 = 0, const char *b3 = 0);
inline void formatAndReportExplicit(const char *str, const MOB *mob, const ITEM *item, BUF b1)
{ formatAndReportExplicit(str, mob, item, b1.buffer()); }
static BUF formatToString(const char *str, const MOB *self, const ITEM *selfitem, const MOB *mob, const ITEM *item, const char *b1 = 0, const char *b2 = 0, const char *b3 = 0);
static BUF formatToString(const char *str, const MOB *self, const ITEM *selfitem, const MOB *mob, const ITEM *item, BUF b1, BUF b2, BUF b3);
// Conjugates a verb with our own tense. If this is an avatar,
// that means "You", otherwise "It".
BUF conjugate(const char *infinitive, bool past=false) const;
// This gets the tense which this mob should be addressed with, ie,
// me, you, he, she, it, they?
VERB_PERSON getPerson() const;
VERB_PERSON getGender() const;
// you, it, he, she, they, etc.
const char *getPronoun() const;
// your, its, his, her, their, etc.
const char *getPossessive() const;
// yours, its, his, hers, theirs, etc.
const char *getOwnership() const;
// yourself, itself, himself, herself, etc
const char *getReflexive() const;
// you, it, him, her, etc.
const char *getAccusative() const;
// dragon, the dragon, a dragon, etc.
BUF getName(bool usearticle = true, bool usedefinite = true,
bool forcevisible = false, bool neverpronoun = false) const;
// The headless is in perfect health. It would be a hard fight.
BUF getDescription() const;
// This displays the long description of this particular mob.
// It will also provide all the other cool facts, like what they
// are wearing, etc.
void viewDescription() const;
// Displays a character dump of the characters abilities.
// Also saves to a file on the PC version.
void characterDump(bool ondeath, bool didwin, bool savefile, int truetime = -1);
void pageCharacterDump(bool ondeath, bool didwin, int truetime = -1);
// Determines if this mob moved last turn. Only works
// for the avatar.
bool hasMovedLastTurn() const;
void getLastMoveDirection(int &dx, int &dy) const;
void resetLastMoveDirection() const;
void flagLastMoveAsOld() const;
// Rename the MOB this name.
void christen(const char *name);
void christen(BUF buf)
{ christen(buf.buffer()); }
// Perform a smarts/str check against the given difficulty.
// Result is:
// -1 - Guaranteed fail
// 0 - Failed a check.
// 1 - Succeeded check.
// 2 - Guaranteed success.
// One should have different text for each so people know if they
// should test again.
int smartsCheck(int smarts);
int strengthCheck(int str);
// Picks up an item, assigns it into a slot.
// Returns false if failed (item is there, or no room)
// Note that this *CAN* delete item! This occurs if it gets
// merged into a stack in the inventory.
bool acquireItem(ITEM *item, int sx, int sy, ITEM **newitem = 0);
bool acquireItem(ITEM *item, ITEM **newitem = 0);
// Finds first free item slot, returns false if none.
bool findItemSlot(int &sx, int &sy) const;
// Gets the item given a slot. Possible null.
ITEM *getItem(int sx, int sy) const;
// Returns a random item from our inventory, null if there are no
// items.
ITEM *randomItem() const;
// Unlinks & returns the item from the given slot.
ITEM *dropItem(int sx, int sy);
// Destroys all items in this inventory.
void destroyInventory();
// Reverses the order of our inventory. Theoritically this
// should be a no-op, but our quiver uses this order.
void reverseInventory();
// Drops one of the rings the creature is wearing, provide
// at least two rings are worn.
void dropOneRing();
// Gets the item from the specified equipped slot (same as
// getItem(0, (int)name)
ITEM *getEquippedItem(ITEMSLOT_NAMES slot) const;
// Determine if any item is equipped (faster than testing
// each slot in turn...)
bool hasAnyEquippedItems() const;
bool hasSlot(ITEMSLOT_NAMES slot) const;
// Note: May return 0 if there is no such slot!
const char *getSlotName(ITEMSLOT_NAMES slot) const;
// Returns the first equipped item, if any, that grants the
// given intrinsic.
ITEM *getSourceOfIntrinsic(INTRINSIC_NAMES intrinsic) const;
// Returns the mob that inflicted the timed intrinsic, if any.
MOB *getInflictorOfIntrinsic(INTRINSIC_NAMES intrinsic) const;
// This will create a new MOB for ourself.
// All stashed mob references will be transfered to the new mob.
// Polymorphing a morphed mob returns it to its original state.
bool actionPolymorph(bool allowcontrol = true,
bool forcecontrol = false,
MOB_NAMES newdef = MOB_NONE);
// This undoes the effect of polymorph.
bool actionUnPolymorph(bool silent = false,
bool systemshock = false);
// This turns the creature into stone.
bool actionPetrify();
// This usually does nothing :>
bool actionUnPetrify();
HUNGER_NAMES getHungerLevel() const;
void starve(int foodval);
void feed(int foodval);
// Applies system shock to this, 10% of maxhp lost
void systemshock();
// Attempts to save this creatures life. Does not attempt
// reverting to original form style saving, only INTRINSIC_LIFESAVED
// type saving.
// Returns true if critter saved, false if not saved. Will destroy
// source of saving.
bool attemptLifeSaving(const char *deathmsg);
// This marks this mob as having just died. This will increment
// the kill counts & also do proper victory stuff when the
// user gets axed.
// This does not mean any one gets the exp, or the mob won't be
// back. For example, kill/res loops will count, as will
// petrifies.
// becameitem flags if the monster died in a way in which it
// can come back
void triggerAsDeath(ATTACK_NAMES attack, MOB *src, ITEM *weapon, bool becameitem);
void triggerAsDeath(const ATTACK_DEF *attack, MOB *src, ITEM *weapon, bool becameitem);
// This adds the given noise to this mob.
void makeNoise(int noiselevel);
// This adds any noise from the given slot.
void makeEquipNoise(ITEMSLOT_NAMES slot);
// This reveals the amount of noise this mob is making.
// If the observer is null, it is the total noise. If it is
// a creature, it is a random number from 0 to max noise. The trick
// is that this will be the same for every call on this time slice
// and with this pair of critters.
int getNoiseLevel(const MOB *observer) const;
protected:
// Internal methods to handle intrinsic counters:
INTRINSIC_COUNTER *getCounter(INTRINSIC_NAMES intrinsic) const;
void removeCounter(INTRINSIC_NAMES intrinsic);
INTRINSIC_COUNTER *addCounter(MOB *inflictor,
INTRINSIC_NAMES intrinsic, int turns);
// myDefinition is what we are now. myOrigDefinition is
// what we were when we were created. Polymorph doesn't
// create this difference, stuff like ghastify does.
u8 myDefinition, myOrigDefinition;
u8 myX, myY, myExpLevel;
// These actually store twice our hit die to allow us to
// gain fractional levels.
u8 myHitDie, myMagicDie;
// This is the amount of noise the mob has made so far. Not saved.
u8 myNoiseLevel;
u8 myDLevel;
u8 myGender;
// Current state in AI FSM. Stored to disk.
u8 myAIFSM;
MOBREF myOwnRef;
// When we are polymorphed, this is non-null and holds the base critter
// type.
MOBREF myBaseType;
// Stores relevant AI state stuff. Not saved.
u16 myAIState;
// Food levels.
u16 myFoodLevel;
// Note, HP had better be able to go negative.
short myHP, myMaxHP;
short myMP, myMaxMP;
short myExp;
MOB *myNext;
// AI related state information:
MOBREF myAITarget;
NAME myName;
ITEM *myInventory;
INTRINSIC myIntrinsic;
INTRINSIC *myWornIntrinsic;
INTRINSIC_COUNTER *myCounters;
static s8 ourAvatarDx, ourAvatarDy;
static SPELL_NAMES ourZapSpell;
static ATTACK_NAMES ourEffectAttack;
static int ourFireBallCount;
static bool ourAvatarOnFreshSquare;
static bool ourAvatarMoveOld;
};
#endif
|