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

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 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);
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);
}
//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,12 +925,14 @@ void killflag(flag_t *f) {
}
}
// 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;
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;
if (flagcausesloscalc(f->id)) {
redolos = getflagpilelocation(f->pile);
if (flagcausesloscalc(f->id)) {
redolos = getflagpilelocation(f->pile);
}
}
// notify
@ -904,14 +984,14 @@ 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)) {
if (lfhasflag(lf, F_ORIGRACE)) {
lf->polyrevert = B_TRUE;
// we will revert to our original form at the end of timeeffectslf().
if (lf && (f->id == F_POLYMORPHED)) {
if (lfhasflag(lf, F_ORIGRACE)) {
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);

41
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,15 +874,36 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
break;
case R_GODDEATH:
msg("\"Behold, the power of death!\"");
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, OT_S_PAIN, who, NULL, who->cell, NULL, NULL);
castspell(god, OT_S_DRAINLIFE, who, NULL, who->cell, NULL, NULL);
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;
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) {
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,14 +3527,14 @@ void doattackcell(char dirch) {
if (dirch == '.') {
// yourself!
c = player->cell;
}
dir = chartodir(dirch);
if (dir == D_NONE) {
msg("Cancelled.");
return;
} else {
dir = chartodir(dirch);
if (dir == D_NONE) {
clearmsg();
return;
} else {
c = getcellindir(player->cell, dir);
}
c = getcellindir(player->cell, dir);
}
if (c) {
@ -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,14 +7097,11 @@ 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) {
setguntarget(player, where->lf);
} else {
setguntarget(player, NULL);
return B_TRUE;
}
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)++;

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 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 = addflag(lf->flags, F_CANWILL, OT_A_STEAL, NA, NA, NULL);
newf->lifetime = FROMSKILL;
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,31 +10731,34 @@ 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)) {
needredraw = B_TRUE;
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();
}
@ -13233,16 +13253,6 @@ void precalclos_new(lifeform_t *lf) {
long allocamt;
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,17 +13381,26 @@ 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
lf->los = malloc(sizeof(cell_t *) * nlos);
for (i = 0; i < nlos; i++) {
lf->los[i] = los[i];
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;
lf->losdark = malloc(sizeof(cell_t *) * nlosdark);
for (i = 0; i < nlosdark; i++) {
lf->losdark[i] = losdark[i];
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;
@ -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");
}
addob(lf->cell->obpile, unsummonob);
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;

156
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,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) ) {
int asleepchance = 70;
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);
// if not already asleep...
if (wantflags && hasflag(wantflags, F_ASLEEP)) {
} else {
// might be asleep based on time.
if (issleepingtimefor(lf)) {
int asleepchance = 70;
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);
} 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?
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;
}
}
@ -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) {
@ -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,12 +5651,13 @@ 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) {
// create new map
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
@ -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);

44
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) {
int amt;
amt = getattr(lf, A_STR) - 10;
if (amt < 0) amt = 0;
if (lf) {
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 (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,16 +1879,16 @@ int opendoor(lifeform_t *lf, object_t *o) {
}
}
}
}
// loosen a bit
if (amt) {
f->val[0] -= amt;
if (f->val[0] <= 0) {
killflag(f);
// loosen a bit
if (amt) {
f->val[0] -= amt;
if (f->val[0] <= 0) {
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) {
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) {
f->lifetime--;
if (f->lifetime <= 0) {
// object dies.
killob(o);
return;
}
if (f && (f->lifetime > 0)) {
f->lifetime--;
if (f->lifetime <= 0) {
//killflag(f);
// object dies.
//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,17 +12219,21 @@ 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 it hasn't been extinguished, fire burns
takedamage(o, 2, DT_FIRE); // TODO: don't hardcode
if (hasflag(o->flags, F_DEAD)) return;
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?
@ -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);

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);
}
}
} 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,9 +2078,9 @@ 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 (!damflag) {
badweapon = B_TRUE;
}
if (badweapon) {
@ -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,23 +6347,26 @@ 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)) {
if (isplayer(caster)) {
getobname(o, buf, 1);
msg("Your %s slides off your %s!", buf, getbodypartname(caster, f->val[0]));
} else if (cansee(player, caster)) {
getobname(o, buf, 1);
msg("%s%s %s slides off its %s!", castername,
getpossessive(castername), buf, getbodypartname(caster, f->val[0]));
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]));
} else if (cansee(player, caster)) {
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;
// 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;
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) {
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, "");
}