- [+] high metalwork/sewing lets you make things into masterwork

(combine two).
- [+] get dizzy if you turn too much.
- [+] stomach
    - [+] obejcts - gems etc (check phone)
    - [+] if you kill it form inside, you get expelled.
- [+] don't say "you hear fighting" when things are attacking you!
- [+] fix crash in polymorph code
- [+] All bandits should demand gold
    - [+] when you give it to them, thel ALL get satisfied.
- [+] more flagpile corruption still happening.
    - [+] wasn't allcoating enough space for losdark in precalclos.
- [+] still missing death announcement for plauyer pets
- [+] reduce #attacks for young hawk to 1
- [+] mercy
    - [+] say this to intelligent mosnters then pass a speech check
    - [+] if you pass:
        - [+] they say something
        - [+] they ko you
- [+] monstesr shouldn'ts randomly move into unconscious/dead lfs
- [+] monsters should take wanted obs from adjacent unconscious lfs
    - [+] when you wake up: "some/all of your items are missing..."
- [+] at beginner weapon skill level: exposed strike - takes longer but
      higher accuracy?
- [+] impaler frog
- [+] sinkmite
    - [+] drills for hands
    - [+] canwill Ot_s_dig
    - [+] targetting:
        - [+] fleeing: downwards
    - [+] can drill downwards to flee
    - [+] can dig through walls
- [+] necrons:
	- [+] trapper - blue
	- [+] reaper - red
	    - [+] scythe
	    - [+] hurricane strike
- [+] bug: necron reaper is not preffering its weapon for attacks....
      why?
    - [+] check attackcell()
- [+] fix colour in retaliation text
- [+] need to announce hurricane strike ability
- [+] amnesia scroll  - lose all skill points!
- Hecta effects
- [+] flay flesh (bleed depending on hitdice)
- [+] hecta's servent (skeletal hand rises, cannot move, grabs adjacent
      lfs, drags underground)
This commit is contained in:
Rob Pearce 2011-12-20 08:03:15 +00:00
parent 27f08ed7ab
commit 585876caee
17 changed files with 707 additions and 77 deletions

101
ai.c
View File

@ -476,6 +476,21 @@ void aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victi
// we should ALWAYS have at least one cell, because aispellok() // we should ALWAYS have at least one cell, because aispellok()
// will check this. // will check this.
if (spellcell) *spellcell = poss[rnd(0,nposs-1)]; if (spellcell) *spellcell = poss[rnd(0,nposs-1)];
} else if (spelltype->id == OT_S_DIG) {
cell_t *cell[MAXCANDIDATES],*poss[MAXCANDIDATES];
int ncells,i,nposs = 0;
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) {
poss[nposs++] = cell[i];
break;
}
}
// aim at an adjacent wall cell
if (spellcell) *spellcell = poss[rnd(0,nposs-1)];
} else if (spelltype->id == OT_S_TELEKINESIS) { } else if (spelltype->id == OT_S_TELEKINESIS) {
float maxweight; float maxweight;
object_t *poss[MAXPILEOBS]; object_t *poss[MAXPILEOBS];
@ -1725,12 +1740,12 @@ int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target) {
switch (o->type->id) { switch (o->type->id) {
case OT_POT_INVIS: case OT_POT_INVIS:
case OT_WAND_INVIS: case OT_WAND_INVIS:
if (lfhasflag(target, F_INVISIBLE)) { if (target && lfhasflag(target, F_INVISIBLE)) {
return B_FALSE; return B_FALSE;
} }
break; break;
case OT_POT_INVULN: case OT_POT_INVULN:
if (lfhasflag(target, F_INVULNERABLE)) { if (target && lfhasflag(target, F_INVULNERABLE)) {
return B_FALSE; return B_FALSE;
} }
break; break;
@ -2025,6 +2040,18 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
} }
} }
} }
} else if (ot->id == OT_S_DIG) {
cell_t *cell[MAXCANDIDATES];
int ncells,i;
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) {
ok = B_TRUE;
break;
}
}
} else if (ot->id == OT_A_JUMP) { } else if (ot->id == OT_A_JUMP) {
cell_t *cell[MAXCANDIDATES],*c; cell_t *cell[MAXCANDIDATES],*c;
int ncells,i; int ncells,i;
@ -2434,11 +2461,11 @@ int lookforobs(lifeform_t *lf) {
if (db) dblog(".oO { no targetcell, so looking for remote objects }"); if (db) dblog(".oO { no targetcell, so looking for remote objects }");
for (i = 0 ; i < lf->nlos; i++) { for (i = 0 ; i < lf->nlos; i++) {
int gothere = B_FALSE; int gothere = B_FALSE;
int celldist;
c = lf->los[i]; c = lf->los[i];
celldist = getcelldist(lf->cell, c);
if ((c != lf->cell) && !c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) { if ((c != lf->cell) && !c->lf && !lfhasflagval(lf, F_IGNORECELL, c->x, c->y, NA, NULL)) {
int celldist;
celldist = getcelldist(lf->cell, c);
for (o = c->obpile->first ; o ; o = nexto) { for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next; nexto = o->next;
@ -2510,6 +2537,72 @@ int lookforobs(lifeform_t *lf) {
return B_FALSE; return B_FALSE;
} }
} }
} else if ((celldist == 1) && c->lf &&
(isunconscious(c->lf) || isasleep(c->lf)) &&
(getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) > IQ_ANIMAL) && !isundead(lf)) {
// intelligent enemies will loot unconscious lfs to make sure they are not a threat.
//
// in this case they'll loot more than normal. even if they wouldn't normally pick up
// some of these objects, they'll assume they are good because the player was holding
// them.
int getit = B_FALSE;
for (o = c->lf->pack->first ; o ; o = nexto) {
nexto = o->next;
getit = B_FALSE;
if (aiwants_real(lf, o, &covets, &noids, oid, oidcovet, &nwantflags, wantflag, wantflagcovet)) {
getit = B_TRUE;
} else if (areenemies(lf, c->lf) && (isweapon(o) || isarmour(o))) {
getit = B_TRUE;
} else {
if (aiobok(lf, o, NULL)) {
flag_t *retflag[MAXCANDIDATES];
int nretflags;
getflags(o->flags, retflag, &nretflags, F_AIBOOSTITEM, F_AIFLEEITEM, F_AIHEALITEM, F_NONE);
if (nretflags) {
getit = B_TRUE;
}
}
}
// if we are in battle only go for it if we covet it
if (getit) {
if (target && !covets) getit = B_FALSE;
if (isdangerousob(o, lf, B_TRUE) || !aipickupok(lf, o)) getit = B_FALSE;
}
if (getit) {
break;
}
}
if (getit) {
int returnnow = B_FALSE;
if (db) dblog(".oO { adjacent unconscious lf has ob i want (%s) }",o->type->name);
// try to pick it up
if (aipickup(lf, o)) {
if (db) dblog(".oO { pickup of %s failed, trying to eat! }",o->type->name);
} else {
returnnow = B_TRUE; // got it!
}
if (!returnnow) {
if (eat(lf, o)) {
if (db) dblog(".oO { eating %s failed }",o->type->name);
} else {
returnnow = B_TRUE;
}
}
if (returnnow) {
// if they were only sleeping, they wake up a bit
f = isasleep(c->lf);
if (f) {
timeeffectsflag(f, 3 + rnd(1,3));
}
return B_TRUE;
}
}
} }
} }
} }

View File

@ -279,10 +279,31 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
attacktarget = o; attacktarget = o;
} else { } else {
// TODO: attack wall? // TODO: attack wall?
if (isplayer(lf) && !lfhasflag(lf, F_HURRICANESTRIKE)) { if (!lfhasflag(lf, F_HURRICANESTRIKE)) {
msg("There is nothing there to attack!"); /*
} flag_t *sf;
return B_TRUE; lifeform_t *stomachlf = NULL;
sf = hasflag(lf->cell->map->flags, F_STOMACHOF);
if (sf) {
stomachlf = findlf(NULL, sf->val[0]);
}
// we ARE allowed to attack stomach walls.
if (sf && stomachlf && (c->type->id == CT_WALLFLESH)) {
attacktype = AT_LF;
attacktarget = stomachlf;
} else {
// not allowed to attack normal walls
if (isplayer(lf)) {
msg("There is nothing there to attack!");
}
return B_TRUE;
}
*/
if (isplayer(lf)) {
msg("There is nothing there to attack!");
}
return B_TRUE;
} // end if !hurricanestrike
} }
} }
} }
@ -350,7 +371,8 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
int first; int first;
// player never invalidates their equipped weapons // player never invalidates their equipped weapons
if (isplayer(lf) && gotweapon) { //if (isplayer(lf) && gotweapon) {
if (gotweapon) {
first = lastweaponidx+1; first = lastweaponidx+1;
} else { } else {
first = 0; first = 0;
@ -921,15 +943,15 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
warn("%s", buf); warn("%s", buf);
} }
} }
if (!isplayer(lf) && !isplayer(victim)) { //if (!isplayer(lf) && !isplayer(victim)) {
noise(lf->cell, lf, NC_OTHER, 3, "fighting.", NULL); noise(lf->cell, lf, NC_FIGHTING, 3, "fighting.", NULL);
} //}
if (fatal) { if (fatal) {
if (strstr(buf, "behead")) { if (strstr(buf, "behead")) {
// we'll need to place the severed head object // we'll need to place the severed head object
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL); addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
} }
if (!hasflag(victim->flags, F_NODEATHANNOUNCE)) { if (cansee(player, victim) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
// don't also say "the xx dies" // don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
} }
@ -1117,7 +1139,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
char damstring[BUFLEN]; char damstring[BUFLEN];
rdam = rolldie(f->val[0], f->val[1]); rdam = rolldie(f->val[0], f->val[1]);
if (cansee(player, victim)) { if (cansee(player, victim)) {
msg("^%c%s%s %s %s %s!", isplayer(victim) ? 'b' : 'n', victimname, getpossessive(victimname), msg("^%c%s%s %s %s %s!", isplayer(lf) ? 'b' : 'n', victimname, getpossessive(victimname),
noprefix(f->text), noprefix(f->text),
getattackverb(victim, NULL, f->val[2], rdam, lf->maxhp), getattackverb(victim, NULL, f->val[2], rdam, lf->maxhp),
attackername); attackername);
@ -1787,8 +1809,8 @@ void getdamrange(object_t *o, flag_t *f, int *min, int *max) {
if (f) { if (f) {
if (hasflag(o->flags, F_MASTERWORK)) { if (hasflag(o->flags, F_MASTERWORK)) {
// 75%-100% // 85%-100%
mindam = pctof(75,f->val[1]); mindam = pctof(85,f->val[1]);
maxdam = f->val[1]; maxdam = f->val[1];
} else if (hasflag(o->flags, F_SHODDY)) { } else if (hasflag(o->flags, F_SHODDY)) {
// 25% - 75% // 25% - 75%

141
data.c
View File

@ -1736,54 +1736,63 @@ void initobjects(void) {
addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 250, NA, NA, NULL);
addot(OT_AMETHYST, "amethyst", "A purple gemstone.", MT_STONE, 0.2, OC_ROCK, SZ_TINY); addot(OT_AMETHYST, "amethyst", "A purple gemstone.", MT_STONE, 0.2, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_MAGENTA, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_MAGENTA, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL);
addot(OT_DIAMOND, "diamond", "A sparkling diamond.", MT_STONE, 0.2, OC_ROCK, SZ_TINY); addot(OT_DIAMOND, "diamond", "A sparkling diamond.", MT_STONE, 0.2, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_UNCOMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 1000, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 1000, NA, NA, NULL);
addot(OT_EMERALD, "emerald", "A deep green gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY); addot(OT_EMERALD, "emerald", "A deep green gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_GREEN, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_GREEN, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_UNCOMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 650, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 650, NA, NA, NULL);
addot(OT_OPAL, "opal", "An amorphous form of silica related to quartz.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addot(OT_OPAL, "opal", "An amorphous form of silica related to quartz.", MT_STONE, 0.1, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_GREY, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_GREY, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 70, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 70, NA, NA, NULL);
addot(OT_PEARL, "pearl", "A small pinkish-white gem.", MT_STONE, 0.1, OC_ROCK, SZ_TINY); addot(OT_PEARL, "pearl", "A small pinkish-white gem.", MT_STONE, 0.1, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 30, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 30, NA, NA, NULL);
addot(OT_RUBY, "ruby", "A large red gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY); addot(OT_RUBY, "ruby", "A large red gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_RED, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_RED, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 110, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 110, NA, NA, NULL);
addot(OT_SAPPHIRE, "sapphire", "A brilliant blue gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY); addot(OT_SAPPHIRE, "sapphire", "A brilliant blue gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_CYAN, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_CYAN, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_UNCOMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 850, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 850, NA, NA, NULL);
addot(OT_TOPAZ, "topaz stone", "A dull blue gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY); addot(OT_TOPAZ, "topaz stone", "A dull blue gem.", MT_STONE, 0.2, OC_ROCK, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_BLUE, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_BLUE, '*', NA, NULL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, "");
addflag(lastot->flags, F_RARITY, H_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 60, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 60, NA, NA, NULL);
@ -2206,6 +2215,9 @@ void initobjects(void) {
// scrolls // scrolls
addot(OT_SCR_AMNESIA, "scroll of amnesia", "Causes the reader to lose all accumulated skill points.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL);
addot(OT_SCR_AWARENESS, "scroll of awareness", "Mimics the effects of a 'heightened awareness' spell.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL); addot(OT_SCR_AWARENESS, "scroll of awareness", "Mimics the effects of a 'heightened awareness' spell.", MT_PAPER, 0.5, OC_SCROLL, SZ_SMALL);
addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 50, NA, NA, NULL);
@ -2430,6 +2442,13 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addot(OT_S_FLAYFLESH, "flay flesh", "Causes invisible tendrils to strike your foe, causing an automatic slash critical on fleshy creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
addot(OT_S_PAIN, "pain", "Causes extreme pain in the target whenever they move.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PAIN, "pain", "Causes extreme pain in the target whenever they move.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the duration of the pain effect."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the duration of the pain effect.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
@ -2975,8 +2994,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
// l4 // l4
addot(OT_S_DIG, "dig", "Blasts away earth to create passages.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_DIG, "dig", "Blasts away earth to create passages.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
@ -2984,6 +3001,8 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addot(OT_S_ENTANGLE, "entangle", "Causes magical vines to hold enemies.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_ENTANGLE, "entangle", "Causes magical vines to hold enemies.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the strength of the vines."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the strength of the vines.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
@ -3567,7 +3586,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_ENHANCE, "enhance", "Enhance a lifeform's stats.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_ENHANCE, "enhance stats", "Enhance a lifeform's stats.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_LEARN, "learn", "Learn new skills.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_LEARN, "learn", "Learn new skills.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
@ -3642,6 +3661,8 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL);
addot(OT_A_ENHANCEOB, "enhance item", "Combine two regular items into a single masterwork item.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_FEIGNDEATH, "feign death", "Pretend to be dead.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); 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); 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); addot(OT_A_FLIP, "flip", "Flip your opponent over your head.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
@ -3655,6 +3676,10 @@ 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); 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_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addot(OT_A_EXPOSEDSTRIKE, "wild strike", "A wild blow directly at your enemy with no regard for safety. Almost always hits, but leaves you completely exposed to follow-up attacks.", 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_STAMCOST, 1, NA, NA, NULL);
addot(OT_A_HEAVYBLOW, "heavy blow", "Mighty blow which knocks enemies backwards.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); 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_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
@ -5655,6 +5680,14 @@ void initobjects(void) {
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "peck"); addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "peck");
addot(OT_DRILL, "drills", "drills object", MT_METAL, 0, OC_WEAPON, SZ_TINY);
addflag(lastot->flags, F_DAM, DT_SLASH, 2, NA, NULL);
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "drill");
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL);
addot(OT_CLAWS, "claws", "claws object", MT_BONE, 0, OC_WEAPON, SZ_TINY); addot(OT_CLAWS, "claws", "claws object", MT_BONE, 0, OC_WEAPON, SZ_TINY);
addflag(lastot->flags, F_DAM, DT_SLASH, 2, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 2, NA, NULL);
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
@ -6994,6 +7027,7 @@ void initrace(void) {
// human monsters... // human monsters...
addrace(R_BANDITLDR, "bandit leader", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID, "Like a regular bandit, but bigger and stronger. Enough so to bully their followers into submission anyway."); addrace(R_BANDITLDR, "bandit leader", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID, "Like a regular bandit, but bigger and stronger. Enough so to bully their followers into submission anyway.");
lastrace->baseid = R_BANDIT;
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL); addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_RARE, NULL);
@ -7024,6 +7058,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_ALL, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL); addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_DEMANDSBRIBE, NA, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4");
@ -8463,6 +8498,23 @@ void initrace(void) {
addflag(lastrace->flags, F_NOFLEE, 5, NA, NA, NULL); addflag(lastrace->flags, F_NOFLEE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addrace(R_SINKMITE, "sinkmite", 2, 'm', C_GREY, MT_FLESH, RC_ANIMAL, "A mutated humanoid with large drills in place of hands. It gained its name from its ability to 'sink' out of range when threatened.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "4d4");
addflag(lastrace->flags, F_DTIMMUNE, DT_PROJECTILE, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_FALL, 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_STARTATT, A_STR, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_DRILL, 5, NA, NULL);
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_DIG, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CASTCHANCE, 50, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "pounds its drills into the ground");
addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE, RC_MAGIC, "A small magical creature surrounded by crackling flames."); addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE, RC_MAGIC, "A small magical creature surrounded by crackling flames.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "small fire"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "small fire");
@ -9196,7 +9248,6 @@ void initrace(void) {
addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL);
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "hop"); addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "hop");
addrace(R_HAWKYOUNG, "young hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL, "A young baby hawk."); // 'A' for Avian addrace(R_HAWKYOUNG, "young hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL, "A young baby hawk."); // 'A' for Avian
setbodytype(lastrace, BT_BIRD); setbodytype(lastrace, BT_BIRD);
lastrace->baseid = R_HAWK; lastrace->baseid = R_HAWK;
@ -9213,6 +9264,7 @@ void initrace(void) {
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+2"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+2");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL);
addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL);
@ -9726,7 +9778,7 @@ void initrace(void) {
//addflag(lastrace->flags, F_WANTSOBFLAG, F_RARITY, NA, NA, NULL); // ie. everything //addflag(lastrace->flags, F_WANTSOBFLAG, F_RARITY, NA, NA, NULL); // ie. everything
addflag(lastrace->flags, F_CANWILL, OT_A_SWALLOW, 5, 5, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SWALLOW, 5, 5, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, NULL); addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "opens its mouth wide..");
addflag(lastrace->flags, F_NOISETEXT, N_WALK, SV_ROAR, NA, "^slithering"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, SV_ROAR, NA, "^slithering");
addflag(lastrace->flags, F_FLEEONHPPCT, 20, NA, NA, ""); addflag(lastrace->flags, F_FLEEONHPPCT, 20, NA, NA, "");
addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL);
@ -10397,7 +10449,58 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addrace(R_QUASIT, "quasit", 4, '&', C_BROWN, MT_FLESH, RC_DEMON, "A tiny, bald humanoid with small spiked horns running down the middle of its scalp, leathery bat-like wings and of course sharp claws.."); addrace(R_NECRONREAPER, "necron reaper", 65, 'N', C_RED, MT_FLESH, RC_DEMON, "An evil demonic creature, covered in spikes and the bright red blood of its victims.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_TAIL, NULL);
addbodypart(lastrace, BP_WINGS, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_RETALIATE, 1, 4, DT_PIERCE, "spikes");
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "6d4");
addflag(lastrace->flags, F_REGENERATES, 1, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 4, 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_STARTATT, A_AGI, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_HURRICANESTRIKE, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 2, NA, NULL);
addflag(lastrace->flags, F_VAMPIRIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_DETECTMAGIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_POLEARMS, PR_SKILLED, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "scythe");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "screechs^an other-wordly screech");
addrace(R_NECRONTRAPPER, "necron trapper", 65, 'N', C_BLUE, MT_FLESH, RC_DEMON, "A wiry, muscled humanoid whose blue-black flesh seems to writhe and pulse. Its elongatd jaw holds razor-sharp fangs which drip with saliva.");
setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_TAIL, NULL);
addbodypart(lastrace, BP_WINGS, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTHIDDENPCT, 70, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4");
addflag(lastrace->flags, F_REGENERATES, 1, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 6, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL);
addflag(lastrace->flags, F_VAMPIRIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL);
addflag(lastrace->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL);
addflag(lastrace->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_DETECTMAGIC, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_STEALTH, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_ENTANGLE, 3, 3, "pw:5;");
addflag(lastrace->flags, F_CANWILL, OT_S_INVISIBILITY, 5, 5, "pw:1;");
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "grins");
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "screechs^an other-wordly screech");
addrace(R_QUASIT, "quasit", 4, '&', C_BROWN, MT_FLESH, RC_DEMON, "A tiny, bald humanoid with small spiked horns running down the middle of its scalp, leathery bat-like wings and of course sharp claws...");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
addbodypart(lastrace, BP_WINGS, NULL); addbodypart(lastrace, BP_WINGS, NULL);
@ -10866,13 +10969,12 @@ void initskills(void) {
addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks.", 50); 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); addskilldesc(SK_LOCKPICKING, PR_NOVICE, "^gYou gain the 'pick locks' ability.^n", B_FALSE);
addskill(SK_METALWORK, "Metalwork", "Lets you repair metal objects.", 100); 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_NOVICE, "^gYou can repair metal items up to 40% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 50% condition.^n", B_FALSE); addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 60% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_ADEPT, "^gYou can repair metal items up to 60% condition.^n", B_FALSE); addskilldesc(SK_METALWORK, PR_ADEPT, "^gYou can repair metal items up to 80% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_SKILLED, "^gYou can repair metal items up to 70% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_SKILLED, "^gYou can re-size metal armour (at the expense of durability).^n", B_FALSE); addskilldesc(SK_METALWORK, PR_SKILLED, "^gYou can re-size metal armour (at the expense of durability).^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_EXPERT, "^gYou can repair metal items up to 85% condition.^n", B_FALSE); addskilldesc(SK_METALWORK, PR_EXPERT, "^gYou can fully repair metal items.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_MASTER, "^gYou can fully repair metal items.^n", B_FALSE); addskilldesc(SK_METALWORK, PR_MASTER, "^gYou can increase an item's quality to masterwork using a duplicate.^n", B_FALSE);
addskill(SK_RANGED, "Ranged Weapons", "Your ability to aim a ranged weapon like a bow or gun.", 50); addskill(SK_RANGED, "Ranged Weapons", "Your ability to aim a ranged weapon like a bow or gun.", 50);
addskilldesc(SK_RANGED, PR_INEPT, "^gYour ranged accuracy decreases by 32%% per cell.^n", B_FALSE); addskilldesc(SK_RANGED, PR_INEPT, "^gYour ranged accuracy decreases by 32%% per cell.^n", B_FALSE);
addskilldesc(SK_RANGED, PR_NOVICE, "^gYour ranged accuracy decreases by 22%% per cell.^n", B_FALSE); addskilldesc(SK_RANGED, PR_NOVICE, "^gYour ranged accuracy decreases by 22%% per cell.^n", B_FALSE);
@ -10885,13 +10987,15 @@ void initskills(void) {
addskilldesc(SK_RANGED, PR_MASTER, "^gYour ranged attacks now deal 50% more damage.^n", B_TRUE); addskilldesc(SK_RANGED, PR_MASTER, "^gYour ranged attacks now deal 50% more damage.^n", B_TRUE);
addskilldesc(SK_RANGED, PR_MASTER, "^gYour ranged accuracy decreases by 6%% per cell.^n", B_FALSE); addskilldesc(SK_RANGED, PR_MASTER, "^gYour ranged accuracy decreases by 6%% per cell.^n", B_FALSE);
addskill(SK_SEWING, "Sewing", "Lets you repair cloth or leather objects.", 100); addskill(SK_SEWING, "Sewing", "Lets you repair cloth or leather objects.", 100);
addskilldesc(SK_SEWING, PR_NOVICE, "^gYou can repair cloth items up to 33% condition.^n", B_FALSE); addskilldesc(SK_SEWING, PR_NOVICE, "^gYou can repair cloth items up to 40% condition.^n", B_FALSE);
addskilldesc(SK_SEWING, PR_BEGINNER, "^gYou can repair cloth items up to 50% condition^n", B_FALSE); addskilldesc(SK_SEWING, PR_BEGINNER, "^gYou can repair cloth items up to 60% condition.^n", B_FALSE);
addskilldesc(SK_SEWING, PR_ADEPT, "^gYou can repair cloth items up to 60% condition^n", B_FALSE); addskilldesc(SK_SEWING, PR_ADEPT, "^gYou can repair cloth items up to 80% condition.^n", B_FALSE);
addskilldesc(SK_SEWING, PR_SKILLED, "^gYou can repair cloth items up to 70% condition^n", B_FALSE);
addskilldesc(SK_SEWING, PR_SKILLED, "^gYou can re-size cloth armour (at the expense of durability).^n", B_FALSE); addskilldesc(SK_SEWING, PR_SKILLED, "^gYou can re-size cloth armour (at the expense of durability).^n", B_FALSE);
addskilldesc(SK_SEWING, PR_EXPERT, "^gYou can repair cloth items up to 85% condition^n", B_FALSE); addskilldesc(SK_SEWING, PR_EXPERT, "^gYou can fully repair cloth items.^n", B_FALSE);
addskilldesc(SK_SEWING, PR_MASTER, "^gYou can fully repair cloth items.^n", B_FALSE); addskilldesc(SK_SEWING, PR_MASTER, "^gYou can increase an item's quality to masterwork using a duplicate.^n", B_FALSE);
addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block attacks.", 50); 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_INEPT, "- Without this skill, shield accuracy penalties are tripled.", B_FALSE);
addskilldesc(SK_SHIELDS, PR_NOVICE, "^gShield accuracy penalties are reduced by 1.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_NOVICE, "^gShield accuracy penalties are reduced by 1.^n", B_FALSE);
@ -11149,6 +11253,7 @@ void initskills(void) {
addskilldesc(sk->id, PR_INEPT, "This skill increases your accuracy and damage when using matching weapons.", B_FALSE); addskilldesc(sk->id, PR_INEPT, "This skill increases your accuracy and damage when using matching weapons.", B_FALSE);
addskilldesc(sk->id, PR_NOVICE, "^g-2 accuracy penalty.^n", B_FALSE); addskilldesc(sk->id, PR_NOVICE, "^g-2 accuracy penalty.^n", B_FALSE);
addskilldesc(sk->id, PR_BEGINNER, "^g-1 accuracy penalty^n", B_FALSE); addskilldesc(sk->id, PR_BEGINNER, "^g-1 accuracy penalty^n", B_FALSE);
addskilldesc(sk->id, PR_BEGINNER, "^gYou gain the 'wild strike' ability.^n", B_FALSE);
addskilldesc(sk->id, PR_ADEPT, "^g+10% damage bonus.^n", B_FALSE); addskilldesc(sk->id, PR_ADEPT, "^g+10% damage bonus.^n", B_FALSE);
addskilldesc(sk->id, PR_ADEPT, "^gYou can now alter your attack style to deal different damage types.", B_FALSE); addskilldesc(sk->id, PR_ADEPT, "^gYou can now alter your attack style to deal different damage types.", B_FALSE);
addskilldesc(sk->id, PR_SKILLED, "^g+2 accuracy, +20% damage bonus.^n", B_FALSE); addskilldesc(sk->id, PR_SKILLED, "^g+2 accuracy, +20% damage bonus.^n", B_FALSE);

Binary file not shown.

22
defs.h
View File

@ -58,6 +58,7 @@
#define WE_PORTAL 3 #define WE_PORTAL 3
#define WE_NOTWALL 4 #define WE_NOTWALL 4
#define WE_NOLF 5 #define WE_NOLF 5
#define WE_SOLID 6
// Booleans // Booleans
#define B_FALSE (0) #define B_FALSE (0)
@ -427,7 +428,8 @@ enum NOISECLASS {
NC_NONE = 0, NC_NONE = 0,
NC_MOVEMENT = 1, NC_MOVEMENT = 1,
NC_SPEECH = 2, NC_SPEECH = 2,
NC_OTHER = 3, NC_FIGHTING = 3,
NC_OTHER = 4,
}; };
enum QUADRANT { enum QUADRANT {
@ -452,6 +454,7 @@ enum SAYPHRASE {
SP_BEGTHANKS, SP_BEGTHANKS,
SP_DIE, SP_DIE,
SP_DRUNK, SP_DRUNK,
SP_MERCYACCEPT,
SP_PAYWARN, SP_PAYWARN,
SP_PAYTHREAT, SP_PAYTHREAT,
SP_PAYTHANKS, SP_PAYTHANKS,
@ -894,6 +897,7 @@ enum RACE {
R_PRIMALSTONEL, R_PRIMALSTONEL,
R_SATYR, R_SATYR,
R_SHADOWCAT, R_SHADOWCAT,
R_SINKMITE,
R_SPRITEFIRE, R_SPRITEFIRE,
R_SPRITEGRAVE, R_SPRITEGRAVE,
R_SPRITEICE, R_SPRITEICE,
@ -974,6 +978,11 @@ enum RACE {
// demons // demons
R_DRETCH, R_DRETCH,
R_LURKINGHORROR, R_LURKINGHORROR,
R_NECRONTRAPPER,
R_NECRONREAPER,
R_NECRONSOWER,
R_NECRONEXTERMINATOR,
R_NECRONHARVESTER,
R_QUASIT, R_QUASIT,
// undead // undead
R_GHAST, R_GHAST,
@ -1206,6 +1215,7 @@ enum OBTYPE {
// scrolls // scrolls
OT_MAP, OT_MAP,
OT_GRAPHPAPER, OT_GRAPHPAPER,
OT_SCR_AMNESIA,
OT_SCR_AWARENESS, OT_SCR_AWARENESS,
OT_SCR_NOTHING, OT_SCR_NOTHING,
OT_SCR_CREATEMONSTER, OT_SCR_CREATEMONSTER,
@ -1246,6 +1256,7 @@ enum OBTYPE {
OT_S_COMMANDUNDEAD, OT_S_COMMANDUNDEAD,
OT_S_DRAINLIFE, OT_S_DRAINLIFE,
OT_S_FEAR, OT_S_FEAR,
OT_S_FLAYFLESH,
OT_S_HECTASSERVANT, OT_S_HECTASSERVANT,
OT_S_PAIN, OT_S_PAIN,
OT_S_PARALYZE, OT_S_PARALYZE,
@ -1440,6 +1451,7 @@ enum OBTYPE {
OT_A_DISARM, // disarm a trap OT_A_DISARM, // disarm a trap
OT_A_DISARMLF, // disarm an opponent OT_A_DISARMLF, // disarm an opponent
OT_A_DRAGUNDERGROUND, OT_A_DRAGUNDERGROUND,
OT_A_ENHANCEOB,
OT_A_FEIGNDEATH, OT_A_FEIGNDEATH,
OT_A_FLIP, OT_A_FLIP,
OT_A_FLURRY, OT_A_FLURRY,
@ -1463,6 +1475,7 @@ enum OBTYPE {
OT_A_SWOOP, OT_A_SWOOP,
OT_A_TRIPLF, // trip an opponent OT_A_TRIPLF, // trip an opponent
OT_A_EMPLOY, OT_A_EMPLOY,
OT_A_EXPOSEDSTRIKE,
OT_A_HEAVYBLOW, OT_A_HEAVYBLOW,
OT_A_HIDE, OT_A_HIDE,
OT_A_INSPECT, OT_A_INSPECT,
@ -1708,6 +1721,7 @@ enum OBTYPE {
// innate / animal weapons // innate / animal weapons
OT_BEAK, OT_BEAK,
OT_CLAWS, OT_CLAWS,
OT_DRILL,
OT_FISTS, OT_FISTS,
OT_HOOKHAND, // for pirate OT_HOOKHAND, // for pirate
OT_STING, OT_STING,
@ -1951,7 +1965,7 @@ enum FLAG {
F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2 F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2
F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs. F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs.
// v0+1 are x/y, v2 is new depth. // v0+1 are x/y, v2 is new depth.
F_STOMACHOF, // this map is the stomach of f->text F_STOMACHOF, // this map is the stomach of lf id V0, name = f->text
// object flags // object flags
F_BADOBJECT, // this object is dangerous. ie. potion of poison, F_BADOBJECT, // this object is dangerous. ie. potion of poison,
// potion of sleep, etc. // potion of sleep, etc.
@ -2373,6 +2387,9 @@ enum FLAG {
F_TOOKACTION, // lf purposely took action in their last turn. F_TOOKACTION, // lf purposely took action in their last turn.
F_MOVED, // lf purposely walked/flew/swum/moved in prev turn F_MOVED, // lf purposely walked/flew/swum/moved in prev turn
F_HASBEENMOVED, // an object moved this lf since their last turn. F_HASBEENMOVED, // an object moved this lf since their last turn.
F_WASROBBED, // your stuff was stolen while you were
// unconscious. announce it when you wake up.
F_TURNED, // lf turned this turn.
F_PRAYEDTO, // player has prayed to this god before. F_PRAYEDTO, // player has prayed to this god before.
F_GAVEMONEY, // v0 tracks how much money we gave away this turn F_GAVEMONEY, // v0 tracks how much money we gave away this turn
// used for r_godgreed anger effects. // used for r_godgreed anger effects.
@ -3473,6 +3490,7 @@ typedef struct lifeform_s {
int x,y; int x,y;
int facing; // which way are we facing int facing; // which way are we facing
int turncounter; // keeps track of # direction changes in a row
int losdirty; int losdirty;
int nlos; // cells which we can see int nlos; // cells which we can see

View File

@ -25,6 +25,7 @@ j = jelly/ooze/leech
k = kobold k = kobold
m = mutant m = mutant
n = small humanoid / nymph / sprite n = small humanoid / nymph / sprite
N = necron
o = orc o = orc
O = ogre O = ogre
p = sPirit p = sPirit

3
flag.c
View File

@ -884,6 +884,7 @@ void killflag(flag_t *f) {
flag_t *nextone, *lastone; flag_t *nextone, *lastone;
flagpile_t *pile; flagpile_t *pile;
lifeform_t *lf; lifeform_t *lf;
enum FLAG fid;
map_t *redolight = NULL; map_t *redolight = NULL;
cell_t *redolos = NULL; cell_t *redolos = NULL;
int redostat = B_FALSE; int redostat = B_FALSE;
@ -892,6 +893,8 @@ void killflag(flag_t *f) {
//checkflagpile(f->pile); //checkflagpile(f->pile);
fid = f->id;
for (i = 0; i < ngodlfs; i++) { for (i = 0; i < ngodlfs; i++) {
dopleasegod[i] = 0; dopleasegod[i] = 0;
} }

5
god.c
View File

@ -876,11 +876,12 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
msg("\"Behold, the power of death!\""); msg("\"Behold, the power of death!\"");
c = NULL; c = NULL;
n = OT_NONE; n = OT_NONE;
switch (rnd(0,3)) { switch (rnd(0,4)) {
case 0: n = OT_S_PAIN; break; case 0: n = OT_S_PAIN; break;
case 1: n = OT_S_DRAINLIFE; break; case 1: n = OT_S_DRAINLIFE; break;
case 2: n = OT_S_BLINDNESS; break; case 2: n = OT_S_BLINDNESS; break;
case 3: n = OT_S_HECTASSERVANT; case 3: n = OT_S_FLAYFLESH; break;
case 4: n = OT_S_HECTASSERVANT;
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
break; break;
} }

40
io.c
View File

@ -1793,11 +1793,13 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
} }
} }
donesomething = B_TRUE; donesomething = B_TRUE;
needredraw = B_TRUE;
} }
break; break;
case F_XRAYVIS: case F_XRAYVIS:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("The walls around you suddenly turn transparent!"); msg("The walls around you suddenly turn transparent!");
needredraw = B_TRUE;
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
@ -1807,7 +1809,8 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
if (donesomething) statdirty = B_TRUE; if (donesomething) statdirty = B_TRUE;
if (statdirty || needredraw) { //if (statdirty || needredraw) {
if (statdirty) {
drawscreen(); drawscreen();
} }
@ -3697,6 +3700,10 @@ void docomms(lifeform_t *lf) {
} else { } else {
addchoice(&prompt, 'j', "Join me on my quest!", NULL, NULL, NULL); addchoice(&prompt, 'j', "Join me on my quest!", NULL, NULL, NULL);
} }
}
if (areenemies(player, lf)) {
addchoice(&prompt, 'm', "Have mercy!", NULL, NULL, NULL);
} }
// if you are allies, use 'trade items' instead // if you are allies, use 'trade items' instead
@ -3714,6 +3721,8 @@ void docomms(lifeform_t *lf) {
addchoice(&prompt, 'p', buf, NULL, NULL, NULL); addchoice(&prompt, 'p', buf, NULL, NULL, NULL);
} }
} }
addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL, NULL); addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL, NULL);
addchoice(&prompt, 'n', "(nothing)", NULL, NULL, NULL); addchoice(&prompt, 'n', "(nothing)", NULL, NULL, NULL);
@ -3935,6 +3944,33 @@ void docomms(lifeform_t *lf) {
} }
recruit(lf); recruit(lf);
break; break;
case 'm': // mercy
msg("You say \"Have mercy!\" to %s.", lfname);
if (islowhp(player) &&
cantalk(lf) &&
canhear(lf, player->cell, SV_SHOUT) &&
(getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) > IQ_ANIMAL) &&
!isundead(lf)) {
if (skillcheck(player, SC_SPEECH, 30, 0)) {
// passed!
sayphrase(lf, SP_MERCYACCEPT, SV_TALK, NA, player->race->name);
// they knock you out
msg("^%d*WHACK*^n", C_YELLOW);
fallasleep(player, ST_KO, rnd(50,100));
// they take all your stuff
/*
for (o = player->pack->first ; o ; o = nexto) {
nexto = o->next;
if (canpickup(lf, o, ALL)) {
pickup(lf, o, ALL, B_FALSE, B_FALSE);
}
}
*/
// they stop attacking you
loseaitargets(lf);
}
}
break;
case 'p': case 'p':
// can we afford this? // can we afford this?
if (givemoney(player, lf, moneyowing)) { if (givemoney(player, lf, moneyowing)) {
@ -9120,7 +9156,7 @@ void drawstatus(void) {
unsetcol(statwin, C_CYAN); unsetcol(statwin, C_CYAN);
} else if ((f = lfhasflag(player, F_ASLEEP)) != NULL) { } else if ((f = lfhasflag(player, F_ASLEEP)) != NULL) {
setcol(statwin, C_MAGENTA); setcol(statwin, C_MAGENTA);
if (f->val[2] == ST_KO) { if (f->val[1] == ST_KO) {
wprintw(statwin, " KO"); wprintw(statwin, " KO");
} else { } else {
wprintw(statwin, " Asleep"); wprintw(statwin, " Asleep");

132
lf.c
View File

@ -1614,7 +1614,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
} }
} else { // player can't see them } else { // player can't see them
if ((targlf == player) || (targcell == player->cell)) { if ((targlf == player) || (targcell == player->cell)) {
if (!lfhasflag(player, F_ASLEEP)) { if (!lfhasflag(player, F_ASLEEP) && !lfhasflag(lf, F_SPELLCASTTEXT)) {
msg("Something casts a spell at you."); msg("Something casts a spell at you.");
} }
} }
@ -2104,6 +2104,7 @@ void debug(lifeform_t *lf) {
// returns true if the player pays. // returns true if the player pays.
int demandbribe(lifeform_t *lf) { int demandbribe(lifeform_t *lf) {
lifeform_t *l;
char lfname[BUFLEN]; char lfname[BUFLEN];
int amtwanted,amtgiven,totmoney; int amtwanted,amtgiven,totmoney;
int hd; int hd;
@ -2189,8 +2190,12 @@ int demandbribe(lifeform_t *lf) {
} }
} }
// either way, kill bribe flag // either way, kill bribe flag for all bandits on the level
killflagsofid(lf->flags, F_DEMANDSBRIBE); for (l = lf->cell->map->lf ; l ; l = l->next) {
if (!isplayer(l) && (l->race->baseid == lf->race->baseid)) {
killflagsofid(l->flags, F_DEMANDSBRIBE);
}
}
return satisfied; return satisfied;
} }
@ -2337,8 +2342,10 @@ void die(lifeform_t *lf) {
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
if (cantalk(lf) && canhear(player, lf->cell, 4)) { if (cantalk(lf) && canhear(player, lf->cell, 4)) {
sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL); sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL);
} else if (cantalk(lf)) { } else if (!cansee(player, lf)) {
warn("You feel a profound sense of loss."); warn("You feel a profound sense of loss.");
// redraw since you can "see" the pet even if it's out of sight
needredraw = B_TRUE;
more(); more();
//} else { //} else {
// makenoise(lf, N_DIE); // makenoise(lf, N_DIE);
@ -8568,6 +8575,12 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
newf = addflag(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL);
newf->lifetime = FROMSKILL; newf->lifetime = FROMSKILL;
} }
} else if (f->val[1] == PR_MASTER) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_ENHANCEOB, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_ENHANCEOB, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
} }
} else if (id == SK_PERCEPTION) { } else if (id == SK_PERCEPTION) {
if ((f->val[1] == PR_ADEPT) || (f->val[1] == PR_MASTER)) { if ((f->val[1] == PR_ADEPT) || (f->val[1] == PR_MASTER)) {
@ -8582,6 +8595,12 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
newf = addflag(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_RESIZE, NA, NA, NULL);
newf->lifetime = FROMSKILL; newf->lifetime = FROMSKILL;
} }
} else if (f->val[1] == PR_MASTER) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_ENHANCEOB, NA, NA, NULL);
if (!newf) {
newf = addflag(lf->flags, F_CANWILL, OT_A_ENHANCEOB, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
} }
} else if (id == SK_SHIELDS) { } else if (id == SK_SHIELDS) {
if (f->val[1] == PR_BEGINNER) { if (f->val[1] == PR_BEGINNER) {
@ -8637,7 +8656,12 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
} }
if (isweaponskill(id)) { if (isweaponskill(id)) {
if (f->val[1] == PR_ADEPT) { if (f->val[1] == PR_BEGINNER) {
if (!hasflagval(lf->flags, F_CANWILL, OT_A_EXPOSEDSTRIKE, NA, NA, NULL)) {
newf = addflag(lf->flags, F_CANWILL, OT_A_EXPOSEDSTRIKE, NA, NA, NULL);
newf->lifetime = FROMSKILL;
}
} else if (f->val[1] == PR_ADEPT) {
if (!hasflagval(lf->flags, F_CANWILL, OT_A_ALTERATTACK, NA, NA, NULL)) { if (!hasflagval(lf->flags, F_CANWILL, OT_A_ALTERATTACK, NA, NA, NULL)) {
newf = addflag(lf->flags, F_CANWILL, OT_A_ALTERATTACK, NA, NA, NULL); newf = addflag(lf->flags, F_CANWILL, OT_A_ALTERATTACK, NA, NA, NULL);
newf->lifetime = FROMSKILL; newf->lifetime = FROMSKILL;
@ -10064,6 +10088,10 @@ int isaquatic(lifeform_t *lf) {
return B_FALSE; return B_FALSE;
} }
flag_t *isasleep(lifeform_t *lf) {
return lfhasflagval(lf, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
}
// is lf behind otherlf? // is lf behind otherlf?
int isbehind(lifeform_t *lf, lifeform_t *otherlf) { int isbehind(lifeform_t *lf, lifeform_t *otherlf) {
int dir; int dir;
@ -10583,7 +10611,6 @@ flag_t *isresting(lifeform_t *lf) {
return NULL; return NULL;
} }
int issleepingtimefor(lifeform_t *lf) { int issleepingtimefor(lifeform_t *lf) {
if (lfhasflag(lf, F_NOCTURNAL) && !isnighttime()) { if (lfhasflag(lf, F_NOCTURNAL) && !isnighttime()) {
return B_TRUE; return B_TRUE;
@ -10718,6 +10745,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
// for precalcing line of sight // for precalcing line of sight
a->facing = rnd(DC_N, DC_NW); a->facing = rnd(DC_N, DC_NW);
a->turncounter = 0;
a->losdirty = B_TRUE; a->losdirty = B_TRUE;
//a->los = malloc( sizeof(cell_t *) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1))); //a->los = malloc( sizeof(cell_t *) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1)));
a->los = NULL; // will be alloced in precalclos a->los = NULL; // will be alloced in precalclos
@ -12761,10 +12789,16 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
dist = getcelldist(l->cell, c); dist = getcelldist(l->cell, c);
// listen check difficulty is based on sound distance vs max hearing distance // listen check difficulty is based on sound distance vs max hearing distance
if ((nclass == NC_SPEECH) && isplayer(l)) { if ((nclass == NC_SPEECH) && isplayer(l)) {
// you always hear it, as long as you're in range // you always hear it, as long as you're in range
difficulty = 0; difficulty = 0;
} else if ((nclass == NC_FIGHTING) && isplayer(l) && (dist <= 1)) {
// players never hear fighting unless it's a small distance away
// this prevents "you hear fighting" when you are attacked from behind.
difficulty = 9999;
} else { } else {
//difficulty = (int) ( ((float)getcelldist(l->cell, c) / (float)gethearingrange(l)) * 20); //difficulty = (int) ( ((float)getcelldist(l->cell, c) / (float)gethearingrange(l)) * 20);
difficulty = (int) ( ((float)getcelldist(l->cell, c) / ((float)gethearingrange(l) + volume)) * 14); difficulty = (int) ( ((float)getcelldist(l->cell, c) / ((float)gethearingrange(l) + volume)) * 14);
@ -12949,12 +12983,15 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
if (willrespond) { if (willrespond) {
// turn to face the sound // turn to face the sound
if (isplayer(noisemaker) && cansee(player, l) && cansee(l, player) && !lfhasflag(l, F_AWARENESS)) { if (isplayer(noisemaker) && cansee(l, player) && !lfhasflag(l, F_AWARENESS)) {
// peaceful things only turn sometimes // peaceful things only turn sometimes
if (!ispeaceful(l) || onein(6)) { if (!ispeaceful(l) || onein(6)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
int prefacing;
prefacing = l->facing;
turntoface(l, c); turntoface(l, c);
if (!lfhasflag(l, F_FEIGNINGDEATH)) { if (!lfhasflag(l, F_FEIGNINGDEATH) && cansee(player, l) &&
(prefacing != l->facing)) {
getlfname(l, lfname); getlfname(l, lfname);
msg("%s turns to face you.", lfname); msg("%s turns to face you.", lfname);
} }
@ -13276,8 +13313,10 @@ void precalclos_new(lifeform_t *lf) {
//int db = B_FALSE; //int db = B_FALSE;
enum SKILLLEVEL plev = PR_INEPT; enum SKILLLEVEL plev = PR_INEPT;
flag_t *missingeye; flag_t *missingeye;
long visdiameter;
long allocamt; long allocamt;
if (gamemode == GM_CLEANUP) return; if (gamemode == GM_CLEANUP) return;
if (lf->cell->type->id == CT_FAKE) return; if (lf->cell->type->id == CT_FAKE) return;
@ -13305,7 +13344,9 @@ void precalclos_new(lifeform_t *lf) {
startxray = 0; startxray = 0;
} }
allocamt = ((MAXVISRANGE*2)+1) * ((MAXVISRANGE*2)+1); // ie. you can see both ways, plus your own cell
visdiameter = (MAXVISRANGE+1)*2;
allocamt = visdiameter * visdiameter;
los = malloc( sizeof(cell_t *) * allocamt); los = malloc( sizeof(cell_t *) * allocamt);
losdark = malloc( sizeof(cell_t *) * allocamt); losdark = malloc( sizeof(cell_t *) * allocamt);
blocker = malloc( sizeof(cell_t *) * allocamt); blocker = malloc( sizeof(cell_t *) * allocamt);
@ -13974,6 +14015,7 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
char buf[BUFLEN]; char buf[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
char *p; char *p;
race_t *r;
switch (what) { switch (what) {
case SP_ALLY_ATTACK: case SP_ALLY_ATTACK:
switch (rnd(1,3)) { switch (rnd(1,3)) {
@ -14075,6 +14117,18 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
} }
say(lf, buf, volume); say(lf, buf, volume);
break; break;
case SP_MERCYACCEPT:
switch (rnd(1,2)) {
case 1:
r = findrace(val0);
snprintf(buf, BUFLEN, "Cowardly %s...", text);
break;
case 2:
snprintf(buf, BUFLEN, "Guess I don't need to actually kill you...");
break;
}
rv = say(lf, buf, volume);
break;
case SP_PAYWARN: case SP_PAYWARN:
switch (rnd(1,3)) { switch (rnd(1,3)) {
case 1: snprintf(buf, BUFLEN, "Hey! Where do you think you're going?"); break; case 1: snprintf(buf, BUFLEN, "Hey! Where do you think you're going?"); break;
@ -15201,7 +15255,7 @@ void startlfturn(lifeform_t *lf) {
enum ERROR error; enum ERROR error;
object_t *o; object_t *o;
flag_t *f; flag_t *f;
flag_t *asp; flag_t *asp, *sf;
char buf[BUFLEN]; char buf[BUFLEN];
lifeform_t *l; lifeform_t *l;
int i; int i;
@ -15214,6 +15268,50 @@ void startlfturn(lifeform_t *lf) {
if (db) dblog("startlfturn for lf id %d %s", lf->id, lf->race->name); if (db) dblog("startlfturn for lf id %d %s", lf->id, lf->race->name);
// MOVE OUT OF STOMACHS WHICH DONT EXIST ANYMORE
sf = hasflag(map->flags, F_STOMACHOF);
if (sf) {
lifeform_t *stomachlf;
stomachlf = findlf(NULL, sf->val[0]);
if (!stomachlf || isdead(stomachlf)) {
object_t *exit;
cell_t *exitcell,*c;
map_t *exitmap;
exitcell = findobinmap(map, OT_STOMACHEXIT);
exit = hasob(exitcell->obpile, OT_STOMACHEXIT);
f = hasflag(exit->flags, F_MAPLINK);
exitmap = findmap(f->val[0]);
c = getcellat(exitmap, f->val[1], f->val[2]);
while (!cellwalkable(lf, c, NULL)) {
c = getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND);
}
// move lf out!
movelf(lf, c);
if (isplayer(lf)) {
msg("You get expelled from %s!", sf->text);
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s gets expelled from %s!", lfname, sf->text);
}
}
}
if (!isdead(lf) && !isunconscious(lf) && hasflag(lf->flags, F_WASROBBED)) {
if (isplayer(lf)) {
if (countobs(lf->pack, B_FALSE)) {
msg("Some of your items are missing!");
} else {
msg("All of your items are missing!");
}
} else {
say(lf, "Hey! Where are my things?", SV_SHOUT);
}
killflagsofid(lf->flags, F_WASROBBED);
}
if (isplayer(lf) && lfhasflag(lf, F_DRUNK)) statdirty = B_TRUE; if (isplayer(lf) && lfhasflag(lf, F_DRUNK)) statdirty = B_TRUE;
// clear one-turn-only flags // clear one-turn-only flags
@ -15222,6 +15320,10 @@ void startlfturn(lifeform_t *lf) {
killflagsofid(lf->flags, F_HASBEENMOVED); killflagsofid(lf->flags, F_HASBEENMOVED);
killflagsofid(lf->flags, F_MOVED); killflagsofid(lf->flags, F_MOVED);
// if we didn't turn lsat move, kill our turncounter
if (!killflagsofid(lf->flags, F_TURNED)) {
lf->turncounter = 0;
}
// update where player knows // update where player knows
// (but without a map you will then slowly forget it) // (but without a map you will then slowly forget it)
@ -17218,10 +17320,12 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) {
// take fall damage. 2d6 per level. // take fall damage. 2d6 per level.
losehp(lf, rolldie(howfar*2, 6), DT_FALL, NULL, "falling"); losehp(lf, rolldie(howfar*2, 6), DT_FALL, NULL, "falling");
killflagsofid(lf->flags, F_FALLDISTANCE); killflagsofid(lf->flags, F_FALLDISTANCE);
// injure legs if (!isimmuneto(lf->flags, DT_FALL, B_FALSE)) {
injure(lf, BP_LEGS, DT_BASH); // injure legs
// fall over injure(lf, BP_LEGS, DT_BASH);
fall(lf, NULL, B_FALSE); // fall over
fall(lf, NULL, B_FALSE);
}
} }
} else if (dir == D_UP) { } else if (dir == D_UP) {
if (hasobwithflagval(lf->cell->obpile, F_PIT, D_UP, NA, NA, NULL)) { if (hasobwithflagval(lf->cell->obpile, F_PIT, D_UP, NA, NA, NULL)) {

2
lf.h
View File

@ -275,6 +275,7 @@ int haslos_fast(lifeform_t *viewer, cell_t *dest);
void interrupt(lifeform_t *lf); void interrupt(lifeform_t *lf);
enum FLAG isairborne(lifeform_t *lf); enum FLAG isairborne(lifeform_t *lf);
int isaquatic(lifeform_t *lf); int isaquatic(lifeform_t *lf);
flag_t *isasleep(lifeform_t *lf);
int isbehind(lifeform_t *lf, lifeform_t *otherlf); int isbehind(lifeform_t *lf, lifeform_t *otherlf);
int isbleeding(lifeform_t *lf); int isbleeding(lifeform_t *lf);
int isblind(lifeform_t *lf); int isblind(lifeform_t *lf);
@ -417,6 +418,7 @@ int useability(lifeform_t *lf, enum OBTYPE aid, lifeform_t *who, cell_t *where);
int useringofmiracles(lifeform_t *lf, int charges); int useringofmiracles(lifeform_t *lf, int charges);
int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb); int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb);
int validateraces(void); int validateraces(void);
void wakeup(lifeform_t *lf, int howmuch);
int wear(lifeform_t *lf, object_t *o); int wear(lifeform_t *lf, object_t *o);
int weild(lifeform_t *lf, object_t *o); int weild(lifeform_t *lf, object_t *o);
int willbleedfrom(lifeform_t *lf, enum BODYPART bp); int willbleedfrom(lifeform_t *lf, enum BODYPART bp);

2
map.c
View File

@ -4935,6 +4935,8 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
} }
} else if (wantempty == WE_NOLF) { } else if (wantempty == WE_NOLF) {
if (!new->lf) ok = B_TRUE; if (!new->lf) ok = B_TRUE;
} else if (wantempty == WE_SOLID) {
if (new->type->solid) ok = B_TRUE;
} else { } else {
// always ok // always ok
ok = B_TRUE; ok = B_TRUE;

13
move.c
View File

@ -2533,6 +2533,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
// if the given dir is behind us, just turn. // if the given dir is behind us, just turn.
if (!strafe) { if (!strafe) {
setfacing(lf, dir); setfacing(lf, dir);
if (isplayer(lf)) {
addflagifneeded(lf->flags, F_TURNED, B_TRUE, NA, NA, NULL);
lf->turncounter++;
if (lf->turncounter >= 5) {
// get dizzy for 2 turns
addtempflag(lf->flags, F_CONFUSED, B_TRUE, NA, NA, NULL, 3);
}
}
taketime(lf, getturnspeed(lf)); taketime(lf, getturnspeed(lf));
return B_FALSE; return B_FALSE;
} else { } else {
@ -3182,6 +3190,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
} }
// don't attack other monsters // don't attack other monsters
// or non-enemies
if (cell->lf) { // if someone is in the way if (cell->lf) { // if someone is in the way
object_t *defenderwep = NULL; object_t *defenderwep = NULL;
if (lf->race->raceclass->id == RC_INSECT) { if (lf->race->raceclass->id == RC_INSECT) {
@ -3200,8 +3209,8 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
} }
if (!isplayer(lf)) { // if we are a monster if (!isplayer(lf)) { // if we are a monster
// if the person in the way isn't our enemy... // if the person in the way isn't our enemy, or is KO'd/dead...
if (!areenemies(lf, cell->lf)) { if (!areenemies(lf, cell->lf) || isdead(cell->lf) || isunconscious(cell->lf)) {
// if they are an ally... // if they are an ally...
if (canswapwith(lf, cell->lf)) { if (canswapwith(lf, cell->lf)) {
return B_TRUE; return B_TRUE;

View File

@ -647,7 +647,7 @@ void checkendgame(void) {
} }
void cleanup(void) { void cleanup(void) {
int i; //int i;
gamemode = GM_CLEANUP; gamemode = GM_CLEANUP;
free(xpposs); free(xpposs);
@ -676,11 +676,14 @@ void cleanup(void) {
while (firstrace) killrace(firstrace); while (firstrace) killrace(firstrace);
// free celltypes // free celltypes
while (firstcelltype) killcelltype(firstcelltype); while (firstcelltype) killcelltype(firstcelltype);
/*
for (i = 0; i < numnpcnames; i++) { for (i = 0; i < numnpcnames; i++) {
// free npcnames // free npcnames
free(npcname[i].name); free(npcname[i].name);
free(&npcname[i]); free(&npcname[i]);
} }
*/
free(npcname);
// free hidden names // free hidden names
while (firsthiddenname) killhiddenname(firsthiddenname); while (firsthiddenname) killhiddenname(firsthiddenname);
//WriteMemLeak(); //WriteMemLeak();

View File

@ -7323,6 +7323,7 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
int i,preburdened = B_FALSE; int i,preburdened = B_FALSE;
int db = B_FALSE; int db = B_FALSE;
int redrawaftermove = B_FALSE; int redrawaftermove = B_FALSE;
lifeform_t *robbedlf = NULL;
flag_t *f; flag_t *f;
reason = E_OK; reason = E_OK;
@ -7332,6 +7333,12 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
return NULL; return NULL;
} }
// object being taken from an unconscious lf?
if (src->pile->owner && isunconscious(src->pile->owner)) {
robbedlf = src->pile->owner;
}
// adjust destination for pits // adjust destination for pits
if (dst->where) { if (dst->where) {
object_t *pit; object_t *pit;
@ -7437,6 +7444,10 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
o->blessknown = B_TRUE; o->blessknown = B_TRUE;
} }
if (robbedlf && !lfhasflag(robbedlf, F_WASROBBED)) {
addflag(robbedlf->flags, F_WASROBBED, B_TRUE, NA, NA, NULL);
}
if (hasflag(o->flags, F_DOOR)) { if (hasflag(o->flags, F_DOOR)) {
killflagsofid(o->flags, F_LOCKED); killflagsofid(o->flags, F_LOCKED);
killflagsofid(o->flags, F_JAMMED); killflagsofid(o->flags, F_JAMMED);
@ -10126,6 +10137,15 @@ int readsomething(lifeform_t *lf, object_t *o) {
if (isplayer(lf)) msg("The scroll crumbles to dust."); if (isplayer(lf)) msg("The scroll crumbles to dust.");
// removeob one of the object // removeob one of the object
removeob(o, 1); removeob(o, 1);
} else if (o->type->id == OT_SCR_AMNESIA) {
// lose all skill points
lf->skillpoints = 0;
lf->skillxp = 0;
if (isplayer(lf)) msg("^%dYou can't seem to remember any of your recent experiences!", C_RED);
if (isplayer(lf)) msg("The scroll crumbles to dust.");
// removeob one of the object
removeob(o, 1);
if (isplayer(lf)) statdirty = B_TRUE;
} else if (o->type->id == OT_SCR_NOTHING) { } else if (o->type->id == OT_SCR_NOTHING) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("The scroll crumbles to dust."); msg("The scroll crumbles to dust.");

4
save.c
View File

@ -234,6 +234,8 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
fscanf(f, "polyrevert: %d\n",&l->polyrevert); fscanf(f, "polyrevert: %d\n",&l->polyrevert);
fscanf(f, "forgettimer: %f\n",&l->forgettimer); fscanf(f, "forgettimer: %f\n",&l->forgettimer);
fscanf(f, "eyeadj: %d\n",&l->eyeadjustment); fscanf(f, "eyeadj: %d\n",&l->eyeadjustment);
fscanf(f, "facing: %d\n",&l->facing);
fscanf(f, "turncounter: %d\n",&l->turncounter);
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted); if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted);
@ -827,6 +829,8 @@ int savelf(FILE *f, lifeform_t *l) {
fprintf(f, "polyrevert: %d\n",l->polyrevert); fprintf(f, "polyrevert: %d\n",l->polyrevert);
fprintf(f, "forgettimer: %f\n",l->forgettimer); fprintf(f, "forgettimer: %f\n",l->forgettimer);
fprintf(f, "eyeadj: %d\n",l->eyeadjustment); fprintf(f, "eyeadj: %d\n",l->eyeadjustment);
fprintf(f, "facing: %d\n",l->facing);
fprintf(f, "turncounter: %d\n",l->turncounter);
// lf flags // lf flags
saveflagpile(f, l->flags); saveflagpile(f, l->flags);

247
spell.c
View File

@ -2041,7 +2041,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// create stomach map // create stomach map
newmap = addmap(); newmap = addmap();
createmap(newmap, 1, r, targcell->map, D_NONE, NULL); createmap(newmap, 1, r, targcell->map, D_NONE, NULL);
addflag(newmap->flags, F_STOMACHOF, NA, NA, NA, username); addflag(newmap->flags, F_STOMACHOF, user->id, NA, NA, username);
} }
// find a random empty cell here // find a random empty cell here
@ -2652,7 +2652,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("You need to weild a weapon first!"); msg("You need to weild a weapon first!");
return B_TRUE; return B_TRUE;
} }
if (slev < PR_SKILLED) { if (slev < PR_ADEPT) {
msg("You are not skilled enough with your weapon to do this!"); msg("You are not skilled enough with your weapon to do this!");
return B_TRUE; return B_TRUE;
} }
@ -2833,6 +2833,131 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
} }
} else if (abilid == OT_A_ENHANCEOB) {
object_t *o,*o2;
enum MATERIAL repairablemats[MAXCANDIDATES];
int cutoffpct[MAXCANDIDATES];
int i,nmats = 0;
char ch,obname[BUFLEN];
if (!isplayer(user)) {
return B_TRUE;
}
// get list of resizable materials
getworkablematerials(user, SK_METALWORK, repairablemats, cutoffpct, &nmats);
getworkablematerials(user, SK_SEWING, repairablemats, cutoffpct, &nmats);
// 1.compile a list of enhancable objects
initprompt(&prompt, "Enhance which object?");
addchoice(&prompt, '-', "Cancel", "Cancel", NULL, NULL);
for (o = user->pack->first ; o ; o = o->next) {
int ok = B_FALSE;
for (i = 0; i < nmats; i++) {
if (o->material->id == repairablemats[i]) {
ok = B_TRUE;
break;
}
}
if (ok && (isweapon(o) || isarmour(o)) && !hasflag(o->flags, F_NOQUALITY) &&
!hasflag(o->flags, F_MASTERWORK)) {
int gotdupe = B_FALSE;
// do we have another?
for (o2 = user->pack->first ; o2 ; o2 = o2->next) {
if ((o2 != o) && (o2->type->id == o->type->id)) {
gotdupe = B_TRUE;
break;
}
}
if (gotdupe) {
// we can enhance this object
getobname(o, obname, o->amt);
addchoice(&prompt, o->letter, obname, NULL, o, NULL);
}
}
}
if (prompt.nchoices <= 1) {
msg("You don't have anything which you are able to enhance.");
return B_TRUE;
}
// 2. ask which ones to enhance
getchoice(&prompt);
o = (object_t *) prompt.result;
getobname(o, obname, 1);
// ask what size we want.
sprintf(buf, "Destroy which object to enahnce %s?", obname);
initprompt(&prompt, buf);
for (o2 = user->pack->first ; o2 ; o2 = o2->next) {
if ((o2 != o) && (o2->type->id == o->type->id)) {
getobname(o2, obname, o2->amt);
addchoice(&prompt, o2->letter, obname, NULL, o2, NULL);
}
}
addchoice(&prompt, '-', "Cancel", "Cancel", NULL, NULL);
prompt.maycancel = B_TRUE;
ch = getchoice(&prompt);
if ((ch == '-') || (ch == '\0')) {
msg("Cancelled.");
return B_TRUE;
}
o2 = (object_t *)prompt.result;
// in case it's on fire, etc
if (touch(user, o)) {
taketime(user, getactspeed(user));
return B_FALSE;
}
if (touch(user, o2)) {
taketime(user, getactspeed(user));
return B_FALSE;
}
// destroy second ob
removeob(o2, ALL);
// fully repair first ob
f = hasflag(o->flags, F_OBHP);
if (f) f->val[0] = f->val[1];
// enhance first ob
addflag(o->flags, F_MASTERWORK, B_TRUE, NA, NA, NULL);
getobname(o, obname, o->amt);
msgnocap("%c - %s", o->letter, obname);
taketime(user, getactspeed(user));
} else if (abilid == OT_A_EXPOSEDSTRIKE) {
flag_t *f;
if (getweaponskill(user, getweapon(user)) < PR_BEGINNER) {
if (isplayer(user)) msg("You are not skilled enough to perform an exposed strike.", HEAVYWEPKG);
return B_TRUE;
}
// ask for direction
if (!targcell) {
char dirch;
dirch = askchar("Exposed strike in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE, B_TRUE);
if (dirch == '.') {
// yourself!
targcell = user->cell;
} else {
int dir;
dir = chartodir(dirch);
if (dir == D_NONE) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE ;
} else {
targcell = getcellindir(user->cell, dir);
}
}
}
f = addflag(user->flags, F_ACCURACYMOD, 100, NA, NA, NULL);
attackcell(user, targcell, B_FALSE);
taketime(user, getattackspeed(user)*2);
killflag(f);
} else if (abilid == OT_A_HEAVYBLOW) { } else if (abilid == OT_A_HEAVYBLOW) {
object_t *wep; object_t *wep;
char dirch; char dirch;
@ -3044,6 +3169,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
int dir; int dir;
cell_t *c; cell_t *c;
flag_t *f,*f2,*f3; flag_t *f,*f2,*f3;
object_t *wep;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You cannot do that while swimming."); if (isplayer(user)) msg("You cannot do that while swimming.");
@ -3061,6 +3187,24 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// remember we are doing a hurricane attack to avoid lots of // remember we are doing a hurricane attack to avoid lots of
// "there is nothing to attack there" messages. // "there is nothing to attack there" messages.
f3 = addflag(user->flags, F_HURRICANESTRIKE, B_TRUE, NA, NA, NULL); f3 = addflag(user->flags, F_HURRICANESTRIKE, B_TRUE, NA, NA, NULL);
wep = getweapon(user);
if (wep) {
char buf[BUFLEN],wepname[BUFLEN];
getobname(wep, buf, 1);
sprintf(wepname, "%s", noprefix(buf));
if (isplayer(user)) {
msg("You swing your %s in a wide arc!", wepname);
} else if (cansee(player, user)) {
msg("%s swings its %s in a wide arc!", username, wepname);
}
} else {
if (isplayer(user)) {
msg("You attack in a wide arc!");
} else if (cansee(player, user)) {
msg("%s attacks in a wide arc!", username);
}
}
// attack all adjacent enemies // attack all adjacent enemies
for (dir = DC_N; dir <= DC_NW; dir++) { for (dir = DC_N; dir <= DC_NW; dir++) {
c = getcellindir(user->cell, dir); c = getcellindir(user->cell, dir);
@ -4795,7 +4939,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int dir; int dir;
if (targcell) { if (targcell) {
dir = getdirtowards(caster->cell, targcell, NULL, B_FALSE, DT_COMPASS); if (targcell == caster->cell) {
dir = D_DOWN;
} else {
dir = getdirtowards(caster->cell, targcell, NULL, B_FALSE, DT_COMPASS);
}
} else { } else {
// don't need line of fire OR sight! // don't need line of fire OR sight!
//if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE; //if (!validatespellcell(caster, &targcell, TT_NONE, spellid, power, frompot)) return B_TRUE;
@ -4805,15 +4953,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE; return B_TRUE;
} else if (ch == '<') { } else if (ch == '<') {
if (seenbyplayer && haslos(player, caster->cell)) *seenbyplayer = B_TRUE; if (seenbyplayer && haslos(player, caster->cell)) *seenbyplayer = B_TRUE;
return digup(caster, NULL); dir = D_UP;
} else if (ch == '>') { } else if (ch == '>') {
if (seenbyplayer && haslos(player, caster->cell)) *seenbyplayer = B_TRUE; if (seenbyplayer && haslos(player, caster->cell)) *seenbyplayer = B_TRUE;
return digdown(caster, NULL); dir = D_DOWN;
} else { } else {
dir = chartodir(ch); dir = chartodir(ch);
} }
} }
if (dir == D_UP) {
return digup(caster, NULL);
} else if (dir == D_DOWN) {
return digdown(caster, NULL);
}
if (dir == DT_NONE) { if (dir == DT_NONE) {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
@ -4830,12 +4984,38 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (c->type->solid) { if (c->type->solid) {
if ((c->type->material->id == MT_STONE) || (c->type->material->id == MT_FLESH)) { if ((c->type->material->id == MT_STONE) || (c->type->material->id == MT_FLESH)) {
setcelltype(c, c->map->habitat->emptycelltype); int d2;
ndigs++;
if (seenthiscell) { if (seenthiscell) {
msg("%s %s collapses!", needan(c->type->name) ? "An" : "A",
c->type->name);
numseen++; numseen++;
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
setcelltype(c, c->map->habitat->emptycelltype);
ndigs++;
if (c->type->material->id == MT_STONE) {
// debris shower
for (d2 = DC_N; d2 <= DC_NW; d2++) {
cell_t *c2;
c2 = getcellindir(c, d2);
if (c2 && !c2->type->solid && c2->lf) {
if (!isimmuneto(c2->lf->flags, DT_PROJECTILE, B_FALSE)) {
if (cansee(player, c2->lf)) {
char lfname[BUFLEN];
getlfname(c2->lf, lfname);
msg("%s %s showed with debris!", lfname, isplayer(c2->lf) ? "are" : "is");
}
losehp(c2->lf, rnd(2,6), DT_PROJECTILE, NULL, "flying debris");
}
}
}
addobsinradius(c, 1, DT_COMPASS, "5-10 stones", B_TRUE);
addob(c->obpile, "5-10 stones");
} else if (c->type->material->id == MT_BLOOD) {
addobsinradius(c, 1, DT_COMPASS, "pool of blood", B_TRUE);
addob(c->obpile, "pool of blood");
}
} else { } else {
// stop. // stop.
break; break;
@ -4863,7 +5043,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
c = getcellindir(c, dir); c = getcellindir(c, dir);
} }
// announce destruction of any walls seen // announce destruction of any walls seen
/*
if (numseen) { if (numseen) {
msg("The wall%s crumble%s to dust!", msg("The wall%s crumble%s to dust!",
(numseen == 1) ? "" : "s", (numseen == 1) ? "" : "s",
@ -4873,6 +5055,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (ndigs == 0) { } else if (ndigs == 0) {
if (isplayer(caster)) nothinghappens(); if (isplayer(caster)) nothinghappens();
} }
*/
if (ndigs == 0) {
if (isplayer(caster)) nothinghappens();
}
} else if (spellid == OT_S_DISORIENT) { } else if (spellid == OT_S_DISORIENT) {
target = targcell->lf; target = targcell->lf;
@ -5315,6 +5501,27 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
brightflash(caster->cell, 2 + (power/4), caster); brightflash(caster->cell, 2 + (power/4), caster);
} else if (spellid == OT_S_FLAYFLESH) {
char targetname[BUFLEN];
target = targcell->lf;
if (!target) {
fizzle(caster);
return B_TRUE;
}
if (target->race->material->id != MT_FLESH) {
fizzle(caster);
return B_TRUE;
}
if (isplayer(target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
msg("Unseen forces rip into your flesh!");
} else if (cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
getlfname(target, targetname);
msg("Unseen forces rip into %s%s flesh!", targetname, getpossessive(targetname));
}
criticalhit(caster, target, getrandomcorebp(target), rnd(1,6), DT_SLASH);
pleasegodmaybe(R_GODDEATH, 3);
} else if (spellid == OT_S_GLYPHWARDING) { } else if (spellid == OT_S_GLYPHWARDING) {
char buf[BUFLEN]; char buf[BUFLEN];
sprintf(buf, "^g*WARD%d*^n", power/2); sprintf(buf, "^g*WARD%d*^n", power/2);
@ -7912,6 +8119,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
race_t *r = NULL; race_t *r = NULL;
target = targcell->lf; target = targcell->lf;
if (frompot) {
caster = target;
}
if (!target) { if (!target) {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
@ -8050,12 +8261,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = hasflag(o->flags, F_OBHP); f = hasflag(o->flags, F_OBHP);
if (f) { if (f) {
f->val[0] = f->val[1]; f->val[0] = f->val[1];
f = hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL); f = hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL);
if (f) { if (f) killflag(f);
killflag(f);
}
donesomething = B_TRUE; donesomething = B_TRUE;
} }
@ -9296,8 +9503,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
target = caster; target = caster;
} }
// works on all undead in _target's_ sight // works on all undead in _target's_ sight
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < target->nlos; i++) {
targcell = caster->los[i]; targcell = target->los[i];
lf = targcell->lf; lf = targcell->lf;
if (lf && (lf != caster) && isundead(lf)) { if (lf && (lf != caster) && isundead(lf)) {
int howlong = 10; int howlong = 10;
@ -9305,7 +9512,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// TODO: does it work? depends on caster level & intelligence & power // TODO: does it work? depends on caster level & intelligence & power
worked = B_TRUE; worked = B_TRUE;
// TODO: how long for? depends on caster level & intelligence & power // TODO: how long for? depends on caster level & intelligence & power
howlong = rnd(10,20); howlong = rnd(10,20)+(power*2);
if (worked) { if (worked) {
// don't use scare() since it will fail due to them being undead. // don't use scare() since it will fail due to them being undead.
addtempflag(lf->flags, F_FLEEFROM, target->id, NA, NA, NULL,howlong); addtempflag(lf->flags, F_FLEEFROM, target->id, NA, NA, NULL,howlong);
@ -10765,11 +10972,11 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair
slev = getskill(lf, skid); slev = getskill(lf, skid);
switch (slev) { switch (slev) {
case PR_NOVICE: cutoff = 33; break; case PR_NOVICE: cutoff = 40; break;
case PR_BEGINNER: cutoff = 50; break; case PR_BEGINNER: cutoff = 60; break;
case PR_ADEPT: cutoff = 60; break; case PR_ADEPT: cutoff = 80; break;
case PR_SKILLED: cutoff = 70; break; case PR_SKILLED: cutoff = 80; break;
case PR_EXPERT: cutoff = 85; break; case PR_EXPERT: cutoff = 100; break;
case PR_MASTER: cutoff = 100; break; case PR_MASTER: cutoff = 100; break;
default: cutoff = 0; break; default: cutoff = 0; break;
} }