- [+] 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()
// will check this.
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) {
float maxweight;
object_t *poss[MAXPILEOBS];
@ -1725,12 +1740,12 @@ int aiobok(lifeform_t *lf, object_t *o, lifeform_t *target) {
switch (o->type->id) {
case OT_POT_INVIS:
case OT_WAND_INVIS:
if (lfhasflag(target, F_INVISIBLE)) {
if (target && lfhasflag(target, F_INVISIBLE)) {
return B_FALSE;
}
break;
case OT_POT_INVULN:
if (lfhasflag(target, F_INVULNERABLE)) {
if (target && lfhasflag(target, F_INVULNERABLE)) {
return B_FALSE;
}
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) {
cell_t *cell[MAXCANDIDATES],*c;
int ncells,i;
@ -2434,11 +2461,11 @@ int lookforobs(lifeform_t *lf) {
if (db) dblog(".oO { no targetcell, so looking for remote objects }");
for (i = 0 ; i < lf->nlos; i++) {
int gothere = B_FALSE;
int celldist;
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)) {
int celldist;
celldist = getcelldist(lf->cell, c);
for (o = c->obpile->first ; o ; o = nexto) {
nexto = o->next;
@ -2510,6 +2537,72 @@ int lookforobs(lifeform_t *lf) {
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;
} else {
// TODO: attack wall?
if (isplayer(lf) && !lfhasflag(lf, F_HURRICANESTRIKE)) {
msg("There is nothing there to attack!");
}
return B_TRUE;
if (!lfhasflag(lf, F_HURRICANESTRIKE)) {
/*
flag_t *sf;
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;
// player never invalidates their equipped weapons
if (isplayer(lf) && gotweapon) {
//if (isplayer(lf) && gotweapon) {
if (gotweapon) {
first = lastweaponidx+1;
} else {
first = 0;
@ -921,15 +943,15 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
warn("%s", buf);
}
}
if (!isplayer(lf) && !isplayer(victim)) {
noise(lf->cell, lf, NC_OTHER, 3, "fighting.", NULL);
}
//if (!isplayer(lf) && !isplayer(victim)) {
noise(lf->cell, lf, NC_FIGHTING, 3, "fighting.", NULL);
//}
if (fatal) {
if (strstr(buf, "behead")) {
// we'll need to place the severed head object
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"
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];
rdam = rolldie(f->val[0], f->val[1]);
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),
getattackverb(victim, NULL, f->val[2], rdam, lf->maxhp),
attackername);
@ -1787,8 +1809,8 @@ void getdamrange(object_t *o, flag_t *f, int *min, int *max) {
if (f) {
if (hasflag(o->flags, F_MASTERWORK)) {
// 75%-100%
mindam = pctof(75,f->val[1]);
// 85%-100%
mindam = pctof(85,f->val[1]);
maxdam = f->val[1];
} else if (hasflag(o->flags, F_SHODDY)) {
// 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_STACKABLE, B_TRUE, NA, NA, "");
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_VALUE, 250, NA, NA, NULL);
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_STACKABLE, B_TRUE, NA, NA, "");
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_VALUE, 15, NA, NA, NULL);
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_STACKABLE, B_TRUE, NA, NA, "");
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_VALUE, 1000, NA, NA, NULL);
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_STACKABLE, B_TRUE, NA, NA, "");
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_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);
addflag(lastot->flags, F_GLYPH, C_GREY, '*', NA, NULL);
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_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, 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);
addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL);
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_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, 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);
addflag(lastot->flags, F_GLYPH, C_RED, '*', NA, NULL);
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_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, 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);
addflag(lastot->flags, F_GLYPH, C_CYAN, '*', NA, NULL);
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_STOMACH, 100, RR_UNCOMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, 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);
addflag(lastot->flags, F_GLYPH, C_BLUE, '*', NA, NULL);
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_STOMACH, 100, RR_COMMON, "");
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_VALUE, 60, NA, NA, NULL);
@ -2206,6 +2215,9 @@ void initobjects(void) {
// 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);
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_AICASTTOATTACK, ST_VICTIM, NA, 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);
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);
@ -2975,8 +2994,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, 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_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
// l4
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_SPELLLEVEL, 4, NA, 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);
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);
@ -3567,7 +3586,7 @@ void initobjects(void) {
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);
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);
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);
@ -3642,6 +3661,8 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
addflag(lastot->flags, F_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);
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);
@ -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);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, 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);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, 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_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);
addflag(lastot->flags, F_DAM, DT_SLASH, 2, NA, NULL);
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
@ -6994,6 +7027,7 @@ void initrace(void) {
// 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.");
lastrace->baseid = R_BANDIT;
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, 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_RARITY, H_ALL, NA, RR_UNCOMMON, 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_SIZE, SZ_HUMAN, NA, NA, NULL);
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_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.");
setbodytype(lastrace, BT_HUMANOID);
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_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
setbodytype(lastrace, BT_BIRD);
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_HASATTACK, OT_CLAWS, 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_ENHANCESMELL, 4, 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_CANWILL, OT_A_SWALLOW, 5, 5, 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_FLEEONHPPCT, 20, NA, NA, "");
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_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);
addbodypart(lastrace, BP_TAIL, NULL);
addbodypart(lastrace, BP_WINGS, NULL);
@ -10866,13 +10969,12 @@ void initskills(void) {
addskill(SK_LOCKPICKING, "Lockpicking", "Enhances your ability to pick locks.", 50);
addskilldesc(SK_LOCKPICKING, PR_NOVICE, "^gYou gain the 'pick locks' ability.^n", B_FALSE);
addskill(SK_METALWORK, "Metalwork", "Lets you repair metal objects.", 100);
addskilldesc(SK_METALWORK, PR_NOVICE, "^gYou can repair metal items up to 33% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_BEGINNER, "^gYou can repair metal items up to 50% condition.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_ADEPT, "^gYou can repair metal items up to 60% 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_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 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 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_MASTER, "^gYou can fully repair metal items.^n", B_FALSE);
addskilldesc(SK_METALWORK, PR_EXPERT, "^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);
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);
@ -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 accuracy decreases by 6%% per cell.^n", B_FALSE);
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_BEGINNER, "^gYou can repair cloth items up to 50% 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_SKILLED, "^gYou can repair cloth items up to 70% 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 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 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_MASTER, "^gYou can fully repair cloth items.^n", B_FALSE);
addskilldesc(SK_SEWING, PR_EXPERT, "^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);
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);
@ -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_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, "^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, "^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);

Binary file not shown.

22
defs.h
View File

@ -58,6 +58,7 @@
#define WE_PORTAL 3
#define WE_NOTWALL 4
#define WE_NOLF 5
#define WE_SOLID 6
// Booleans
#define B_FALSE (0)
@ -427,7 +428,8 @@ enum NOISECLASS {
NC_NONE = 0,
NC_MOVEMENT = 1,
NC_SPEECH = 2,
NC_OTHER = 3,
NC_FIGHTING = 3,
NC_OTHER = 4,
};
enum QUADRANT {
@ -452,6 +454,7 @@ enum SAYPHRASE {
SP_BEGTHANKS,
SP_DIE,
SP_DRUNK,
SP_MERCYACCEPT,
SP_PAYWARN,
SP_PAYTHREAT,
SP_PAYTHANKS,
@ -894,6 +897,7 @@ enum RACE {
R_PRIMALSTONEL,
R_SATYR,
R_SHADOWCAT,
R_SINKMITE,
R_SPRITEFIRE,
R_SPRITEGRAVE,
R_SPRITEICE,
@ -974,6 +978,11 @@ enum RACE {
// demons
R_DRETCH,
R_LURKINGHORROR,
R_NECRONTRAPPER,
R_NECRONREAPER,
R_NECRONSOWER,
R_NECRONEXTERMINATOR,
R_NECRONHARVESTER,
R_QUASIT,
// undead
R_GHAST,
@ -1206,6 +1215,7 @@ enum OBTYPE {
// scrolls
OT_MAP,
OT_GRAPHPAPER,
OT_SCR_AMNESIA,
OT_SCR_AWARENESS,
OT_SCR_NOTHING,
OT_SCR_CREATEMONSTER,
@ -1246,6 +1256,7 @@ enum OBTYPE {
OT_S_COMMANDUNDEAD,
OT_S_DRAINLIFE,
OT_S_FEAR,
OT_S_FLAYFLESH,
OT_S_HECTASSERVANT,
OT_S_PAIN,
OT_S_PARALYZE,
@ -1440,6 +1451,7 @@ enum OBTYPE {
OT_A_DISARM, // disarm a trap
OT_A_DISARMLF, // disarm an opponent
OT_A_DRAGUNDERGROUND,
OT_A_ENHANCEOB,
OT_A_FEIGNDEATH,
OT_A_FLIP,
OT_A_FLURRY,
@ -1463,6 +1475,7 @@ enum OBTYPE {
OT_A_SWOOP,
OT_A_TRIPLF, // trip an opponent
OT_A_EMPLOY,
OT_A_EXPOSEDSTRIKE,
OT_A_HEAVYBLOW,
OT_A_HIDE,
OT_A_INSPECT,
@ -1708,6 +1721,7 @@ enum OBTYPE {
// innate / animal weapons
OT_BEAK,
OT_CLAWS,
OT_DRILL,
OT_FISTS,
OT_HOOKHAND, // for pirate
OT_STING,
@ -1951,7 +1965,7 @@ enum FLAG {
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.
// 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
F_BADOBJECT, // this object is dangerous. ie. potion of poison,
// potion of sleep, etc.
@ -2373,6 +2387,9 @@ enum FLAG {
F_TOOKACTION, // lf purposely took action in their last turn.
F_MOVED, // lf purposely walked/flew/swum/moved in prev 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_GAVEMONEY, // v0 tracks how much money we gave away this turn
// used for r_godgreed anger effects.
@ -3473,6 +3490,7 @@ typedef struct lifeform_s {
int x,y;
int facing; // which way are we facing
int turncounter; // keeps track of # direction changes in a row
int losdirty;
int nlos; // cells which we can see

View File

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

3
flag.c
View File

@ -884,6 +884,7 @@ void killflag(flag_t *f) {
flag_t *nextone, *lastone;
flagpile_t *pile;
lifeform_t *lf;
enum FLAG fid;
map_t *redolight = NULL;
cell_t *redolos = NULL;
int redostat = B_FALSE;
@ -892,6 +893,8 @@ void killflag(flag_t *f) {
//checkflagpile(f->pile);
fid = f->id;
for (i = 0; i < ngodlfs; i++) {
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!\"");
c = NULL;
n = OT_NONE;
switch (rnd(0,3)) {
switch (rnd(0,4)) {
case 0: n = OT_S_PAIN; break;
case 1: n = OT_S_DRAINLIFE; break;
case 2: n = OT_S_BLINDNESS; break;
case 3: n = OT_S_HECTASSERVANT;
case 3: n = OT_S_FLAYFLESH; break;
case 4: n = OT_S_HECTASSERVANT;
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
break;
}

40
io.c
View File

@ -1793,11 +1793,13 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
}
}
donesomething = B_TRUE;
needredraw = B_TRUE;
}
break;
case F_XRAYVIS:
if (isplayer(lf)) { // don't know if monsters get it
msg("The walls around you suddenly turn transparent!");
needredraw = B_TRUE;
donesomething = B_TRUE;
}
break;
@ -1807,7 +1809,8 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
if (donesomething) statdirty = B_TRUE;
if (statdirty || needredraw) {
//if (statdirty || needredraw) {
if (statdirty) {
drawscreen();
}
@ -3699,6 +3702,10 @@ void docomms(lifeform_t *lf) {
}
}
if (areenemies(player, lf)) {
addchoice(&prompt, 'm', "Have mercy!", NULL, NULL, NULL);
}
// if you are allies, use 'trade items' instead
if (isadjacent(lf->cell, player->cell) && !areallies(player,lf)) {
addchoice(&prompt, 'd', "(donate an item)", NULL, NULL, NULL);
@ -3714,6 +3721,8 @@ void docomms(lifeform_t *lf) {
addchoice(&prompt, 'p', buf, NULL, NULL, NULL);
}
}
addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL, NULL);
addchoice(&prompt, 'n', "(nothing)", NULL, NULL, NULL);
@ -3935,6 +3944,33 @@ void docomms(lifeform_t *lf) {
}
recruit(lf);
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':
// can we afford this?
if (givemoney(player, lf, moneyowing)) {
@ -9120,7 +9156,7 @@ void drawstatus(void) {
unsetcol(statwin, C_CYAN);
} else if ((f = lfhasflag(player, F_ASLEEP)) != NULL) {
setcol(statwin, C_MAGENTA);
if (f->val[2] == ST_KO) {
if (f->val[1] == ST_KO) {
wprintw(statwin, " KO");
} else {
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
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.");
}
}
@ -2104,6 +2104,7 @@ void debug(lifeform_t *lf) {
// returns true if the player pays.
int demandbribe(lifeform_t *lf) {
lifeform_t *l;
char lfname[BUFLEN];
int amtwanted,amtgiven,totmoney;
int hd;
@ -2189,8 +2190,12 @@ int demandbribe(lifeform_t *lf) {
}
}
// either way, kill bribe flag
killflagsofid(lf->flags, F_DEMANDSBRIBE);
// either way, kill bribe flag for all bandits on the level
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;
}
@ -2337,8 +2342,10 @@ void die(lifeform_t *lf) {
if (ispetof(lf, player)) {
if (cantalk(lf) && canhear(player, lf->cell, 4)) {
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.");
// redraw since you can "see" the pet even if it's out of sight
needredraw = B_TRUE;
more();
//} else {
// 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->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) {
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->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) {
if (f->val[1] == PR_BEGINNER) {
@ -8637,7 +8656,12 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL 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)) {
newf = addflag(lf->flags, F_CANWILL, OT_A_ALTERATTACK, NA, NA, NULL);
newf->lifetime = FROMSKILL;
@ -10064,6 +10088,10 @@ int isaquatic(lifeform_t *lf) {
return B_FALSE;
}
flag_t *isasleep(lifeform_t *lf) {
return lfhasflagval(lf, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
}
// is lf behind otherlf?
int isbehind(lifeform_t *lf, lifeform_t *otherlf) {
int dir;
@ -10583,7 +10611,6 @@ flag_t *isresting(lifeform_t *lf) {
return NULL;
}
int issleepingtimefor(lifeform_t *lf) {
if (lfhasflag(lf, F_NOCTURNAL) && !isnighttime()) {
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
a->facing = rnd(DC_N, DC_NW);
a->turncounter = 0;
a->losdirty = B_TRUE;
//a->los = malloc( sizeof(cell_t *) * ((MAXVISRANGE*2+1)*(MAXVISRANGE*2+1)));
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);
// listen check difficulty is based on sound distance vs max hearing distance
if ((nclass == NC_SPEECH) && isplayer(l)) {
// you always hear it, as long as you're in range
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 {
//difficulty = (int) ( ((float)getcelldist(l->cell, c) / (float)gethearingrange(l)) * 20);
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) {
// 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
if (!ispeaceful(l) || onein(6)) {
char lfname[BUFLEN];
int prefacing;
prefacing = l->facing;
turntoface(l, c);
if (!lfhasflag(l, F_FEIGNINGDEATH)) {
if (!lfhasflag(l, F_FEIGNINGDEATH) && cansee(player, l) &&
(prefacing != l->facing)) {
getlfname(l, lfname);
msg("%s turns to face you.", lfname);
}
@ -13276,8 +13313,10 @@ void precalclos_new(lifeform_t *lf) {
//int db = B_FALSE;
enum SKILLLEVEL plev = PR_INEPT;
flag_t *missingeye;
long visdiameter;
long allocamt;
if (gamemode == GM_CLEANUP) return;
if (lf->cell->type->id == CT_FAKE) return;
@ -13305,7 +13344,9 @@ void precalclos_new(lifeform_t *lf) {
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);
losdark = 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 buf2[BUFLEN];
char *p;
race_t *r;
switch (what) {
case SP_ALLY_ATTACK:
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);
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:
switch (rnd(1,3)) {
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;
object_t *o;
flag_t *f;
flag_t *asp;
flag_t *asp, *sf;
char buf[BUFLEN];
lifeform_t *l;
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);
// 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;
// clear one-turn-only flags
@ -15222,6 +15320,10 @@ void startlfturn(lifeform_t *lf) {
killflagsofid(lf->flags, F_HASBEENMOVED);
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
// (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.
losehp(lf, rolldie(howfar*2, 6), DT_FALL, NULL, "falling");
killflagsofid(lf->flags, F_FALLDISTANCE);
// injure legs
injure(lf, BP_LEGS, DT_BASH);
// fall over
fall(lf, NULL, B_FALSE);
if (!isimmuneto(lf->flags, DT_FALL, B_FALSE)) {
// injure legs
injure(lf, BP_LEGS, DT_BASH);
// fall over
fall(lf, NULL, B_FALSE);
}
}
} else if (dir == D_UP) {
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);
enum FLAG isairborne(lifeform_t *lf);
int isaquatic(lifeform_t *lf);
flag_t *isasleep(lifeform_t *lf);
int isbehind(lifeform_t *lf, lifeform_t *otherlf);
int isbleeding(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 usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb);
int validateraces(void);
void wakeup(lifeform_t *lf, int howmuch);
int wear(lifeform_t *lf, object_t *o);
int weild(lifeform_t *lf, object_t *o);
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) {
if (!new->lf) ok = B_TRUE;
} else if (wantempty == WE_SOLID) {
if (new->type->solid) ok = B_TRUE;
} else {
// always ok
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 (!strafe) {
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));
return B_FALSE;
} else {
@ -3182,6 +3190,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
}
// don't attack other monsters
// or non-enemies
if (cell->lf) { // if someone is in the way
object_t *defenderwep = NULL;
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 the person in the way isn't our enemy...
if (!areenemies(lf, cell->lf)) {
// if the person in the way isn't our enemy, or is KO'd/dead...
if (!areenemies(lf, cell->lf) || isdead(cell->lf) || isunconscious(cell->lf)) {
// if they are an ally...
if (canswapwith(lf, cell->lf)) {
return B_TRUE;

View File

@ -647,7 +647,7 @@ void checkendgame(void) {
}
void cleanup(void) {
int i;
//int i;
gamemode = GM_CLEANUP;
free(xpposs);
@ -676,11 +676,14 @@ void cleanup(void) {
while (firstrace) killrace(firstrace);
// free celltypes
while (firstcelltype) killcelltype(firstcelltype);
/*
for (i = 0; i < numnpcnames; i++) {
// free npcnames
free(npcname[i].name);
free(&npcname[i]);
}
*/
free(npcname);
// free hidden names
while (firsthiddenname) killhiddenname(firsthiddenname);
//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 db = B_FALSE;
int redrawaftermove = B_FALSE;
lifeform_t *robbedlf = NULL;
flag_t *f;
reason = E_OK;
@ -7332,6 +7333,12 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
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
if (dst->where) {
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;
}
if (robbedlf && !lfhasflag(robbedlf, F_WASROBBED)) {
addflag(robbedlf->flags, F_WASROBBED, B_TRUE, NA, NA, NULL);
}
if (hasflag(o->flags, F_DOOR)) {
killflagsofid(o->flags, F_LOCKED);
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.");
// removeob one of the object
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) {
if (isplayer(lf)) {
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, "forgettimer: %f\n",&l->forgettimer);
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);
@ -827,6 +829,8 @@ int savelf(FILE *f, lifeform_t *l) {
fprintf(f, "polyrevert: %d\n",l->polyrevert);
fprintf(f, "forgettimer: %f\n",l->forgettimer);
fprintf(f, "eyeadj: %d\n",l->eyeadjustment);
fprintf(f, "facing: %d\n",l->facing);
fprintf(f, "turncounter: %d\n",l->turncounter);
// lf 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
newmap = addmap();
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
@ -2652,7 +2652,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
msg("You need to weild a weapon first!");
return B_TRUE;
}
if (slev < PR_SKILLED) {
if (slev < PR_ADEPT) {
msg("You are not skilled enough with your weapon to do this!");
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) {
object_t *wep;
char dirch;
@ -3044,6 +3169,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
int dir;
cell_t *c;
flag_t *f,*f2,*f3;
object_t *wep;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
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
// "there is nothing to attack there" messages.
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
for (dir = DC_N; dir <= DC_NW; dir++) {
c = getcellindir(user->cell, dir);
@ -4795,7 +4939,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int dir;
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 {
// don't need line of fire OR sight!
//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;
} else if (ch == '<') {
if (seenbyplayer && haslos(player, caster->cell)) *seenbyplayer = B_TRUE;
return digup(caster, NULL);
dir = D_UP;
} else if (ch == '>') {
if (seenbyplayer && haslos(player, caster->cell)) *seenbyplayer = B_TRUE;
return digdown(caster, NULL);
dir = D_DOWN;
} else {
dir = chartodir(ch);
}
}
if (dir == D_UP) {
return digup(caster, NULL);
} else if (dir == D_DOWN) {
return digdown(caster, NULL);
}
if (dir == DT_NONE) {
fizzle(caster);
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->material->id == MT_STONE) || (c->type->material->id == MT_FLESH)) {
setcelltype(c, c->map->habitat->emptycelltype);
ndigs++;
int d2;
if (seenthiscell) {
msg("%s %s collapses!", needan(c->type->name) ? "An" : "A",
c->type->name);
numseen++;
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 {
// stop.
break;
@ -4863,7 +5043,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
c = getcellindir(c, dir);
}
// announce destruction of any walls seen
/*
if (numseen) {
msg("The wall%s crumble%s to dust!",
(numseen == 1) ? "" : "s",
@ -4873,6 +5055,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if (ndigs == 0) {
if (isplayer(caster)) nothinghappens();
}
*/
if (ndigs == 0) {
if (isplayer(caster)) nothinghappens();
}
} else if (spellid == OT_S_DISORIENT) {
target = targcell->lf;
@ -5315,6 +5501,27 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
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) {
char buf[BUFLEN];
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;
target = targcell->lf;
if (frompot) {
caster = target;
}
if (!target) {
fizzle(caster);
return B_TRUE;
@ -8050,12 +8261,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = hasflag(o->flags, F_OBHP);
if (f) {
f->val[0] = f->val[1];
f = hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL);
if (f) {
killflag(f);
}
if (f) killflag(f);
donesomething = B_TRUE;
}
@ -9296,8 +9503,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
target = caster;
}
// works on all undead in _target's_ sight
for (i = 0; i < caster->nlos; i++) {
targcell = caster->los[i];
for (i = 0; i < target->nlos; i++) {
targcell = target->los[i];
lf = targcell->lf;
if (lf && (lf != caster) && isundead(lf)) {
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
worked = B_TRUE;
// TODO: how long for? depends on caster level & intelligence & power
howlong = rnd(10,20);
howlong = rnd(10,20)+(power*2);
if (worked) {
// don't use scare() since it will fail due to them being undead.
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);
switch (slev) {
case PR_NOVICE: cutoff = 33; break;
case PR_BEGINNER: cutoff = 50; break;
case PR_ADEPT: cutoff = 60; break;
case PR_SKILLED: cutoff = 70; break;
case PR_EXPERT: cutoff = 85; break;
case PR_NOVICE: cutoff = 40; break;
case PR_BEGINNER: cutoff = 60; break;
case PR_ADEPT: cutoff = 80; break;
case PR_SKILLED: cutoff = 80; break;
case PR_EXPERT: cutoff = 100; break;
case PR_MASTER: cutoff = 100; break;
default: cutoff = 0; break;
}