- [+] CRASH in killflag()

- [+] symptoms
        - [+] often happens right after creating a new map (ie. trigger
              it through a gate spell)
            - [+] bug in createriver(). fixed.
            - [+] somehow casting GATE is causing object flagpiles on
                  the PLAYER's map to become corrupted.
        - [+] "the young hawk wakes up" CRASH, flagpile corrupt on
              stone.
        - [+] object itself seems okay.
        - [+] o->flags is becoming corrupt!!!
            - [+] so all its flags are becoming corrupt (id = massive
                  number, next = fffff)
        - [+] traceback:
            - [+] #0  0x0000000100081188 in killflag (f=0x103321090) at
                  flag.c:815
                  #1  0x0000000100081b3a in timeeffectsflag
                  (f=0x103321090, howlong=1) at flag.c:1075
                  #2  0x00000001000825f8 in timeeffectsflags
                  (fp=0x1038e0600) at flag.c:1302
                  #3  0x0000000100129b01 in timeeffectsob
                  (o=0x1036e2460) at objects.c:11877
                  #4  0x0000000100005114 in timeeffectsworld
                  (map=0x102aa1a00, updategametime=-1) at nexus.c:1685
                  #5  0x0000000100003a28 in donextturn
                  (map=0x102aa1a00) at nexus.c:952
                  #6  0x00000001000029b1 in main (argc=1,
                  argv=0x7fff5fbff848) at nexus.c:525
        - [+] try this: in timeeffectsflags on objects, check PREVIOUS
              object's flagpile.
        - [+] try this: add checkflagS() after updatefpindex
        - [+] NOT happening during timeeffectsob().
        - [+] compile with optimisation.................
        - [+] hapepning in createmap. but objects on the PLAYER's map
              are being corrupted, not the new one.
        - [+] happening in addrandomthing()
        - [+] happening in addmonster().
            - [+]                 lf = addmonster(c, R_RANDOM, NULL,
                  B_TRUE, 1, B_TRUE, nadded);
            - [+] (glowbug was created)
        - [+] happening in addlf()
            - [+] glowbug again!! to do with light recalc ??
        - [+] happening in setrace()
            - [+] happening while inheriting F_AWARENESS.  have double
                  checked to confirm this!
        - [+] in HASLOS????!!
        - [+] addflag->flagcausesloscalc, so haslos for all on the map.
               problem happens when we call haslos() for the lf getting
              F_AWARENESS added.
        - [+] is the problem that doing a los recalc breaks when we are
              still missing half our racial flags ?
        - [+] QUICK FIX:
            - [+] dont recalc los for any lf where born = 0. just set
                  nlos to 0
            - [+] and manually recalc los just before returning from
                  addlf
        - [+] put sawgrsaas back to being common, not frequent
        - [+] is this finally fixed now? i think so!!
        - [+] if so, remove calls to "checkallflags" and most calls to
              checkflags()
    - [+] remove agility bonuses for weapon acc. now comes just from
          skill and from agi scaling on weapons.
    - [+] maybe difference in hit dice is a bad way to determine
          shieldblock difficulty.
        - [+] ...because the player rapidly gets higher than all other
              monsters on their dungeonlev.
        - [+] maybe just use monster's hitdice, ignore players.
    - [+] bug: abilities costing no stamina?
- [+] in addmap, i am not initialising enough nextmap[]s 
- [+] flag.c bug: don't need to set player->losdirty when recalcing
      light on a different map
- [+] lfs with F_DOESNTMOVE weren't attacking
- [+] manuals are starting off known. why??
    - [+] they don't appear in knowledge, so don't appear to have a
          hiddenname at all.
- [+] make magical barriers block view.
- [+] when describing armour / shield penalty, say
    - [+] "will lower your accuracy by 1"
    - [+] instead of
    - [+] "will lower your accuracy by 5%"
- [+] make firstaid skill incrase your hp per level
- [+] high agility seems to be giving a MASSIVE accuracy increase when
      higher than weapon's stat.
    - [+] maybe remove or reduce AGI acc bonuses.
- [+] sack started off containing a FOOD VENDOR!@#
    - [+] size check obviously isn't working.
    - [+] need "obfits" in givestartobs!!
- [+] hitting ESC when firing with F doesn't cancel.f
- [+] hunter should start with fur cloak
- [+] spellbooks are too cheap ($12)
- [+] remove'p' for lockpick- just operate the lockpickobject.
    - [+] removed,
    - [+] ...but now tha tI've removed 'p' for picklocks, can i still
          use 'o' on a dagger or similar?
    - [+] NO
    - [+] maybe turn "pick lock" into a still
    - [+] how do you gain this? level 1 lockpicking 
    - [+] then make lockpicks etc non-operable
- [+] fix crash when drunk lfs take damage
- [+] sleeping powder costs nothing
- [+] memleaks??? 700mb usage!!
    - [+] valgrind
        - [+] found a memleak problem:  definitely lost: 10,719,039
              bytes in 11,420 blocks
        - [+] not killing flags when we kill an object!!!!! fixed now.
        - [+] memory usage is now ticking up heaps more slowly.
        - [+] investigate further with valgrind again.....
- [+] when summoning, prefer cells for which the player has los.
- [+] make jammed doors harder to open.
- [+] no forcing a door open on your first go. should be:
    - [+] the door is jammed!
    - [+] you force it open.
    - [+] used f_jammed v1 = known
This commit is contained in:
Rob Pearce 2011-12-16 19:54:08 +00:00
parent 58f23588e8
commit edd16853c8
18 changed files with 669 additions and 269 deletions

View File

@ -1,5 +1,5 @@
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h data.c data.h flag.c flag.h god.c god.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h shops.c shops.h spell.c spell.h vault.c vault.h nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h data.c data.h flag.c flag.h god.c god.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h shops.c shops.h spell.c spell.h vault.c vault.h
gcc -Wall -g -o nexus nexus.c ai.c attack.c data.c flag.c god.c io.c lf.c map.c move.c objects.c text.c save.c spell.c shops.c vault.c -lncurses -lsqlite3 gcc -Wall -g -o nexus nexus.c ai.c attack.c data.c flag.c god.c io.c lf.c map.c move.c objects.c text.c save.c spell.c shops.c vault.c -lncurses -lsqlite3
#gcc -Wall -g -o nexus nexus.c ai.c attack.c data.c flag.c god.c io.c lf.c map.c move.c objects.c text.c save.c spell.c shops.c vault.c findleak.c -lncurses -lsqlite3 #gcc -Wall -g -o nexus nexus.c ai.c attack.c data.c flag.c god.c io.c lf.c map.c move.c objects.c text.c save.c spell.c shops.c vault.c findleak.c -lncurses -lsqlite3
check: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h data.c data.h flag.c flag.h god.c god.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h shops.c shops.h spell.c spell.h vault.c vault.h check: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h data.c data.h flag.c flag.h god.c god.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h shops.c shops.h spell.c spell.h vault.c vault.h

16
ai.c
View File

@ -1414,6 +1414,9 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// run away for a while // run away for a while
fleefrom(lf, spelllf, rnd(10,20), B_TRUE); fleefrom(lf, spelllf, rnd(10,20), B_TRUE);
} }
if ((spell == OT_A_DRAGUNDERGROUND) && (lf->race->id == R_HECTASSERVANT)) {
lf->hp = 0;
}
return B_FALSE; return B_FALSE;
} }
} }
@ -1467,6 +1470,14 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// try to get to our ideal range from them. // try to get to our ideal range from them.
if (db) dblog(".oO { i am at distance %d, want to be at %d-%d }", dist, wantdistmin, wantdistmax); if (db) dblog(".oO { i am at distance %d, want to be at %d-%d }", dist, wantdistmin, wantdistmax);
if (dist > wantdistmax) { if (dist > wantdistmax) {
// want to move but our race doesn't move?
if (lfhasflag(lf, F_DOESNTMOVE)) {
if (db) dblog(".oO { want to move towards target but have f_doesntmove - abandonning target. }");
loseaitargets(lf);
return B_TRUE;
}
if (db) { if (db) {
dblog(".oO { moving towards target. }"); dblog(".oO { moving towards target. }");
} }
@ -1584,8 +1595,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
if (db) dblog(".oO { ...successfully }"); if (db) dblog(".oO { ...successfully }");
// we now don't know their last known dir. // we now don't know their last known dir.
if (targetflag) { if (targetflag) {
free(targetflag->text); changeflagtext(targetflag, "");
targetflag->text = strdup("");
} }
return B_FALSE; return B_FALSE;
} }
@ -1739,6 +1749,8 @@ void aiturn(lifeform_t *lf) {
enum ATTRBRACKET iqb; enum ATTRBRACKET iqb;
checkflagpile(lf->flags);
/* /*
if (wantdb && haslos(player, lf->cell)) { if (wantdb && haslos(player, lf->cell)) {
db = B_TRUE; db = B_TRUE;

View File

@ -859,7 +859,8 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
// blocked by defender's shield? // blocked by defender's shield?
sprintf(attackname, "%s%s attack", attackername, getpossessive(attackername)); sprintf(attackname, "%s%s attack", attackername, getpossessive(attackername));
difficulty = 25 + ((gethitdice(lf) - gethitdice(victim))*3 ); //difficulty = 20 + ((gethitdice(lf) - gethitdice(victim)) );
difficulty = 20 + gethitdice(lf);
if (check_for_block(lf, victim, dam[i], damtype[i], difficulty, attackname)) { if (check_for_block(lf, victim, dam[i], damtype[i], difficulty, attackname)) {
blocked = B_TRUE; blocked = B_TRUE;
break; // stop processing damage now. break; // stop processing damage now.
@ -1511,7 +1512,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d
msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname)); msg("%s%s %s protects it.", victimname, getpossessive(victimname), noprefix(obname));
} }
*/ */
takedamage(armour, dam, damtype); takedamage(o, dam, damtype);
} }
} else { } else {
injure(victim, BP_HEAD, damtype); injure(victim, BP_HEAD, damtype);
@ -1560,7 +1561,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d
if ((armour = getarmour(victim, hitpos)) != NULL) { if ((armour = getarmour(victim, hitpos)) != NULL) {
int min,max; int min,max;
protected = checkcritprotection(victim,armour); protected = checkcritprotection(victim,armour);
max = getobmaxhp(o); max = getobmaxhp(armour);
min = max / 2; min = max / 2;
limit(&min, 1, NA); limit(&min, 1, NA);
takedamage(armour, rnd(min,max), DT_EXPLOSIVE); takedamage(armour, rnd(min,max), DT_EXPLOSIVE);

80
data.c
View File

@ -443,6 +443,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "50 arrows"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "50 arrows");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "throwing net"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "throwing net");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "fur cloak armour");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "cloth trousers"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "cloth trousers");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of leather boots"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of leather boots");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of leather gloves"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "pair of leather gloves");
@ -1792,6 +1793,7 @@ void initobjects(void) {
addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash");
addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash");
addflag(lastot->flags, F_VALUE, 100, NA, NA, NULL);
addot(OT_ASHCONCEAL, "pile of concealing powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addot(OT_ASHCONCEAL, "pile of concealing powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
@ -1801,6 +1803,7 @@ void initobjects(void) {
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash");
addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash");
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 80, NA, NA, NULL);
addot(OT_ASHSLEEP, "pile of sleeping powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addot(OT_ASHSLEEP, "pile of sleeping powder", "A pile of ash.", MT_STONE, 0.1, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL); addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
@ -1809,6 +1812,7 @@ void initobjects(void) {
addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash"); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of ash");
addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash"); addflag(lastot->flags, F_FEELTEXT, NA, NA, NA, "some ash");
addflag(lastot->flags, F_VALUE, 80, NA, NA, NULL);
addot(OT_GEMOFSEEING, "gem of seeing", "Magically enhances your eyesight.", MT_STONE, 1, OC_ROCK, SZ_TINY); addot(OT_GEMOFSEEING, "gem of seeing", "Magically enhances your eyesight.", MT_STONE, 1, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_HOLDCONFER, F_XRAYVIS, 1, NA, NULL); addflag(lastot->flags, F_HOLDCONFER, F_XRAYVIS, 1, NA, NULL);
addflag(lastot->flags, F_HOLDCONFER, F_SEEINVIS, B_TRUE, NA, NULL); addflag(lastot->flags, F_HOLDCONFER, F_SEEINVIS, B_TRUE, NA, NULL);
@ -2407,7 +2411,7 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addot(OT_S_DRAINLIFE, "drain life", "Draws life force from the victim in order to heal the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_DRAINLIFE, "necrotic beam", "Draws life force from the victim in order to heal the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The amount of life force drained is ^b1d6+power^n."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The amount of life force drained is ^b1d6+power^n.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
@ -2454,6 +2458,10 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l5
addot(OT_S_HECTASSERVANT, "hecta's hand", "Summons an enormous skeletal hand to drag foes to their doom. BEWARE: the hand will attack anything living, including the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
// l6 // l6
addot(OT_S_POSSESSION, "possession", "Completely possess an enemy, moving your consciousness into their body.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_POSSESSION, "possession", "Completely possess an enemy, moving your consciousness into their body.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines its resistability."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines its resistability.");
@ -3614,6 +3622,10 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
addot(OT_A_DRAGUNDERGROUND, "drag underground", "You drag your foe underground to its doom.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL);
addot(OT_A_FEIGNDEATH, "feign death", "Pretend to be dead.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_FEIGNDEATH, "feign death", "Pretend to be dead.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_FLIP, "flip", "Flip your opponent over your head.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_FLIP, "flip", "Flip your opponent over your head.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
@ -3627,7 +3639,6 @@ void initobjects(void) {
addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_XPVAL, 10, NA, NA, NULL);
addot(OT_A_HEAVYBLOW, "heavy blow", "Mighty blow which knocks enemies backwards.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_HEAVYBLOW, "heavy blow", "Mighty blow which knocks enemies backwards.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
@ -3646,6 +3657,8 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SPECIAL, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_STAMCOST, 3, NA, NA, NULL); addflag(lastot->flags, F_STAMCOST, 3, NA, NA, NULL);
addot(OT_A_PICKLOCK, "pick locks", "Attempt to open a lock using a small object.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_POLYREVERT, "revertform", "Revert to your original form.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_POLYREVERT, "revertform", "Revert to your original form.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_NOANNOUNCE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOANNOUNCE, B_TRUE, NA, NA, NULL);
@ -3918,7 +3931,6 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 10, B_DIEONFAIL, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 10, B_DIEONFAIL, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addot(OT_PANPIPES, "set of panpipes", "A set of musical pipes.", MT_METAL, 0.5, OC_TOOLS, SZ_TINY); addot(OT_PANPIPES, "set of panpipes", "A set of musical pipes.", MT_METAL, 0.5, OC_TOOLS, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
@ -4079,7 +4091,6 @@ void initobjects(void) {
addflag(lastot->flags, F_STACKABLE, B_FALSE, NA, NA, NULL); addflag(lastot->flags, F_STACKABLE, B_FALSE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 2, NA, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 2, NA, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
addot(OT_PAPERCLIP, "paperclip", "A thin, looped wire for holding paper together.", MT_WIRE, 0.01, OC_TECH, SZ_TINY); addot(OT_PAPERCLIP, "paperclip", "A thin, looped wire for holding paper together.", MT_WIRE, 0.01, OC_TECH, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 90, NA, NULL);
addflag(lastot->flags, F_VALUE, 5, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 5, NA, NA, NULL);
@ -4087,7 +4098,6 @@ void initobjects(void) {
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
addflag(lastot->flags, F_PICKLOCKS, 4, B_DIEONFAIL, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 4, B_DIEONFAIL, NA, NULL);
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
// can use as a (very bad) weapon too... // can use as a (very bad) weapon too...
addflag(lastot->flags, F_DAM, DT_PIERCE, 1, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 1, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 50, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 50, NA, NA, NULL);
@ -4956,6 +4966,7 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_YELLOW, UNI_SHADEDARK, NA, NULL); addflag(lastot->flags, F_GLYPH, C_YELLOW, UNI_SHADEDARK, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_REALLYIMPASSABLE, NA, NA, NA, NULL); addflag(lastot->flags, F_REALLYIMPASSABLE, NA, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_BLOCKSLOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes"); addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes");
@ -5138,14 +5149,21 @@ void initobjects(void) {
// armour - shoulders // armour - shoulders
addot(OT_CLOAK, "cloak", "A standard leather cloak.", MT_LEATHER, 4, OC_ARMOUR, SZ_MEDIUM); addot(OT_CLOAK, "leather cloak", "A standard leather cloak.", MT_LEATHER, 4, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_WATERPROOF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_WATERPROOF, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 2, NA, NA, NULL);
addot(OT_CLOAKFUR, "fur cloak", "A warm and lightweight fur cloak, great for winter camping trips.", MT_FLESH, 3, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_DTRESIST, DT_COLD, NA, NULL);
addflag(lastot->flags, F_HELPSREST, 5, NA, NA, NULL); addflag(lastot->flags, F_HELPSREST, 5, NA, NA, NULL);
addot(OT_APRON, "apron", "A sturdy rubber apron, designed to protect against stains.", MT_RUBBER, 2, OC_ARMOUR, SZ_MEDIUM); addot(OT_APRON, "apron", "A sturdy rubber apron, designed to protect against stains.", MT_RUBBER, 2, OC_ARMOUR, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
@ -7646,7 +7664,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, 87, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 87, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, 87, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_SWAMP, 87, RR_COMMON, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+3"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+3");
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
@ -10102,7 +10120,6 @@ void initrace(void) {
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+0"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+0");
@ -10405,6 +10422,32 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
// special: fully heal if our origrace is a vampire, and we are resting over a coffin // special: fully heal if our origrace is a vampire, and we are resting over a coffin
addrace(R_HECTASSERVANT, "skeletal hand", 20, 'Z', C_MAGENTA, MT_BONE, RC_UNDEAD, "An enormous skeletal hand.");
addbodypart(lastrace, BP_WEAPON, NULL);
setbodypartname(lastrace, BP_WEAPON, "digits");
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "5-20 bones");
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HATESALL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "10d4");
addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_DRAGUNDERGROUND, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastrace->flags, F_DTRESIST, DT_PIERCE, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_TREMORSENSE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_XPVAL, 0, NA, NA, NULL);
addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL, RC_OTHER, "A magically animated weapon."); addrace(R_DANCINGWEAPON, "dancing weapon", 0, ')', C_GREY, MT_METAL, RC_OTHER, "A magically animated weapon.");
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
@ -10570,7 +10613,13 @@ void initskills(void) {
addskilldesc(SK_FIRSTAID, PR_INEPT, "- Lets you recognise how healthy your opponents are.", B_FALSE); addskilldesc(SK_FIRSTAID, PR_INEPT, "- Lets you recognise how healthy your opponents are.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_INEPT, "- Determines how fast you heal when resting. ", B_FALSE); addskilldesc(SK_FIRSTAID, PR_INEPT, "- Determines how fast you heal when resting. ", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_INEPT, "- Determines how long poison effects will last.", B_FALSE); addskilldesc(SK_FIRSTAID, PR_INEPT, "- Determines how long poison effects will last.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_NOVICE, "+2 hit points per level.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_BEGINNER, "+4 hit points per level.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_ADEPT, "+6 hit points per level.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_ADEPT, "^gYou can now recognise when poison is potentially fatal.^n", B_TRUE); addskilldesc(SK_FIRSTAID, PR_ADEPT, "^gYou can now recognise when poison is potentially fatal.^n", B_TRUE);
addskilldesc(SK_FIRSTAID, PR_SKILLED, "+8 hit points per level.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_EXPERT, "+10 hit points per level.", B_FALSE);
addskilldesc(SK_FIRSTAID, PR_MASTER, "+12 hit points per level.", B_FALSE);
addskill(SK_LISTEN, "Listen", "How good you are at hearing and interpreting sounds.", 200); addskill(SK_LISTEN, "Listen", "How good you are at hearing and interpreting sounds.", 200);
addskilldesc(SK_LISTEN, PR_NOVICE, "^gYou now gauge the distance of sounds.^n", B_TRUE); addskilldesc(SK_LISTEN, PR_NOVICE, "^gYou now gauge the distance of sounds.^n", B_TRUE);
addskilldesc(SK_LISTEN, PR_BEGINNER, "^gYou now more accurately gauge the distance of sounds.^n", B_TRUE); addskilldesc(SK_LISTEN, PR_BEGINNER, "^gYou now more accurately gauge the distance of sounds.^n", B_TRUE);
@ -10579,6 +10628,7 @@ void initskills(void) {
addskilldesc(SK_LISTEN, PR_EXPERT, "^gYou can now identify monsters based on sound.^n", B_TRUE); addskilldesc(SK_LISTEN, PR_EXPERT, "^gYou can now identify monsters based on sound.^n", B_TRUE);
addskilldesc(SK_LISTEN, PR_MASTER, "^gYou can now locate monsters based on sound.^n", B_TRUE); addskilldesc(SK_LISTEN, PR_MASTER, "^gYou can now locate monsters based on sound.^n", B_TRUE);
addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks.", 50); addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks.", 50);
addskilldesc(SK_LOCKPICKING, PR_NOVICE, "^gYou gain the 'pick locks' ability.^n", B_FALSE);
addskill(SK_METALWORK, "Metalwork", "Lets you repair metal objects.", 100); addskill(SK_METALWORK, "Metalwork", "Lets you repair metal objects.", 100);
addskilldesc(SK_METALWORK, PR_NOVICE, "^gYou can repair metal items up to 33% condition.^n", B_FALSE); addskilldesc(SK_METALWORK, PR_NOVICE, "^gYou can repair metal items up to 33% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 50% condition.^n", B_FALSE); addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 50% condition.^n", B_FALSE);
@ -10608,13 +10658,13 @@ void initskills(void) {
addskilldesc(SK_SEWING, PR_MASTER, "^gYou can fully repair cloth items.^n", B_FALSE); addskilldesc(SK_SEWING, PR_MASTER, "^gYou can fully repair cloth items.^n", B_FALSE);
addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block attacks.", 50); addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block attacks.", 50);
addskilldesc(SK_SHIELDS, PR_INEPT, "- Without this skill, shield accuracy penalties are tripled.", B_FALSE); addskilldesc(SK_SHIELDS, PR_INEPT, "- Without this skill, shield accuracy penalties are tripled.", B_FALSE);
addskilldesc(SK_SHIELDS, PR_NOVICE, "^gShield accuracy penalties are reduced by 5%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_NOVICE, "^gShield accuracy penalties are reduced by 1.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gShield accuracy penalties are reduced by 10%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gShield accuracy penalties are reduced by 2.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gYou gain the 'shield bash' ability.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gYou gain the 'shield bash' ability.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_ADEPT, "^gShield accuracy penalties are reduced by 15%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_ADEPT, "^gShield accuracy penalties are reduced by 3.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_SKILLED, "^gShield accuracy penalties are reduced by 20%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_SKILLED, "^gShield accuracy penalties are reduced by 4.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 25%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 5.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_MASTER, "^gShield accuracy penalties are reduced by 30%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_MASTER, "^gShield accuracy penalties are reduced by 6.^n", B_FALSE);
addskill(SK_SPEECH, "Negotiation", "Your skill at haggling prices, or swaying others through speech.", 50); addskill(SK_SPEECH, "Negotiation", "Your skill at haggling prices, or swaying others through speech.", 50);
addskilldesc(SK_SPEECH, PR_NOVICE, "^gShop item prices are reduced by 5%.^n", B_FALSE); addskilldesc(SK_SPEECH, PR_NOVICE, "^gShop item prices are reduced by 5%.^n", B_FALSE);
addskilldesc(SK_SPEECH, PR_BEGINNER, "^gShop item prices are reduced by 10%.^n", B_FALSE); addskilldesc(SK_SPEECH, PR_BEGINNER, "^gShop item prices are reduced by 10%.^n", B_FALSE);

Binary file not shown.

7
defs.h
View File

@ -556,6 +556,7 @@ enum GAMEMODE {
GM_CHARGEN, GM_CHARGEN,
GM_GAMESTARTED, GM_GAMESTARTED,
GM_GAMEOVER, GM_GAMEOVER,
GM_CLEANUP,
}; };
enum ATTRIB { enum ATTRIB {
@ -977,6 +978,7 @@ enum RACE {
R_DANCINGWEAPON, R_DANCINGWEAPON,
R_FLOATINGDISC, R_FLOATINGDISC,
R_GASCLOUD, R_GASCLOUD,
R_HECTASSERVANT,
}; };
enum JOB { enum JOB {
@ -1235,6 +1237,7 @@ enum OBTYPE {
OT_S_COMMANDUNDEAD, OT_S_COMMANDUNDEAD,
OT_S_DRAINLIFE, OT_S_DRAINLIFE,
OT_S_FEAR, OT_S_FEAR,
OT_S_HECTASSERVANT,
OT_S_PAIN, OT_S_PAIN,
OT_S_PARALYZE, OT_S_PARALYZE,
OT_S_INFINITEDEATH, OT_S_INFINITEDEATH,
@ -1426,6 +1429,7 @@ enum OBTYPE {
OT_A_DARKWALK, OT_A_DARKWALK,
OT_A_DISARM, // disarm a trap OT_A_DISARM, // disarm a trap
OT_A_DISARMLF, // disarm an opponent OT_A_DISARMLF, // disarm an opponent
OT_A_DRAGUNDERGROUND,
OT_A_FEIGNDEATH, OT_A_FEIGNDEATH,
OT_A_FLIP, OT_A_FLIP,
OT_A_FLURRY, OT_A_FLURRY,
@ -1452,6 +1456,7 @@ enum OBTYPE {
OT_A_HIDE, OT_A_HIDE,
OT_A_INSPECT, OT_A_INSPECT,
OT_A_HURRICANESTRIKE, OT_A_HURRICANESTRIKE,
OT_A_PICKLOCK,
OT_A_POLYREVERT, OT_A_POLYREVERT,
OT_A_QUIVERINGPALM, OT_A_QUIVERINGPALM,
OT_A_STEAL, OT_A_STEAL,
@ -1615,6 +1620,7 @@ enum OBTYPE {
OT_VELVETROBE, OT_VELVETROBE,
// armour - shoulders // armour - shoulders
OT_CLOAK, OT_CLOAK,
OT_CLOAKFUR,
// armour - waist // armour - waist
OT_BELTLEATHER, OT_BELTLEATHER,
// armour - legs // armour - legs
@ -2150,6 +2156,7 @@ enum FLAG {
F_LOCKED,// door is locked F_LOCKED,// door is locked
// v1 is difficulty to disarm // v1 is difficulty to disarm
F_JAMMED, // is this door jammed? v0 is # turns it'll take to open it. F_JAMMED, // is this door jammed? v0 is # turns it'll take to open it.
// v1 = have we tried this door yet?
F_SECRET, // this object is secret. v0 is sc_search difficulty F_SECRET, // this object is secret. v0 is sc_search difficulty
// to find it. // to find it.
// NA means 'can never find this' // NA means 'can never find this'

131
flag.c
View File

@ -59,6 +59,8 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
int i; int i;
int rv; int rv;
//checkflagpile(fp);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// identified things mean all new flags are autmaticlaly known. // identified things mean all new flags are autmaticlaly known.
if (hasflag(fp, F_IDENTIFIED)) { if (hasflag(fp, F_IDENTIFIED)) {
@ -96,6 +98,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
} }
val1 = nextorder; val1 = nextorder;
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
lf = fp->owner; lf = fp->owner;
@ -119,6 +122,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
//////////////////////////////// ////////////////////////////////
// ACTUAL FLAG ADDITION IS HERE // ACTUAL FLAG ADDITION IS HERE
@ -179,6 +183,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
f = f->next; f = f->next;
*/ */
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// fill in props // fill in props
f->id = id; f->id = id;
@ -213,8 +218,12 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
f->pile = fp; f->pile = fp;
//checkflagpile(fp);
updatefpindex(fp); updatefpindex(fp);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// notify // notify
if (f->pile->owner) { if (f->pile->owner) {
if ( ((gamemode == GM_CHARGEN) && isplayer(f->pile->owner)) || if ( ((gamemode == GM_CHARGEN) && isplayer(f->pile->owner)) ||
@ -236,6 +245,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
break; break;
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
f->known = B_TRUE; f->known = B_TRUE;
if (f->obfrom) { if (f->obfrom) {
@ -260,36 +270,51 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
// player flags which cause a redraw // player flags which cause a redraw
rv = flagcausesredraw(f->pile->owner, f->id); rv = flagcausesredraw(f->pile->owner, f->id);
if (rv < redrawscreenatend) redrawscreenatend = rv; if (rv < redrawscreenatend) redrawscreenatend = rv;
if (flagcausesstatredraw(f->pile->owner, f->id)) redrawstatatend = B_TRUE; if (flagcausesstatredraw(f->pile->owner, f->id)) redrawstatatend = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} else if (f->pile->ob) { } else if (f->pile->ob) {
if (gamemode == GM_GAMESTARTED) { if (gamemode == GM_GAMESTARTED) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (announceobflaggain(f->pile->ob, f)) { if (announceobflaggain(f->pile->ob, f)) {
f->known = B_TRUE; f->known = B_TRUE;
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (flagcausesloscalc(f->id)) { if (flagcausesloscalc(f->id)) {
cell_t *where = NULL; cell_t *where = NULL;
// everyone who can see this cell recalcs their los // everyone who can see this cell recalcs their los
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
where = getflagpilelocation(f->pile); where = getflagpilelocation(f->pile);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (where) { if (where) {
lifeform_t *l; lifeform_t *l;
for (l = where->map->lf ; l ; l = l->next) { for (l = where->map->lf ; l ; l = l->next) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (haslos(l, where)) { if (haslos(l, where)) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
setlosdirty(l); setlosdirty(l);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
//precalclos(l); //precalclos(l);
if (isplayer(l)) { if (isplayer(l)) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (!redrawscreenatend) redrawscreenatend = B_TRUE; if (!redrawscreenatend) redrawscreenatend = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
// special effects // special effects
@ -315,11 +340,16 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
} }
if ((gamemode == GM_GAMESTARTED) && (redrawscreenatend || redrawstatatend || redolight)) { if ((gamemode == GM_GAMESTARTED) && (redrawscreenatend || redrawstatatend || redolight)) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (redolight) { if (redolight) {
//dblog("CALCINGLIGHT from flag\n"); //dblog("CALCINGLIGHT from flag\n");
if (!redrawscreenatend) redrawscreenatend = B_TRUE; if (!redrawscreenatend) redrawscreenatend = B_TRUE;
calclight(redolight); calclight(redolight);
setlosdirty(player); //if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (redolight == player->cell->map) {
setlosdirty(player);
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
//precalclos(player); //precalclos(player);
} }
//dblog("DRAWINGSCREEN from flag\n"); //dblog("DRAWINGSCREEN from flag\n");
@ -327,12 +357,16 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
if (redrawscreenatend) needredraw = B_TRUE; if (redrawscreenatend) needredraw = B_TRUE;
if (redrawstatatend) statdirty = B_TRUE; if (redrawstatatend) statdirty = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (redrawscreenatend == B_FORCE) { if (redrawscreenatend == B_FORCE) {
forceredraw(); forceredraw();
} else { } else {
drawscreen(); drawscreen();
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
//checkflagpile(fp);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
return f; return f;
} }
@ -386,6 +420,48 @@ void changeflagtext(flag_t *f, char *newtext) {
} }
} }
void checkmapflags(map_t *m) {
cell_t *c;
object_t *o;
int nbad = 0,x,y;
for (y = 0; y < m->h; y++) {
for (x = 0; x < m->w; x++) {
c = getcellat(m, x, y);
if (c) {
for (o = c->obpile->first ; o ; o = o->next) {
if (fpisbad(o->flags)) {
dblog("bad flagpile found in ob %s at (%d,%d)",o->type->name, c->x, c->y);
nbad++;
}
}
}
}
}
if (nbad) {
dblog("total bad flagpiles: %d", nbad);
assert("found bad flagpiles in checkmapflags!" == 0);
}
}
void checkflagpile(flagpile_t *fp) {
if (fpisbad(fp)) {
assert("flagpile is corrupt!" == 0);
}
}
int fpisbad(flagpile_t *fp) {
flag_t *f;
for (f = fp->first ; f ; f = f->next) {
if (fp->ob && fp->owner) {
return B_TRUE;
}
}
return B_FALSE;
}
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) {
flag_t *f; flag_t *f;
for (f = src->first ; f ; f = f->next) { for (f = src->first ; f ; f = f->next) {
@ -808,6 +884,8 @@ void killflag(flag_t *f) {
int redoscreen = B_FALSE; int redoscreen = B_FALSE;
int i,dopleasegod[MAXGODS]; int i,dopleasegod[MAXGODS];
//checkflagpile(f->pile);
for (i = 0; i < ngodlfs; i++) { for (i = 0; i < ngodlfs; i++) {
dopleasegod[i] = 0; dopleasegod[i] = 0;
} }
@ -847,12 +925,14 @@ void killflag(flag_t *f) {
} }
} }
// flags which cause a redraw if (gamemode == GM_GAMESTARTED) {
if (flagcausesredraw(f->pile->owner, f->id)) redoscreen = B_TRUE; // flags which cause a redraw
if (flagcausesstatredraw(f->pile->owner, f->id)) redostat = B_TRUE; if (flagcausesredraw(f->pile->owner, f->id)) redoscreen = B_TRUE;
if (flagcausesstatredraw(f->pile->owner, f->id)) redostat = B_TRUE;
if (flagcausesloscalc(f->id)) { if (flagcausesloscalc(f->id)) {
redolos = getflagpilelocation(f->pile); redolos = getflagpilelocation(f->pile);
}
} }
// notify // notify
@ -904,14 +984,14 @@ void killflag(flag_t *f) {
} else if (f->pile->ob && !isdeadob(f->pile->ob)) { } else if (f->pile->ob && !isdeadob(f->pile->ob)) {
announceobflagloss(f->pile->ob, f); announceobflagloss(f->pile->ob, f);
} }
}
// we will revert to our original form at the end of timeeffectslf(). // we will revert to our original form at the end of timeeffectslf().
if (lf && (f->id == F_POLYMORPHED)) { if (lf && (f->id == F_POLYMORPHED)) {
if (lfhasflag(lf, F_ORIGRACE)) { if (lfhasflag(lf, F_ORIGRACE)) {
lf->polyrevert = B_TRUE; lf->polyrevert = B_TRUE;
}
} }
} }
///////////////////////////////////////////// /////////////////////////////////////////////
// now we are actually removing the flag. // now we are actually removing the flag.
@ -921,10 +1001,17 @@ void killflag(flag_t *f) {
pile = f->pile; pile = f->pile;
// free mem // free mem
if (f->text) free(f->text); if (f->text) {
free(f->text);
f->text = NULL;
}
if (f->altval) { if (f->altval) {
if (f->altval->text) free(f->altval->text); if (f->altval->text) {
free(f->altval->text);
f->altval->text = NULL;
}
free(f->altval); free(f->altval);
f->altval = NULL;
} }
// remove from list // remove from list
@ -997,15 +1084,19 @@ void killflag(flag_t *f) {
drawscreen(); drawscreen();
} }
} }
//checkflagpile(pile);
} }
void killflagpile(flagpile_t *fp) { void killflagpile(flagpile_t *fp) {
if (fp->ob && !fp->ob->dying) { if (fp->ob && !fp->ob->dying) {
assert(0 == "calling killflagpile on non-dying object"); assert(0 == "calling killflagpile on non-dying object");
} }
//checkflagpile(fp);
while (fp->first) { while (fp->first) {
killflag(fp->first); killflag(fp->first);
} }
//checkflagpile(fp);
free(fp); free(fp);
} }
@ -1049,6 +1140,7 @@ int killtransitoryflagvals(flagpile_t *fp, enum FLAG fid, int val1, int val2, in
} }
void timeeffectsflag(flag_t *f, int howlong) { void timeeffectsflag(flag_t *f, int howlong) {
// special case: // special case:
if (f->id == F_TRAIL) { if (f->id == F_TRAIL) {
return; return;
@ -1275,8 +1367,7 @@ flag_t *modflag(flagpile_t *fp, enum FLAG fid, int val1, int val2, int val3, cha
if (val2 != NA) f->val[1] = val2; if (val2 != NA) f->val[1] = val2;
if (val3 != NA) f->val[2] = val3; if (val3 != NA) f->val[2] = val3;
if (text) { if (text) {
free(f->text); changeflagtext(f, text);
f->text = strdup(text);
} }
return f; return f;
} }
@ -1300,19 +1391,25 @@ void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2) {
void timeeffectsflags(flagpile_t *fp) { void timeeffectsflags(flagpile_t *fp) {
flag_t *f,*nextf; flag_t *f,*nextf;
//checkflagpile(fp);
for (f = fp->first ; f ; f = nextf) { for (f = fp->first ; f ; f = nextf) {
nextf = f->next; nextf = f->next;
timeeffectsflag(f, 1); timeeffectsflag(f, 1);
} }
//checkflagpile(fp);
} }
// generate an index // generate an index
void updatefpindex(flagpile_t *fp) { void updatefpindex(flagpile_t *fp) {
flag_t *f; flag_t *f;
fp->nitems = 0; fp->nitems = 0;
for (f = fp->first ;f ; f = f->next) { for (f = fp->first ;f ; f = f->next) {
fp->item[fp->nitems] = f; fp->item[fp->nitems] = f;
fp->nitems++; fp->nitems++;
assert(fp->nitems < MAXFLAGS);
} }
//checkflagpile(fp);
} }

3
flag.h
View File

@ -10,6 +10,9 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
flagpile_t *addflagpile(lifeform_t *owner, object_t *o); flagpile_t *addflagpile(lifeform_t *owner, object_t *o);
int canbemadepermenant(enum FLAG id); int canbemadepermenant(enum FLAG id);
void changeflagtext(flag_t *f, char *newtext); void changeflagtext(flag_t *f, char *newtext);
void checkmapflags(map_t *m);
int fpisbad(flagpile_t *fp);
void checkflagpile(flagpile_t *fp);
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id); void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id);
void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime); void copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int countflags(flagpile_t *fp); int countflags(flagpile_t *fp);

41
god.c
View File

@ -841,7 +841,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
cell_t *c; cell_t *c;
object_t *o; object_t *o;
object_t *oposs[MAXPILEOBS]; object_t *oposs[MAXPILEOBS];
int noposs = 0; int noposs = 0, n;
case R_GODPURITY: case R_GODPURITY:
msg("\"Witness the holy radiance of purity!\""); msg("\"Witness the holy radiance of purity!\"");
c = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND); c = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
@ -874,15 +874,36 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
break; break;
case R_GODDEATH: case R_GODDEATH:
msg("\"Behold, the power of death!\""); msg("\"Behold, the power of death!\"");
for (i = 1; i < lf->nlos; i++) { c = NULL;
lifeform_t *who; n = OT_NONE;
who = lf->los[i]->lf; switch (rnd(0,3)) {
if (who && !areallies(lf, who)) { case 0: n = OT_S_PAIN; break;
if (isundead(who)) { case 1: n = OT_S_DRAINLIFE; break;
makepeaceful(who); case 2: n = OT_S_BLINDNESS; break;
} else { case 3: n = OT_S_HECTASSERVANT;
castspell(god, OT_S_PAIN, who, NULL, who->cell, NULL, NULL); c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
castspell(god, OT_S_DRAINLIFE, who, NULL, who->cell, NULL, NULL); break;
}
if (n == OT_S_HECTASSERVANT) {
if (c) {
castspell(god, n, player, NULL, c, NULL, NULL);
n = OT_NONE;
} else {
n = OT_S_DRAINLIFE;
}
}
if (n != OT_NONE) {
for (i = 1; i < lf->nlos; i++) {
lifeform_t *who;
who = lf->los[i]->lf;
if (who && !areallies(lf, who)) {
if (isundead(who)) {
makepeaceful(who);
} else {
castspell(god, n, who, NULL, who->cell, NULL, NULL);
break;
}
} }
} }
} }

60
io.c
View File

@ -877,7 +877,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
if (lf2) { if (lf2) {
char lfname2[BUFLEN]; char lfname2[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
getlfname(lf2, lfname2); getlfnamea(lf2, lfname2);
snprintf(buf2, BUFLEN, "holding %s",lfname2); snprintf(buf2, BUFLEN, "holding %s",lfname2);
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2); strcat(extrainfo, buf2);
@ -891,7 +891,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
if (lf2) { if (lf2) {
char lfname2[BUFLEN]; char lfname2[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
getlfname(lf2, lfname2); getlfnamea(lf2, lfname2);
snprintf(buf2, BUFLEN, "held by %s",lfname2); snprintf(buf2, BUFLEN, "held by %s",lfname2);
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2); strcat(extrainfo, buf2);
@ -1075,7 +1075,6 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
} }
} }
inaskcoords = B_FALSE; inaskcoords = B_FALSE;
clearmsg(); clearmsg();
restoregamewindows(); restoregamewindows();
@ -3516,7 +3515,7 @@ void describespell(objecttype_t *ot) {
} }
void doattackcell(char dirch) { void doattackcell(char dirch) {
int dir; int dir = D_NONE;
flag_t *f; flag_t *f;
cell_t *c; cell_t *c;
@ -3528,14 +3527,14 @@ void doattackcell(char dirch) {
if (dirch == '.') { if (dirch == '.') {
// yourself! // yourself!
c = player->cell; c = player->cell;
}
dir = chartodir(dirch);
if (dir == D_NONE) {
msg("Cancelled.");
return;
} else { } else {
dir = chartodir(dirch); c = getcellindir(player->cell, dir);
if (dir == D_NONE) {
clearmsg();
return;
} else {
c = getcellindir(player->cell, dir);
}
} }
if (c) { if (c) {
@ -4677,7 +4676,7 @@ char *makedesc_ob(object_t *o, char *retbuf) {
int acc,accnum; int acc,accnum;
acc = getobaccuracy(o, NULL); acc = getobaccuracy(o, NULL);
accnum = getaccuracynum(acc); accnum = getaccuracynum(acc);
sprintf(buf, "@It has an accuracy modifier of %c%d (%s).\n",(accnum < 0) ? '-' : '+', abs(accnum), getaccuracyname(acc)); sprintf(buf, "@It has a base accuracy of %c%d (%s).\n",(accnum < 0) ? '-' : '+', abs(accnum), getaccuracyname(acc));
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} }
f = hasflag(o->flags, F_RANGE); f = hasflag(o->flags, F_RANGE);
@ -5359,11 +5358,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
amt = adjustarmourpenalty(player, f->val[1]); amt = adjustarmourpenalty(player, f->val[1]);
amt2 = adjustarmourpenalty(player, f->val[2]); amt2 = adjustarmourpenalty(player, f->val[2]);
if (amt > 0) { if (amt > 0) {
sprintf(buf2, "^B%s lowers your accuracy by %d%%. (Armour skill penalty)^n\n", buf, amt); sprintf(buf2, "^B%s lowers your accuracy by %d. (Armour skill penalty)^n\n", buf, getaccuracymodnum(amt));
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
} }
if (amt2 > 0) { if (amt2 > 0) {
sprintf(buf2, "^B%s lowers your evasion by %d%%. (Armour skill penalty)^n\n", buf, amt2); sprintf(buf2, "^B%s lowers your evasion by %d. (Armour skill penalty)^n\n", buf, amt2);
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
} }
break; break;
@ -5371,11 +5370,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
amt = adjustshieldpenalty(player, f->val[1]); amt = adjustshieldpenalty(player, f->val[1]);
amt2 = adjustshieldpenalty(player, f->val[2]); amt2 = adjustshieldpenalty(player, f->val[2]);
if (amt > 0) { if (amt > 0) {
sprintf(buf2, "^B%s lowers your attack accuracy by %d%%. (Shields skill too low)^n\n", buf, amt); sprintf(buf2, "^B%s lowers your attack accuracy by %d. (Shields skill too low)^n\n", buf, getaccuracymodnum(amt));
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
} }
if (amt2 > 0) { if (amt2 > 0) {
sprintf(buf2, "^B%s lowers your evasion by %d%%. (Shields skill penalty)^n\n", buf, amt2); sprintf(buf2, "^B%s lowers your evasion by %d. (Shields skill penalty)^n\n", buf, amt2);
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
} }
break; break;
@ -5706,10 +5705,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
(f->val[2] == 0) ? "" : " effectively"); (f->val[2] == 0) ? "" : " effectively");
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
msg("^wYou low %s will lower your %s with this weapon.",
getattrname(retflag[i]->val[0]),
(retflag[i]->val[0] == A_AGI) ? "accuracy" : "damage");
if (usable && isweapon(o)) { if (usable && isweapon(o)) {
if (pctmod > 0) { if (pctmod > 0) {
sprintf(buf, "^%dYour high %s will increase your %s with this weapon.^n\n", C_GREEN, sprintf(buf, "^%dYour high %s will increase your %s with this weapon.^n\n", C_GREEN,
@ -5852,11 +5847,12 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
case AT_VLOW: sprintf(ch, "%-4s", "xxx"); col = C_RED; break; case AT_VLOW: sprintf(ch, "%-4s", "xxx"); col = C_RED; break;
case AT_LOW: sprintf(ch, "%-4s", "xx"); col = C_RED; break; case AT_LOW: sprintf(ch, "%-4s", "xx"); col = C_RED; break;
case AT_LTAVERAGE: sprintf(ch, "%-4s", "x"); col = C_RED; break; case AT_LTAVERAGE: sprintf(ch, "%-4s", "x"); col = C_RED; break;
case AT_AVERAGE: sprintf(ch, "%-4s", "-"); col = C_GREY; break;
case AT_GTAVERAGE: sprintf(ch, "%-4s", "+"); col = C_GREEN; break; case AT_GTAVERAGE: sprintf(ch, "%-4s", "+"); col = C_GREEN; break;
case AT_HIGH: sprintf(ch, "%-4s", "++"); col = C_GREEN; break; case AT_HIGH: sprintf(ch, "%-4s", "++"); col = C_GREEN; break;
case AT_VHIGH: sprintf(ch, "%-4s", "+++"); col = C_GREEN; break; case AT_VHIGH: sprintf(ch, "%-4s", "+++"); col = C_GREEN; break;
case AT_EXHIGH: sprintf(ch, "%-4s", "++++"); col = C_BOLDBLUE; break; case AT_EXHIGH: sprintf(ch, "%-4s", "++++"); col = C_BOLDBLUE; break;
default:
case AT_AVERAGE: sprintf(ch, "%-4s", "-"); col = C_GREY; break;
} }
} else { } else {
sprintf(ch, "%-4s", "?"); sprintf(ch, "%-4s", "?");
@ -6066,7 +6062,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra) {
case F_FASTMETAB: sprintf(buf, "Fast metabolism (needs to eat often)"); break; case F_FASTMETAB: sprintf(buf, "Fast metabolism (needs to eat often)"); break;
case F_MATVULN: case F_MATVULN:
mt = findmaterial(f->val[0]); mt = findmaterial(f->val[0]);
sprintf(buf, "Takes %d%% damage from weapons made of %s.", retflag[i]->val[1], mt->name); sprintf(buf, "Takes %d%% damage from weapons made of %s.", f->val[1], mt->name);
break; break;
case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break; case F_MPMOD: if (f->val[0] < 0) sprintf(buf, "%d Mana", f->val[0]); break;
case F_NEEDSWATER: sprintf(buf, "Will suffocate without water"); break; case F_NEEDSWATER: sprintf(buf, "Will suffocate without water"); break;
@ -6230,7 +6226,7 @@ char *makedesc_spell(objecttype_t *ot, char *retbuf) {
} }
stamcost = getstamcost(player, ot->id); stamcost = getstamcost(player, ot->id);
if (stamcost) { if (stamcost > 0) {
sprintf(buf, "It costs %d stamina to use.\n",stamcost); sprintf(buf, "It costs %d stamina to use.\n",stamcost);
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
} }
@ -7101,14 +7097,11 @@ int doselguntarget(void) {
addflag(player->flags, F_THROWING, B_TRUE, NA, NA, NULL); addflag(player->flags, F_THROWING, B_TRUE, NA, NA, NULL);
where = askcoords(buf, buf2, TT_MONSTER, player, UNLIMITED, getfirearmloftype(player), B_TRUE); where = askcoords(buf, buf2, TT_MONSTER, player, UNLIMITED, getfirearmloftype(player), B_TRUE);
killflagsofid(player->flags, F_THROWING); killflagsofid(player->flags, F_THROWING);
if (where) { if (where && where->lf) {
//if (where->lf && haslof(player->cell, where, LOF_NEED, NULL)) { setguntarget(player, where->lf);
if (where->lf) { } else {
setguntarget(player, where->lf); setguntarget(player, NULL);
} else { return B_TRUE;
setguntarget(player, NULL);
return B_TRUE;
}
} }
return B_FALSE; return B_FALSE;
} }
@ -9811,6 +9804,7 @@ void showlfstats(lifeform_t *lf, int showall) {
strcat(buf, buf2); strcat(buf, buf2);
} }
break; break;
/*
case A_AGI: case A_AGI:
if (accmod != 0) { if (accmod != 0) {
snprintf(buf2, BUFLEN, ", %c%d acc",(accmod >= 0) ? '+' : '-', snprintf(buf2, BUFLEN, ", %c%d acc",(accmod >= 0) ? '+' : '-',
@ -9818,6 +9812,7 @@ void showlfstats(lifeform_t *lf, int showall) {
strcat(buf, buf2); strcat(buf, buf2);
} }
break; break;
*/
default: default:
break; break;
} }
@ -11713,6 +11708,8 @@ void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
if (!strlen(buf)) return; if (!strlen(buf)) return;
w = getmaxx(win);
// remember the amount of spaces at the end // remember the amount of spaces at the end
p = buf + strlen(buf) - 1; p = buf + strlen(buf) - 1;
while (*p == ' ') { while (*p == ' ') {
@ -11733,7 +11730,6 @@ void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
repword = strrep(repword, "@", " ", &rv); repword = strrep(repword, "@", " ", &rv);
} }
// if this word won't fit, put it on the next line. // if this word won't fit, put it on the next line.
w = getmaxx(win);
if (*x != 0) { if (*x != 0) {
if (*x + strlen(repword) >= w) { if (*x + strlen(repword) >= w) {
(*y)++; (*y)++;

181
lf.c
View File

@ -1418,7 +1418,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
int needtovalidate = B_FALSE; int needtovalidate = B_FALSE;
int targettype; int targettype;
int cost; int cost;
flag_t *f,*willflag; flag_t *f,*willflag = NULL;
int power; int power;
objecttype_t *sp; objecttype_t *sp;
@ -3430,6 +3430,9 @@ void enhanceskills(lifeform_t *lf) {
// update hp // update hp
hpratio = ((float)lf->hp / (float)lf->maxhp); hpratio = ((float)lf->hp / (float)lf->maxhp);
lf->maxhp += rollhitdice(lf, isplayer(lf) ? B_FALSE : B_TRUE); lf->maxhp += rollhitdice(lf, isplayer(lf) ? B_FALSE : B_TRUE);
lf->maxhp += (getskill(lf, SK_FIRSTAID)*2);
lf->hp = hpratio * (float)lf->maxhp; lf->hp = hpratio * (float)lf->maxhp;
// update mp // update mp
@ -5930,18 +5933,21 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
acc += (lf->level * 2); acc += (lf->level * 2);
if (lfhasflag(lf, F_RAGE)) { if (lfhasflag(lf, F_RAGE)) {
// assume maximum dex // huge bonus
acc += 50; acc += 50;
} else { }
/*
else {
int dexmod; int dexmod;
// modify with dexterity // modify with dexterity
dexmod = getstatmod(lf, A_AGI); dexmod = getstatmod(lf, A_AGI) / 2; // -25 - +25
// double dex penalties when dual weilding // double dex penalties when dual weilding
if (isdualweilding(lf) && (dexmod < 0)) { if (isdualweilding(lf) && (dexmod < 0)) {
dexmod *= 2; dexmod *= 2;
} }
acc += dexmod; acc += dexmod;
} }
*/
// modify for blindness // modify for blindness
if (isblind(lf)) { if (isblind(lf)) {
@ -8440,6 +8446,12 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
newf = addflag(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL);
newf->lifetime = FROMSKILL; newf->lifetime = FROMSKILL;
} }
} else if (id == SK_LOCKPICKING) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_PICKLOCK, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_PICKLOCK, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
} else if (id == SK_METALWORK) { } else if (id == SK_METALWORK) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL); newf = hasflagval(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL);
if (!newf) { if (!newf) {
@ -8453,8 +8465,11 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
newf->lifetime = FROMSKILL; newf->lifetime = FROMSKILL;
} }
} else if (id == SK_THIEVERY) { } else if (id == SK_THIEVERY) {
newf = addflag(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL); newf = hasflagval(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL);
newf->lifetime = FROMSKILL; if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
} else if (id == SK_TRAPS) { } else if (id == SK_TRAPS) {
newf = addflag(lf->flags, F_CANWILL, OT_A_DISARM, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_DISARM, NA, NA, NULL);
newf->lifetime = FROMSKILL; newf->lifetime = FROMSKILL;
@ -8882,6 +8897,18 @@ void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp) {
} }
} }
// TODO: maybe add object to temp cell, then MOVE it to the destination pile.
// this will make sure the right checks happen.
// some things aren't possible...
if (o) {
if (!obfits(o, op)) {
killob(o);
} else if (op->parentob && hasflag(o->flags, F_CONTAINER)) {
// don't put containers in other containers
killob(o);
}
}
// added an object? // added an object?
if (o) { if (o) {
@ -9877,20 +9904,7 @@ int getviscell(lifeform_t *lf, cell_t *cell) {
*/ */
int haslos(lifeform_t *viewer, cell_t *dest) { int haslos(lifeform_t *viewer, cell_t *dest) {
int numpixels; if (gamemode == GM_CLEANUP) return B_FALSE;
int i;
int x1,y1;
int maxvisrange;
int xray = 0;
//int wentuphill = B_FALSE;
//int origheight;
//int shopwall;
flag_t *f;
int x2,y2;
map_t *map;
int currange;
int nvrange;
cell_t *retcell[MAXRETCELLS];
if (!viewer) return B_FALSE; if (!viewer) return B_FALSE;
if (!dest) return B_FALSE; if (!dest) return B_FALSE;
@ -9904,7 +9918,6 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
//if (isdead(viewer) && !isplayer(viewer)) return B_FALSE; //if (isdead(viewer) && !isplayer(viewer)) return B_FALSE;
if (lfhasflag(viewer, F_DEAD) && !isplayer(viewer)) return B_FALSE; if (lfhasflag(viewer, F_DEAD) && !isplayer(viewer)) return B_FALSE;
if (viewer->losdirty) { if (viewer->losdirty) {
precalclos(viewer); precalclos(viewer);
viewer->losdirty = B_FALSE; viewer->losdirty = B_FALSE;
@ -9912,11 +9925,17 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
// can we use pre-calced los? // can we use pre-calced los?
// //
//if ((viewer->cell->map->lf == viewer) && viewer->los) { /*
if (viewer->los) { if (viewer->los) {
return haslos_fast(viewer, dest); return haslos_fast(viewer, dest);
} }
*/
assert(viewer->los || (viewer->nlos == 0));
return haslos_fast(viewer, dest);
/*
// THIS CODE IS NO LONGER EVER USED
map = dest->map; map = dest->map;
x1 = viewer->cell->x; x1 = viewer->cell->x;
@ -9965,11 +9984,9 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
return B_FALSE; return B_FALSE;
} }
// if we went uphill, stop here // if we went uphill, stop here
/* //if (wentuphill) {
if (wentuphill) { // return B_FALSE;
return B_FALSE; //}
}
*/
if (!celltransparentfor(viewer, cell, &xray, &rangemod)) { if (!celltransparentfor(viewer, cell, &xray, &rangemod)) {
return B_FALSE; return B_FALSE;
@ -9981,15 +9998,14 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
if (xray) xray--; if (xray) xray--;
// if you went uphill, can't see any further // if you went uphill, can't see any further
/* //if (getheight(x,y,z) > origheight) {
if (getheight(x,y,z) > origheight) { // wentuphill = B_TRUE;
wentuphill = B_TRUE; //}
}
*/
} }
} }
return B_TRUE; return B_TRUE;
*/
} }
int haslosdark(lifeform_t *viewer, cell_t *dest) { int haslosdark(lifeform_t *viewer, cell_t *dest) {
@ -10715,31 +10731,34 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
// init flags // init flags
a->flags = addflagpile(a, NULL); a->flags = addflagpile(a, NULL);
// link cell back to lf
cell->lf = a;
// set race - this will inherit race flags and material // set race - this will inherit race flags and material
a->race = NULL; a->race = NULL;
setrace(a, rid, B_FALSE); setrace(a, rid, B_FALSE);
// now do everything which must occur AFTER setting the race:
// remember original attribs so that if we are polymorphed, we're // remember original attribs so that if we are polymorphed, we're
// able to revert back. // able to revert back.
for (i = 0; i < MAXATTS; i++) { for (i = 0; i < MAXATTS; i++) {
a->origatt[i] = a->baseatt[i]; a->origatt[i] = a->baseatt[i];
} }
// set stamina AFTER setrace as it depends on your attribs // set stamina AFTER setrace as it depends on your attribs
a->stamina = getmaxstamina(a); a->stamina = getmaxstamina(a);
// give start objets AFTER setrace as some races start with objects
// update other things
cell->lf = a;
// give start objetcs
if ((gamemode != GM_LOADING) && (gamemode != GM_VALIDATION)) { if ((gamemode != GM_LOADING) && (gamemode != GM_VALIDATION)) {
outfitlf(a); outfitlf(a);
} }
a->created = B_TRUE; a->created = B_TRUE;
a->born = B_TRUE; // now finished creating it. a->born = B_TRUE; // now finished creating it.
if ((gamemode == GM_GAMESTARTED) && cansee(player, a)) { if (gamemode == GM_GAMESTARTED) {
needredraw = B_TRUE; if (cansee(player, a)) {
needredraw = B_TRUE;
}
} }
return a; return a;
} }
@ -10859,7 +10878,7 @@ void addskilldesc(enum SKILL id, enum SKILLLEVEL lev, char *text, int wantmsg) {
object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int doscents) { object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int doscents) {
object_t *footprint, *scent,*retob = NULL; object_t *footprint, *scent,*retob = NULL;
flag_t *fpflag; flag_t *fpflag = NULL;
// no tracks at all? // no tracks at all?
if (where->type->solid) { if (where->type->solid) {
@ -11016,7 +11035,8 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) {
//adjustdammaterial((unsigned int *)amt, damtype, getlfmaterial(lf)); //adjustdammaterial((unsigned int *)amt, damtype, getlfmaterial(lf));
adjustdamhardness(amt, damtype, getlfmaterial(lf)); adjustdamhardness(amt, damtype, getlfmaterial(lf));
if (lfhasflag(lf, F_DRUNK)) { f = lfhasflag(lf, F_DRUNK);
if (f) {
*amt -= rnd(1,f->val[0]); *amt -= rnd(1,f->val[0]);
} }
@ -12084,7 +12104,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
if (isplayer(lf)) { if (isplayer(lf)) {
int warnthresh; int warnthresh;
warnthresh = (int)((float)0.25 * (float)lf->maxhp); warnthresh = (int)((float)0.25 * (float)lf->maxhp);
if (lf->hp <= warnthresh) { if ((lf->hp <= warnthresh) && (lf->hp > 0)) {
warn("*** LOW HITPOINT WARNING ***"); warn("*** LOW HITPOINT WARNING ***");
more(); more();
} }
@ -13233,16 +13253,6 @@ void precalclos_new(lifeform_t *lf) {
long allocamt; long allocamt;
if (lf->cell->type->id == CT_FAKE) return; if (lf->cell->type->id == CT_FAKE) return;
f = hasflag(lf->flags, F_XRAYVIS);
if (f) {
startxray = f->val[0];
} else {
startxray = 0;
}
// right eye missing?
missingeye = lfhasflagval(lf, F_INJURY, IJ_EYEDESTROYED, NA, NA, NULL);
if (lf->los) { if (lf->los) {
free(lf->los); lf->los = NULL; free(lf->los); lf->los = NULL;
@ -13251,6 +13261,22 @@ void precalclos_new(lifeform_t *lf) {
free(lf->losdark); lf->losdark = NULL; free(lf->losdark); lf->losdark = NULL;
} }
if (!lf->born) {
lf->nlos = 0;
lf->nlosdark = 0;
return;
}
// right eye missing?
missingeye = lfhasflagval(lf, F_INJURY, IJ_EYEDESTROYED, NA, NA, NULL);
f = hasflag(lf->flags, F_XRAYVIS);
if (f) {
startxray = f->val[0];
} else {
startxray = 0;
}
allocamt = ((MAXVISRANGE*2)+1) * ((MAXVISRANGE*2)+1); allocamt = ((MAXVISRANGE*2)+1) * ((MAXVISRANGE*2)+1);
los = malloc( sizeof(cell_t *) * allocamt); los = malloc( sizeof(cell_t *) * allocamt);
losdark = malloc( sizeof(cell_t *) * allocamt); losdark = malloc( sizeof(cell_t *) * allocamt);
@ -13304,6 +13330,7 @@ void precalclos_new(lifeform_t *lf) {
currange = 0; currange = 0;
// calc path to end cell // calc path to end cell
calcbresnham(lf->cell->map, lf->cell->x, lf->cell->y, endx[nn], endy[nn], retcell, &numpixels ); calcbresnham(lf->cell->map, lf->cell->x, lf->cell->y, endx[nn], endy[nn], retcell, &numpixels );
assert(numpixels < MAXRETCELLS);
// keep going until we lose los // keep going until we lose los
for (n = 0; keepgoing && (n < numpixels); n++) { for (n = 0; keepgoing && (n < numpixels); n++) {
c = retcell[n]; c = retcell[n];
@ -13354,17 +13381,26 @@ void precalclos_new(lifeform_t *lf) {
} // end foreach cell and while keepgoing } // end foreach cell and while keepgoing
} }
assert(nlos < (MAX_MAPW * MAX_MAPH)); assert(nlos < (MAX_MAPW * MAX_MAPH));
assert(nlosdark < (MAX_MAPW * MAX_MAPH));
// now fill in lifeform structure // now fill in lifeform structure
lf->los = malloc(sizeof(cell_t *) * nlos); if (nlos) {
for (i = 0; i < nlos; i++) { lf->los = malloc(sizeof(cell_t *) * nlos);
lf->los[i] = los[i]; for (i = 0; i < nlos; i++) {
lf->los[i] = los[i];
}
} else {
lf->los = NULL;
} }
lf->nlos = nlos; lf->nlos = nlos;
lf->losdark = malloc(sizeof(cell_t *) * nlosdark); if (nlosdark) {
for (i = 0; i < nlosdark; i++) { lf->losdark = malloc(sizeof(cell_t *) * nlosdark);
lf->losdark[i] = losdark[i]; for (i = 0; i < nlosdark; i++) {
lf->losdark[i] = losdark[i];
}
} else {
lf->losdark = NULL;
} }
lf->nlosdark = nlosdark; lf->nlosdark = nlosdark;
@ -14316,6 +14352,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags; int nretflags;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
newrace = findrace(rid); newrace = findrace(rid);
if (isplayer(lf)) { if (isplayer(lf)) {
@ -14326,6 +14363,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
retainhp = B_TRUE; retainhp = B_TRUE;
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (frompolymorph && (gamemode == GM_GAMESTARTED) && lf->race) { if (frompolymorph && (gamemode == GM_GAMESTARTED) && lf->race) {
race_t *origrace = NULL; race_t *origrace = NULL;
@ -14388,6 +14426,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
// stop stoning. // stop stoning.
killflagsofid(lf->flags, F_BEINGSTONED); killflagsofid(lf->flags, F_BEINGSTONED);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// first remove flags from existing race, or temporary ones // first remove flags from existing race, or temporary ones
lf->born = B_FALSE; lf->born = B_FALSE;
for (f = lf->flags->first ; f ; f = nextf) { for (f = lf->flags->first ; f ; f = nextf) {
@ -14401,6 +14440,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// set race // set race
lf->race = newrace; lf->race = newrace;
@ -14414,7 +14454,9 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
case F_MPDICE: case F_MPDICE:
break; break;
default: default:
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
addflag_real(lf->flags, f->id, f->val[0], f->val[1], f->val[2], f->text, FROMRACE, f->known, -1); addflag_real(lf->flags, f->id, f->val[0], f->val[1], f->val[2], f->text, FROMRACE, f->known, -1);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
break; break;
} }
} }
@ -14426,6 +14468,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
*/ */
// certain other flags are rnadom // certain other flags are rnadom
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
getflags(lf->flags, retflag, &nretflags, F_RNDHOSTILE, F_NONE); getflags(lf->flags, retflag, &nretflags, F_RNDHOSTILE, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
@ -14436,6 +14479,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
killflag(f); killflag(f);
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// generate stats // generate stats
for (i = 0; i < MAXATTS; i++) { for (i = 0; i < MAXATTS; i++) {
@ -14484,6 +14528,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
enum BODYPART bp; enum BODYPART bp;
object_t *o,*nexto; object_t *o,*nexto;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// no pack? // no pack?
if (lfhasflag(lf, F_NOPACK)) { if (lfhasflag(lf, F_NOPACK)) {
// drop everything // drop everything
@ -14501,6 +14546,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
moveob(o, lf->cell->obpile, o->amt); moveob(o, lf->cell->obpile, o->amt);
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) { for (bp = BP_WEAPON; bp < MAXBODYPARTS; bp++) {
if (!hasbp(lf, bp)) { if (!hasbp(lf, bp)) {
@ -14520,6 +14566,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
for (o = lf->pack->first ; o ; o = nexto) { for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
@ -14539,6 +14586,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
} }
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (isplayer(lf)) { if (isplayer(lf)) {
needredraw = B_TRUE; needredraw = B_TRUE;
@ -14546,8 +14594,10 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
} else if (cansee(player, lf)) { } else if (cansee(player, lf)) {
needredraw = B_TRUE; needredraw = B_TRUE;
} }
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} // end if gamestarted } // end if gamestarted
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} }
void setlastdam(lifeform_t *lf, char *buf) { void setlastdam(lifeform_t *lf, char *buf) {
@ -14728,7 +14778,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
break; break;
/////////////// ///////////////
case SC_OPENLOCKS: case SC_OPENLOCKS:
attrib = getattr(lf, A_AGI); attrib = (getattr(lf, A_AGI)/2);
break; break;
case SC_WILL: case SC_WILL:
attrib = getattr(lf, A_WIS); attrib = getattr(lf, A_WIS);
@ -15273,13 +15323,14 @@ void startlfturn(lifeform_t *lf) {
// players lose stamina based on swimming skill // players lose stamina based on swimming skill
// monsters don't. // monsters don't.
switch (getskill(lf, SK_SWIMMING)) { switch (getskill(lf, SK_SWIMMING)) {
case PR_INEPT: lossamt = 3; break;
case PR_NOVICE: lossamt = 1; break; case PR_NOVICE: lossamt = 1; break;
case PR_BEGINNER: lossamt = 1; break; case PR_BEGINNER: lossamt = 1; break;
case PR_ADEPT: lossamt = 0.5; break; case PR_ADEPT: lossamt = 0.5; break;
case PR_SKILLED: lossamt = 0; break; case PR_SKILLED: lossamt = 0; break;
case PR_EXPERT: lossamt = 0; break; case PR_EXPERT: lossamt = 0; break;
case PR_MASTER: lossamt = 0; break; case PR_MASTER: lossamt = 0; break;
default:
case PR_INEPT: lossamt = 3; break;
} }
if (lossamt) modstamina(lf, -lossamt); if (lossamt) modstamina(lf, -lossamt);
} else if (isclimbing(lf) && !lfhasflag(lf, F_SPIDERCLIMB)) { } else if (isclimbing(lf) && !lfhasflag(lf, F_SPIDERCLIMB)) {
@ -16755,7 +16806,9 @@ void unsummon(lifeform_t *lf, int vanishobs) {
} else { } else {
strcpy(unsummonob, "puff of smoke"); strcpy(unsummonob, "puff of smoke");
} }
addob(lf->cell->obpile, unsummonob); if (strlen(unsummonob)) {
addob(lf->cell->obpile, unsummonob);
}
} }
int unweild(lifeform_t *lf, object_t *o) { int unweild(lifeform_t *lf, object_t *o) {
@ -17041,7 +17094,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
// straight back down! // straight back down!
if (hasflag(o->flags, F_PIT) && (dir == D_UP) && !isairborne(lf)) { if (hasflag(o->flags, F_PIT) && (dir == D_UP) && !isairborne(lf)) {
cell_t *noholecell; cell_t *noholecell;
noholecell = real_getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL); noholecell = real_getrandomadjcell(newcell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL, NULL);
if (noholecell) { if (noholecell) {
// go here instead // go here instead
newcell = noholecell; newcell = noholecell;

156
map.c
View File

@ -160,7 +160,7 @@ map_t *addmap(void) {
// props // props
a->id = id; a->id = id;
a->lf = NULL; a->lf = NULL;
for (i = 0; i < MAXDIR_ORTH; i++) { for (i = 0; i < MAXDIR_MAP; i++) {
a->nextmap[i] = -1; a->nextmap[i] = -1;
} }
for (i = 0 ; i < MAX_MAPW*MAX_MAPH; i++) { for (i = 0 ; i < MAX_MAPW*MAX_MAPH; i++) {
@ -177,7 +177,7 @@ map_t *addmap(void) {
// when monsters are made during level generation, autogen will be true. otherwise false; // when monsters are made during level generation, autogen will be true. otherwise false;
// if "rid" RR_NONE, parse racename to get the race. // if "rid" RR_SPECIFIED, parse racename to get the race.
// otherwise just use the given race. // otherwise just use the given race.
lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded) { lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded) {
lifeform_t *lf = NULL; lifeform_t *lf = NULL;
@ -188,6 +188,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
if (nadded) *nadded = 0; if (nadded) *nadded = 0;
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// ie. don't create mosnters on closed doors! // ie. don't create mosnters on closed doors!
if (!cellwalkable(NULL, c, NULL)) { if (!cellwalkable(NULL, c, NULL)) {
return NULL; return NULL;
@ -203,7 +205,9 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
// get params // get params
wantflags = addflagpile(NULL, NULL); wantflags = addflagpile(NULL, NULL);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
rid = parserace(racename, wantflags, &wantjob); rid = parserace(racename, wantflags, &wantjob);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (rid == R_RANDOM) { if (rid == R_RANDOM) {
r = getrandomrace(c, NA); r = getrandomrace(c, NA);
@ -220,6 +224,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
snprintf(buf, BUFLEN, "addmonster for '%s'->%s",racename, r->name); snprintf(buf, BUFLEN, "addmonster for '%s'->%s",racename, r->name);
dbtimestart(buf); dbtimestart(buf);
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
//if (db) dblog("adding rand lf %s to cell %d,%d",r->name,c->x,c->y); //if (db) dblog("adding rand lf %s to cell %d,%d",r->name,c->x,c->y);
@ -237,8 +242,10 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
lf = addlf(c, r->id, getrandommonlevel(r, c->map)); lf = addlf(c, r->id, getrandommonlevel(r, c->map));
if (db) dbtime("finished lf addition"); if (db) dbtime("finished lf addition");
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (lf) { if (lf) {
flag_t *f; flag_t *f;
@ -269,6 +276,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} else { } else {
givejob(lf, wantjob); givejob(lf, wantjob);
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (autogen) { if (autogen) {
// sometimes start off hiding/asleep in new maps // sometimes start off hiding/asleep in new maps
@ -282,18 +290,22 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
if (!lfhasflag(lf, F_HIDING) && !lfhasflag(lf, F_DEAF) && cansleep(lf) ) { if (!lfhasflag(lf, F_HIDING) && !lfhasflag(lf, F_DEAF) && cansleep(lf) ) {
int asleepchance = 70; // if not already asleep...
f = lfhasflag(lf, F_STARTASLEEPPCT); if (wantflags && hasflag(wantflags, F_ASLEEP)) {
if (f) {
asleepchance = f->val[0];
}
// TODO: base this on the time, and whether monster is nocturnal
if (pctchance(asleepchance)) {
addflag(lf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
} else { } else {
// might be asleep based on time. int asleepchance = 70;
if (issleepingtimefor(lf)) { f = lfhasflag(lf, F_STARTASLEEPPCT);
if (f) {
asleepchance = f->val[0];
}
// TODO: base this on the time, and whether monster is nocturnal
if (pctchance(asleepchance)) {
addflag(lf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL); addflag(lf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
} else {
// might be asleep based on time.
if (issleepingtimefor(lf)) {
addflag(lf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
}
} }
} }
} }
@ -304,6 +316,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// appears in groups? // appears in groups?
if (db) dbtime("handling groups"); if (db) dbtime("handling groups");
@ -322,7 +335,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
lifeform_t *newlf; lifeform_t *newlf;
// find an adjacent cell to one of the newly added monsters, // find an adjacent cell to one of the newly added monsters,
// starting with the first one // starting with the first one
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL); adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
// did we find one? // did we find one?
if (!adjcell) break; if (!adjcell) break;
@ -337,7 +350,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
addflag(lf->flags, F_MINION, newlf->id, NA, NA, NULL); addflag(lf->flags, F_MINION, newlf->id, NA, NA, NULL);
// if master is asleep, minions will also be asleep // if master is asleep, minions will also be asleep
if (lfhasflag(lf, F_ASLEEP)) { if (lfhasflag(lf, F_ASLEEP) || (wantflags && hasflag(wantflags, F_ASLEEP))) {
addflag(newlf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL); addflag(newlf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
} }
if (!newlf->cell->map->lit && !lfhasflag(newlf, F_SEEINDARK)) { if (!newlf->cell->map->lit && !lfhasflag(newlf, F_SEEINDARK)) {
@ -353,6 +366,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// minons? // minons?
// appears in groups? // appears in groups?
@ -371,7 +385,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
lifeform_t *newlf; lifeform_t *newlf;
race_t *newr; race_t *newr;
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL); adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
if (!adjcell) break; if (!adjcell) break;
newr = findracebyname(f->text); newr = findracebyname(f->text);
@ -383,7 +397,9 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
if (nadded) (*nadded)++; if (nadded) (*nadded)++;
newlf->born = B_FALSE; newlf->born = B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) addflag(newlf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL); if (lfhasflag(lf, F_ASLEEP) || (wantflags && hasflag(wantflags, F_ASLEEP))) {
addflag(newlf->flags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
}
if (!newlf->cell->map->lit && !lfhasflag(newlf, F_SEEINDARK)) { if (!newlf->cell->map->lit && !lfhasflag(newlf, F_SEEINDARK)) {
if (getraceclass(newlf) != RC_HUMANOID) { if (getraceclass(newlf) != RC_HUMANOID) {
@ -395,11 +411,12 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (db) dbtime("handling random objects"); if (db) dbtime("handling random objects");
// sometimes give the lf random objects (extra monsters through // sometimes give the lf random objects (extra monsters through
// 'numappears' don't get them. // 'numappears' don't get them).
if (lfhasflag(lf, F_HUMANOID) && !lfhasflag(lf, F_NOPACK)) { if (lfhasflag(lf, F_HUMANOID) && !lfhasflag(lf, F_NOPACK)) {
if (rnd(1,3) == 1) { if (rnd(1,3) == 1) {
int nobs = rnd(1,3); int nobs = rnd(1,3);
@ -416,6 +433,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (db) dbtime("giving torches"); if (db) dbtime("giving torches");
// humanoids on dark levels which can't see will probably have some // humanoids on dark levels which can't see will probably have some
@ -443,20 +461,24 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (wantflags) { if (wantflags) {
// wantflags? // wantflags?
copyflags(lf->flags, wantflags, NA); copyflags(lf->flags, wantflags, NA);
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
lf->born = B_TRUE; lf->born = B_TRUE;
} // end if lf } // end if lf
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// free mem // free mem
if (wantflags) { if (wantflags) {
killflagpile(wantflags); killflagpile(wantflags);
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (db) dbtimeend("finished addmonster"); if (db) dbtimeend("finished addmonster");
@ -487,16 +509,22 @@ int addrandomthing(cell_t *c, int obchance, int *nadded) {
if (!cellwalkable(NULL, c, NULL) || (rnd(1,100) <= obchance)) { if (!cellwalkable(NULL, c, NULL) || (rnd(1,100) <= obchance)) {
object_t *o; object_t *o;
// object // object
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
o = addrandomob(c); o = addrandomob(c);
if (o) { if (o) {
if (nadded) *nadded = o->amt; if (nadded) *nadded = o->amt;
rv = TT_OBJECT; rv = TT_OBJECT;
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
} else { } else {
lifeform_t *lf;
// monster // monster
if (addmonster(c, R_RANDOM, NULL, B_TRUE, 1, B_TRUE, nadded)) { //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
lf = addmonster(c, R_RANDOM, NULL, B_TRUE, 1, B_TRUE, nadded);
if (lf) {
rv = TT_MONSTER; rv = TT_MONSTER;
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
} }
return rv; return rv;
} }
@ -1875,7 +1903,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
int numrooms = 0; int numrooms = 0;
cell_t *cell, *c; cell_t *cell, *c;
object_t *o; object_t *o;
int db = B_FALSE; int db = B_TRUE;
int digdb = B_FALSE;
// parameters // parameters
int turnpct = DEF_TURNPCT; int turnpct = DEF_TURNPCT;
@ -1917,7 +1946,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
cell = getrandomcell(map); cell = getrandomcell(map);
setcelltype(cell, emptycell); setcelltype(cell, emptycell);
cell->visited = B_TRUE; cell->visited = B_TRUE;
if (db) printf("- Starting (%d,%d)\n",cell->x, cell->y); if (digdb) printf("- Starting (%d,%d)\n",cell->x, cell->y);
lastdir = D_UNKNOWN; lastdir = D_UNKNOWN;
done = B_FALSE; done = B_FALSE;
@ -1929,7 +1958,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
dir = D_NONE; dir = D_NONE;
while (dir == D_NONE) { while (dir == D_NONE) {
int badcount; int badcount;
if (db) printf("- At (%d,%d), moved %d, finding new direction...\n",cell->x, cell->y, moved); if (digdb) printf("- At (%d,%d), moved %d, finding new direction...\n",cell->x, cell->y, moved);
dir = getnewdigdir(cell, lastdir, (moved < 2) ? 0 : turnpct, &moved); dir = getnewdigdir(cell, lastdir, (moved < 2) ? 0 : turnpct, &moved);
@ -1947,19 +1976,19 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!isempty(cell)) { while (!isempty(cell)) {
cell = getrandomcell(map); cell = getrandomcell(map);
} }
if (db) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",cell->x, cell->y); if (digdb) printf("--- Couldn't find a valid direction. Jumped to (%d,%d).\n",cell->x, cell->y);
// pick a new random dir // pick a new random dir
dir = getnewdigdir(cell, lastdir, turnpct, &moved); dir = getnewdigdir(cell, lastdir, turnpct, &moved);
} }
if (!done) { if (!done) {
if (db) printf("- Digging %s from (%d,%d).\n",getdirname(dir),cell->x, cell->y); if (digdb) printf("- Digging %s from (%d,%d).\n",getdirname(dir),cell->x, cell->y);
} }
} }
if (!done) { if (!done) {
// move to adjacent cell in the given direction // move to adjacent cell in the given direction
cell = getcellindir(cell, dir); cell = getcellindir(cell, dir);
if (db) printf("- Now at (%d,%d)\n",cell->x, cell->y); if (digdb) printf("- Now at (%d,%d)\n",cell->x, cell->y);
moved++; moved++;
// blank it // blank it
@ -1970,7 +1999,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
cell_t *thiscell; cell_t *thiscell;
thiscell = getcellindir(cell, d); thiscell = getcellindir(cell, d);
if (thiscell) { if (thiscell) {
if (db) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y); if (digdb) printf("* Marking surrounding cell in dir %d (%d,%d) as visited.\n",d, thiscell->x, thiscell->y);
thiscell->visited = B_TRUE; thiscell->visited = B_TRUE;
} }
} }
@ -1994,7 +2023,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
} }
} }
if (db) dblog("%d unused cell(s)\n",unused); if (digdb) dblog("%d unused cell(s)\n",unused);
//dumpmap(map); //dumpmap(map);
//getchar(); //getchar();
@ -2150,6 +2179,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
} }
} }
o = addobfast(c->obpile, OT_STAIRSUP); o = addobfast(c->obpile, OT_STAIRSUP);
assert(o);
linkstairs(o, NULL); linkstairs(o, NULL);
} }
} }
@ -2164,6 +2194,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM);
} }
o = addobfast(c->obpile, OT_STAIRSDOWN); o = addobfast(c->obpile, OT_STAIRSDOWN);
assert(o);
linkstairs(o, NULL); linkstairs(o, NULL);
} }
} }
@ -2251,11 +2282,13 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
// river? // river?
if ((depth >= 4) && pctchance(20)) { // TODO FIX
//if ((depth >= 4) && pctchance(20)) {
//if (depth > 1) {
if (0) {
createriver(map); createriver(map);
} }
// now do a border // now do a border
y = 0; y = 0;
for (x = 0; x < map->w; x++) { for (x = 0; x < map->w; x++) {
@ -2460,6 +2493,8 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
int nthings = 0,failed; int nthings = 0,failed;
int db = B_TRUE; int db = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// determine habitat based on region // determine habitat based on region
// note: we might override this later based on our region outline // note: we might override this later based on our region outline
habitat = region->rtype->defaulthabitat; habitat = region->rtype->defaulthabitat;
@ -2491,6 +2526,8 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
map->nextmap[i] = -1; map->nextmap[i] = -1;
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// look for adjacent maps above/below this one // look for adjacent maps above/below this one
if (db) dblog(" look for adjacent maps above/below this one"); if (db) dblog(" look for adjacent maps above/below this one");
for (i = depth-1; i <= depth+1; i += 2) { for (i = depth-1; i <= depth+1; i += 2) {
@ -2508,16 +2545,19 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// did we come from a previous map in the same region? // did we come from a previous map in the same region?
if (parentmap) { if (parentmap && (exitdir != D_NONE)) {
if ((parentmap->region->id == map->region->id) || if ((parentmap->region->id == map->region->id) ||
(map->region->rtype->majorbranch)) { (map->region->rtype->majorbranch)) {
if (db) dblog(" linking to parentmap %s in dir %s", parentmap->name, getdirname(diropposite(exitdir))); if (db) dblog(" linking to parentmap %s in dir %s", parentmap->name, getdirname(diropposite(exitdir)));
parentmap->nextmap[exitdir] = map->id; parentmap->nextmap[exitdir] = map->id;
assert(exitdir >= 0);
map->nextmap[diropposite(exitdir)] = parentmap->id; map->nextmap[diropposite(exitdir)] = parentmap->id;
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
/* /*
if (map->region->rtype->id == RG_WORLDMAP) { if (map->region->rtype->id == RG_WORLDMAP) {
@ -2605,6 +2645,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
addflag(map->flags, F_MAPCOORDS, x, y, NA, NULL); addflag(map->flags, F_MAPCOORDS, x, y, NA, NULL);
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// we now have the map name! // we now have the map name!
getregionname(buf2, map, B_TRUE); getregionname(buf2, map, B_TRUE);
@ -2667,19 +2708,24 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
if (db) dblog(" region has no outline."); if (db) dblog(" region has no outline.");
} }
if (db) dblog(" %d things remembered for later.",nthings); if (db) dblog(" %d things remembered for later.",nthings);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
failed = B_TRUE; failed = B_TRUE;
while (failed) { while (failed) {
failed = B_FALSE; failed = B_FALSE;
// build it... // build it...
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (db) dblog(" creating map habitat."); if (db) dblog(" creating map habitat.");
createhabitat(map, depth, parentmap, exitdir, entryob); createhabitat(map, depth, parentmap, exitdir, entryob);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// add home objects // add home objects
if (db) dblog(" adding home objects."); if (db) dblog(" adding home objects.");
for (lf = map->lf ; lf ; lf = lf->next) { for (lf = map->lf ; lf ; lf = lf->next) {
addhomeobs(lf); addhomeobs(lf);
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// add outline things // add outline things
if (db) dblog(" adding remembered region outline things..."); if (db) dblog(" adding remembered region outline things...");
@ -2694,7 +2740,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
if (db) dblog(" adding forced regionthing object: %s", thing[i]->what); if (db) dblog(" adding forced regionthing object: %s", thing[i]->what);
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM);
if (!c) c = getrandomcell(map); if (!c) c = getrandomcell(map);
c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL); c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
addob(c->obpile, thing[i]->what); addob(c->obpile, thing[i]->what);
break; break;
case RT_REGIONLINK: case RT_REGIONLINK:
@ -2723,6 +2769,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
break; break;
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// ensure there are no unreachable areas // ensure there are no unreachable areas
if (!failed) { if (!failed) {
@ -2730,12 +2777,14 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
failed = B_TRUE; failed = B_TRUE;
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (failed) { if (failed) {
dblog("********* got errors - restarting map creation. *********"); dblog("********* got errors - restarting map creation. *********");
unlinkstairsto(map); unlinkstairsto(map);
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// special cases // special cases
// village - add town walls and clear it out // village - add town walls and clear it out
@ -2871,6 +2920,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// try to join up any unlinked staircases in this map. // try to join up any unlinked staircases in this map.
if (db) dblog(" joining unlinked stairs..."); if (db) dblog(" joining unlinked stairs...");
for (y = 0; y < map->h; y++) { for (y = 0; y < map->h; y++) {
@ -2899,12 +2949,14 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// link up holes - this will create NEW holes in THIS map connecting to // link up holes - this will create NEW holes in THIS map connecting to
// EXISTING unlinked holes in adjacent maps // EXISTING unlinked holes in adjacent maps
i = linkholes(map); i = linkholes(map);
if (db) { if (db) {
if (db) dblog(" autolinked to %d holes in adjacent maps.",i); if (db) dblog(" autolinked to %d holes in adjacent maps.",i);
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// add random objects and monsters // add random objects and monsters
if (db) dblog(" adding random objects+monsters"); if (db) dblog(" adding random objects+monsters");
@ -2920,6 +2972,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// look for adjacent maps // look for adjacent maps
if (db) dblog(" linking to adjacent maps"); if (db) dblog(" linking to adjacent maps");
@ -2956,6 +3009,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
} }
} }
} }
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
map->beingcreated = B_FALSE; map->beingcreated = B_FALSE;
if (db) dblog(" Map creation finished."); if (db) dblog(" Map creation finished.");
@ -3188,8 +3242,10 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
assert(c); assert(c);
} }
o = addobfast(c->obpile, OT_GRATINGROOF); o = addobfast(c->obpile, OT_GRATINGROOF);
assert(o);
// have to force these stairs to go back to a different region. // have to force these stairs to go back to a different region.
f = hasflag(o->flags, F_CLIMBABLE); f = hasflag(o->flags, F_CLIMBABLE);
assert(f);
f->val[1] = map->region->parentregion->id; f->val[1] = map->region->parentregion->id;
linkstairs(o, entryob); linkstairs(o, entryob);
@ -3933,9 +3989,10 @@ void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIO
void createriver(map_t *m) { void createriver(map_t *m) {
int dir,width,startcentre,endcentre; int dir,width,startcentre,endcentre;
cell_t *retcell[MAXRETCELLS]; cell_t *retcell[MAX_MAPW*MAX_MAPH];
cell_t *dirtcell[MAXRETCELLS]; cell_t *dirtcell[MAX_MAPW*MAX_MAPH];
int nretcell,ndirtcells,i; int nretcell,ndirtcells,i;
dblog("Creating river on map %s (depth %d)!", m->name, m->depth);
// pick direction // pick direction
dir = rnd(B_VERT,B_HORZ); dir = rnd(B_VERT,B_HORZ);
// pick random river width // pick random river width
@ -3952,6 +4009,8 @@ void createriver(map_t *m) {
calcbresnham(m, 0, startcentre, m->w - 1, endcentre, retcell, &nretcell); calcbresnham(m, 0, startcentre, m->w - 1, endcentre, retcell, &nretcell);
} }
assert(nretcell < (MAX_MAPW*MAX_MAPH));
// for each centrelist // for each centrelist
for (i = 0; i < nretcell; i++) { for (i = 0; i < nretcell; i++) {
int pos,start,end,n; int pos,start,end,n;
@ -4623,7 +4682,7 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) {
int i; int i;
int turned = B_FALSE; int turned = B_FALSE;
cell_t *newcell; cell_t *newcell;
int db = B_TRUE; int db = B_FALSE;
char err[BUFLEN]; char err[BUFLEN];
// haven't tried any dirs yet // haven't tried any dirs yet
@ -4776,15 +4835,16 @@ char *getregionname(char *buf, map_t *m, int withlevel) {
} }
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) { cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand) {
return real_getrandomadjcell(c, wantempty, allowexpand, LOF_NEED, NULL); return real_getrandomadjcell(c, wantempty, allowexpand, LOF_NEED, NULL, NULL);
} }
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob) { cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob, lifeform_t *preferlos) {
int radius = 1; int radius = 1;
int x,y; int x,y;
cell_t *poss[MAXCANDIDATES]; cell_t *poss[MAXCANDIDATES];
int nposs = 0; cell_t *losposs[MAXCANDIDATES];
cell_t *new; int nposs = 0,nlosposs = 0;
cell_t *new,*sel = NULL;
int done = B_FALSE; int done = B_FALSE;
while (!done) { while (!done) {
@ -4837,6 +4897,9 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
} }
if (ok) { if (ok) {
if (preferlos && haslos(preferlos, new)) {
losposs[nlosposs++] = new;
}
poss[nposs++] = new; poss[nposs++] = new;
} }
} }
@ -4859,8 +4922,14 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
} }
} }
} }
return poss[rnd(0,nposs-1)]; // select a random cell
if (preferlos && nlosposs) {
sel = losposs[rnd(0,nlosposs-1)];
} else {
sel = poss[rnd(0,nposs-1)];
}
return sel;
} }
cell_t *getrandomcell(map_t *map) { cell_t *getrandomcell(map_t *map) {
@ -5119,6 +5188,8 @@ int hasknownobject(cell_t *c) {
object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tflag, lifeform_t *viewer) { object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tflag, lifeform_t *viewer) {
object_t *o; object_t *o;
flag_t *f; flag_t *f;
// default
if (tflag) *tflag = NULL;
for (o = op->first ; o ; o = o->next) { for (o = op->first ; o ; o = o->next) {
if (viewer && !canseeob(viewer, o)) continue; if (viewer && !canseeob(viewer, o)) continue;
if ((oid == NA) || (o->type->id == oid)) { if ((oid == NA) || (o->type->id == oid)) {
@ -5547,7 +5618,7 @@ int linkholes(map_t *map) {
// this will automatically avoid lifeforms since we're using // this will automatically avoid lifeforms since we're using
// we_walkable rather than we_notwall. this saves problems // we_walkable rather than we_notwall. this saves problems
// with someine coming up underneath you! // with someine coming up underneath you!
c2 = real_getrandomadjcell(c2, WE_NOLF, B_ALLOWEXPAND, LOF_DONTNEED, &ot->id); c2 = real_getrandomadjcell(c2, WE_NOLF, B_ALLOWEXPAND, LOF_DONTNEED, &ot->id, NULL);
} }
// clear out the cell if required // clear out the cell if required
if (c2->type->solid) { if (c2->type->solid) {
@ -5580,12 +5651,13 @@ object_t *linkportal(object_t *srcportal, int wantdepth) {
cell_t *srcloc,*newcell; cell_t *srcloc,*newcell;
map_t *newmap = NULL; map_t *newmap = NULL;
object_t *dstportal = NULL; object_t *dstportal = NULL;
srcloc = getoblocation(srcportal); srcloc = getoblocation(srcportal);
newmap = findregionmap(srcloc->map->region->id, wantdepth); newmap = findregionmap(srcloc->map->region->id, wantdepth);
if (!newmap) { if (!newmap) {
// create new map // create new map
newmap = addmap(); newmap = addmap();
createmap(newmap, wantdepth, srcloc->map->region, NULL, D_NONE, NULL); createmap(newmap, wantdepth, srcloc->map->region, NULL, D_NONE, NULL);
} }
// find a random cell there // find a random cell there
@ -5595,6 +5667,8 @@ object_t *linkportal(object_t *srcportal, int wantdepth) {
} }
// add the dst portal // add the dst portal
dstportal = addob(newcell->obpile, "magic portal"); dstportal = addob(newcell->obpile, "magic portal");
assert(dstportal);
// link the dst portal // link the dst portal
addflag_real(dstportal->flags, F_MAPLINK, srcloc->map->id, srcloc->x, srcloc->y, NULL, PERMENANT, B_FALSE, -1); addflag_real(dstportal->flags, F_MAPLINK, srcloc->map->id, srcloc->x, srcloc->y, NULL, PERMENANT, B_FALSE, -1);

2
map.h
View File

@ -91,7 +91,7 @@ int getobchance(int habitat);
char *getregionname(char *buf, map_t *m, int withlevel); char *getregionname(char *buf, map_t *m, int withlevel);
int getthingchance(int habitat); int getthingchance(int habitat);
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand); cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob); cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob, lifeform_t *preferlos);
cell_t *getrandomcell(map_t *map); cell_t *getrandomcell(map_t *map);
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id); cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id);
int getrandomdir(int dirtype); int getrandomdir(int dirtype);

44
move.c
View File

@ -1842,17 +1842,22 @@ int opendoor(lifeform_t *lf, object_t *o) {
} else { } else {
int openit = B_TRUE; int openit = B_TRUE;
f = hasflag(o->flags, F_JAMMED); f = hasflag(o->flags, F_JAMMED);
if (f) { if (f && lf) {
int amt; if (isplayer(lf) && (f->val[1] != B_TRUE)) { // not known yet
amt = getattr(lf, A_STR) - 10; msg("The %s is jammed.", noprefix(obname));
if (amt < 0) amt = 0; openit = B_FALSE;
f->val[1] = B_TRUE;
if (lf) { } else {
// known - try to force it
int amt;
amt = getattr(lf, A_STR) - 10;
if (amt < 0) amt = 0;
if (isplayer(lf)) { if (isplayer(lf)) {
if (amt > 0) { if (amt > 0) {
msg("The %s moves slightly but seems jammed.", noprefix(obname)); msg("The %s moves slightly but remains jammed.", noprefix(obname));
} else { } else {
msg("The %s is jammed.", noprefix(obname)); msg("You cannot budge the jammed %s.", noprefix(obname));
} }
} else { } else {
// ai chasing someone and not strong enough to unjam the door? // ai chasing someone and not strong enough to unjam the door?
@ -1874,16 +1879,16 @@ int opendoor(lifeform_t *lf, object_t *o) {
} }
} }
} }
} // loosen a bit
// loosen a bit if (amt) {
if (amt) { f->val[0] -= amt;
f->val[0] -= amt; if (f->val[0] <= 0) {
if (f->val[0] <= 0) { killflag(f);
killflag(f); }
} }
} openit = B_FALSE; // don't open the door
openit = B_FALSE; // don't open the door } // end if jammedknown
} } // end if jammed
if (openit) { if (openit) {
cell_t *where; cell_t *where;
// open it // open it
@ -2637,9 +2642,10 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
tf = ispetortarget(l, lf); tf = ispetortarget(l, lf);
if (tf) { if (tf) {
if (cansee(l, lf)) { if (cansee(l, lf)) {
char dirbuf[BUFLEN];
// update text field // update text field
free(tf->text); sprintf(dirbuf, "%d", dir);
asprintf(&(tf->text), "%d", dir); changeflagtext(tf, dirbuf);
} }
} }
} }

13
nexus.c
View File

@ -346,6 +346,7 @@ int main(int argc, char **argv) {
sb1 = addob(player->pack, "spellbook of wild magic"); sb1 = addob(player->pack, "spellbook of wild magic");
break; break;
default: default:
sb1 = NULL;
break; break;
} }
if (sb1) { if (sb1) {
@ -378,6 +379,7 @@ int main(int argc, char **argv) {
sb2 = addob(player->pack, "spellbook of translocation magic"); sb2 = addob(player->pack, "spellbook of translocation magic");
break; break;
default: default:
sb2 = NULL;
break; break;
} }
if (sb2) { if (sb2) {
@ -645,6 +647,8 @@ void checkendgame(void) {
void cleanup(void) { void cleanup(void) {
gamemode = GM_CLEANUP;
free(xpposs); free(xpposs);
free(raceposs); free(raceposs);
@ -1589,6 +1593,8 @@ void timeeffectsworld(map_t *map, int updategametime) {
enum SKILLLEVEL cartskill; enum SKILLLEVEL cartskill;
warning_t *w,*nextw; warning_t *w,*nextw;
dblog("------ tick (time=%ld) ----", curtime);
cartskill = getskill(player, SK_CARTOGRAPHY); cartskill = getskill(player, SK_CARTOGRAPHY);
// now go through the list and make the first element be 0 // now go through the list and make the first element be 0
@ -1681,7 +1687,9 @@ void timeeffectsworld(map_t *map, int updategametime) {
// go through each object in the cell... // go through each object in the cell...
for (o = c->obpile->first ; o ; o = nexto) { for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
assert(nexto != o);
checkflagpile(o->flags);
timeeffectsob(o); timeeffectsob(o);
} // end foreach object here } // end foreach object here
@ -1705,6 +1713,7 @@ void timeeffectsworld(map_t *map, int updategametime) {
noredraw = B_TRUE; noredraw = B_TRUE;
getflags(map->flags, retflag, &nretflags, F_NEWWATERDEPTH, F_NONE); getflags(map->flags, retflag, &nretflags, F_NEWWATERDEPTH, F_NONE);
assert(nretflags < MAXCANDIDATES); // oooooooooooooo
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
cell_t *c; cell_t *c;
f = retflag[i]; f = retflag[i];
@ -1718,12 +1727,14 @@ void timeeffectsworld(map_t *map, int updategametime) {
} }
setwaterdepth(c, f->val[2]); setwaterdepth(c, f->val[2]);
} }
killflag(f);
} }
killflagsofid(map->flags, F_NEWWATERDEPTH);
noredraw = B_FALSE; noredraw = B_FALSE;
// now handle effects on lifeforms and/or their objects // now handle effects on lifeforms and/or their objects
for (l = map->lf ; l ; l = l->next) { for (l = map->lf ; l ; l = l->next) {
checkflagpile(l->flags);
timeeffectslf(l); timeeffectslf(l);
} }

View File

@ -1201,8 +1201,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
ok = B_TRUE; ok = B_TRUE;
break; break;
case F_JAMMED: case F_JAMMED:
val[0] = rnd(1,obloc->map->depth+3); val[0] = rnd(1,obloc->map->depth+5);
val[1] = NA; val[1] = B_FALSE; // not known yet
val[2] = NA; val[2] = NA;
ok = B_TRUE; ok = B_TRUE;
break; break;
@ -1664,8 +1664,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} }
} }
// locked? // locked?
if (!lockchance) { if (!lockchance) {
f = hasflag(o->flags, F_CANBELOCKED); f = hasflag(o->flags, F_CANBELOCKED);
@ -1812,6 +1810,7 @@ obmod_t *addobmod(enum OBMOD id, char *prefix) {
obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob) { obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob) {
obpile_t *op; obpile_t *op;
int i;
op = malloc(sizeof(obpile_t)); op = malloc(sizeof(obpile_t));
op->first = NULL; op->first = NULL;
op->last = NULL; op->last = NULL;
@ -1819,6 +1818,10 @@ obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob) {
op->where = where; op->where = where;
op->parentob = parentob; op->parentob = parentob;
for (i = 0;i < MAXPILEOBS; i++) {
op->oblist[i] = -1;
}
return op; return op;
} }
@ -2798,9 +2801,6 @@ int doobdieconvert(object_t *o, int wantannounce) {
} else { } else {
snprintf(desc, BUFLEN, "%s destroyed", OB1(o,"is","are")); snprintf(desc, BUFLEN, "%s destroyed", OB1(o,"is","are"));
} }
if (strstr(o->type->name, "stain") || (o->type->id == OT_ROASTMEAT)) {
assert(0 == 1);
}
if (strlen(desc)) { if (strlen(desc)) {
if (o->pile->owner) { if (o->pile->owner) {
@ -3534,6 +3534,7 @@ int getobvalue(object_t *o) {
return getcharges(o); return getcharges(o);
} }
// base value: weight * material value // base value: weight * material value
price = (float)getobweight(o) * (float)getmaterialvalue(o->material->id); price = (float)getobweight(o) * (float)getmaterialvalue(o->material->id);
//adjustprice(o->type, &price); //adjustprice(o->type, &price);
@ -3544,6 +3545,10 @@ int getobvalue(object_t *o) {
price += f->val[0]; price += f->val[0];
} }
if (o->type->id == OT_SPELLBOOK) {
price += (89*countobs(o->contents, B_FALSE));
}
getflags(o->flags, retflag, &nretflags, F_ARMOURRATING, F_ARMOURSIZE, F_BONUS, F_DAM, F_EDIBLE, F_LINKSPELL, F_MANUALOF, F_NONE); getflags(o->flags, retflag, &nretflags, F_ARMOURRATING, F_ARMOURSIZE, F_BONUS, F_DAM, F_EDIBLE, F_LINKSPELL, F_MANUALOF, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
@ -3575,9 +3580,7 @@ int getobvalue(object_t *o) {
} }
// one-off magical effects (linkspell) - use spell price // one-off magical effects (linkspell) - use spell price
if (f->id == F_LINKSPELL) { if (f->id == F_LINKSPELL) {
if (o->type->obclass->id == OC_BOOK) { if (o->type->obclass->id == OC_SCROLL) {
price += (pow(getspelllevel(f->val[0]), 2) * 30);
} else if (o->type->obclass->id == OC_SCROLL) {
price += (pow(getspelllevel(f->val[0]), 2) * 2); price += (pow(getspelllevel(f->val[0]), 2) * 2);
} else if (o->type->obclass->id == OC_POTION) { } else if (o->type->obclass->id == OC_POTION) {
price += (pow(getspelllevel(f->val[0]), 2)); price += (pow(getspelllevel(f->val[0]), 2));
@ -3953,7 +3956,8 @@ char *gethiddenname(object_t *o) {
return o->type->name; return o->type->name;
} }
// otherwise special case for unidentified books... // otherwise special case for unidentified books...
if (o->type->id == OT_SPELLBOOK) { //if (o->type->id == OT_SPELLBOOK) {
if (o->type->obclass->id == OC_BOOK) {
flag_t *f; flag_t *f;
f = hasflag(o->flags, F_HASHIDDENNAME); f = hasflag(o->flags, F_HASHIDDENNAME);
if (f) { if (f) {
@ -6412,7 +6416,8 @@ int isknown(object_t *o) {
} }
// unidentified books are always unknown // unidentified books are always unknown
if (o->type->id == OT_SPELLBOOK) { //if (o->type->id == OT_SPELLBOOK) {
if (o->type->obclass->id == OC_BOOK) {
return B_FALSE; return B_FALSE;
} }
@ -6879,6 +6884,12 @@ void killmaterial(material_t *m) {
void killob(object_t *o) { void killob(object_t *o) {
object_t *nextone, *lastone; object_t *nextone, *lastone;
dblog("killing object id %ld (%d x %s)", o->id, o->amt, o->type->name);
if (o->pile->where) {
dblog(" from cell %d,%d", o->pile->where->x, o->pile->where->y);
}
// debugging // debugging
/* /*
if (o->type->id == OT_STAIRSUP) { if (o->type->id == OT_STAIRSUP) {
@ -6888,6 +6899,8 @@ void killob(object_t *o) {
} }
*/ */
o->dying = B_TRUE;
// remove flags conferred by this object // remove flags conferred by this object
if (o->pile->owner) { if (o->pile->owner) {
loseobflags(o->pile->owner, o, ALLCONFERRED); loseobflags(o->pile->owner, o, ALLCONFERRED);
@ -8602,10 +8615,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
capitalise(buf); capitalise(buf);
msg("%s looks at %s.",buf, obname); msg("%s looks at %s.",buf, obname);
} }
} else if ((o->type->id == OT_LOCKPICK)
|| (o->type->id == OT_PAPERCLIP)
|| (o->type->id == OT_CREDITCARD)) {
lockpick(lf, NULL, NULL, o);
} else if (o->type->id == OT_LOCKHACKER) { } else if (o->type->id == OT_LOCKHACKER) {
char ch; char ch;
int dir; int dir;
@ -8721,7 +8730,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
ch = askchar(buf, "yn", "y", B_TRUE, B_FALSE); ch = askchar(buf, "yn", "y", B_TRUE, B_FALSE);
if (ch == 'y') { if (ch == 'y') {
msg("You tighten the hinges on %s.", obname); msg("You tighten the hinges on %s.", obname);
addflag(o->flags, F_JAMMED, rnd(1,10), NA, NA, NULL); addflag(o->flags, F_JAMMED, rnd(5,10), B_TRUE, NA, NULL);
taketime(lf, getactspeed(lf)); taketime(lf, getactspeed(lf));
donesomething = B_TRUE; donesomething = B_TRUE;
} }
@ -10348,8 +10357,8 @@ void removedeadobs(obpile_t *op) {
for (o = op->first ; o ; o = nexto) { for (o = op->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
if (hasflag(o->flags, F_DEAD)) { if (hasflag(o->flags, F_DEAD)) {
checkflagpile(o->flags);
obdie(o); obdie(o);
continue;
} }
} }
} }
@ -10437,7 +10446,7 @@ int sethiddenname(objecttype_t *ot, char *text) {
int n; int n;
int gotcolour = B_FALSE; int gotcolour = B_FALSE;
// add knowledge for it (unless it's a book // add knowledge for it (unless it's a book)
if (ot->obclass->id != OC_BOOK) { if (ot->obclass->id != OC_BOOK) {
addknowledge(ot->id, text, B_UNKNOWN); addknowledge(ot->id, text, B_UNKNOWN);
} }
@ -10650,6 +10659,7 @@ int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf) {
msg("%s %s covered with oil!", targetname, is(target)); msg("%s %s covered with oil!", targetname, is(target));
} }
// target is temporarily vulnerable to fire. // target is temporarily vulnerable to fire.
howlong = rnd(5,10);
addtempflag(target->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6", howlong); addtempflag(target->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6", howlong);
break; break;
case OT_POT_RUM: case OT_POT_RUM:
@ -11869,21 +11879,24 @@ void timeeffectsob(object_t *o) {
owner = NULL; owner = NULL;
} }
checkflagpile(o->flags);
// special case for trail flags // special case for trail flags
f = hasflag(o->flags, F_TRAIL); f = hasflag(o->flags, F_TRAIL);
if (f) { if (f && (f->lifetime > 0)) {
if (f->lifetime > 0) { f->lifetime--;
f->lifetime--; if (f->lifetime <= 0) {
if (f->lifetime <= 0) { //killflag(f);
// object dies. // object dies.
killob(o); //killob(o);
return; removeob(o, o->amt);
} return;
} }
} }
// expire flags // expire flags
timeeffectsflags(o->flags); timeeffectsflags(o->flags);
checkflagpile(o->flags);
// blessed weapons glow when held near undead // blessed weapons glow when held near undead
if (isblessed(o) && isweapon(o)) { if (isblessed(o) && isweapon(o)) {
@ -12054,7 +12067,7 @@ void timeeffectsob(object_t *o) {
if (haslos(player, location)) { if (haslos(player, location)) {
msg("%s vanish%s.", obname, OB1(o,"es","")); msg("%s vanish%s.", obname, OB1(o,"es",""));
} }
killob(o); removeob(o, o->amt);
return; return;
} }
} }
@ -12206,17 +12219,21 @@ void timeeffectsob(object_t *o) {
// is object on fire? // is object on fire?
if (f->id == F_ONFIRE) { if (f->id == F_ONFIRE) {
int wasputout = B_FALSE;
// water puts out fire // water puts out fire
for (oo = o->pile->first ; oo ; oo = nextoo) { for (oo = o->pile->first ; oo ; oo = nextoo) {
nextoo = oo->next; nextoo = oo->next;
if ((oo != o) && (oo->material->id == MT_WATER)) { if ((oo != o) && (oo->material->id == MT_WATER)) {
extinguish(o); extinguish(o);
continue; wasputout = B_TRUE;
break;
} }
} }
// if it hasn't been extinguished, fire burns if (!wasputout) {
takedamage(o, 2, DT_FIRE); // TODO: don't hardcode // if it hasn't been extinguished, fire burns
if (hasflag(o->flags, F_DEAD)) return; takedamage(o, 2, DT_FIRE); // TODO: don't hardcode
if (hasflag(o->flags, F_DEAD)) return;
}
} }
// will current object convert other obs to something else? // will current object convert other obs to something else?
@ -12292,6 +12309,7 @@ void timeeffectsob(object_t *o) {
} }
} // end for each object flag } // end for each object flag
checkflagpile(o->flags);
} }
// both trapob and oid are passed, because trapob might be NULL if // both trapob and oid are passed, because trapob might be NULL if
@ -13120,13 +13138,14 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
} }
switch (slev) { switch (slev) {
case PR_INEPT: cellpenalty = 32; break;
case PR_NOVICE: cellpenalty = 22; break; case PR_NOVICE: cellpenalty = 22; break;
case PR_BEGINNER: cellpenalty = 16; break; case PR_BEGINNER: cellpenalty = 16; break;
case PR_ADEPT: cellpenalty = 12; break; case PR_ADEPT: cellpenalty = 12; break;
case PR_SKILLED: cellpenalty = 10; break; case PR_SKILLED: cellpenalty = 10; break;
case PR_EXPERT: cellpenalty = 8; break; case PR_EXPERT: cellpenalty = 8; break;
case PR_MASTER: cellpenalty = 6; break; case PR_MASTER: cellpenalty = 6; break;
default:
case PR_INEPT: cellpenalty = 32; break;
} }
howfar = getcelldist(thrower->cell, where); howfar = getcelldist(thrower->cell, where);

97
spell.c
View File

@ -947,6 +947,15 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("%s tries to disarm %s, but fail.",username, targetname); msg("%s tries to disarm %s, but fail.",username, targetname);
} }
} }
} else if (abilid == OT_A_DRAGUNDERGROUND) {
// announce
if (cansee(player, target)) {
msg("%s drags %s underground.", username, targetname);
}
addflag(target->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(target->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
target->hp = 0;
killallobs(target->pack);
} else if (abilid == OT_A_FEIGNDEATH) { } else if (abilid == OT_A_FEIGNDEATH) {
lifeform_t *lf; lifeform_t *lf;
if (hasflag(user->flags, F_FEIGNINGDEATH)) { if (hasflag(user->flags, F_FEIGNINGDEATH)) {
@ -1389,6 +1398,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
fall(user, NULL, B_TRUE); fall(user, NULL, B_TRUE);
} }
} }
} else if (abilid == OT_A_PICKLOCK) {
lockpick(user, NULL, NULL, NULL);
} else if (abilid == OT_A_RAGE) { } else if (abilid == OT_A_RAGE) {
int howlong; int howlong;
f = lfhasflag(user, F_RAGE); f = lfhasflag(user, F_RAGE);
@ -2042,7 +2053,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
flag_t *f; flag_t *f;
char targetname[BUFLEN]; char targetname[BUFLEN];
int badweapon = B_FALSE; int badweapon = B_FALSE;
flag_t *damflag; flag_t *damflag = NULL;
obpile_t *op = NULL; obpile_t *op = NULL;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
@ -2067,9 +2078,9 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
badweapon = B_TRUE; badweapon = B_TRUE;
} }
damflag = hasflag(wep->flags, F_DAM); damflag = hasflag(wep->flags, F_DAM);
if (!damflag) { }
badweapon = B_TRUE; if (!damflag) {
} badweapon = B_TRUE;
} }
if (badweapon) { if (badweapon) {
@ -4282,7 +4293,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
objecttype_t *ot; objecttype_t *ot;
object_t *o; object_t *o;
char obname[BUFLEN]; char obname[BUFLEN];
int i,amt; int i,amt = 1;
if (!targcell || targcell->type->solid) { if (!targcell || targcell->type->solid) {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
@ -5156,7 +5167,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
badoid[1] = OT_NONE; badoid[1] = OT_NONE;
for (i = 0; i < amt; i++) { for (i = 0; i < amt; i++) {
cell_t *c; cell_t *c;
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, badoid); c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_WALLSTOP, badoid, NULL);
if (c) { if (c) {
object_t *water; object_t *water;
water = addob(c->obpile, "water"); water = addob(c->obpile, "water");
@ -6100,7 +6111,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
closedoor(NULL, o); closedoor(NULL, o);
addflag(o->flags, F_JAMMED, power*2, NA, NA, NULL); addflag(o->flags, F_JAMMED, power*2, haslos(player, targcell) ? B_TRUE : B_FALSE, NA, NULL);
if (haslos(player, targcell)) { if (haslos(player, targcell)) {
char buf[BUFLEN]; char buf[BUFLEN];
@ -6336,23 +6347,26 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = caster->pack->first ; o ; o = nexto) { for (o = caster->pack->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
if (ismetal(o->material->id)) { if (ismetal(o->material->id)) {
if (isequippedon(o, BP_RIGHTFINGER) || isequippedon(o, BP_LEFTFINGER)) { f = hasflag(o->flags, F_EQUIPPED);
if (isplayer(caster)) { if (f) {
getobname(o, buf, 1); if ((f->val[0] == BP_RIGHTFINGER) || (f->val[0] == BP_LEFTFINGER)) {
msg("Your %s slides off your %s!", buf, getbodypartname(caster, f->val[0])); if (isplayer(caster)) {
} else if (cansee(player, caster)) { getobname(o, buf, 1);
getobname(o, buf, 1); msg("Your %s slides off your %s!", buf, getbodypartname(caster, f->val[0]));
msg("%s%s %s slides off its %s!", castername, } else if (cansee(player, caster)) {
getpossessive(castername), buf, getbodypartname(caster, f->val[0])); getobname(o, buf, 1);
msg("%s%s %s slides off its %s!", castername,
getpossessive(castername), buf, getbodypartname(caster, f->val[0]));
}
moveob(o, caster->cell->obpile, o->amt);
} else {
if (isplayer(caster)) {
getobname(o, buf, 1);
msg("Your %s pulls away from you a little.", noprefix(buf));
}
fizzle(caster);
return B_FALSE;
} }
moveob(o, caster->cell->obpile, o->amt);
} else if (isequipped(o)) {
if (isplayer(caster)) {
getobname(o, buf, 1);
msg("Your %s pulls away from you a little.", noprefix(buf));
}
fizzle(caster);
return B_FALSE;
} }
} }
} }
@ -6914,13 +6928,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *srcportal,*dstportal; object_t *srcportal,*dstportal;
// find adjacent cell for portal // find adjacent cell for portal
srccell = getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND); srccell = real_getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
if (!srccell) { if (!srccell) {
fizzle(caster); fizzle(caster);
return B_FALSE; return B_FALSE;
} }
// create the source portal // create the source portal
srcportal = addobfast(srccell->obpile, OT_PORTAL); srcportal = addobfast(srccell->obpile, OT_PORTAL);
assert(srcportal);
setobcreatedby(srcportal, caster); setobcreatedby(srcportal, caster);
// announce, because we might have a delay creating the level... // announce, because we might have a delay creating the level...
@ -6929,7 +6944,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
wrefresh(msgwin); wrefresh(msgwin);
} }
dstportal = linkportal(srcportal, newdepth); dstportal = linkportal(srcportal, newdepth);
setobcreatedby(dstportal, caster); setobcreatedby(dstportal, caster);
//newmap = findmapofdepth(newdepth); //newmap = findmapofdepth(newdepth);
@ -8407,7 +8424,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
badoid[0] = OT_MUDPOOL; badoid[0] = OT_MUDPOOL;
badoid[1] = OT_NONE; badoid[1] = OT_NONE;
for (i = 0; i < powerleft; i++) { for (i = 0; i < powerleft; i++) {
c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, badoid); c = real_getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND, LOF_DONTNEED, badoid, NULL);
if (c) { if (c) {
o = addob(c->obpile, "pool of mud"); o = addob(c->obpile, "pool of mud");
if (o) { if (o) {
@ -9118,13 +9135,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
(spellid == OT_S_SUMMONANIMALSMD) || (spellid == OT_S_SUMMONANIMALSMD) ||
(spellid == OT_S_SUMMONANIMALSLG) || (spellid == OT_S_SUMMONANIMALSLG) ||
(spellid == OT_S_FRIENDS) || (spellid == OT_S_FRIENDS) ||
(spellid == OT_S_HECTASSERVANT) ||
(spellid == OT_S_SUMMONDEMON)) { (spellid == OT_S_SUMMONDEMON)) {
int lifetime, nwant,ngot,successrate; int lifetime, nwant,ngot,successrate;
enum LFSIZE wantsize; enum LFSIZE wantsize;
enum RACECLASS wantrc; enum RACECLASS wantrc;
enum RACE wantrace = R_NONE; enum RACE wantrace = R_NONE;
int friendly; int friendly;
lifetime = (power * 9) + rnd(1,power*2); lifeform_t *summoner = NULL;
if (spellid == OT_S_HECTASSERVANT) {
lifetime = 10;
} else {
lifetime = (power * 9) + rnd(1,power*2);
}
switch (spellid) { switch (spellid) {
case OT_S_FRIENDS: case OT_S_FRIENDS:
@ -9138,6 +9161,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
successrate = 100; successrate = 100;
friendly = B_FALSE; friendly = B_FALSE;
break; break;
case OT_S_HECTASSERVANT:
wantrace = R_HECTASSERVANT;
wantrc = RC_ANY;
wantsize = SZ_ANY;
nwant = 1;
successrate = 100;
friendly = B_FALSE;
break;
case OT_S_SUMMONDEMON: case OT_S_SUMMONDEMON:
wantrc = RC_DEMON; wantrc = RC_DEMON;
wantsize = SZ_ANY; wantsize = SZ_ANY;
@ -9173,8 +9204,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
friendly = B_TRUE; friendly = B_TRUE;
break; break;
default: default:
wantrc = RC_ANY;
wantsize = SZ_ANY; wantsize = SZ_ANY;
nwant = 1;
successrate = 100; successrate = 100;
friendly = B_TRUE;
break; break;
} }
@ -9182,6 +9216,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
// special case, mainly used for when gods summon creatures for you
if (target) {
summoner = target;
} else {
summoner = caster;
}
ngot = summonlfs(caster, caster->cell, wantrace, wantrc, wantsize, AL_NONE, nwant, lifetime, friendly); ngot = summonlfs(caster, caster->cell, wantrace, wantrc, wantsize, AL_NONE, nwant, lifetime, friendly);
if (!ngot) { if (!ngot) {
@ -9801,7 +9841,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (hasflag(o->flags, F_IMPASSABLE)) { if (hasflag(o->flags, F_IMPASSABLE)) {
cell_t *newloc; cell_t *newloc;
// if so, don't put it where the player is! // if so, don't put it where the player is!
newloc = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL); newloc = real_getrandomadjcell(target->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, target);
o = relinkob(o, newloc->obpile); o = relinkob(o, newloc->obpile);
} }
if (o) { if (o) {
@ -10866,7 +10906,8 @@ int summonlfs(lifeform_t *caster, cell_t *where, enum RACE wantrace, enum RACECL
ncreated = 0; ncreated = 0;
for (i = 0; i < howmany; i++) { for (i = 0; i < howmany; i++) {
// get random adjacent cell // get random adjacent cell
c = getrandomadjcell(where, WE_EMPTY, B_ALLOWEXPAND); // (prefer cells in sight of caster)
c = real_getrandomadjcell(where, WE_EMPTY, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
if (!c) { if (!c) {
return ncreated; return ncreated;
} }

13
text.c
View File

@ -1677,6 +1677,15 @@ void texttospellopts(char *text, ... ) {
"stamcost:", "stamcost:",
NULL, NULL,
}; };
int argdefault[] = {
0,
-1, // string
B_FALSE,
0,
-1, // string
0,
-99, // last
};
char argtype[] = { char argtype[] = {
'i', 'i',
's', 's',
@ -1706,9 +1715,9 @@ void texttospellopts(char *text, ... ) {
// blank our dest buffer // blank our dest buffer
if (argtype[foundidx] == 'i') { if (argtype[foundidx] == 'i') {
*((int *)writeto) = 0; *((int *)writeto) = argdefault[foundidx];
} else if (argtype[foundidx] == 'b') { } else if (argtype[foundidx] == 'b') {
*((int *)writeto) = B_FALSE; *((int *)writeto) = argdefault[foundidx];
} else if (argtype[foundidx] == 's') { } else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, ""); strcpy((char *)writeto, "");
} }