diff --git a/Makefile b/Makefile index 1d4b2fe..fc1d193 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ #all: 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 -all: ai.o attack.o data.o findleak.o flag.o god.o io.o lf.o map.o move.o nexus.o objects.o save.o shops.o spell.o text.o vault.o ai.h attack.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h nexus.h objects.h save.h shops.h spell.h text.h vault.h +nexus: ai.o attack.o data.o findleak.o flag.o god.o io.o lf.o map.o move.o nexus.o objects.o save.o shops.o spell.o text.o vault.o ai.h attack.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h nexus.h objects.h save.h shops.h spell.h text.h vault.h gcc -g -Wall -o nexus ai.o attack.o data.o findleak.o flag.o god.o io.o lf.o map.o move.o nexus.o objects.o save.o shops.o spell.o text.o vault.o -lncurses -lsqlite3 ai.o: ai.c ai.h attack.h data.h defs.h findleak.h flag.h god.h io.h lf.h map.h move.h ai.h objects.h save.h shops.h spell.h text.h vault.h diff --git a/ai.c b/ai.c index 347fcf6..f00b5ae 100644 --- a/ai.c +++ b/ai.c @@ -23,9 +23,13 @@ extern int playerhasmoved; int wantdb = B_TRUE; void addignorecell(lifeform_t *lf, cell_t *c) { - if (c && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) { - addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 20); - } + if (!c) return; + // TEST: just have one ignorecell at once. + killflagsofid(lf->flags, F_IGNORECELL); + addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 10); + //if (c && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) { + // addtempflag(lf->flags, F_IGNORECELL, c->x, c->y, NA, NULL, 10); + //} } // returns true on failure @@ -655,7 +659,8 @@ cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *l f = ispetortarget(lf, target); if (f) { c = getcellat(lf->cell->map, f->val[1], f->val[2]); - if (c && cellwalkable(lf, c, NULL)) { + //if (c && cellwalkable(lf, c, NULL)) { + if (c) { if (lastx) *lastx = c->x; if (lasty) *lasty = c->y; if (strlen(f->text)) { @@ -1928,6 +1933,8 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { int movefailed = B_FALSE; int closethrowok = B_FALSE; + if (db) dblog(".oO { can see my target }"); + // pet movement if (ismaster) { if (isresting(target)) { @@ -2245,6 +2252,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { int lastx,lasty; int lastdir = D_NONE; + if (db) dblog(".oO { CANNOT see my target }"); targcell = aigetlastknownpos(lf, target, &lastx, &lasty, &lastdir); if (targcell) { diff --git a/attack.c b/attack.c index dcebd58..027ee9f 100644 --- a/attack.c +++ b/attack.c @@ -2991,6 +2991,10 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical, if (lfhasflagval(lf, F_GRABBEDBY, victim->id, NA, NA, NULL)) { acc += 30; } + // MUCH easier to hit things which you have grabbed + if (lfhasflagval(lf, F_GRABBING, victim->id, NA, NA, NULL)) { + acc += 50; + } if (!canreach(lf, victim, &reachpenalty)) { acc -= (10*reachpenalty); diff --git a/data.c b/data.c index 21666e8..5ba4a94 100644 --- a/data.c +++ b/data.c @@ -597,13 +597,13 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_RANGED, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_SEWING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_STEALTH, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_THROWING, PR_NOVICE, NA, NULL); // learnable skills addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CLUBS, NA, NA, NULL); - addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_EVASION, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_STAVES, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, NA, NA, NULL); @@ -1281,7 +1281,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CASTCHANCE, 30, NA, NA, NULL); */ - addjob(J_AIRMAGE, "Skymage", "Those wizards who choose to specialise in the school of air learn to bend the very winds to their will. While initially the weakest of the mages, higher level Skymages become both extremely versatile and extremely power.", JC_MAGE); + addjob(J_AIRMAGE, "Skymage", "Those wizards who choose to specialise in the school of air learn to bend the very winds to their will. While initially the weakest of the mages, higher level Skymages become both extremely versatile and extremely powerful.", JC_MAGE); // stats addflag(lastjob->flags, F_JOBATTRMOD, A_STR, -20, NA, NULL); addflag(lastjob->flags, F_JOBATTRMOD, A_IQ, 20, NA, NULL); @@ -3596,7 +3596,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_VALUE, 75, NA, NA, NULL); - addot(OT_POT_FURY, "potion of fury", "Causes the drinker to enter a state of berzerk rage.", MT_GLASS, 1, OC_POTION, SZ_TINY); + addot(OT_POT_FURY, "potion of fury", "Causes the drinker to enter a state of berzerk rage, granting enhanced strength and accuracy at the expence of conscious control.", MT_GLASS, 1, OC_POTION, SZ_TINY); addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, NULL); addflag(lastot->flags, F_VALUE, 70, NA, NA, NULL); @@ -4101,6 +4101,7 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); addot(OT_S_PROPELMISSILE, "propel missile", "Calls a short but powerful jet of air to accelerate a thrown missile.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Target must be at least two metres away."); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power affects the speed at which missiles are fired."); addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 5, 2, NA, NULL); @@ -4654,7 +4655,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); - addot(OT_S_ABSORBWOOD, "absorb wood", "Destroys nearby wooden objects to boost caster's mana. Does NOT affect carried or equipped items.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addot(OT_S_ABSORBWOOD, "absorb wood", "Instantly destroys nearby wooden objects to boost caster's hit points. Does NOT affect carried or equipped items.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the maximum amount of wood which can be absorbed."); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); @@ -4948,6 +4949,11 @@ void initobjects(void) { addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); + addot(OT_S_VENTRILOQUISM, "ventriloquism", "Causes your voice to originate from the target area, distracting enemies.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); + addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); + addflag(lastot->flags, F_TARGETTEDSPELL, TT_NONE, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); // l2 addot(OT_S_ANTICIPATE, "anticipate action", "Allows the caster to automatically dodge the target's attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power detemines the number of attacks dodged."); @@ -14218,7 +14224,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 8, NA, NULL); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 110, "5-10"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 110, "10-30"); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 3, NA, NULL); addflag(lastrace->flags, F_REGENERATES, 2, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); @@ -15454,7 +15460,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "whines in pain^whining"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "howls^a howl"); addflag(lastrace->flags, F_NOISETEXT, N_FRUSTRATED, 3, NA, "growls^growling"); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, "10-15"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, "10-30"); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL); addflag(lastrace->flags, F_CRITKNOCKDOWN, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_BEGINNER, NA, NULL); @@ -16035,7 +16041,7 @@ void initrace(void) { 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, "2-4"); + 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); @@ -16171,7 +16177,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL); addflag(lastrace->flags, F_TR, 3, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 80, "5-10"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 80, "20-50"); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL); addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); @@ -16440,7 +16446,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, 5, NA, NA, NULL); addflag(lastrace->flags, F_TR, 6, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, "10-20"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, "20-50"); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 3, NA, NULL); // strong! addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL); // don't announce spellcasting addflag(lastrace->flags, F_CASTWITHOUTIQ, B_TRUE, NA, NA, NULL); @@ -17520,7 +17526,7 @@ void initrace(void) { addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL); addflag(lastrace->flags, F_TR, 3, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 6, NA, NULL); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 90, "10-15"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 90, "20-50"); addflag(lastrace->flags, F_HITCONFERVALS, P_WEAKNESS, 3, NA, NULL); addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); @@ -17959,7 +17965,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_STING, 3, NA, NULL); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, "3-5"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 100, "20-50"); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 2, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL); addflag(lastrace->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL); @@ -18149,7 +18155,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HASATTACK, OT_TOUCHPOISON, 4, NA, NULL); - addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 115, "5-10"); + addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 115, "20-50"); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 3, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); addflag(lastrace->flags, F_CANCAST, OT_S_BLIGHT, NA, NA, "pw:5;"); @@ -18830,6 +18836,7 @@ void initrace(void) { addflag(r->flags, F_SEEINVIS, B_TRUE, NA, NA, NULL); addflag(r->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;"); addflag(r->flags, F_FILLPOT, OT_POT_AMBROSIA, NA, NA, NULL); + addflag(r->flags, F_GIFTTIMER, 0, 50, NA, NULL); } else if (r->raceclass->id == RC_MAGIC) { addflag(r->flags, F_NOBREATH, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); diff --git a/data/hiscores.db b/data/hiscores.db index fe2e7f9..8d93558 100644 Binary files a/data/hiscores.db and b/data/hiscores.db differ diff --git a/defs.h b/defs.h index 9e44c79..4d7e5fe 100644 --- a/defs.h +++ b/defs.h @@ -1813,6 +1813,7 @@ enum OBTYPE { OT_S_STUN, OT_S_STUNMASS, OT_S_TELEKINESIS, + OT_S_VENTRILOQUISM, // nature / enviromancy OT_S_ABSORBWOOD, OT_S_ANIMATETREE, @@ -3231,6 +3232,10 @@ enum FLAG { F_TURNED, // lf turned this turn. F_PRAYEDTO, // player has prayed to this god before. F_GODBLOCKED, // player may NOT pray to this god + F_GIFTTIMER, // v0 = ticks down to zero whenever you please this + // god. when at 0, they might give you a gift. + // v1 = what v0 will reset to once you get a gift. + // increases by 50% each time you get one. F_HPDRAIN, // lf loses v0 hit points eath turn. // v1 = damtype // text = killer damage string @@ -4007,6 +4012,7 @@ enum MOVEREASON { MR_OTHER, MR_LF, MR_OB, + MR_SOUND, }; diff --git a/god.c b/god.c index ed35475..0c54989 100644 --- a/god.c +++ b/god.c @@ -886,7 +886,7 @@ void givegodbonus(enum RACE rid, flag_t *bf) { godsay(rid, B_TRUE, "Very impressive..."); break; case R_GODDEATH: - godsay(rid, B_TRUE, "Your killing is impressive..."); + godsay(rid, B_TRUE, "Your kills are impressive..."); break; case R_GODFIRE: godsay(rid, B_TRUE, "DESTROY!"); @@ -1108,6 +1108,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { int piety,gotgift = B_FALSE; enum PIETYLEV plev; int chance; + flag_t *timerflag; god = findgod(rid); piety = getpiety(rid); plev = getpietylev(rid, NULL, NULL); @@ -1123,6 +1124,14 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { chance = 0; } + // check whether gift timer is ready + timerflag = lfhasflag(god, F_GIFTTIMER); + assert(timerflag); + if (timerflag && (timerflag->val[0] > 0)) { + timerflag->val[0]--; + return B_FALSE; + } + if (pctchance(chance)) { // if this is true, you get a gift. char obtogive[BUFLEN]; int rollagain = B_TRUE; @@ -1598,11 +1607,14 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { } } - // since you got a gift, lower piety a little. - //setpiety(rid, 101); + // since you got a gift, have to wait before getting another one. + /* if (!fromtemple) { modpiety(rid, -50); } + */ + timerflag->val[0] = timerflag->val[1]; + timerflag->val[1] = pctof(150,timerflag->val[1]); } // end if (pctchance enough to get a gift) return gotgift; } @@ -1947,7 +1959,7 @@ void pleasegod(enum RACE rid, int amt) { break; } } - //godgiftmaybe(rid, B_FALSE); + godgiftmaybe(rid, B_FALSE); } // checkgodbonus(rid,newplev, oldplev); diff --git a/io.c b/io.c index 7b34614..17504b1 100644 --- a/io.c +++ b/io.c @@ -1734,7 +1734,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { msg("^%cYou feel invulnerable!", getlfcol(lf, CC_VGOOD)); donesomething = B_TRUE; } else { - msg("^%c%s looks invulnerable!", lfname, getlfcol(lf, CC_VGOOD)); + msg("^%c%s looks invulnerable!", getlfcol(lf, CC_VGOOD), lfname); donesomething = B_TRUE; } break; @@ -7157,7 +7157,7 @@ char *makedesc_ob(object_t *o, char *retbuf) { strncat(retbuf, buf2, HUGEBUFLEN); break; case F_STAMBOOST: - sprintf(buf2, "%s boosts your stamina by %d.\n", buf, f->val[0]); + sprintf(buf2, "%s boosts your stamina by %d.\n", buf, f->val[1]); strncat(retbuf, buf2, HUGEBUFLEN); break; case F_STENCH: @@ -7166,7 +7166,7 @@ char *makedesc_ob(object_t *o, char *retbuf) { break; case F_PRODUCESLIGHT: sprintf(buf2, "%s produces light out to %d metre%s.\n", buf, - f->val[0], (f->val[0] == 1) ? "" : "s"); + f->val[1], (f->val[1] == 1) ? "" : "s"); strncat(retbuf, buf2, HUGEBUFLEN); break; case F_RETALIATE: @@ -10534,7 +10534,7 @@ void handleinput(void) { } gotcmd = B_FALSE; break; - case CMD_AGAIN: // repeat last command + case 'g': // repeat last command f = hasflag(player->flags, F_LASTCMD); if (f) { ch = f->text[0]; diff --git a/lf.c b/lf.c index 5e4621e..2af42b0 100644 --- a/lf.c +++ b/lf.c @@ -330,7 +330,7 @@ void breakaitargets(lifeform_t *lf, int onlylowerlev) { } long calcscore(lifeform_t *lf) { - flag_t *f; + flag_t *winner; long points = 0; object_t *o; flag_t *retflag[MAXCANDIDATES]; @@ -338,10 +338,16 @@ long calcscore(lifeform_t *lf) { if (lfhasflag(lf, F_NOSCORE)) { return 0; } + winner = hasflag(player->flags, F_WINNER); // objects for (o = lf->pack->first ; o ; o = o->next) { - // full points - points += getobpoints(o); + // only partial points if you didn't win + // the game. + if (winner) { + points += getobpoints(o); + } else { + points += (getobpoints(o)/4); + } } // donated items etc getflags(lf->flags, retflag, &nretflags, F_SCOREBONUS, F_NONE); @@ -353,11 +359,11 @@ long calcscore(lifeform_t *lf) { // points for xp points += (lf->xp / 10); - f = hasflag(player->flags, F_WINNER); - if (f) { - if (f->val[0] == WT_DEMIGOD) { + winner = hasflag(player->flags, F_WINNER); + if (winner) { + if (winner->val[0] == WT_DEMIGOD) { points *= 13; - } else if (f->val[0] == WT_GOD) { + } else if (winner->val[0] == WT_GOD) { points *= 23; } } @@ -4765,7 +4771,7 @@ int eat(lifeform_t *lf, object_t *o) { } else if (cansee(player, lf)) { msg("%s finishes %s.", lfname, drinking ? "drinking" : "eating"); } else { - noise(lf->cell, lf, NC_OTHER, SV_TALK, drinking ? "something being quaffed." : "something being eaten.", NULL); + noise(lf->cell, lf, NC_OTHER, SV_WHISPER, drinking ? "something being quaffed." : "something being eaten.", NULL); } } else { if (isplayer(lf)) { @@ -4774,7 +4780,7 @@ int eat(lifeform_t *lf, object_t *o) { } else if (cansee(player, lf)) { msg("%s %s %s.", lfname, drinking ? "drinks" : "eats", obname); } else { - noise(lf->cell, lf, NC_OTHER, SV_TALK, drinking ? "something being quaffed." : "something being eaten.", NULL); + noise(lf->cell, lf, NC_OTHER, SV_WHISPER, drinking ? "something being quaffed." : "something being eaten.", NULL); } } } else { @@ -8694,7 +8700,7 @@ int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag, } if (nnflags) { - noiseflag = nflag[rnd(0,nnflags-1)]; + if (noiseflag) noiseflag = nflag[rnd(0,nnflags-1)]; } } @@ -10947,7 +10953,9 @@ void givejob(lifeform_t *lf, enum JOB jobid) { killflag(f); } } - // for monsters, override alignment from race + + /* + // for monsters, DONT override alignment from race // // for players, keep it, we'll use it to figure out our // choices when generating our alignment. @@ -10956,6 +10964,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) { killflagsofid(lf->flags, F_ALIGNMENT); } } + */ // apply attrib mods from this job @@ -10970,6 +10979,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) { // inherit all flags except: // - hpmod ones // - skills which we already have f_noskill for. + // - alignment (in the case of monsters) for (f = j->flags->first ; f ; f = f->next) { int val[3],id,ignorethis = B_FALSE; char *text; @@ -11005,6 +11015,9 @@ void givejob(lifeform_t *lf, enum JOB jobid) { } switch (f->id) { + case F_ALIGNMENT: + if (!isplayer(lf)) ignorethis = B_TRUE; + break; case F_MAXHPMOD: case F_JOBATTRMOD: //case F_CANHAVESUBJOB: @@ -17424,35 +17437,73 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, isplayer(l) ? "your" : "its"); } } else { // not asleep, but can hear it. - // monsters will turn to face the sound, as long as they're + // monsters will go to investigate the sound, as long as they're // not attacking something if (!isplayer(l)) { int willrespond = B_FALSE; + flag_t *tf; + + tf = aihastarget(l); if (lfhasflag(l, F_AUTOROTATE)) { - } else if (aihastarget(l)) { - // will probably ignore the sound... - if ((volume >= 5) && onein(2)) { - willrespond = B_TRUE; + } else if (noisemaker && !isplayer(noisemaker) && (nclass == NC_MOVEMENT)) { + // monsters won't turn to face other monsters' footsteps + } else if (tf) { + if (tf->id == F_TARGETLF) { + lifeform_t *targlf; + // will probably ignore the sound unless + // it is closer. + targlf = gettargetlf(l); + if (getcelldist(l->cell, c) < getcelldist(l->cell, targlf->cell)) { + if ((volume >= 4) && onein(2)) { + willrespond = B_TRUE; + } + } + } else { + // will respond if the sound is closer than our target cell. + cell_t *tc; + tc = getcellat(l->cell->map, tf->val[0], tf->val[1]); + if (getcelldist(l->cell, c) < getcelldist(l->cell, tc)) { + willrespond = B_TRUE; + } } } else willrespond = B_TRUE; if (willrespond) { - // turn to face the sound - if (isplayer(noisemaker) && cansee(l, player) && !lfhasflag(l, F_AWARENESS) && !isdead(l)) { - // peaceful things only turn sometimes - //if (!ispeaceful(l) || onein(6)) { - if (!isfriendly(l)) { + // abandon non-lf targets. + if (!gettargetlf(l)) { + loseaitargets(l); + } + + // if within lof, turn to face it. + if (haslof(l->cell, c, LOF_WALLSTOP, NULL)) { + // turn to face the player + //if (isplayer(noisemaker) && cansee(l, player) && + // !lfhasflag(l, F_AWARENESS) && !isdead(l) && + // !isfriendly(l)) { + if (!haslos(l, c) && !isfriendly(l)) { char lfname[BUFLEN]; int prefacing; prefacing = l->facing; turntoface(l, c); + + // announce if (!lfhasflag(l, F_FEIGNINGDEATH) && cansee(player, l) && (prefacing != l->facing)) { + char dname[BUFLEN]; + strcpy(dname, getdirname(l->facing)); + dname[0] = tolower(dname[0]); getlfname(l, lfname); - msg("%s turns to face you.", lfname); + msg("%s turns to face %s.", lfname, + cansee(l, player) ? + "you" : dname); } } + } else { + int chasetime; + // if NOT within lof, go and investigate + chasetime = volume * 10; + aigoto(l, c, MR_SOUND, NULL, chasetime); } } } @@ -20465,8 +20516,9 @@ int modskillcheckroll(lifeform_t *lf, enum CHECKTYPE ct, int *roll) { othermod += 50; } // nocturnal monsters asleep at night, or diurnal during the day + // count as being in a deep sleep if (isasleep(lf) && issleepingtimefor(lf)) { - othermod -= 35; + othermod -= 20; } } else if (ct == SC_MORALE) { if (isbleeding(lf) || islowhp(lf)) { @@ -20733,13 +20785,19 @@ int slipon(lifeform_t *lf, object_t *o) { } getlfname(lf,lfname); - getobname(o, obname, 1); + if (o) getobname(o, obname, 1); // slip! if (isplayer(lf) || cansee(player, lf)) { + char onwhat[BUFLEN]; char damstring[BUFLEN]; - msg("%s slip%s on %s and fall%s to the ground.",lfname, isplayer(lf) ? "" : "s", obname, - isplayer(lf) ? "" : "s"); - snprintf(damstring, BUFLEN, "slipping on %s",obname); + if (o) { + sprintf(onwhat, "%s", obname); + } else { + sprintf(onwhat, "the %s", lf->cell->type->name); + } + msg("%s slip%s on %s and fall%s to the ground.",lfname, isplayer(lf) ? "" : "s", onwhat, + isplayer(lf) ? "" : "s"); + snprintf(damstring, BUFLEN, "slipping on %s",onwhat); losehp(lf, 1, DT_FALL, NULL, damstring); } noise(lf->cell, lf, NC_OTHER, SV_TALK, "a thump.", NULL); @@ -20750,20 +20808,22 @@ int slipon(lifeform_t *lf, object_t *o) { real_warnabout("(use 's' to walk carefully)", PERMENANT, B_FALSE); } - // object gets damaged? - if (hasflag(o->flags, F_DAMAGABLE)) { - takedamage(o, 1, DT_DIRECT, NULL); - } - // object moves? - if (hasflag(o->flags, F_SLIPMOVE)) { - cell_t *cur, *new; - cur = getoblocation(o); - new = getrandomadjcell(cur, WE_WALKABLE, B_NOEXPAND); - if (new) { - if (haslos(player, cur) || haslos(player, new)) { - msg("%s slips across the floor.", obname); + if (o) { + // object gets damaged? + if (hasflag(o->flags, F_DAMAGABLE)) { + takedamage(o, 1, DT_DIRECT, NULL); + } + // object moves? + if (hasflag(o->flags, F_SLIPMOVE)) { + cell_t *cur, *new; + cur = getoblocation(o); + new = getrandomadjcell(cur, WE_WALKABLE, B_NOEXPAND); + if (new) { + if (haslos(player, cur) || haslos(player, new)) { + msg("%s slips across the floor.", obname); + } + moveob(o, new->obpile, 1); } - moveob(o, new->obpile, 1); } } loseconcentration(lf); @@ -24076,7 +24136,6 @@ int validateraces(void) { printf("ERROR in race '%s' - description refers to wings but race has no bp_wings.\n", r->name); goterror = B_TRUE; } - if (!hasflag(r->flags, F_SIZE)) { printf("ERROR in race '%s' - missing F_SIZE.\n", r->name); @@ -25509,6 +25568,19 @@ enum SKILLLEVEL whichlevforabil(enum SKILL skid, enum OBTYPE oid) { return PR_INEPT; } +int willattackdoors(lifeform_t *lf) { + lifeform_t *targ; + targ = gettargetlf(lf); + if (targ) { + int vol; + getnoisedetails(lf, N_WALK, NULL, NULL, NULL, &vol); + if (canhear(lf, targ->cell, vol, NULL) || cansee(lf, targ)) { + return B_TRUE; + } + } + return B_FALSE; +} + int willbackstab(lifeform_t *lf, lifeform_t *victim, object_t *wep) { if (getraceclass(victim) == RC_PLANT) return B_FALSE; diff --git a/lf.h b/lf.h index 846ae89..ec707a9 100644 --- a/lf.h +++ b/lf.h @@ -522,6 +522,7 @@ void wakeup(lifeform_t *lf, int howmuch); int wear(lifeform_t *lf, object_t *o); int weild(lifeform_t *lf, object_t *o); enum SKILLLEVEL whichlevforabil(enum SKILL skid, enum OBTYPE oid); +int willattackdoors(lifeform_t *lf); int willbackstab(lifeform_t *lf, lifeform_t *victim, object_t *wep); int willbleedfrom(lifeform_t *lf, enum BODYPART bp); int willburden(lifeform_t *lf, object_t *o, int howmany); diff --git a/map.c b/map.c index b703e4d..cc934a9 100644 --- a/map.c +++ b/map.c @@ -3294,7 +3294,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ // randomise dungeon parameters turnpct += (rnd(0,40)-20); // (-20 to +20)% - sparseness += (rnd(0,20)-10); // -10 to +10 + sparseness += (rnd(0,30)-10); // -10 to +20 looppct -= (rnd(0,10)); // subtract 0 - 10 if (shape == MS_NORMAL) { @@ -3304,7 +3304,6 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_ } // is the map lit? - if (depth < 5) { map->illumination = IL_FULLLIT; } else if (depth < 10) { diff --git a/move.c b/move.c index e7833f6..ed07e29 100644 --- a/move.c +++ b/move.c @@ -2024,10 +2024,14 @@ int opendoor(lifeform_t *lf, object_t *o) { if (isplayer(lf)) { msg("You have no hands with which to open the door!"); } else { - // ai will try to break down doors - if (gettargetlf(lf)) { + // ai will try to break down doors if they know the lf they are + // chasing is behind it. ie. if they can still "see" them (maybe via + // scent) or can hear them. + // + if (willattackdoors(lf)) { attackcell(lf, doorcell, B_TRUE); - return B_FALSE; + } else { + loseaitargets(lf); } } return B_TRUE; @@ -2090,13 +2094,12 @@ int opendoor(lifeform_t *lf, object_t *o) { if (isplayer(lf)) { msg("The %s is locked.", noprefix(obname)); } else { - if (gettargetlf(lf)) { - // ai will automatically attack locked doors to - // get at the player + if (willattackdoors(lf)) { attackcell(lf, doorcell, B_TRUE); return B_FALSE; } else { noise(doorcell, NULL, NC_OTHER, SV_TALK, "a door handle rattling.", NULL); + loseaitargets(lf); } } } @@ -2135,7 +2138,7 @@ int opendoor(lifeform_t *lf, object_t *o) { } } else { // ai chasing someone and not strong enough to unjam the door? - if ((amt == 0) && gettargetlf(lf)) { + if ((amt == 0) && willattackdoors(lf)) { attackcell(lf, doorcell, B_TRUE); return B_FALSE; } else { @@ -3256,7 +3259,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { if (isplayer(lf)) stoppathfinding(lf); } } else { - if (lfhasflag(lf, F_RAGE) || !canopendoors(lf)) { + if (lfhasflag(lf, F_RAGE) || (!canopendoors(lf) && willattackdoors(lf))) { // attack it return attackcell(lf, cell, B_FALSE); } else { diff --git a/nexus.c b/nexus.c index d46236f..5182beb 100644 --- a/nexus.c +++ b/nexus.c @@ -1213,6 +1213,7 @@ void donextturn(map_t *map) { who->turnsskipped = 0; } } + noise(who->cell, who, NC_OTHER, SV_SHOUT, "sounds of training.", NULL); rest(who, B_TRUE); donormalmove = B_FALSE; } @@ -2065,9 +2066,11 @@ void timeeffectsworld(map_t *map, int updategametime) { while (timeleft >= TICK_INTERVAL) { flag_t *f; int i; + int th,tm,ts; + splittime(&th, &tm, &ts); timeleft -= TICK_INTERVAL; - dblog("------ tick (time=%ld) ----", curtime); + dblog("------ tick (time=%ld %d:%d:%d) ----", curtime,th,tm,ts); // global time-based effects on map or map objects for (y = 0; y < map->h; y++) { diff --git a/objects.c b/objects.c index b96e77a..d2cbcb7 100644 --- a/objects.c +++ b/objects.c @@ -2032,6 +2032,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum flag_t *f; f = hasflag(o->flags, F_OBHP); if (f) { + // double hit points. f->val[0] *= 2; f->val[1] *= 2; } @@ -2042,6 +2043,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum flag_t *f; f = hasflag(o->flags, F_OBHP); if (f) { + // half hit points. f->val[0] /= 2; if (f->val[0] < 1) f->val[0] = 1; f->val[1] /= 2; if (f->val[1] < 1) f->val[1] = 1; @@ -14559,7 +14561,6 @@ void timeeffectsob(object_t *o) { } } - if (location && !owner) { lifeform_t *who; who = location->lf; @@ -14629,7 +14630,7 @@ void timeeffectsob(object_t *o) { // creator no longer has los? creator = getobcreatedby(o); - if (!creator || !haslos(creator, location)) { + if (creator && !haslos(creator, location)) { willvanish = B_TRUE; } @@ -14908,6 +14909,8 @@ void timeeffectsob(object_t *o) { } if (lfloc) { + char *revivetext; + revivetext = strdup(f->text); // revive! lf = addmonster(lfloc, f->val[2], NULL, B_FALSE, 1, B_FALSE, NULL); // gain flags form corpse @@ -14918,9 +14921,10 @@ void timeeffectsob(object_t *o) { removeob(o, o->amt); // announce if (haslos(player, lfloc) || haslos(player, obloc)) { - msg("^W%s %s!^n", obname, f->text); + msg("^W%s %s!^n", obname, revivetext); interrupt(player); } + free(revivetext); return; } } else if ((f->val[1] - f->val[0]) <= 10) { diff --git a/spell.c b/spell.c index 9e5e4ff..c0f88ea 100644 --- a/spell.c +++ b/spell.c @@ -345,7 +345,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef char obname[BUFLEN], buf[BUFLEN],ch; int madenewmap = B_TRUE; cell_t *origcell = NULL; - lifeform_t *inway = NULL; + lifeform_t *inway = NULL, *movedlf = NULL; cell_t *c; object_t *stairs; int stairdir; @@ -431,9 +431,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef noredraw = B_TRUE; // move any lfs at the other end out of the way. - if (movelfsoutofway(c)) { - // can't move them? ie. no adj cells. - inway = c->lf; + if (c->lf) { + if (movelfsoutofway(c)) { + // can't move them? ie. no adj cells. + inway = c->lf; + } else { + movedlf = c->lf; + } } if (!inway) { @@ -736,9 +740,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef user->born = B_FALSE; // temporarily give the player 360degree sight awareness = addflag(user->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); + // we now need born to be true so that precalclos() works. + user->born = B_TRUE; + noredraw = B_FALSE; // allow redraws setlosdirty(user); // this will redraw the screen askcoords("Peek (ESC when done)->", "Peek (ESC when done)->", TT_NONE, user, UNLIMITED, LOF_DONTNEED, B_FALSE); + user->born = B_FALSE; killflag(awareness); user->born = B_TRUE; } else { @@ -751,6 +759,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef user->cell = origcell; origcell->lf = user; } + + if (movedlf) { + // move lf back + movelf(movedlf, c, B_FALSE); + } noredraw = B_FALSE; if (ch == 'p') { @@ -8870,7 +8883,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ addflag(targob->flags, F_MISSILEALWAYSDIES, B_TRUE, NA, NA, NULL); addflag(caster->flags, F_TKTHROW, A_IQ, SK_SS_AIR, NA, NULL); f = addflag(caster->flags, F_ACCURACYMOD, 50, NA, NA, NULL); - real_fireat(caster, targob, 1, targcell, 5, NULL, B_TRUE, spellid, NULL); + real_fireat(caster, targob, 1, targcell, 4+power, NULL, B_TRUE, spellid, NULL); killflag(f); killflagsofid(caster->flags, F_TKTHROW); } else if (spellid == OT_S_TRAVEL) { @@ -10043,7 +10056,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f = addtempflag(caster->flags, F_GRAVLESSENED, power, NA, NA, NULL, FROMSPELL); f->obfrom = spellid; } else if (spellid == OT_S_GUSTOFWIND) { - int pen = 0; obpile_t *op; object_t *o, *nexto; object_t *poss[MAXPILEOBS],*blowob[MAXPILEOBS]; @@ -10107,21 +10119,24 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } } - // easyish save to avoid falling - switch (getlfsize(target)) { - case SZ_MEDIUM: - pen = -15; break; - case SZ_SMALL: - pen = -25; break; - case SZ_TINY: - pen = -35; break; - case SZ_MINI: - pen = -45; break; - break; - default: pen = 0; break; - } - if (target && !skillcheck(target, SC_FALL, 60 + (power*5), pen)) { - fall(target, NULL, B_TRUE); + if (target) { + int pen = 0; + // easyish save to avoid falling + switch (getlfsize(target)) { + case SZ_MEDIUM: + pen = -15; break; + case SZ_SMALL: + pen = -25; break; + case SZ_TINY: + pen = -35; break; + case SZ_MINI: + pen = -45; break; + break; + default: pen = 0; break; + } + if (!skillcheck(target, SC_FALL, 60 + (power*5), pen)) { + fall(target, NULL, B_TRUE); + } } needredraw = B_TRUE; } else if (spellid == OT_S_MIST) { @@ -12400,6 +12415,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (seenbyplayer) *seenbyplayer = B_TRUE; } swapplaces(caster, target, B_CHANGEDIR, B_NOCHANGEDIR, B_ONPURPOSE); + } else if (spellid == OT_S_VENTRILOQUISM) { + if (isplayer(caster)) { + noise(targcell, NULL, NC_OTHER, SV_SHOUT, "your voice shouting", "You hear your voice shouting."); + } else { + noise(targcell, NULL, NC_OTHER, SV_SHOUT, "shouting", "You hear shouting."); + } } else if ((spellid == OT_S_SUMMONANIMALSSM) || (spellid == OT_S_SUMMONANIMALSMD) || (spellid == OT_S_SUMMONANIMALSLG) ||