diff --git a/ai.c b/ai.c index cce806a..1816065 100644 --- a/ai.c +++ b/ai.c @@ -915,8 +915,8 @@ int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim getradiuscells(lf->cell, 1, DT_COMPASS, B_TRUE, LOF_DONTNEED, B_FALSE, cell, &ncells, 0); for (i = 0; i < ncells; i++) { if (cell[i]->type->solid && - (cell[i]->type->material->id == MT_STONE) && - getcelldist(cell[i], victim->cell) == 1) { + (isdiggable(cell[i], OT_NONE) && + getcelldist(cell[i], victim->cell) == 1)) { poss[nposs++] = cell[i]; break; } diff --git a/data.c b/data.c index 8197874..779bddb 100644 --- a/data.c +++ b/data.c @@ -11950,7 +11950,7 @@ void initrace(void) { setbodypartname(lastrace, BP_RIGHTFINGER, "right foreclaw"); setbodypartname(lastrace, BP_LEFTFINGER, "left foreclaw"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_MASTERVAULTS, NA, RR_COMMON, NULL); @@ -13495,7 +13495,7 @@ void initrace(void) { addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, RR_UNCOMMON, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, 60, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_CAVE, 60, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 66, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_SWAMP, 66, RR_UNCOMMON, NULL); @@ -15802,6 +15802,8 @@ void initrace(void) { addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_TOOCLOSE, 2, NA, "clacks its mandibles^a loud clacking"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); + //addflag(lastrace->flags, F_CANWILL, OT_S_DIG, NA, NA, "pw:1;"); + //addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_DIG, NA, NA, "burrows into the wall"); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL); @@ -16640,6 +16642,46 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^squeaking"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 1, NA, "squeaks^squeaking"); + addrace(R_RATMIND, "mesmerat", 3, 'r', C_PINK, MT_FLESH, RC_ANIMAL, "Glowing, irradiated rats which exhibit amazing mental powers."); + setbodytype(lastrace, BT_QUADRAPED); + addbodypart(lastrace, BP_TAIL, NULL); + addflag(lastrace->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL); + addflag(lastrace->flags, F_NOSMELL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_RANDOM, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, ""); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_SIZE, SZ_TINY, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); + addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); + addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_UNCOMMON, NULL); + addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_FREQUENT, NULL); + addflag(lastrace->flags, F_HITDICE, 0, 1, NA, NULL); + addflag(lastrace->flags, F_TR, 1, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 1, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 1, NA, NULL); + addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 60, "5-20"); + addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL); + addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_SNATCH, NA, NA, "range:1;"); + addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "scuttle"); + addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^squeaking"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 1, NA, "squeaks^squeaking"); + addflag(lastrace->flags, F_POISONCORPSE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FILLPOT, OT_POT_POISON, BLOODFORPOT, NA, NULL); + addflag(lastrace->flags, F_GERMS, NA, NA, NA, NULL); + addrace(R_RATPLAGUE, "plague rat", 3, 'r', C_GREEN, MT_FLESH, RC_ANIMAL, "Plague rats are named both for their infectious bite as well as the great speed at which they run."); setbodytype(lastrace, BT_QUADRAPED); addbodypart(lastrace, BP_TAIL, NULL); @@ -18740,6 +18782,47 @@ void initrace(void) { addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_FOLLOWTIME, 0, NA, NA, NULL); + addrace(R_ZOMBIECON, "contagion zombie", 50, 'Z', C_BLUE, MT_FLESH, RC_UNDEAD, "Unlike regular zombies, these once-living creatures have been turned into monsters by some kind of horrible disease. A disease which is said to be contagious..."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, NA, NA, "30"); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL); + addflag(lastrace->flags, F_RARITY, H_ICECAVE, NA, RR_VERYRARE, NULL); + addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_VERYRARE, NULL); + addflag(lastrace->flags, F_NOSTAIRS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); + 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_HUMAN, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL); + addflag(lastrace->flags, F_TR, 3, NA, NA, NULL); + addflag(lastrace->flags, F_ARMOURRATING, 5, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL); + addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RANDOMTALKPCT, 20, NA, NA, NULL); + addflag(lastrace->flags, F_RANDOMTALK, NA, SV_WHISPER, SV_TALK, "Braaaains..."); + addflag(lastrace->flags, F_RANDOMTALK, NA, SV_WHISPER, SV_TALK, "Fooodd..."); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "moans^a gutteral moan"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "groans^a gutteral groan"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "gurgles^a gurgle"); + addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "growls^a growl"); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_HITCONFER, F_REVIVETIMER, SC_POISON, 165, NULL); + addflag(lastrace->flags, F_HITCONFERVALS, 0, 5, R_ZOMBIECON, "twists and morphs into a zombie!"); + addrace(R_SKELETON, "skeleton", 20, 'Z', C_BONE, MT_BONE, RC_UNDEAD, "A walking set of bones, animated through the use of necromancy. Due to their lack of soft flesh, they have little to fear from edged weapons."); setbodytype(lastrace, BT_HUMANOID); setbodypartname(lastrace, BP_WEAPON, "right metacarpals"); @@ -19041,9 +19124,9 @@ void initrace(void) { addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); - addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); - addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL); + addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_RARE, NULL); + addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_STENCH, 3, 1, NA, NULL); addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL); @@ -19997,6 +20080,7 @@ void initskills(void) { addskilldesc(SK_LORE_CHEMISTRY, PR_NOVICE, "^gYou can now mix venom sacs into potions to create poison.^n", B_TRUE); addskilldesc(SK_LORE_CHEMISTRY, PR_BEGINNER, "^gYou can now recognise very common potions.^n", B_TRUE); addskilldesc(SK_LORE_CHEMISTRY, PR_ADEPT, "^gYou can now recognise common potions.^n", B_TRUE); + addskilldesc(SK_LORE_CHEMISTRY, PR_SKILLED, "^gYou can now bottle the blood of all creatures.^n", B_TRUE); addskilldesc(SK_LORE_CHEMISTRY, PR_EXPERT, "^gYou can now recognise uncommon potions.^n", B_TRUE); addskilldesc(SK_LORE_CHEMISTRY, PR_MASTER, "^gYou can now recognise rare potions.^n", B_TRUE); addskill(SK_LORE_DEMONS, "Lore:Demonology", "Determines your knowledge about demons.", 5); @@ -20168,6 +20252,8 @@ void initskills(void) { addskilldesc(sk->id, PR_ADEPT, buf, B_TRUE); snprintf(buf, BUFLEN, "^gYou can now anticipate how %s will react.^n", rc->pluralname); addskilldesc(sk->id, PR_SKILLED, buf, B_TRUE); + snprintf(buf, BUFLEN, "^gYou can now bottle the blood of some %s.^n", rc->pluralname); + addskilldesc(sk->id, PR_SKILLED, buf, B_TRUE); snprintf(buf, BUFLEN, "^gYou now know everything there is to know about %s.^n", rc->pluralname); addskilldesc(sk->id, PR_MASTER, buf, B_TRUE); } diff --git a/data/hiscores.db b/data/hiscores.db index b7cae15..432e003 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index f24cd2d..edd29f5 100644 --- a/defs.h +++ b/defs.h @@ -1500,6 +1500,7 @@ enum RACE { R_WRAITHBOG, R_WRAITHICE, R_ZOMBIE, + R_ZOMBIECON, // special R_DANCINGWEAPONS, R_DANCINGWEAPON, @@ -2804,6 +2805,10 @@ enum FLAG { F_ENCHANTABLE, // object can get +1/-1 ect F_FILLPOT, // can fill empty flasks with this object to create // a potion of obtype v0. + // v1 = how many objects need to exist before oyu + // can fill a flask from it. + // v2 = need lore of this creature's race to + // fill . F_GEM, // this object is a gem. F_JEWELERY, // this object counts as jewelery F_GODGIFT, // this was a gift form god with race v0. @@ -2977,7 +2982,8 @@ enum FLAG { F_CRITKNOCKDOWN, // lf knocks down victims on a critical hit F_HITCONFER, // hitting with this gives flagid=v0 - // with timeleft = text ("min-max") + // with timeleft = text ("min-max" + // or NULL for permenant) // unless you pass a val1 skillcheck, diff val2 // if val1 = NA, no check. // MUST ALSO HAVE HITCONFERVALS. @@ -4494,6 +4500,7 @@ enum ERROR { E_DANGEROUS, E_INJURED, E_STASIS, + E_TOOCOLD, }; diff --git a/io.c b/io.c index 783f453..fbd6bc2 100644 --- a/io.c +++ b/io.c @@ -7372,14 +7372,16 @@ char *makedesc_ob(object_t *o, char *retbuf) { col = C_GREY; } if (f->val[1] != NA) { - sprintf(buf, "^%dIt requires at least %d %s to use%s.^n\n", col, f->val[1], getattrname(f->val[0]), - strlen(f->text) ? " effectively" : ""); + sprintf(buf, "^%dMinimum %s to use%s: %d to use.", col, getattrname(f->val[0]), + strlen(f->text) ? " effectively" : "", f->val[1]); strncat(retbuf, buf, HUGEBUFLEN); } if (f->val[2] != NA) { - sprintf(buf, "^nIt can be used more effectively with at least %d %s^n.\n", f->val[2], getattrname(f->val[0])); - strncat(retbuf, buf, HUGEBUFLEN); + sprintf(buf, " (bonus at %d)^n.\n", f->val[2]); + } else { + sprintf(buf, "\n"); } + strncat(retbuf, buf, HUGEBUFLEN); if (usable && isweapon(o)) { if (pctmod > 0) { diff --git a/lf.c b/lf.c index 1c04658..e22c6bd 100644 --- a/lf.c +++ b/lf.c @@ -1396,7 +1396,11 @@ int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos) { if (uselos) { // no line of sight? if (!haslos(viewer, viewee->cell)) { - return B_FALSE; + if ((dist <= tremordist)) { + } else if ((dist <= smelldist)) { + } else { + return B_FALSE; + } } } @@ -2654,6 +2658,9 @@ int check_rest_ok(lifeform_t *lf) { case E_STASIS: msg("You cannot rest while your body is in stasis."); break; + case E_TOOCOLD: + msg("The extreme cold prevents you from sleeping."); + break; default: msg("You cannot rest for some reason."); break; @@ -3098,6 +3105,12 @@ int demandbribe(lifeform_t *lf) { for (i = 0; i < nminions; i++) { makepeaceful(minion[i], player); } + // special cases + if (lf->race->id == R_BOGGART) { + // help the player out. + say(lf, "I have a present for you too!", SV_TALK); + dospelleffects(NULL, OT_S_BARKSKIN, 10, player, NULL, player->cell, B_TRUE, NULL, B_FALSE, NULL); + } } // either way, kill bribe flag for all bandits on the level @@ -13423,7 +13436,7 @@ int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype, enum INJUR if (isplayer(lf)) setlosdirty(lf); break; case IJ_HAMSTRUNG: - fall(lf, NULL, B_TRUE); + if (!isairborne(lf, NULL)) fall(lf, NULL, B_TRUE); break; case IJ_SHOULDERDISLOCATED: wep = getweapon(lf); @@ -19646,6 +19659,13 @@ int startresting(lifeform_t *lf, int willtrain) { if (isplayer(lf)) { if (willtrain) { msg("You start training..."); + } else { + if (getlftemp(lf) >= T_HOT) { + if (!isimmuneto(lf->flags, DT_FIRE, B_FALSE) && + !isresistantto(lf->flags, DT_FIRE, B_FALSE)) { + msg("You sleep fitfully due to the heat (reduced healing rate)."); + } + } } drawmsg(); drawcursor(); @@ -19762,6 +19782,13 @@ int safetorest(lifeform_t *lf) { } } + if (getlftemp(lf) <= T_VCOLD) { + if (!isimmuneto(lf->flags, DT_COLD, B_FALSE) && !isresistantto(lf->flags, DT_COLD, B_FALSE)) { + reason = E_TOOCOLD; + return B_FALSE; + } + } + // extra checks for monsters if (!isplayer(lf)) { int timeneeded; @@ -21751,6 +21778,8 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r // higher roll is better roll = rnd(1,100); + //roll = rnd(1,50); + // debugging for new skillcheck code if (lfhasflag(lf, F_DEBUG)) dblog("%s initial roll=%d",dbtag,roll); ////////////////////////////////////// @@ -21988,9 +22017,9 @@ void startlfturn(lifeform_t *lf) { // more debug if (isplayer(lf)) { if ((gamemode == GM_GAMESTARTED) && (getalignment(lf) != playerorigalignment)) { - dblog("WARNING: player alignment has changed!!!"); - msg("WARNING: player alignment has changed!!!"); - more(); + //dblog("WARNING: player alignment has changed!!!"); + //msg("WARNING: player alignment has changed!!!"); + //more(); } } @@ -25761,6 +25790,20 @@ int rest(lifeform_t *lf, int onpurpose) { } } + // hot? + if (!isimmuneto(lf->flags, DT_FIRE, B_FALSE) && + !isresistantto(lf->flags, DT_FIRE, B_FALSE)) { + switch (getlftemp(lf)) { + case T_HOT: + healtime *= 2; + break; + case T_VHOT: + healtime *= 3; + break; + default: break; + } + } + if (f->val[0] >= healtime) { int difficulty; if (isplayer(lf)) { diff --git a/map.c b/map.c index 1b8d9a8..351257c 100644 --- a/map.c +++ b/map.c @@ -5194,7 +5194,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex // link up holes - this will create NEW holes in THIS map connecting to // EXISTING unlinked holes in adjacent maps // - // do this BEFORE linkind stairs, in case the act of linking holes generates the next map. + // do this BEFORE linking stairs, in case the act of linking holes generates the next map. // if this happens then we want to also join up unlinked stairs. // if we don't do this then when the player tries to use stairs, we will find // that an existing map below/above exists but has no stairs linked, @@ -5316,6 +5316,9 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex } //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging + // put a last fixreachability call in... + fix_reachability(map); + noredraw = B_FALSE; map->beingcreated = B_FALSE; @@ -9580,6 +9583,7 @@ void makedoor(cell_t *cell, int openchance) { m = cell->map; setcelltype(cell, getcellempty(cell)); + assert(!cell->type->solid); strcpy(doorbuf, ""); // in master vaults, doors are always locked. diff --git a/move.c b/move.c index fb18bf0..c0ab008 100644 --- a/move.c +++ b/move.c @@ -308,7 +308,7 @@ int celldangerous(lifeform_t *lf, cell_t *cell, int onlyifknown, enum ERROR *err } else if (wis >= AT_AVERAGE) { // don't walk on sharp objects without boots if (hasflag(o->flags, F_SHARP)) { - if (!getequippedob(lf->pack, BP_FEET)) { + if (!isairborne(lf, NULL) && !getequippedob(lf->pack, BP_FEET)) { if (error) { *error = E_AVOIDOB; rdata = o; @@ -1135,7 +1135,7 @@ int moveeffects(lifeform_t *lf, int moved) { // effects which only happen if you actually moved (not attacked) if (moved) { - if (lfhasflagval(lf, F_INJURY, IJ_HAMSTRUNG, NA, NA, NULL)) { + if (!isairborne(lf, NULL) && lfhasflagval(lf, F_INJURY, IJ_HAMSTRUNG, NA, NA, NULL)) { if (!skillcheck(lf, SC_FALL, 80, 0)) { fall(lf, NULL, B_TRUE); if (isplayer(lf)) didmsg = B_TRUE; @@ -1456,7 +1456,7 @@ int movelf(lifeform_t *lf, cell_t *newcell, int onpurpose) { } f = hasflag(o->flags, F_SHARP); - if (f && hasbp(lf, BP_FEET) && !lfhasflag(lf, F_CAREFULMOVE)) { + if (f && hasbp(lf, BP_FEET) && !lfhasflag(lf, F_CAREFULMOVE) && !isairborne(lf, NULL)) { object_t *boots; // has boots on? boots = getequippedob(lf->pack, BP_FEET); diff --git a/nexus.c b/nexus.c index b46ca9c..05653b7 100644 --- a/nexus.c +++ b/nexus.c @@ -337,6 +337,16 @@ int main(int argc, char **argv) { //where = real_getrandomadjcell(where, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL); where = findobinmap(dmap, OT_PLAYERSTART); + if (!where) { + msg("error: couldn't find ot_playerstart. picking random loc."); + more(); + condset_t cs; + initcondv(&cs, CC_WALKABLE, B_TRUE, NA, + CC_ISROOM, B_TRUE, NA, + CC_NONE + ); + where = getcell_cond(dmap, &cs); + } if (!where) { dblog("fatal error: couldn't find player start position!"); msg("fatal error: couldn't find player start position!"); diff --git a/objects.c b/objects.c index b3d2a38..fb964c5 100644 --- a/objects.c +++ b/objects.c @@ -5873,7 +5873,6 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan } else { strcpy(basename, ""); } - // monster lorelevel of beginner or higher - you get "newt footprints" lorelev = getlorelevel(player, r->raceclass->id); @@ -11226,9 +11225,23 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { notenough = oo; } } else { - dippable = B_TRUE; - anydippable = B_TRUE; - notenough = NULL; + flag_t *rf; + int ok = B_FALSE; + rf = hasflag(oo->flags, F_LINKRACE); + if (rf) { + if (getlorelevel(player, rf->val[0]) >= PR_SKILLED) { + ok = B_TRUE; + } else if (getskill(player, SK_LORE_CHEMISTRY)) { + ok = B_TRUE; + } + } else if (!rf) { + ok = B_TRUE; + } + if (ok) { + dippable = B_TRUE; + anydippable = B_TRUE; + notenough = NULL; + } } } diff --git a/save.c b/save.c index 3ddf172..fc6d4fa 100644 --- a/save.c +++ b/save.c @@ -904,7 +904,6 @@ int savebones(map_t *m, room_t *r) { } // other flags. fprintf(f, "tag:bones\n"); - fprintf(f, "maintainedge\n"); fprintf(f, "rarity:frequent\n"); fprintf(f, "goesin:%s\n", m->habitat->name); fprintf(f, "dlevmin:%d\n", m->depth); diff --git a/spell.c b/spell.c index 39c1d99..a77e509 100644 --- a/spell.c +++ b/spell.c @@ -1941,6 +1941,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // 2. ask which ones to resize (or ALL) getchoice(&prompt); o = (object_t *) prompt.result; + if (!o) { + msg("Cancelled."); + return B_TRUE; + } getobname(o, obname, 1); origsize = getarmoursize(o); @@ -4639,8 +4643,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_BARKSKIN) { flag_t *f; // always targetted at caster - targcell = caster->cell; - target = caster; + if (!target) { + targcell = caster->cell; + target = caster; + } //f = addtempflag(caster->flags, F_MAGICARMOUR, power*2, NA, NA, "skin of bark", FROMSPELL); //f->obfrom = spellid;