- [+] corpses should inherit lf vulnerabilities/immunities

- [+] change bloodsplatter for full leeches to no longer use fireat code
    - [+] was a bug - wasn't handling NA for speed in F_DIESPLATTER
    - [+] change fireat code to not announce "xxx flies through the
          air" for platters
- [+] fix it so that things flying through the air (via fragments())
      can hit people.
- [+] when calling fragments(), don't announce every single "a shard
      flies at xxx"
    - [+] fireat() needs "announcethrow"
- [+] stop running when adjacent to any monster (evne peaceful)
- [+] monsters should always turn to face their attackers, even if they
      aren't adjacent.
- [+] multiple ring types are getting the same hiddenname:
    - [+] Rings
             ring of strength          (flourite ring)
             ring of stench           (flourite ring)
    - [+] validateobs now checks for this.
    - [+] nearly everything seems to have 2 entries.
    - [+] maybe also put a check inside addhiddenname!
    - [+] addhiddenname no longer triggering dupes.
- [+] bug: planeshift not working when cast by enemies.
- [+] bug: skillxp being boosted by massive amounts sometimes
    - [+]  Exp Level: 15 (32150 XP, -1581 for next)
    - [+] bug in getlfaccuracy - returning 9937 and boosting xpval by
          massive amounts!
- [+] motel bug:
    - [+] How many hours will you pay for (you have $1073)? 4 hours
          ($440)
          You start resting (in your motel room)...  You finish resting.
          You wake up.
          "Sleep well!"
    - [+] say"sleep well" BEFORE sleeping!
- [+] for some reason i'm gaining massive amounts of skill points!
    - [+] killed  giant ant, got 3 points???
    - [+] pointsforsp not going up fast enough, especially at high
          levles (13+)
    - [+] was a bug in getlfaccuracy
- [+] yumi should only check attacking helpless on your FIRST attack.
    - [+] if you have subsequent ones, they're ok since you can't
          control them!
- [+] don't please or anger gods when fighting gods
This commit is contained in:
Rob Pearce 2012-01-15 23:18:20 +00:00
parent d063040341
commit db0b726088
12 changed files with 234 additions and 108 deletions

4
ai.c
View File

@ -968,6 +968,9 @@ int ai_healing(lifeform_t *lf) {
// don't have or can't use our healing items
// no enemies in sight?
if (safetorest(lf)) {
// gods will only sleep/meditate if they are in the realm of gods
if (isgod(lf) && (lf->cell->habitat->id != H_HEAVEN)) {
} else {
// if it's "night time" for us, sleep forever.
// otehrwise just sleep until we're healed
if (!gotosleep(lf, issleepingtimefor(lf) ? B_TRUE : B_FALSE)) {
@ -978,6 +981,7 @@ int ai_healing(lifeform_t *lf) {
}
}
}
}
return B_FALSE;
}

View File

@ -483,6 +483,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
// god effects...
if ((attacktype == AT_LF) && isplayer(lf) && attacktarget) {
if (!isgod(attacktarget)) {
if (attackedfriend) {
angergodmaybe(R_GODMERCY, 100, GA_ATTACKALLY);
angergodmaybe(R_GODPURITY, 100, GA_ATTACKALLY);
@ -524,6 +525,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
pleasegodmaybe(R_GODDEATH, 3);
}
}
}
if (isplayer(lf)) {
// lose a bit of stamina
@ -1557,7 +1559,7 @@ int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag) {
setcelltype(c, c->map->habitat->emptycelltype);
// announce
if (haslos(player, c)) {
msg("%s %s!", cellname, shattered ? "shatters" : "is destroyed");
msg("%s %s!", cellname, willshatter(cellmat) ? "shatters" : "is destroyed");
}
// shatter?
if (willshatter(cellmat)) {
@ -1565,7 +1567,7 @@ int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag) {
shattered = B_TRUE;
noise(c, NULL, NC_OTHER, SV_CAR, "something shattering.", NULL);
if (getshardobname(cellmat, what)) {
fragments(c, what, 0, 3); // TODO: use speed so shards will hit lfs
fragments(c, what, 3, 3);
}
}
break;

10
data.c
View File

@ -928,7 +928,7 @@ void initobjects(void) {
for (i = 0; strlen(ringadjective[i]) ; i++) {
char buf2[BUFLEN];
snprintf(buf2, BUFLEN, "%s %s",ringadjective[i], buf);
addhiddenname(OC_RING, buf);
addhiddenname(OC_RING, buf2);
}
}
@ -943,8 +943,6 @@ void initobjects(void) {
}
}
shufflehiddennames();
// object modifiers - flags can be either known or not, depending on if it's obvious
addobmod(OM_BLOODSTAINED,"bloodstained");
@ -1286,6 +1284,10 @@ void initobjects(void) {
addoc(OC_ABILITY, "Abilities", "A special ability", '&', C_GREY, RR_NEVER); // this is a "virtual" object class
// shuffle hidden names and ensure no duplicates
shufflehiddennames();
validatehiddennames();
// object types
// dungeon features
@ -2557,6 +2559,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SMITEGOOD, "smite good", "Instantly deals 1-^bpower*2^n damage to good creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -2632,6 +2635,7 @@ void initobjects(void) {
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);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, 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.");

5
defs.h
View File

@ -2955,6 +2955,11 @@ enum FLAG {
F_RUNNING, // are we running? (shift+dir)
// v0 is last dir moved.
// v1 is whether we have turned yet.
// v2 = what walls to our left and right are:
// 0 = l+r cells clear
// 1 = l cell walled, r cell clear
// 2 = l cell clear, r cell walled
// 3 = l+r cells walled
// nutrition
F_HUNGER, // val0 = hunger, higher = hungrier

36
io.c
View File

@ -1294,6 +1294,8 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
} else {
if (f->val[1] == ST_ASLEEP) {
msg("%s fall%s asleep.",lfname, isplayer(lf) ? "" : "s");
} else if (f->val[1] == ST_MEDITATING) {
msg("%s enter%s a trance.",lfname, isplayer(lf) ? "" : "s");
} else {
msg("%s lose%s consciousness.",lfname, isplayer(lf) ? "" : "s");
}
@ -3723,7 +3725,7 @@ void docomms(lifeform_t *lf) {
}
// TODO: allow you to ask this of allies, but only on the level they started on.
if (!areallies(player, lf)) {
if (!areallies(player, lf) && !isgod(lf)) {
if (ispeaceful(lf) && cantalk(lf)) {
addchoice(&prompt, 'i', "What can you tell me about this area?", NULL, NULL, NULL);
addchoice(&prompt, 'x', "Any dangers nearby that I should look out for?", NULL, NULL, NULL);
@ -3735,7 +3737,7 @@ void docomms(lifeform_t *lf) {
}
// if you are allies, use 'trade items' instead
if (isadjacent(lf->cell, player->cell) && !areallies(player,lf)) {
if (isadjacent(lf->cell, player->cell) && !areallies(player,lf) && !isgod(lf)) {
addchoice(&prompt, 'd', "(donate an item)", NULL, NULL, NULL);
}
@ -8637,11 +8639,13 @@ void handleinput(void) {
if (f) {
int rundir = D_NONE;
int lastdir;
int ihaveturned;
int ihaveturned,walls;
int stopnow = B_FALSE;
int i;
object_t *o;
lastdir = f->val[0];
ihaveturned = f->val[1];
walls = f->val[2];
// certain objects in the current cell will stop us from running.
for (o = player->cell->obpile->first ; o ; o = o->next) {
@ -8651,6 +8655,24 @@ void handleinput(void) {
}
}
for (i = 0; i < player->nlos; i++) {
lifeform_t *thislf;
thislf = player->los[i]->lf;
if (thislf && !isplayer(thislf) && !areallies(player, thislf) && cansee(player, thislf)) {
if (areenemies(player, player->los[i]->lf)) {
// visible hostile monsters stop us
stopnow = B_TRUE;
break;
} else if (getcelldist(player->cell, player->los[i]) <= 1) {
// any non-ally lf in adjacent cells should stop us
stopnow = B_TRUE;
break;
}
}
}
// adjacent doors stop us.
if (countadjcellswithflag(player->cell, F_DOOR, DT_COMPASS)) {
stopnow = B_TRUE;
}
@ -8662,8 +8684,14 @@ void handleinput(void) {
// something here?
if (stopnow) {
} else if (!ihaveturned && moveclear(player, lastdir, NULL)) {
// go the same dir if we can.
// haven't turned yet?
// if walls to our l+r have changed...
if (getleftrightwalls(player) != walls) {
stopnow = B_TRUE;
} else {
// otherwise go the same dir if we can.
rundir = lastdir;
}
} else {
int dir;
int poss[MAXDIR_COMPASS],nposs;

42
lf.c
View File

@ -1627,7 +1627,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
needtovalidate = B_TRUE;
} else if (targcell) {
targettype = TT_NONE;
needtovalidate = B_TRUE;
needtovalidate = B_FALSE;
}
if (needtovalidate) {
@ -1664,7 +1664,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
power += countplantsinsight(lf);
limit(&power, NA, 10);
}
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 20 + power, 0)) {
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 20 + power, 0) && !isgod(lf)) {
if (power > 1) {
// half strength
power /= 2;
@ -2680,6 +2680,12 @@ void die(lifeform_t *lf) {
flag_t *f;
f = lfhasflag(lf, F_DIESPLATTER);
if (f) {
int speed,howfar;
howfar = f->val[0];
speed = f->val[1];
if (speed < 0) speed = 0;
if (howfar < 0) howfar = UNLIMITED;
fragments(corpsecell, f->text, f->val[1], f->val[0]);
}
}
@ -4155,11 +4161,13 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
// turn to face our attacker
if (!lfhasflag(lf, F_STUNNED) && !isdead(lf)) {
if (isadjacent(lf->cell, attacker->cell)) {
if (!isfleeing(lf)) {
//if (isadjacent(lf->cell, attacker->cell)) {
turntoface(lf, attacker->cell);
}
//}
aiattack(lf, attacker, aigetchasetime(lf));
}
}
// any nearby monsters which will help out?
if (getallegiance(lf) != AL_FRIENDLY) {
@ -6099,6 +6107,26 @@ int getlastdir(lifeform_t *lf) {
return D_NONE;
}
int getleftrightwalls(lifeform_t *lf) {
cell_t *rightcell,*leftcell;
int rightdir,leftdir;
int walls = 0;
// remember walls to left and right
leftdir = lf->facing - 1;
if (leftdir < DC_N) leftdir = DC_NW;
rightdir = lf->facing + 1;
if (rightdir > DC_NW) rightdir = DC_N;
leftcell = getcellindir(lf->cell, leftdir);
rightcell = getcellindir(lf->cell, rightdir);
if (!leftcell || (leftcell && leftcell->type->solid)) {
walls += 1;
}
if (!rightcell || (rightcell && rightcell->type->solid)) {
walls += 2;
}
return walls;
}
int getlfaccuracy(lifeform_t *lf, object_t *wep) {
flag_t *f;
object_t *o;
@ -6197,7 +6225,11 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) {
f = lfhasflag(lf, F_DRUNK);
if (f) {
int amt;
amt = (f->lifetime/TM_DRUNKTIME)+1;
int time;
time = f->lifetime;
if (time < 0) time = 70; // ie permenant
limit(&time, NA, 70);
amt = (time/TM_DRUNKTIME)+1;
if (hasjob(lf, J_PIRATE)) {
acc += (10*amt);
} else {

1
lf.h
View File

@ -161,6 +161,7 @@ char *gethungername(lifeform_t *lf, enum HUNGER hunger, char *buf);
int gethungerval(lifeform_t *lf);
job_t *getjob(lifeform_t *lf);
int getlastdir(lifeform_t *lf);
int getleftrightwalls(lifeform_t *lf);
int getlfaccuracy(lifeform_t *lf, object_t *wep);
char getlfcol(lifeform_t *lf, enum MSGCHARCOL cc);
enum LFCONDITION getlfcondition(lifeform_t *lf);

4
move.c
View File

@ -2099,8 +2099,8 @@ int tryrun(lifeform_t *lf, int dir) {
}
rv = trymove(lf, dir, B_TRUE, B_TRUE);
if (!rv && willrun) {
// successful move
addflag(lf->flags, F_RUNNING, dir, B_FALSE, NA, NULL);
// successful move - start running.
addflag(lf->flags, F_RUNNING, dir, B_FALSE, getleftrightwalls(lf), NULL);
}
return rv;
}

View File

@ -1131,6 +1131,7 @@ int init(void) {
initoptions();
initcommands();
initobjects();
validatehiddennames();
initskills();
initjobs();
initrace();
@ -1142,6 +1143,9 @@ int init(void) {
// create the dungeon layout
initmap();
validatehiddennames();
gamemode = GM_VALIDATION;
if (validateobs()) {
return B_TRUE;

View File

@ -1,6 +1,7 @@
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -305,6 +306,9 @@ object_t *addemptyob(obpile_t *where, object_t *o) {
hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text) {
hiddenname_t *a;
// make sure it doesn't already exist
assert(counthiddennames(obclass, text) == 0);
// add to the end of the list
if (firsthiddenname == NULL) {
firsthiddenname = malloc(sizeof(hiddenname_t));
@ -2753,6 +2757,17 @@ void copyobprops(object_t *dst, object_t *src) {
}
int counthiddennames(enum OBCLASS ocid, char *text) {
int count = 0;
hiddenname_t *hn;
for (hn = firsthiddenname ; hn ; hn = hn->next) {
if ((hn->obclass == ocid) && streq(hn->text, text)) {
count++;
}
}
return count;
}
int countmoney(obpile_t *op) {
object_t *o;
int amt = 0;
@ -3366,8 +3381,7 @@ recipe_t *findrecipefor(enum OBTYPE result) {
void fragments(cell_t *centre, char *what, int speed, int howfar) {
cell_t *c,*dst;
int n;
int dir;
int n,dir;
for (dir = DC_N; dir <= DC_NW; dir++) {
int wantdist = 0;
@ -3392,20 +3406,24 @@ void fragments(cell_t *centre, char *what, int speed, int howfar) {
}
}
limit(&maxdist, NA, howfar);
// pick random distance
if (maxdist == 0) {
wantdist = 0;
} else {
/*
int realmax;
if (howfar > maxdist) {
realmax = (maxdist-1);
} else {
realmax = howfar-1;
}
if (realmax < 1) {
*/
if (maxdist < 1) {
wantdist = 0;
} else {
wantdist = rnd(1,realmax);
wantdist = rnd(1,maxdist);
}
}
// go that far
@ -3424,7 +3442,7 @@ void fragments(cell_t *centre, char *what, int speed, int howfar) {
// add object then fire it
o = addob(centre->obpile, what);
if (o) {
fireat(NULL, o, o->amt, dst, speed, NULL);
real_fireat(NULL, o, o->amt, dst, speed, NULL, B_FALSE);
}
} else {
// add object
@ -11109,7 +11127,6 @@ void shufflehiddennames(void) {
hiddenname_t *a, *temp;
int shuffleamt = 500;
total = 0;
for (a = firsthiddenname ; a ; a = a->next) {
total++;
@ -11489,8 +11506,12 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
return damtaken;
}
// throw speed/2 is the damage multiplier
int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm) {
return real_fireat(thrower, o, amt, where, speed, firearm, B_TRUE);
}
// throw speed/2 is the damage multiplier
int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm, int announcethrow) {
char throwername[BUFLEN];
char throwernamea[BUFLEN];
char realthrowername[BUFLEN];
@ -11653,6 +11674,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
}
// announce it ("xx throws xx" "at yy")
if (announcethrow) {
if (thrower && isplayer(thrower)) {
// player is throwing something
if (!firearm) {
@ -11693,7 +11715,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
strcat(throwstring, ".");
msg("%s", throwstring);
}
}
//taketime(thrower, SPEED_THROW);
@ -13156,14 +13178,36 @@ int usecharges(object_t *o, int amt) {
return -1;
}
int validatehiddennames(void) {
objectclass_t *oc;
hiddenname_t *hn;
int goterror = B_FALSE;
// check hidden names for duplicates
for (oc = objectclass ; oc ; oc = oc->next) {
for (hn = firsthiddenname ; hn ; hn = hn->next) {
if (hn->obclass == oc->id) {
int count;
count = counthiddennames(oc->id, hn->text);
if (count > 1) {
printf("Error - duplicate hiddenname found for class %s, text '%s'. (%d found)\n", oc->name, hn->text, count);
goterror = B_TRUE;
}
}
}
}
if (goterror) {
raise(SIGINT);
}
return goterror;
}
int validateobs(void) {
objecttype_t *ot;
flag_t *f;
int foundspells = B_FALSE;
int goterror = B_FALSE;
flag_t *f;
for (ot = objecttype ; ot ; ot = ot->next) {
// fix up glyphs
f = hasflag(ot->flags, F_GLYPH);
if (f) {

View File

@ -39,6 +39,7 @@ int getcritprotection(object_t *o);
int checkobnames(char *haystack, char *needle);
void colourmatchob(object_t *o, lifeform_t *lf);
void copyobprops(object_t *dst, object_t *src);
int counthiddennames(enum OBCLASS ocid, char *text);
int countmoney(obpile_t *op);
int countnames(char **list);
int countobs(obpile_t *op, int onlyifknown);
@ -265,8 +266,8 @@ object_t *splitob(object_t *o);
int takedamage(object_t *o, int howmuch, int damtype);
int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce);
int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm);
int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm, int announcethrow);
void timeeffectsob(object_t *o);
//void trapeffects(object_t *trapob, enum OBTYPE oid, lifeform_t *lf);
void trapeffects(object_t *trapob, enum OBTYPE oid, cell_t *c);
void turnoff(lifeform_t *lf, object_t *o);
void turnon(lifeform_t *lf, object_t *o);
@ -274,6 +275,7 @@ int uncurseob(object_t *o, int *seen);
int usecharge(object_t *o);
int usecharges(object_t *o, int amt);
int usefountaincharge(object_t *o, flag_t *drinkflag);
int validatehiddennames(void);
int validateobs(void);
int wepdullable(object_t *o);
int willshatter(enum MATERIAL mat);

View File

@ -7053,8 +7053,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
m = findregionmap(RG_HEAVEN, 1);
// alwyas go realm of gods
m = heaven;
}
if (m) {
int ntries = 0;