- [+] 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

16
ai.c
View File

@ -1414,6 +1414,9 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// run away for a while
fleefrom(lf, spelllf, rnd(10,20), B_TRUE);
}
if ((spell == OT_A_DRAGUNDERGROUND) && (lf->race->id == R_HECTASSERVANT)) {
lf->hp = 0;
}
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.
if (db) dblog(".oO { i am at distance %d, want to be at %d-%d }", dist, wantdistmin, 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) {
dblog(".oO { moving towards target. }");
}
@ -1584,8 +1595,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
if (db) dblog(".oO { ...successfully }");
// we now don't know their last known dir.
if (targetflag) {
free(targetflag->text);
targetflag->text = strdup("");
changeflagtext(targetflag, "");
}
return B_FALSE;
}
@ -1739,6 +1749,8 @@ void aiturn(lifeform_t *lf) {
enum ATTRBRACKET iqb;
checkflagpile(lf->flags);
/*
if (wantdb && haslos(player, lf->cell)) {
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?
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)) {
blocked = B_TRUE;
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));
}
*/
takedamage(armour, dam, damtype);
takedamage(o, dam, damtype);
}
} else {
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) {
int min,max;
protected = checkcritprotection(victim,armour);
max = getobmaxhp(o);
max = getobmaxhp(armour);
min = max / 2;
limit(&min, 1, NA);
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, "throwing net");
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, "pair of leather boots");
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_HASHIDDENNAME, B_TRUE, NA, NA, "pile of 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);
addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL);
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_FEELTEXT, NA, NA, NA, "some ash");
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);
addflag(lastot->flags, F_GLYPH, NA, ',', NA, NULL);
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_HASHIDDENNAME, B_TRUE, NA, NA, "pile of 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);
addflag(lastot->flags, F_HOLDCONFER, F_XRAYVIS, 1, 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_AICASTTOATTACK, ST_VICTIM, NA, 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_SPELLSCHOOL, SS_DEATH, 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_AICASTTOATTACK, ST_VICTIM, NA, 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
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.");
@ -3614,6 +3622,10 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, 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);
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);
@ -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);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, 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);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, 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_AICASTTOFLEE, ST_SPECIAL, 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);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, 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_VALUE, 10, NA, 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);
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_NOBLESS, B_TRUE, 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);
addflag(lastot->flags, F_RARITY, H_ALL, 90, 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_RARITY, H_ALL, 70, 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...
addflag(lastot->flags, F_DAM, DT_PIERCE, 1, 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_IMPASSABLE, SZ_MIN, SZ_MAX, 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_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "vanishes");
@ -5138,14 +5149,21 @@ void initobjects(void) {
// 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_FOREST, 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, 1, NA, 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_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);
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);
@ -7646,7 +7664,7 @@ void initrace(void) {
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_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_MOVESPEED, SP_NORMAL, NA, NA, NULL);
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_ACTIONSPEED, SP_NORMAL, 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_SWAMP, NA, RR_COMMON, NULL);
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_NOSLEEP, B_TRUE, NA, NA, NULL);
// 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.");
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, "- 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_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_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);
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);
@ -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_MASTER, "^gYou can now locate monsters based on sound.^n", B_TRUE);
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);
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);
@ -10608,13 +10658,13 @@ void initskills(void) {
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);
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_BEGINNER, "^gShield accuracy penalties are reduced by 10%.^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 2.^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_SKILLED, "^gShield accuracy penalties are reduced by 20%.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 25%.^n", B_FALSE);
addskilldesc(SK_SHIELDS, PR_MASTER, "^gShield accuracy penalties are reduced by 30%.^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 4.^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 6.^n", B_FALSE);
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_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_GAMESTARTED,
GM_GAMEOVER,
GM_CLEANUP,
};
enum ATTRIB {
@ -977,6 +978,7 @@ enum RACE {
R_DANCINGWEAPON,
R_FLOATINGDISC,
R_GASCLOUD,
R_HECTASSERVANT,
};
enum JOB {
@ -1235,6 +1237,7 @@ enum OBTYPE {
OT_S_COMMANDUNDEAD,
OT_S_DRAINLIFE,
OT_S_FEAR,
OT_S_HECTASSERVANT,
OT_S_PAIN,
OT_S_PARALYZE,
OT_S_INFINITEDEATH,
@ -1426,6 +1429,7 @@ enum OBTYPE {
OT_A_DARKWALK,
OT_A_DISARM, // disarm a trap
OT_A_DISARMLF, // disarm an opponent
OT_A_DRAGUNDERGROUND,
OT_A_FEIGNDEATH,
OT_A_FLIP,
OT_A_FLURRY,
@ -1452,6 +1456,7 @@ enum OBTYPE {
OT_A_HIDE,
OT_A_INSPECT,
OT_A_HURRICANESTRIKE,
OT_A_PICKLOCK,
OT_A_POLYREVERT,
OT_A_QUIVERINGPALM,
OT_A_STEAL,
@ -1615,6 +1620,7 @@ enum OBTYPE {
OT_VELVETROBE,
// armour - shoulders
OT_CLOAK,
OT_CLOAKFUR,
// armour - waist
OT_BELTLEATHER,
// armour - legs
@ -2150,6 +2156,7 @@ enum FLAG {
F_LOCKED,// door is locked
// v1 is difficulty to disarm
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
// to find it.
// NA means 'can never find this'

109
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 rv;
//checkflagpile(fp);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// identified things mean all new flags are autmaticlaly known.
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;
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
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
@ -179,6 +183,7 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
f = f->next;
*/
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// fill in props
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;
//checkflagpile(fp);
updatefpindex(fp);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// notify
if (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;
}
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
f->known = B_TRUE;
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
rv = flagcausesredraw(f->pile->owner, f->id);
if (rv < redrawscreenatend) redrawscreenatend = rv;
if (flagcausesstatredraw(f->pile->owner, f->id)) redrawstatatend = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} else if (f->pile->ob) {
if (gamemode == GM_GAMESTARTED) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (announceobflaggain(f->pile->ob, f)) {
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)) {
cell_t *where = NULL;
// everyone who can see this cell recalcs their los
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
where = getflagpilelocation(f->pile);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (where) {
lifeform_t *l;
for (l = where->map->lf ; l ; l = l->next) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (haslos(l, where)) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
setlosdirty(l);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
//precalclos(l);
if (isplayer(l)) {
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
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
@ -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) checkmapflags(player->cell->map); // debugging
if (redolight) {
//dblog("CALCINGLIGHT from flag\n");
if (!redrawscreenatend) redrawscreenatend = B_TRUE;
calclight(redolight);
//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);
}
//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 (redrawstatatend) statdirty = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (redrawscreenatend == B_FORCE) {
forceredraw();
} else {
drawscreen();
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
}
//checkflagpile(fp);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
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) {
flag_t *f;
for (f = src->first ; f ; f = f->next) {
@ -808,6 +884,8 @@ void killflag(flag_t *f) {
int redoscreen = B_FALSE;
int i,dopleasegod[MAXGODS];
//checkflagpile(f->pile);
for (i = 0; i < ngodlfs; i++) {
dopleasegod[i] = 0;
}
@ -847,6 +925,7 @@ void killflag(flag_t *f) {
}
}
if (gamemode == GM_GAMESTARTED) {
// flags which cause a redraw
if (flagcausesredraw(f->pile->owner, f->id)) redoscreen = B_TRUE;
if (flagcausesstatredraw(f->pile->owner, f->id)) redostat = B_TRUE;
@ -854,6 +933,7 @@ void killflag(flag_t *f) {
if (flagcausesloscalc(f->id)) {
redolos = getflagpilelocation(f->pile);
}
}
// notify
if (gamemode == GM_GAMESTARTED) {
@ -904,7 +984,6 @@ void killflag(flag_t *f) {
} else if (f->pile->ob && !isdeadob(f->pile->ob)) {
announceobflagloss(f->pile->ob, f);
}
}
// we will revert to our original form at the end of timeeffectslf().
if (lf && (f->id == F_POLYMORPHED)) {
@ -912,6 +991,7 @@ void killflag(flag_t *f) {
lf->polyrevert = B_TRUE;
}
}
}
/////////////////////////////////////////////
// now we are actually removing the flag.
@ -921,10 +1001,17 @@ void killflag(flag_t *f) {
pile = f->pile;
// free mem
if (f->text) free(f->text);
if (f->text) {
free(f->text);
f->text = NULL;
}
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);
f->altval = NULL;
}
// remove from list
@ -997,15 +1084,19 @@ void killflag(flag_t *f) {
drawscreen();
}
}
//checkflagpile(pile);
}
void killflagpile(flagpile_t *fp) {
if (fp->ob && !fp->ob->dying) {
assert(0 == "calling killflagpile on non-dying object");
}
//checkflagpile(fp);
while (fp->first) {
killflag(fp->first);
}
//checkflagpile(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) {
// special case:
if (f->id == F_TRAIL) {
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 (val3 != NA) f->val[2] = val3;
if (text) {
free(f->text);
f->text = strdup(text);
changeflagtext(f, text);
}
return f;
}
@ -1300,19 +1391,25 @@ void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2) {
void timeeffectsflags(flagpile_t *fp) {
flag_t *f,*nextf;
//checkflagpile(fp);
for (f = fp->first ; f ; f = nextf) {
nextf = f->next;
timeeffectsflag(f, 1);
}
//checkflagpile(fp);
}
// generate an index
void updatefpindex(flagpile_t *fp) {
flag_t *f;
fp->nitems = 0;
for (f = fp->first ;f ; f = f->next) {
fp->item[fp->nitems] = f;
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);
int canbemadepermenant(enum FLAG id);
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 copyflags(flagpile_t *dst, flagpile_t *src, int lifetime);
int countflags(flagpile_t *fp);

27
god.c
View File

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

44
io.c
View File

@ -877,7 +877,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
if (lf2) {
char lfname2[BUFLEN];
char buf2[BUFLEN];
getlfname(lf2, lfname2);
getlfnamea(lf2, lfname2);
snprintf(buf2, BUFLEN, "holding %s",lfname2);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
@ -891,7 +891,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
if (lf2) {
char lfname2[BUFLEN];
char buf2[BUFLEN];
getlfname(lf2, lfname2);
getlfnamea(lf2, lfname2);
snprintf(buf2, BUFLEN, "held by %s",lfname2);
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, buf2);
@ -1075,7 +1075,6 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
}
}
inaskcoords = B_FALSE;
clearmsg();
restoregamewindows();
@ -3516,7 +3515,7 @@ void describespell(objecttype_t *ot) {
}
void doattackcell(char dirch) {
int dir;
int dir = D_NONE;
flag_t *f;
cell_t *c;
@ -3528,15 +3527,15 @@ void doattackcell(char dirch) {
if (dirch == '.') {
// yourself!
c = player->cell;
} else {
}
dir = chartodir(dirch);
if (dir == D_NONE) {
clearmsg();
msg("Cancelled.");
return;
} else {
c = getcellindir(player->cell, dir);
}
}
if (c) {
// update last cmd
@ -4677,7 +4676,7 @@ char *makedesc_ob(object_t *o, char *retbuf) {
int acc,accnum;
acc = getobaccuracy(o, NULL);
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);
}
f = hasflag(o->flags, F_RANGE);
@ -5359,11 +5358,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
amt = adjustarmourpenalty(player, f->val[1]);
amt2 = adjustarmourpenalty(player, f->val[2]);
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);
}
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);
}
break;
@ -5371,11 +5370,11 @@ char *makedesc_ob(object_t *o, char *retbuf) {
amt = adjustshieldpenalty(player, f->val[1]);
amt2 = adjustshieldpenalty(player, f->val[2]);
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);
}
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);
}
break;
@ -5706,10 +5705,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
(f->val[2] == 0) ? "" : " effectively");
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 (pctmod > 0) {
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_LOW: sprintf(ch, "%-4s", "xx"); 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_HIGH: 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;
default:
case AT_AVERAGE: sprintf(ch, "%-4s", "-"); col = C_GREY; break;
}
} else {
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_MATVULN:
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;
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;
@ -6230,7 +6226,7 @@ char *makedesc_spell(objecttype_t *ot, char *retbuf) {
}
stamcost = getstamcost(player, ot->id);
if (stamcost) {
if (stamcost > 0) {
sprintf(buf, "It costs %d stamina to use.\n",stamcost);
strncat(retbuf, buf, HUGEBUFLEN);
}
@ -7101,15 +7097,12 @@ int doselguntarget(void) {
addflag(player->flags, F_THROWING, B_TRUE, NA, NA, NULL);
where = askcoords(buf, buf2, TT_MONSTER, player, UNLIMITED, getfirearmloftype(player), B_TRUE);
killflagsofid(player->flags, F_THROWING);
if (where) {
//if (where->lf && haslof(player->cell, where, LOF_NEED, NULL)) {
if (where->lf) {
if (where && where->lf) {
setguntarget(player, where->lf);
} else {
setguntarget(player, NULL);
return B_TRUE;
}
}
return B_FALSE;
}
@ -9811,6 +9804,7 @@ void showlfstats(lifeform_t *lf, int showall) {
strcat(buf, buf2);
}
break;
/*
case A_AGI:
if (accmod != 0) {
snprintf(buf2, BUFLEN, ", %c%d acc",(accmod >= 0) ? '+' : '-',
@ -9818,6 +9812,7 @@ void showlfstats(lifeform_t *lf, int showall) {
strcat(buf, buf2);
}
break;
*/
default:
break;
}
@ -11713,6 +11708,8 @@ void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
if (!strlen(buf)) return;
w = getmaxx(win);
// remember the amount of spaces at the end
p = buf + strlen(buf) - 1;
while (*p == ' ') {
@ -11733,7 +11730,6 @@ void wrapprint(WINDOW *win, int *y, int *x, char *format, ... ) {
repword = strrep(repword, "@", " ", &rv);
}
// if this word won't fit, put it on the next line.
w = getmaxx(win);
if (*x != 0) {
if (*x + strlen(repword) >= w) {
(*y)++;

161
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 targettype;
int cost;
flag_t *f,*willflag;
flag_t *f,*willflag = NULL;
int power;
objecttype_t *sp;
@ -3430,6 +3430,9 @@ void enhanceskills(lifeform_t *lf) {
// update hp
hpratio = ((float)lf->hp / (float)lf->maxhp);
lf->maxhp += rollhitdice(lf, isplayer(lf) ? B_FALSE : B_TRUE);
lf->maxhp += (getskill(lf, SK_FIRSTAID)*2);
lf->hp = hpratio * (float)lf->maxhp;
// update mp
@ -5930,18 +5933,21 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
acc += (lf->level * 2);
if (lfhasflag(lf, F_RAGE)) {
// assume maximum dex
// huge bonus
acc += 50;
} else {
}
/*
else {
int dexmod;
// modify with dexterity
dexmod = getstatmod(lf, A_AGI);
dexmod = getstatmod(lf, A_AGI) / 2; // -25 - +25
// double dex penalties when dual weilding
if (isdualweilding(lf) && (dexmod < 0)) {
dexmod *= 2;
}
acc += dexmod;
}
*/
// modify for blindness
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->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) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL);
if (!newf) {
@ -8453,8 +8465,11 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
newf->lifetime = FROMSKILL;
}
} else if (id == SK_THIEVERY) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
} else if (id == SK_TRAPS) {
newf = addflag(lf->flags, F_CANWILL, OT_A_DISARM, NA, NA, NULL);
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?
if (o) {
@ -9877,20 +9904,7 @@ int getviscell(lifeform_t *lf, cell_t *cell) {
*/
int haslos(lifeform_t *viewer, cell_t *dest) {
int numpixels;
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 (gamemode == GM_CLEANUP) return B_FALSE;
if (!viewer) 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 (lfhasflag(viewer, F_DEAD) && !isplayer(viewer)) return B_FALSE;
if (viewer->losdirty) {
precalclos(viewer);
viewer->losdirty = B_FALSE;
@ -9912,11 +9925,17 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
// can we use pre-calced los?
//
//if ((viewer->cell->map->lf == viewer) && viewer->los) {
/*
if (viewer->los) {
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;
x1 = viewer->cell->x;
@ -9965,11 +9984,9 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
return B_FALSE;
}
// if we went uphill, stop here
/*
if (wentuphill) {
return B_FALSE;
}
*/
//if (wentuphill) {
// return B_FALSE;
//}
if (!celltransparentfor(viewer, cell, &xray, &rangemod)) {
return B_FALSE;
@ -9981,15 +9998,14 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
if (xray) xray--;
// if you went uphill, can't see any further
/*
if (getheight(x,y,z) > origheight) {
wentuphill = B_TRUE;
}
*/
//if (getheight(x,y,z) > origheight) {
// wentuphill = B_TRUE;
//}
}
}
return B_TRUE;
*/
}
int haslosdark(lifeform_t *viewer, cell_t *dest) {
@ -10715,32 +10731,35 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
// init flags
a->flags = addflagpile(a, NULL);
// link cell back to lf
cell->lf = a;
// set race - this will inherit race flags and material
a->race = NULL;
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
// able to revert back.
for (i = 0; i < MAXATTS; i++) {
a->origatt[i] = a->baseatt[i];
}
// set stamina AFTER setrace as it depends on your attribs
a->stamina = getmaxstamina(a);
// update other things
cell->lf = a;
// give start objetcs
// give start objets AFTER setrace as some races start with objects
if ((gamemode != GM_LOADING) && (gamemode != GM_VALIDATION)) {
outfitlf(a);
}
a->created = B_TRUE;
a->born = B_TRUE; // now finished creating it.
if ((gamemode == GM_GAMESTARTED) && cansee(player, a)) {
if (gamemode == GM_GAMESTARTED) {
if (cansee(player, a)) {
needredraw = B_TRUE;
}
}
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 *footprint, *scent,*retob = NULL;
flag_t *fpflag;
flag_t *fpflag = NULL;
// no tracks at all?
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));
adjustdamhardness(amt, damtype, getlfmaterial(lf));
if (lfhasflag(lf, F_DRUNK)) {
f = lfhasflag(lf, F_DRUNK);
if (f) {
*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)) {
int warnthresh;
warnthresh = (int)((float)0.25 * (float)lf->maxhp);
if (lf->hp <= warnthresh) {
if ((lf->hp <= warnthresh) && (lf->hp > 0)) {
warn("*** LOW HITPOINT WARNING ***");
more();
}
@ -13234,16 +13254,6 @@ void precalclos_new(lifeform_t *lf) {
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) {
free(lf->los); lf->los = NULL;
}
@ -13251,6 +13261,22 @@ void precalclos_new(lifeform_t *lf) {
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);
los = malloc( sizeof(cell_t *) * allocamt);
losdark = malloc( sizeof(cell_t *) * allocamt);
@ -13304,6 +13330,7 @@ void precalclos_new(lifeform_t *lf) {
currange = 0;
// calc path to end cell
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
for (n = 0; keepgoing && (n < numpixels); n++) {
c = retcell[n];
@ -13354,18 +13381,27 @@ void precalclos_new(lifeform_t *lf) {
} // end foreach cell and while keepgoing
}
assert(nlos < (MAX_MAPW * MAX_MAPH));
assert(nlosdark < (MAX_MAPW * MAX_MAPH));
// now fill in lifeform structure
if (nlos) {
lf->los = malloc(sizeof(cell_t *) * nlos);
for (i = 0; i < nlos; i++) {
lf->los[i] = los[i];
}
} else {
lf->los = NULL;
}
lf->nlos = nlos;
if (nlosdark) {
lf->losdark = malloc(sizeof(cell_t *) * nlosdark);
for (i = 0; i < nlosdark; i++) {
lf->losdark[i] = losdark[i];
}
} else {
lf->losdark = NULL;
}
lf->nlosdark = nlosdark;
free(los);
@ -14316,6 +14352,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
flag_t *retflag[MAXCANDIDATES];
int nretflags;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
newrace = findrace(rid);
if (isplayer(lf)) {
@ -14326,6 +14363,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
retainhp = B_TRUE;
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
if (frompolymorph && (gamemode == GM_GAMESTARTED) && lf->race) {
race_t *origrace = NULL;
@ -14388,6 +14426,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
// stop stoning.
killflagsofid(lf->flags, F_BEINGSTONED);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// first remove flags from existing race, or temporary ones
lf->born = B_FALSE;
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
lf->race = newrace;
@ -14414,7 +14454,9 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
case F_MPDICE:
break;
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);
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
break;
}
}
@ -14426,6 +14468,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
*/
// certain other flags are rnadom
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
getflags(lf->flags, retflag, &nretflags, F_RNDHOSTILE, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
@ -14436,6 +14479,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
killflag(f);
}
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// generate stats
for (i = 0; i < MAXATTS; i++) {
@ -14484,6 +14528,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
enum BODYPART bp;
object_t *o,*nexto;
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
// no pack?
if (lfhasflag(lf, F_NOPACK)) {
// drop everything
@ -14501,6 +14546,7 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
moveob(o, lf->cell->obpile, o->amt);
}
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
for (bp = BP_WEAPON; bp < MAXBODYPARTS; 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) {
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)) {
needredraw = B_TRUE;
@ -14546,8 +14594,10 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
} else if (cansee(player, lf)) {
needredraw = B_TRUE;
}
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
} // end if gamestarted
//if (gamemode == GM_GAMESTARTED) checkmapflags(player->cell->map); // debugging
}
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;
///////////////
case SC_OPENLOCKS:
attrib = getattr(lf, A_AGI);
attrib = (getattr(lf, A_AGI)/2);
break;
case SC_WILL:
attrib = getattr(lf, A_WIS);
@ -15273,13 +15323,14 @@ void startlfturn(lifeform_t *lf) {
// players lose stamina based on swimming skill
// monsters don't.
switch (getskill(lf, SK_SWIMMING)) {
case PR_INEPT: lossamt = 3; break;
case PR_NOVICE: lossamt = 1; break;
case PR_BEGINNER: lossamt = 1; break;
case PR_ADEPT: lossamt = 0.5; break;
case PR_SKILLED: lossamt = 0; break;
case PR_EXPERT: lossamt = 0; break;
case PR_MASTER: lossamt = 0; break;
default:
case PR_INEPT: lossamt = 3; break;
}
if (lossamt) modstamina(lf, -lossamt);
} else if (isclimbing(lf) && !lfhasflag(lf, F_SPIDERCLIMB)) {
@ -16755,7 +16806,9 @@ void unsummon(lifeform_t *lf, int vanishobs) {
} else {
strcpy(unsummonob, "puff of smoke");
}
if (strlen(unsummonob)) {
addob(lf->cell->obpile, unsummonob);
}
}
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!
if (hasflag(o->flags, F_PIT) && (dir == D_UP) && !isairborne(lf)) {
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) {
// go here instead
newcell = noholecell;

132
map.c
View File

@ -160,7 +160,7 @@ map_t *addmap(void) {
// props
a->id = id;
a->lf = NULL;
for (i = 0; i < MAXDIR_ORTH; i++) {
for (i = 0; i < MAXDIR_MAP; i++) {
a->nextmap[i] = -1;
}
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;
// 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.
lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded) {
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 (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// ie. don't create mosnters on closed doors!
if (!cellwalkable(NULL, c, NULL)) {
return NULL;
@ -203,7 +205,9 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
// get params
wantflags = addflagpile(NULL, NULL);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
rid = parserace(racename, wantflags, &wantjob);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (rid == R_RANDOM) {
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);
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);
@ -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));
if (db) dbtime("finished lf addition");
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (lf) {
flag_t *f;
@ -269,6 +276,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} else {
givejob(lf, wantjob);
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (autogen) {
// sometimes start off hiding/asleep in new maps
@ -282,6 +290,9 @@ 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 not already asleep...
if (wantflags && hasflag(wantflags, F_ASLEEP)) {
} else {
int asleepchance = 70;
f = lfhasflag(lf, F_STARTASLEEPPCT);
if (f) {
@ -297,6 +308,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
}
}
}
}
// nonhuman monsters who on dark levels can always see in the dark
if (!lf->cell->map->lit && !lfhasflag(lf, F_SEEINDARK)) {
if (getraceclass(lf) != RC_HUMANOID) {
@ -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?
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;
// find an adjacent cell to one of the newly added monsters,
// 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?
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);
// 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);
}
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?
// appears in groups?
@ -371,7 +385,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
lifeform_t *newlf;
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;
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)++;
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 (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");
// 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 (rnd(1,3) == 1) {
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");
// 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) {
// wantflags?
copyflags(lf->flags, wantflags, NA);
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
lf->born = B_TRUE;
} // end if lf
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// free mem
if (wantflags) {
killflagpile(wantflags);
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
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)) {
object_t *o;
// object
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
o = addrandomob(c);
if (o) {
if (nadded) *nadded = o->amt;
rv = TT_OBJECT;
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
} else {
lifeform_t *lf;
// 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;
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
}
return rv;
}
@ -1875,7 +1903,8 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
int numrooms = 0;
cell_t *cell, *c;
object_t *o;
int db = B_FALSE;
int db = B_TRUE;
int digdb = B_FALSE;
// parameters
int turnpct = DEF_TURNPCT;
@ -1917,7 +1946,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
cell = getrandomcell(map);
setcelltype(cell, emptycell);
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;
done = B_FALSE;
@ -1929,7 +1958,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
dir = D_NONE;
while (dir == D_NONE) {
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);
@ -1947,19 +1976,19 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
while (!isempty(cell)) {
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
dir = getnewdigdir(cell, lastdir, turnpct, &moved);
}
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) {
// move to adjacent cell in the given direction
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++;
// blank it
@ -1970,7 +1999,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
cell_t *thiscell;
thiscell = getcellindir(cell, d);
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;
}
}
@ -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);
//getchar();
@ -2150,6 +2179,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
}
}
o = addobfast(c->obpile, OT_STAIRSUP);
assert(o);
linkstairs(o, NULL);
}
}
@ -2164,6 +2194,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
c = getrandomroomcell(map, ANYROOM);
}
o = addobfast(c->obpile, OT_STAIRSDOWN);
assert(o);
linkstairs(o, NULL);
}
}
@ -2251,11 +2282,13 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
// river?
if ((depth >= 4) && pctchance(20)) {
// TODO FIX
//if ((depth >= 4) && pctchance(20)) {
//if (depth > 1) {
if (0) {
createriver(map);
}
// now do a border
y = 0;
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 db = B_TRUE;
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// determine habitat based on region
// note: we might override this later based on our region outline
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;
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// 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) {
@ -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?
if (parentmap) {
if (parentmap && (exitdir != D_NONE)) {
if ((parentmap->region->id == map->region->id) ||
(map->region->rtype->majorbranch)) {
if (db) dblog(" linking to parentmap %s in dir %s", parentmap->name, getdirname(diropposite(exitdir)));
parentmap->nextmap[exitdir] = map->id;
assert(exitdir >= 0);
map->nextmap[diropposite(exitdir)] = parentmap->id;
}
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
/*
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);
}
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// we now have the map name!
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(" %d things remembered for later.",nthings);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
failed = B_TRUE;
while (failed) {
failed = B_FALSE;
// build it...
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (db) dblog(" creating map habitat.");
createhabitat(map, depth, parentmap, exitdir, entryob);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// add home objects
if (db) dblog(" adding home objects.");
for (lf = map->lf ; lf ; lf = lf->next) {
addhomeobs(lf);
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// add 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);
c = getrandomroomcell(map, ANYROOM);
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);
break;
case RT_REGIONLINK:
@ -2723,6 +2769,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
break;
}
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// ensure there are no unreachable areas
if (!failed) {
@ -2730,12 +2777,14 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
failed = B_TRUE;
}
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (failed) {
dblog("********* got errors - restarting map creation. *********");
unlinkstairsto(map);
}
}
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
// special cases
// 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.
if (db) dblog(" joining unlinked stairs...");
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
// EXISTING unlinked holes in adjacent maps
i = linkholes(map);
if (db) {
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
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
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;
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);
}
o = addobfast(c->obpile, OT_GRATINGROOF);
assert(o);
// have to force these stairs to go back to a different region.
f = hasflag(o->flags, F_CLIMBABLE);
assert(f);
f->val[1] = map->region->parentregion->id;
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) {
int dir,width,startcentre,endcentre;
cell_t *retcell[MAXRETCELLS];
cell_t *dirtcell[MAXRETCELLS];
cell_t *retcell[MAX_MAPW*MAX_MAPH];
cell_t *dirtcell[MAX_MAPW*MAX_MAPH];
int nretcell,ndirtcells,i;
dblog("Creating river on map %s (depth %d)!", m->name, m->depth);
// pick direction
dir = rnd(B_VERT,B_HORZ);
// pick random river width
@ -3952,6 +4009,8 @@ void createriver(map_t *m) {
calcbresnham(m, 0, startcentre, m->w - 1, endcentre, retcell, &nretcell);
}
assert(nretcell < (MAX_MAPW*MAX_MAPH));
// for each centrelist
for (i = 0; i < nretcell; i++) {
int pos,start,end,n;
@ -4623,7 +4682,7 @@ int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved) {
int i;
int turned = B_FALSE;
cell_t *newcell;
int db = B_TRUE;
int db = B_FALSE;
char err[BUFLEN];
// 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) {
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 x,y;
cell_t *poss[MAXCANDIDATES];
int nposs = 0;
cell_t *new;
cell_t *losposs[MAXCANDIDATES];
int nposs = 0,nlosposs = 0;
cell_t *new,*sel = NULL;
int done = B_FALSE;
while (!done) {
@ -4837,6 +4897,9 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
}
if (ok) {
if (preferlos && haslos(preferlos, new)) {
losposs[nlosposs++] = new;
}
poss[nposs++] = new;
}
}
@ -4860,7 +4923,13 @@ 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) {
@ -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 *o;
flag_t *f;
// default
if (tflag) *tflag = NULL;
for (o = op->first ; o ; o = o->next) {
if (viewer && !canseeob(viewer, o)) continue;
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
// we_walkable rather than we_notwall. this saves problems
// 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
if (c2->type->solid) {
@ -5580,6 +5651,7 @@ object_t *linkportal(object_t *srcportal, int wantdepth) {
cell_t *srcloc,*newcell;
map_t *newmap = NULL;
object_t *dstportal = NULL;
srcloc = getoblocation(srcportal);
newmap = findregionmap(srcloc->map->region->id, wantdepth);
if (!newmap) {
@ -5595,6 +5667,8 @@ object_t *linkportal(object_t *srcportal, int wantdepth) {
}
// add the dst portal
dstportal = addob(newcell->obpile, "magic portal");
assert(dstportal);
// link the dst portal
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);
int getthingchance(int habitat);
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 *getrandomcelloftype(map_t *map, enum CELLTYPE id);
int getrandomdir(int dirtype);

22
move.c
View File

@ -1842,17 +1842,22 @@ int opendoor(lifeform_t *lf, object_t *o) {
} else {
int openit = B_TRUE;
f = hasflag(o->flags, F_JAMMED);
if (f) {
if (f && lf) {
if (isplayer(lf) && (f->val[1] != B_TRUE)) { // not known yet
msg("The %s is jammed.", noprefix(obname));
openit = B_FALSE;
f->val[1] = B_TRUE;
} else {
// known - try to force it
int amt;
amt = getattr(lf, A_STR) - 10;
if (amt < 0) amt = 0;
if (lf) {
if (isplayer(lf)) {
if (amt > 0) {
msg("The %s moves slightly but seems jammed.", noprefix(obname));
msg("The %s moves slightly but remains jammed.", noprefix(obname));
} else {
msg("The %s is jammed.", noprefix(obname));
msg("You cannot budge the jammed %s.", noprefix(obname));
}
} else {
// ai chasing someone and not strong enough to unjam the door?
@ -1874,7 +1879,6 @@ int opendoor(lifeform_t *lf, object_t *o) {
}
}
}
}
// loosen a bit
if (amt) {
f->val[0] -= amt;
@ -1883,7 +1887,8 @@ int opendoor(lifeform_t *lf, object_t *o) {
}
}
openit = B_FALSE; // don't open the door
}
} // end if jammedknown
} // end if jammed
if (openit) {
cell_t *where;
// open it
@ -2637,9 +2642,10 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
tf = ispetortarget(l, lf);
if (tf) {
if (cansee(l, lf)) {
char dirbuf[BUFLEN];
// update text field
free(tf->text);
asprintf(&(tf->text), "%d", dir);
sprintf(dirbuf, "%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");
break;
default:
sb1 = NULL;
break;
}
if (sb1) {
@ -378,6 +379,7 @@ int main(int argc, char **argv) {
sb2 = addob(player->pack, "spellbook of translocation magic");
break;
default:
sb2 = NULL;
break;
}
if (sb2) {
@ -645,6 +647,8 @@ void checkendgame(void) {
void cleanup(void) {
gamemode = GM_CLEANUP;
free(xpposs);
free(raceposs);
@ -1589,6 +1593,8 @@ void timeeffectsworld(map_t *map, int updategametime) {
enum SKILLLEVEL cartskill;
warning_t *w,*nextw;
dblog("------ tick (time=%ld) ----", curtime);
cartskill = getskill(player, SK_CARTOGRAPHY);
// 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...
for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next;
assert(nexto != o);
checkflagpile(o->flags);
timeeffectsob(o);
} // end foreach object here
@ -1705,6 +1713,7 @@ void timeeffectsworld(map_t *map, int updategametime) {
noredraw = B_TRUE;
getflags(map->flags, retflag, &nretflags, F_NEWWATERDEPTH, F_NONE);
assert(nretflags < MAXCANDIDATES); // oooooooooooooo
for (i = 0; i < nretflags; i++) {
cell_t *c;
f = retflag[i];
@ -1718,12 +1727,14 @@ void timeeffectsworld(map_t *map, int updategametime) {
}
setwaterdepth(c, f->val[2]);
}
killflag(f);
}
killflagsofid(map->flags, F_NEWWATERDEPTH);
noredraw = B_FALSE;
// now handle effects on lifeforms and/or their objects
for (l = map->lf ; l ; l = l->next) {
checkflagpile(l->flags);
timeeffectslf(l);
}

View File

@ -1201,8 +1201,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
ok = B_TRUE;
break;
case F_JAMMED:
val[0] = rnd(1,obloc->map->depth+3);
val[1] = NA;
val[0] = rnd(1,obloc->map->depth+5);
val[1] = B_FALSE; // not known yet
val[2] = NA;
ok = B_TRUE;
break;
@ -1664,8 +1664,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
}
}
// locked?
if (!lockchance) {
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 *op;
int i;
op = malloc(sizeof(obpile_t));
op->first = NULL;
op->last = NULL;
@ -1819,6 +1818,10 @@ obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob) {
op->where = where;
op->parentob = parentob;
for (i = 0;i < MAXPILEOBS; i++) {
op->oblist[i] = -1;
}
return op;
}
@ -2798,9 +2801,6 @@ int doobdieconvert(object_t *o, int wantannounce) {
} else {
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 (o->pile->owner) {
@ -3534,6 +3534,7 @@ int getobvalue(object_t *o) {
return getcharges(o);
}
// base value: weight * material value
price = (float)getobweight(o) * (float)getmaterialvalue(o->material->id);
//adjustprice(o->type, &price);
@ -3544,6 +3545,10 @@ int getobvalue(object_t *o) {
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);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
@ -3575,9 +3580,7 @@ int getobvalue(object_t *o) {
}
// one-off magical effects (linkspell) - use spell price
if (f->id == F_LINKSPELL) {
if (o->type->obclass->id == OC_BOOK) {
price += (pow(getspelllevel(f->val[0]), 2) * 30);
} else if (o->type->obclass->id == OC_SCROLL) {
if (o->type->obclass->id == OC_SCROLL) {
price += (pow(getspelllevel(f->val[0]), 2) * 2);
} else if (o->type->obclass->id == OC_POTION) {
price += (pow(getspelllevel(f->val[0]), 2));
@ -3953,7 +3956,8 @@ char *gethiddenname(object_t *o) {
return o->type->name;
}
// 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;
f = hasflag(o->flags, F_HASHIDDENNAME);
if (f) {
@ -6412,7 +6416,8 @@ int isknown(object_t *o) {
}
// 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;
}
@ -6879,6 +6884,12 @@ void killmaterial(material_t *m) {
void killob(object_t *o) {
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
/*
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
if (o->pile->owner) {
loseobflags(o->pile->owner, o, ALLCONFERRED);
@ -8602,10 +8615,6 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
capitalise(buf);
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) {
char ch;
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);
if (ch == 'y') {
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));
donesomething = B_TRUE;
}
@ -10348,8 +10357,8 @@ void removedeadobs(obpile_t *op) {
for (o = op->first ; o ; o = nexto) {
nexto = o->next;
if (hasflag(o->flags, F_DEAD)) {
checkflagpile(o->flags);
obdie(o);
continue;
}
}
}
@ -10437,7 +10446,7 @@ int sethiddenname(objecttype_t *ot, char *text) {
int n;
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) {
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));
}
// target is temporarily vulnerable to fire.
howlong = rnd(5,10);
addtempflag(target->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6", howlong);
break;
case OT_POT_RUM:
@ -11869,21 +11879,24 @@ void timeeffectsob(object_t *o) {
owner = NULL;
}
checkflagpile(o->flags);
// special case for trail flags
f = hasflag(o->flags, F_TRAIL);
if (f) {
if (f->lifetime > 0) {
if (f && (f->lifetime > 0)) {
f->lifetime--;
if (f->lifetime <= 0) {
//killflag(f);
// object dies.
killob(o);
//killob(o);
removeob(o, o->amt);
return;
}
}
}
// expire flags
timeeffectsflags(o->flags);
checkflagpile(o->flags);
// blessed weapons glow when held near undead
if (isblessed(o) && isweapon(o)) {
@ -12054,7 +12067,7 @@ void timeeffectsob(object_t *o) {
if (haslos(player, location)) {
msg("%s vanish%s.", obname, OB1(o,"es",""));
}
killob(o);
removeob(o, o->amt);
return;
}
}
@ -12206,18 +12219,22 @@ void timeeffectsob(object_t *o) {
// is object on fire?
if (f->id == F_ONFIRE) {
int wasputout = B_FALSE;
// water puts out fire
for (oo = o->pile->first ; oo ; oo = nextoo) {
nextoo = oo->next;
if ((oo != o) && (oo->material->id == MT_WATER)) {
extinguish(o);
continue;
wasputout = B_TRUE;
break;
}
}
if (!wasputout) {
// if it hasn't been extinguished, fire burns
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?
if ((f->id == F_MATCONVERT) && !hasflag(o->flags, F_NOMATCONVERT)) {
@ -12292,6 +12309,7 @@ void timeeffectsob(object_t *o) {
}
} // end for each object flag
checkflagpile(o->flags);
}
// 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) {
case PR_INEPT: cellpenalty = 32; break;
case PR_NOVICE: cellpenalty = 22; break;
case PR_BEGINNER: cellpenalty = 16; break;
case PR_ADEPT: cellpenalty = 12; break;
case PR_SKILLED: cellpenalty = 10; break;
case PR_EXPERT: cellpenalty = 8; break;
case PR_MASTER: cellpenalty = 6; break;
default:
case PR_INEPT: cellpenalty = 32; break;
}
howfar = getcelldist(thrower->cell, where);

63
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);
}
}
} 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) {
lifeform_t *lf;
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);
}
}
} else if (abilid == OT_A_PICKLOCK) {
lockpick(user, NULL, NULL, NULL);
} else if (abilid == OT_A_RAGE) {
int howlong;
f = lfhasflag(user, F_RAGE);
@ -2042,7 +2053,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
flag_t *f;
char targetname[BUFLEN];
int badweapon = B_FALSE;
flag_t *damflag;
flag_t *damflag = NULL;
obpile_t *op = NULL;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
@ -2067,10 +2078,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
badweapon = B_TRUE;
}
damflag = hasflag(wep->flags, F_DAM);
}
if (!damflag) {
badweapon = B_TRUE;
}
}
if (badweapon) {
if (isplayer(user)) msg("You need a long piercing weapon to perform a thrust!" );
@ -4282,7 +4293,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
objecttype_t *ot;
object_t *o;
char obname[BUFLEN];
int i,amt;
int i,amt = 1;
if (!targcell || targcell->type->solid) {
fizzle(caster);
return B_TRUE;
@ -5156,7 +5167,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
badoid[1] = OT_NONE;
for (i = 0; i < amt; i++) {
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) {
object_t *water;
water = addob(c->obpile, "water");
@ -6100,7 +6111,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
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)) {
char buf[BUFLEN];
@ -6336,7 +6347,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
for (o = caster->pack->first ; o ; o = nexto) {
nexto = o->next;
if (ismetal(o->material->id)) {
if (isequippedon(o, BP_RIGHTFINGER) || isequippedon(o, BP_LEFTFINGER)) {
f = hasflag(o->flags, F_EQUIPPED);
if (f) {
if ((f->val[0] == BP_RIGHTFINGER) || (f->val[0] == BP_LEFTFINGER)) {
if (isplayer(caster)) {
getobname(o, buf, 1);
msg("Your %s slides off your %s!", buf, getbodypartname(caster, f->val[0]));
@ -6346,7 +6359,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
getpossessive(castername), buf, getbodypartname(caster, f->val[0]));
}
moveob(o, caster->cell->obpile, o->amt);
} else if (isequipped(o)) {
} else {
if (isplayer(caster)) {
getobname(o, buf, 1);
msg("Your %s pulls away from you a little.", noprefix(buf));
@ -6356,6 +6369,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
}
}
}
// add the magnetic field!
addtempflag(caster->flags, F_MAGSHIELD, B_TRUE, NA, NA, NULL, 25 + (power*2));
@ -6914,13 +6928,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
object_t *srcportal,*dstportal;
// 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) {
fizzle(caster);
return B_FALSE;
}
// create the source portal
srcportal = addobfast(srccell->obpile, OT_PORTAL);
assert(srcportal);
setobcreatedby(srcportal, caster);
// 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);
}
dstportal = linkportal(srcportal, newdepth);
setobcreatedby(dstportal, caster);
//newmap = findmapofdepth(newdepth);
@ -8407,7 +8424,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
badoid[0] = OT_MUDPOOL;
badoid[1] = OT_NONE;
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) {
o = addob(c->obpile, "pool of mud");
if (o) {
@ -9118,13 +9135,19 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
(spellid == OT_S_SUMMONANIMALSMD) ||
(spellid == OT_S_SUMMONANIMALSLG) ||
(spellid == OT_S_FRIENDS) ||
(spellid == OT_S_HECTASSERVANT) ||
(spellid == OT_S_SUMMONDEMON)) {
int lifetime, nwant,ngot,successrate;
enum LFSIZE wantsize;
enum RACECLASS wantrc;
enum RACE wantrace = R_NONE;
int friendly;
lifeform_t *summoner = NULL;
if (spellid == OT_S_HECTASSERVANT) {
lifetime = 10;
} else {
lifetime = (power * 9) + rnd(1,power*2);
}
switch (spellid) {
case OT_S_FRIENDS:
@ -9138,6 +9161,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
successrate = 100;
friendly = B_FALSE;
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:
wantrc = RC_DEMON;
wantsize = SZ_ANY;
@ -9173,8 +9204,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
friendly = B_TRUE;
break;
default:
wantrc = RC_ANY;
wantsize = SZ_ANY;
nwant = 1;
successrate = 100;
friendly = B_TRUE;
break;
}
@ -9182,6 +9216,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster);
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);
if (!ngot) {
@ -9801,7 +9841,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (hasflag(o->flags, F_IMPASSABLE)) {
cell_t *newloc;
// 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);
}
if (o) {
@ -10866,7 +10906,8 @@ int summonlfs(lifeform_t *caster, cell_t *where, enum RACE wantrace, enum RACECL
ncreated = 0;
for (i = 0; i < howmany; i++) {
// 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) {
return ncreated;
}

13
text.c
View File

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