- [+] move pctchance for individual spells from F_AICASTTOxxx to

F_AISPELLTARGETOVERRIDE v2.
    - [+] change code:
        - [+] F_AISPELLTARGETOVERRIDE v0=spellid, v1=F_AICASTTOxxx
              v2=TT_xxx text=pctchance or NULL.
        - [+] aispellok(xx, purpose) : check this _before_ checking
              spell->f_aicasttoxxx
    - [+] add spelltargetoverride for vampire
    - [+] add spelltargetoverride for werewolf
- [+] retain F_FLEEFROM on polymorph.
- [+] lycanthropes
    - [+] show up as "human" unless your animal/magic lore is high
          enough
    - [+] vulnerable to silver weapons
    - [+] Wererat (3hd, weapon damage)
        - [+] uses short blades
        - [+] stench
        - [+] want alcohol?
        - [+] transform into fast version of rat. plague rat?
        - [+] summon small animals. summon # override? "count:"
    - [+] Werewolf (4hd, 6 dam)
        - [+] summon wolves ?
        - [+] shapeshift to dire wolf
        - [+] regenerates
        - [+] firstaid skill (fast healing when resting)
    - [+] Werebear
        - [+] 6 hd
        - [+] shapeshift to grizzly bear
        - [+] summon 2-3 black bears
        - [+] firstaid skill (fast healing)
- [+] shapeshifting monsters sometimes start as animal form
- [+] if you are good/evil different alignments, mosnters should flat
      out refuse to join you.
- [+] more different sayphrases for recruitment.
- [+] when placing homelevobs, try to stick to rooms, not corridors
    - [+] getrandomroomcell() needs WE_xxx argument.
    - [+] implement cellmatchescondition(c, cond)
    - [+] real_getrandomadjcell() should use this too
- [+] swoop ability should only work with claw attacks
    - [+] F_FORCEATTACKOB
        - [+] getweapons() needs to honour this.
    - [+] spell.c: check if you have the right attack type
    - [+] aispellok: only if you have the right attack yype
- [+] horse - 2hd, brown u
- [+] Hippogriff (3hd , horse/eagle, 'u') - yellow
- [+] centaur (4hd, u) - grey
- [+] make pegasus be cyan
- [+] CATs
    - [+] Griffon (7hd, tr4-5, u, hates horses) - lion/eagle - yellow
          'f'
This commit is contained in:
Rob Pearce 2012-03-15 09:19:05 +00:00
parent 192afcec2b
commit 5d61533c15
12 changed files with 642 additions and 180 deletions

38
ai.c
View File

@ -895,7 +895,7 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
} else { } else {
getflags(lf->flags, retflag, &nretflags, F_HATESRACEWITHFLAG, F_NONE); getflags(lf->flags, retflag, &nretflags, F_HATESRACEWITHFLAG, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
if (lfhasflag(who, retflag[i]->id) && if (lfhasflagval(who, retflag[i]->val[0], retflag[i]->val[1], retflag[i]->val[2], NA, NULL) &&
!areallies(lf, who)) { !areallies(lf, who)) {
if (db) dblog(".oO { found a target with hated flags - lfid %d (%s) ! }",who->id, who->race->name); if (db) dblog(".oO { found a target with hated flags - lfid %d (%s) ! }",who->id, who->race->name);
@ -2096,6 +2096,9 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
int needlos = B_TRUE; int needlos = B_TRUE;
enum LOFTYPE needlof = LOF_NEED; enum LOFTYPE needlof = LOF_NEED;
int castchance = 0;
enum SPELLTARGET targettype = TT_NONE;
if (lfhasflag(lf, F_DEBUG)) { if (lfhasflag(lf, F_DEBUG)) {
db = B_TRUE; db = B_TRUE;
} }
@ -2177,11 +2180,31 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
} }
} }
f = hasflag(ot->flags, purpose); f = lfhasflagval(lf, F_AISPELLTARGETOVERRIDE, ot->id, purpose, NA, NULL);
if (f) {
if (strlen(f->text)) {
castchance = atoi(f->text);
} else {
castchance = 100;
}
targettype = f->val[2];
} else {
f = hasflag(ot->flags, purpose);
if (f) {
if (f->val[1] == NA) {
castchance = 100;
} else {
castchance = f->val[1];
}
targettype = f->val[0];
}
}
if (f) { if (f) {
if ((f->val[1] == NA) || pctchance(f->val[1])) { if (pctchance(castchance)) {
int range; int range;
switch (f->val[0]) { switch (targettype) {
case ST_VICTIM: case ST_VICTIM:
range = getspellrange(lf, spellid, getspellpower(lf, spellid)); range = getspellrange(lf, spellid, getspellpower(lf, spellid));
if ((range == UNLIMITED) || (getcelldist(lf->cell, victim->cell) <= range)) { if ((range == UNLIMITED) || (getcelldist(lf->cell, victim->cell) <= range)) {
@ -2229,10 +2252,13 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
case ST_SPECIAL: case ST_SPECIAL:
specialcase = B_TRUE; specialcase = B_TRUE;
break; break;
case ST_NONE:
ok = B_FALSE;
break;
} }
// now check for line of sight / fire // now check for line of sight / fire
switch (f->val[0]) { switch (targettype) {
case ST_VICTIM: case ST_VICTIM:
case ST_ADJVICTIM: case ST_ADJVICTIM:
if (needlos && (!victim || !cansee(lf, victim)) ) { if (needlos && (!victim || !cansee(lf, victim)) ) {
@ -2533,6 +2559,8 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} else if ((ot->id == OT_A_SWOOP) && !lfhasflag(lf, F_FLYING)) { } else if ((ot->id == OT_A_SWOOP) && !lfhasflag(lf, F_FLYING)) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} else if ((ot->id == OT_A_SWOOP) && !lfhasflagval(lf, F_HASATTACK, OT_CLAWS, NA, NA, NULL)) {
specificcheckok = B_FALSE;
} else if (getcelldist(lf->cell, victim->cell) > srange) { } else if (getcelldist(lf->cell, victim->cell) > srange) {
specificcheckok = B_FALSE; specificcheckok = B_FALSE;
} else if (getcelldist(lf->cell, victim->cell) == 1) { // ie already adjacent } else if (getcelldist(lf->cell, victim->cell) == 1) { // ie already adjacent

293
data.c
View File

@ -3984,7 +3984,6 @@ void initobjects(void) {
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how powerful a creature you can become."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how powerful a creature you can become.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
oooooooo
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, 10, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, 10, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
// l5 // l5
@ -7816,7 +7815,7 @@ void initrace(void) {
// races / monsters // races / monsters
// playable races // playable races
addrace(R_HUMAN, "human", 75, '@', C_GREY, MT_FLESH, RC_HUMANOID, "Your average example of the Homo Sapiens species."); addrace(R_HUMAN, "human", 75, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Your average example of the Homo Sapiens species.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_PLAYABLE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_PLAYABLE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
@ -8917,6 +8916,42 @@ void initrace(void) {
addflag(lastrace->flags, F_MINIONS, 20, 1, 3, "goblin warrior"); addflag(lastrace->flags, F_MINIONS, 20, 1, 3, "goblin warrior");
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addrace(R_CENTAUR, "centaur", 500, 'u', C_GREY, MT_FLESH, RC_ANIMAL, "Centaurs look like horses with their neck upwards replaced by a human torso and arms.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_RANDOM, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_HOOF, 6, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_HOOF, 6, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL);
// 50% chance of a shortbow.
// if not, then 50% chance of a longbow
f = addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "short bow");
addcondition(f, FC_NOCONDITION, 50);
addaltval(f, F_STARTOB, 50, NA, NA, "longbow");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10-30 arrows");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "shield");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "lance");
addflag(lastrace->flags, F_STARTOB, 80, NA, NA, "1-20 gold coins");
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 4, NA, "screams in pain^screams of pain");
addflag(lastrace->flags, F_MORALE, 14, NA, NA, NULL);
addflag(lastrace->flags, F_EQUINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_RANGED, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_SHIELDS, PR_ADEPT, NA, NULL);
addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH, RC_DRAGON, "A small two-legged wyrm with a rooster's head. Its touch is said to petrify the flesh of living creatures."); addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH, RC_DRAGON, "A small two-legged wyrm with a rooster's head. Its touch is said to petrify the flesh of living creatures.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_WINGS, NULL); addbodypart(lastrace, BP_WINGS, NULL);
@ -9324,7 +9359,7 @@ void initrace(void) {
// TODO: storm giant // TODO: storm giant
// TODO: storm titan // TODO: storm titan
addrace(R_GNOLL, "gnoll", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID, "Gnolls are doglike warriors - the gladiators of the kobold race. They are highly organised and often travel in packs."); addrace(R_GNOLL, "gnoll", 130, 'k', C_YELLOW, MT_FLESH, RC_HUMANOID, "Gnolls are doglike warriors - the gladiators of the kobold race. They are highly organised and often travel in packs.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
setbodypartname(lastrace, BP_HANDS, "claws"); setbodypartname(lastrace, BP_HANDS, "claws");
setbodypartname(lastrace, BP_RIGHTFINGER, "right foreclaw"); setbodypartname(lastrace, BP_RIGHTFINGER, "right foreclaw");
@ -9650,6 +9685,74 @@ void initrace(void) {
addflag(lastrace->flags, F_CANCAST, OT_S_GASEOUSFORM, NA, NA, "pw:1;"); addflag(lastrace->flags, F_CANCAST, OT_S_GASEOUSFORM, NA, NA, "pw:1;");
// gremlins also cause tech to fail around them. // gremlins also cause tech to fail around them.
addrace(R_GRIFFON, "griffon", 220, 'f', C_YELLOW, MT_FLESH, RC_ANIMAL, "Griffons have a lion's body and the head, torso and forelegs of an eagle.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, 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_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, 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_NATURALFLIGHT, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 4, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_BEAK, 14, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "screeches^a screeches");
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain");
addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 8, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, NA, NA, NULL);
addflag(lastrace->flags, F_SWOOPRANGE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 12, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EQUINE, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addflag(lastrace->flags, F_FELINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_AVIAN, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HATESRACEWITHFLAG, F_EQUINE, NA, NA, NULL);
addrace(R_HIPPOGRIFF, "hippogriff", 500, 'u', C_YELLOW, MT_FLESH, RC_ANIMAL, "Hippogriffs are fierce hybrids of a horse and an eagle. Their head, wings and claws take the form of the latter.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_NATURALFLIGHT, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 3, 3, NA, NULL);
addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 6, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_BEAK, 10, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 4, NA, "screams in pain^screams of pain");
addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, "");
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL);
addflag(lastrace->flags, F_EQUINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, NA, NA, NULL);
addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_YELLOW, MT_FLESH, RC_HUMANOID, "A larger, stronger, smarter and more menacing form of a goblin."); addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_YELLOW, MT_FLESH, RC_HUMANOID, "A larger, stronger, smarter and more menacing form of a goblin.");
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);
@ -9934,7 +10037,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, 66, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 66, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, 66, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_SWAMP, 66, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL); addflag(lastrace->flags, F_HITDICE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 4, NA, NA, NULL); addflag(lastrace->flags, F_TR, 5, NA, NA, NULL);
addflag(lastrace->flags, F_EVASION, -5, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, -5, NA, NA, NULL);
addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL); addflag(lastrace->flags, F_ARMOURRATING, 11, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
@ -10281,9 +10384,10 @@ void initrace(void) {
addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_COLD, NA, "80"); addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_COLD, NA, "80");
addrace(R_PEGASUS, "pegasus", 130, 'Q', C_WHITE, MT_FLESH, RC_MAGIC, "A legendary white, winged horse."); addrace(R_PEGASUS, "pegasus", 500, 'u', C_CYAN, MT_FLESH, RC_ANIMAL, "A legendary white, winged horse.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL); addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANTALK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANTALK, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, 57, NA, ""); addflag(lastrace->flags, F_RARITY, H_DUNGEON, 57, NA, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, 57, NA, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, 57, NA, NULL);
@ -10304,13 +10408,15 @@ void initrace(void) {
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 3, 3, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 3, 3, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, NA, NA, NULL);
addflag(lastrace->flags, F_CANCAST, OT_S_SMITEEVIL, NA, NA, "pw:8;");
addflag(lastrace->flags, F_SWOOPRANGE, 4, NA, NA, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 4, NA, NA, NULL);
addflag(lastrace->flags, F_CANCAST, OT_S_SMITEEVIL, NA, NA, "pw:8;");
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 4, NA, "screams in pain^screams of pain"); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 4, NA, "screams in pain^screams of pain");
addflag(lastrace->flags, F_RESISTMAG, 5, NA, NA, NULL); addflag(lastrace->flags, F_RESISTMAG, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 25, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 25, NA, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL);
addflag(lastrace->flags, F_VEGETARIAN, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL);
addflag(lastrace->flags, F_EQUINE, B_TRUE, NA, NA, NULL);
addrace(R_PIXIE, "pixie", 5, 'n', C_GREEN, MT_FLESH, RC_MAGIC, "A small magical woodland creature, flying around on moth-like wings."); addrace(R_PIXIE, "pixie", 5, 'n', C_GREEN, MT_FLESH, RC_MAGIC, "A small magical woodland creature, flying around on moth-like wings.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
@ -11762,7 +11868,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_WATERJET, NA, NA, "pw:4;"); addflag(lastrace->flags, F_CANWILL, OT_S_WATERJET, NA, NA, "pw:4;");
addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_MASTER, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_SWIMMING, PR_MASTER, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL); addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, NULL);
addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_FLOOD, ST_SELF, NA, NULL); addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_FLOOD, F_AICASTTOATTACK, ST_SELF, "100");
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "hop"); addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "hop");
addflag(lastrace->flags, F_EATCONFER, F_BREATHWATER, B_TRUE, NA, "50"); addflag(lastrace->flags, F_EATCONFER, F_BREATHWATER, B_TRUE, NA, "50");
@ -11906,7 +12012,30 @@ void initrace(void) {
addflag(lastrace->flags, F_TAMABLE, 40, NA, NA, NULL); addflag(lastrace->flags, F_TAMABLE, 40, NA, NA, NULL);
addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL);
addrace(R_HORSE, "horse", 500, 'u', C_BROWN, MT_FLESH, RC_ANIMAL, "Large quadrapeds with many purposes: transport, moving goods, pulling ploughs to name but a few.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, "");
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, 2, 2, NA, NULL);
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_HOOF, 6, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_HOOF, 6, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 4, NA, "screams in pain^screams of pain");
addflag(lastrace->flags, F_FLEEONHPPCT, 80, NA, NA, "");
addflag(lastrace->flags, F_MORALE, 1, NA, NA, NULL);
addflag(lastrace->flags, F_EQUINE, B_TRUE, NA, NA, NULL);
addrace(R_FROG, "impaler frog", 10, ';', C_BOLDGREEN, MT_FLESH, RC_ANIMAL, "As their name implies, impaler frogs are dangerous frogs whose tongues end in a very sharp point. They use this to spear their enemies from afar, often while hiding underwater."); addrace(R_FROG, "impaler frog", 10, ';', C_BOLDGREEN, MT_FLESH, RC_ANIMAL, "As their name implies, impaler frogs are dangerous frogs whose tongues end in a very sharp point. They use this to spear their enemies from afar, often while hiding underwater.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
@ -12212,7 +12341,8 @@ void initrace(void) {
addflag(lastrace->flags, F_RETALIATE, 1, 4, DT_PIERCE, "sharp spines"); addflag(lastrace->flags, F_RETALIATE, 1, 4, DT_PIERCE, "sharp spines");
addflag(lastrace->flags, F_CORPSEFLAG, F_SHARP, 1, 4, NULL); addflag(lastrace->flags, F_CORPSEFLAG, F_SHARP, 1, 4, NULL);
addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL);
addrace(R_RAT, "dire rat", 3, 'r', C_BROWN, MT_FLESH, RC_ANIMAL, "A rodent of unusual size.");
addrace(R_RAT, "giant rat", 3, 'r', C_BROWN, MT_FLESH, RC_ANIMAL, "An aggressive rodent, approximately the size of a cat.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
@ -12237,6 +12367,58 @@ void initrace(void) {
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_RATDIRE, "dire rat", 3, 'r', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Dire rats are massive rats, larger than most dogs. Unlike dogs, dire rats are equipped with razor sharp shark-like teeth and their bite is very much worse than their bark.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, "");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 8, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 7, NA, NA, NULL);
addrace(R_RATPLAGUE, "plague rat", 3, 'r', C_GREEN, MT_FLESH, RC_ANIMAL, "Plague rats are named both for their infectious bite as well as the great speed at which they run.");
setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, "");
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_SIZE, SZ_TINY, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_FREQUENT, NULL);
addflag(lastrace->flags, F_HITDICE, 0, 1, NA, NULL);
addflag(lastrace->flags, F_TR, 1, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 1, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 1, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 10, "2-4");
addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL);
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 1, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addrace(R_ROC, "roc", 1, 'A', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Rocs are unbelievably gargantuan birds or prey, large enough to carry a fully-grown elephant. They are generally peaceful, but deadly once provoked."); // 'A' for Avian addrace(R_ROC, "roc", 1, 'A', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Rocs are unbelievably gargantuan birds or prey, large enough to carry a fully-grown elephant. They are generally peaceful, but deadly once provoked."); // 'A' for Avian
setbodytype(lastrace, BT_BIRD); setbodytype(lastrace, BT_BIRD);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL);
@ -12687,6 +12869,7 @@ void initrace(void) {
addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL, "Highly intelligent members of the canine family."); addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL, "Highly intelligent members of the canine family.");
setbodytype(lastrace, BT_QUADRAPED); setbodytype(lastrace, BT_QUADRAPED);
addbodypart(lastrace, BP_TAIL, NULL); addbodypart(lastrace, BP_TAIL, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
@ -12721,6 +12904,7 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, 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_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, ""); addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, "");
addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 6, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
@ -13963,7 +14147,7 @@ void initrace(void) {
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_GHOST, "ghost", 50, 'p', C_BLUE, MT_MAGIC, RC_UNDEAD, "Wispy spirits formed when a soul refuses to depart the earthly realm after death, ghosts exist part way between dimensions. The sight of a ghost can cause fear in all who behold it, and their ethereal nature makes them immune to most attacks."); // p for sPirit addrace(R_GHOST, "ghost", 50, 'p', C_GREY, MT_MAGIC, RC_UNDEAD, "Wispy spirits formed when a soul refuses to depart the earthly realm after death, ghosts exist part way between dimensions. The sight of a ghost can cause fear in all who behold it, and their ethereal nature makes them immune to most attacks."); // p for sPirit
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_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_GTAVERAGE, NA, NULL);
@ -14181,6 +14365,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:3;"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:3;");
addflag(lastrace->flags, F_CANCAST, OT_S_STUN, 5, 5, "pw:1;"); addflag(lastrace->flags, F_CANCAST, OT_S_STUN, 5, 5, "pw:1;");
addflag(lastrace->flags, F_CANCAST, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:vampire bat;"); addflag(lastrace->flags, F_CANCAST, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:vampire bat;");
addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_SHAPESHIFT, F_AICASTTOATTACK, ST_SELF, "100");
addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL);
addflag(lastrace->flags, F_DETECTOBS, 10, OT_COFFIN, NA, NULL); addflag(lastrace->flags, F_DETECTOBS, 10, OT_COFFIN, NA, NULL);
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pile of ash"); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "pile of ash");
@ -14191,6 +14376,86 @@ void initrace(void) {
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
addrace(R_WEREBEAR, "werebear", 90, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Stout, well-muscled humans with large, thick beards.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_MATVULN, MT_SILVER, 200, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 3, 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_SPELLSPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 6, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 6, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 6, NA, NULL);
addflag(lastrace->flags, F_REGENERATES, 1, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_GRAB, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d8;");
addflag(lastrace->flags, F_CANCAST, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:grizzly bear;");
addflag(lastrace->flags, F_CANCAST, OT_S_SUMMONANIMALSLG, 10, 10, "pw:5;race:black bear;count:2;");
addflag(lastrace->flags, F_CASTCHANCE, 20, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "bares its teeth");
addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_SHAPESHIFT, F_AICASTTOATTACK, ST_SELF, "100");
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_FIRSTAID, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_UNARMED, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "hatchet");
addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL);
addflag(lastrace->flags, F_HATESRACE, R_WERERAT, NA, NA, NULL);
addflag(lastrace->flags, F_HATESRACE, R_WEREWOLF, NA, NA, NULL);
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_LYCANTHROPE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 14, NA, NA, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
addrace(R_WERERAT, "wererat", 50, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Weedy humans with shifty eyes and whiskers, wererats are known for their extreme cunning.");
setbodytype(lastrace, BT_HUMANOID);
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_HIGH, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CON, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_SEWER, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_MATVULN, MT_SILVER, 200, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 7, 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_SPELLSPEED, SP_ULTRAFAST, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL);
addflag(lastrace->flags, F_TR, 3, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
addflag(lastrace->flags, F_REGENERATES, 1, NA, NA, NULL);
addflag(lastrace->flags, F_CANCAST, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:plague rat;");
addflag(lastrace->flags, F_CANCAST, OT_S_SUMMONANIMALSSM, 10, 10, "pw:5;race:giant rat;count:5;");
addflag(lastrace->flags, F_STARTOBWEPSK, 100, SK_SHORTBLADES, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 10, NA, NA, "potion of rum");
addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_SHAPESHIFT, F_AICASTTOFLEE, ST_SELF, "100");
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_THIEVERY, PR_BEGINNER, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL);
addflag(lastrace->flags, F_WANTS, OT_POT_RUM, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "twitches its nose");
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_LYCANTHROPE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
addrace(R_WEREWOLF, "werewolf", 100, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Shaggy humans with the uncanny ability to shapeshift into a ferocious wolf."); addrace(R_WEREWOLF, "werewolf", 100, '@', C_BROWN, MT_FLESH, RC_HUMANOID, "Shaggy humans with the uncanny ability to shapeshift into a ferocious wolf.");
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);
@ -14200,10 +14465,10 @@ void initrace(void) {
addflag(lastrace->flags, F_STARTATT, A_CON, AT_GTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_GTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, 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_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, 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_DTVULN, DT_LIGHT, NA, NA, "3d6");
addflag(lastrace->flags, F_MATVULN, MT_SILVER, 200, NA, NULL); addflag(lastrace->flags, F_MATVULN, MT_SILVER, 200, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
@ -14214,11 +14479,17 @@ void initrace(void) {
addflag(lastrace->flags, F_REGENERATES, 1, NA, NA, NULL); addflag(lastrace->flags, F_REGENERATES, 1, NA, NA, NULL);
addflag(lastrace->flags, F_CANCAST, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:dire wolf;"); addflag(lastrace->flags, F_CANCAST, OT_S_SHAPESHIFT, 3, 3, "pw:1;race:dire wolf;");
addflag(lastrace->flags, F_CANCAST, OT_S_SUMMONANIMALSMD, 10, 10, "pw:5;race:young wolf;"); addflag(lastrace->flags, F_CANCAST, OT_S_SUMMONANIMALSMD, 10, 10, "pw:5;race:young wolf;");
addflag(lastrace->flags, F_AISPELLTARGETOVERRIDE, OT_S_SHAPESHIFT, F_AICASTTOATTACK, ST_SELF, "100");
addflag(lastrace->flags, F_STARTSKILL, SK_FIRSTAID, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_FIRSTAID, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_ADEPT, NA, NULL);
addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 3, NA, NA, NULL);
addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 40, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "howls"); addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "howls");
addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_LYCANTHROPE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); // ie. cats will know!
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
// special monsters // special monsters

42
defs.h
View File

@ -62,6 +62,7 @@
//#define UNI_SOLID '#' //#define UNI_SOLID '#'
// getrandomemptycell() params // getrandomemptycell() params
#define WE_NONE 0
#define WE_WALKABLE 1 #define WE_WALKABLE 1
#define WE_EMPTY 2 #define WE_EMPTY 2
#define WE_PORTAL 3 #define WE_PORTAL 3
@ -982,6 +983,7 @@ enum RACE {
// monsters // monsters
R_BEHOLDER, R_BEHOLDER,
R_BUGBEAR, R_BUGBEAR,
R_CENTAUR,
R_COCKATRICE, R_COCKATRICE,
R_CREEPINGCLAW, R_CREEPINGCLAW,
R_CRYMIDIA, R_CRYMIDIA,
@ -1003,6 +1005,8 @@ enum RACE {
R_GOBLINWAR, R_GOBLINWAR,
R_GOBLINSHOOTER, R_GOBLINSHOOTER,
R_GREMLIN, R_GREMLIN,
R_GRIFFON,
R_HIPPOGRIFF,
R_HOBGOBLIN, R_HOBGOBLIN,
R_HOBGOBLINWAR, R_HOBGOBLINWAR,
R_KOBOLD, R_KOBOLD,
@ -1046,6 +1050,8 @@ enum RACE {
R_TROLLSNOW, R_TROLLSNOW,
R_TROLLSWAMP, R_TROLLSWAMP,
R_VAMPIRE, R_VAMPIRE,
R_WEREBEAR,
R_WERERAT,
R_WEREWOLF, R_WEREWOLF,
R_XAT, R_XAT,
// fish // fish
@ -1094,12 +1100,15 @@ enum RACE {
R_HAWKYOUNG, R_HAWKYOUNG,
R_HAWKBLOOD, R_HAWKBLOOD,
R_HAWKFROST, R_HAWKFROST,
R_HORSE,
R_FROG, R_FROG,
R_LEECH, R_LEECH,
R_MAMMOTH, R_MAMMOTH,
R_NEWT, R_NEWT,
R_PORCUPINE, R_PORCUPINE,
R_RAT, R_RAT,
R_RATDIRE,
R_RATPLAGUE,
R_ROC, R_ROC,
R_SLUG, R_SLUG,
R_SNAIL, R_SNAIL,
@ -2243,6 +2252,14 @@ enum SLEEPTYPE {
ST_KO, ST_KO,
}; };
enum ANIMALTYPE {
AT_AVIAN,
AT_CANINE,
AT_EQUINE,
AT_FELINE,
};
enum FLAG { enum FLAG {
F_NONE = 0, // dummy flag F_NONE = 0, // dummy flag
// map flags // map flags
@ -2326,8 +2343,10 @@ enum FLAG {
F_THROWMISSILE, // weapon would make a good thrown missle - used by AI F_THROWMISSILE, // weapon would make a good thrown missle - used by AI
F_CANHOME, // this object can have the 'homing' flag F_CANHOME, // this object can have the 'homing' flag
F_UNIQUE, // only one may appear F_UNIQUE, // only one may appear
F_GLYPH, // override the glyph with the first char of text. F_GLYPH, // override the glyph with f->val[1]
// v0 is either NA (white) or colourid (C_xxx). // v0 is either NA (white) or colourid (C_xxx).
// OPTIONAL v2: if you lorelev for this race is less
// then v2,
F_NOGLYPH, // this object doesn't appear normally F_NOGLYPH, // this object doesn't appear normally
F_COSMETIC, // this object is mostly cosmetic, don't say 'you see xx' F_COSMETIC, // this object is mostly cosmetic, don't say 'you see xx'
// also don't stop the player running past it. // also don't stop the player running past it.
@ -3003,6 +3022,8 @@ enum FLAG {
// sight // sight
F_HATESRACECLASS, // lf will attack lfs with raceclass->id=v0 F_HATESRACECLASS, // lf will attack lfs with raceclass->id=v0
F_HATESRACEWITHFLAG, // lf will attack lfs with flag v0 on sight F_HATESRACEWITHFLAG, // lf will attack lfs with flag v0 on sight
// will also check flag v0=this v1 and
// flag v1 = this v2
F_TERRITORIAL, // lf will attack ALL other visible lfs within range v0 F_TERRITORIAL, // lf will attack ALL other visible lfs within range v0
F_HARMLESS, // it is safe to rest around this lf F_HARMLESS, // it is safe to rest around this lf
F_RNDHOSTILE, // v0% chance of being hostile. F_RNDHOSTILE, // v0% chance of being hostile.
@ -3010,8 +3031,8 @@ enum FLAG {
F_FRIENDLY, // lf will attack all non-players if in sight F_FRIENDLY, // lf will attack all non-players if in sight
F_FATALFOOD, // if lf eats food with id = v0, they die. F_FATALFOOD, // if lf eats food with id = v0, they die.
F_NATURALFLIGHT, // lf can fly natural using wings or similar F_NATURALFLIGHT, // lf can fly natural using wings or similar
F_WANTS, // lf will try to pick up object type val0. if F_WANTS, // lf will try to pick up object type val0.
// val1 = B_COVETS, will even abandon attacks // if val1 = B_COVETS, will even abandon attacks
// for it! // for it!
F_WANTSOBFLAG, // lf will look for obs with this flag. val1=covets F_WANTSOBFLAG, // lf will look for obs with this flag. val1=covets
F_WANTSBETTERWEP, // lf will look for better weapons, val1=covets F_WANTSBETTERWEP, // lf will look for better weapons, val1=covets
@ -3062,9 +3083,13 @@ enum FLAG {
// for spellid v0 // for spellid v0
F_SPELLCASTTIME, // override F_CASTINGTIME to v0 when this lf F_SPELLCASTTIME, // override F_CASTINGTIME to v0 when this lf
// casts spellid v1. // casts spellid v1.
F_AISPELLTARGETOVERRIDE, // when casting spellid v0, this lf will F_AISPELLTARGETOVERRIDE, // when casting spellid v0,
// use v1 (ST_xxx) instead of what the AICASTTOxxx // use AICASTTOxxx=v1 instead of the one
// flag specifies. // from the spell.
// use targettype = v2, intsead of the one
// from the spell.
// OPTIONAL: text = pctchance to cast for
// thispurpose. if not given, chance is 100.
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
F_NODEATHSPEECH, // lf doesn't talk when dying F_NODEATHSPEECH, // lf doesn't talk when dying
F_BEHEADED, // use special corpse drop code F_BEHEADED, // use special corpse drop code
@ -3142,12 +3167,16 @@ enum FLAG {
F_AQUATIC, // this race can attack normally in water and suffers no F_AQUATIC, // this race can attack normally in water and suffers no
// movement penalties. they can also swim at master // movement penalties. they can also swim at master
// level. // level.
F_AVIAN, // this race is an avian F_AVIAN, // this race is an avian
F_CANINE, // this race is a canine F_CANINE, // this race is a canine
F_EQUINE, // this race is an equine
F_FELINE, // this race is a feline F_FELINE, // this race is a feline
F_HUMANOID, // this race is a humanoid F_HUMANOID, // this race is a humanoid
// (can wear armour / use weapons) // (can wear armour / use weapons)
F_INSECT, // this race is classed as an insect F_INSECT, // this race is classed as an insect
F_LYCANTHROPE, // this race is a lycanthrope
F_UNDEAD, // this race is classed as undead F_UNDEAD, // this race is classed as undead
F_COLDBLOOD, // this race is coldblooded F_COLDBLOOD, // this race is coldblooded
F_NOBODYPART, // this race doesn't have bodypart val0 F_NOBODYPART, // this race doesn't have bodypart val0
@ -3349,6 +3378,7 @@ enum FLAG {
F_HASATTACK, // v0 = obid to use when attacking unarmed F_HASATTACK, // v0 = obid to use when attacking unarmed
// if v1 is set, it overrides DR(damagerating) // if v1 is set, it overrides DR(damagerating)
// if text is set, it overrides the damage // if text is set, it overrides the damage
F_FORCEATTACK, // this lf may only attack using F_HASATTACK v0
F_EVASION, // % chance of evading an attack F_EVASION, // % chance of evading an attack
// healing/resting/training // healing/resting/training

View File

@ -11,7 +11,7 @@ A = avian / bird
b = small roBot b = small roBot
B = bat B = bat
c = cockatrice / chicken / small bird c = cockatrice / chicken / small bird
C = celestial / divine ? C = ? celestial/divine?
d = canine/dog d = canine/dog
D = ? D = ?
e = eye or floating thing e = eye or floating thing
@ -25,9 +25,11 @@ H = large humanoid
i = insect i = insect
I = large insect I = large insect
j = jelly/ooze/leech j = jelly/ooze/leech
k = kobold J = ?
k = dog-like humanoid (kobold, gnoll)
K = ?
L = lich, or other powerful undead ? L = lich, or other powerful undead ?
m = mutant / magic creature m = mutant / hybrid creature
M = mummy M = mummy
n = small humanoid / nymph / sprite n = small humanoid / nymph / sprite
N = ling / alieN creature N = ling / alieN creature
@ -35,7 +37,7 @@ o = orc
O = monstrous humanoid (ie. ogre) O = monstrous humanoid (ie. ogre)
P = gastropod P = gastropod
p = sPirit p = sPirit
q = quadraped q = medium quadraped
Q = large quadraped Q = large quadraped
r = rodent r = rodent
R = robot R = robot
@ -43,7 +45,7 @@ s = snake
S = spider S = spider
t = troll t = troll
T = walkingtree-like monster (dryad, treant) T = walkingtree-like monster (dryad, treant)
u = ? make this be horse? if so, change pegasus. u = horse.
U = unearthly/horrific creature U = unearthly/horrific creature
v = ? v = ?
V = vampire V = vampire

18
io.c
View File

@ -11771,14 +11771,16 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
// non-intrinsic effecst like polymorph, eye shading // non-intrinsic effecst like polymorph, eye shading
f = lfhasknownflag(lf, F_POLYMORPHED); if (isplayer(lf)) {
if (f && (f->known)) { f = lfhasknownflag(lf, F_POLYMORPHED);
snprintf(buf, BUFLEN, "%s have been polymorphed into a %s.",you(lf), lf->race->name); if (f && (f->known)) {
//if (lfhasflag(lf, F_OMNIPOTENT) || lfhasflag(lf, F_EXTRAINFO)) { snprintf(buf, BUFLEN, "%s have been polymorphed into a %s.",you(lf), lf->race->name);
snprintf(buf2, BUFLEN, " [%d left]", f->lifetime); //if (lfhasflag(lf, F_OMNIPOTENT) || lfhasflag(lf, F_EXTRAINFO)) {
strcat(buf, buf2); snprintf(buf2, BUFLEN, " [%d left]", f->lifetime);
// } strcat(buf, buf2);
wrapprint(mainwin, &y, &x, 0, "%s ", buf); // }
wrapprint(mainwin, &y, &x, 0, "%s ", buf);
}
} }
if (!canuseweapons(lf)) { if (!canuseweapons(lf)) {

181
lf.c
View File

@ -2856,7 +2856,7 @@ void die(lifeform_t *lf) {
if (premaxhp < lf->maxhp) { if (premaxhp < lf->maxhp) {
float ratio; float ratio;
ratio = (float)premaxhp / (float) lf->maxhp; ratio = (float)premaxhp / (float) lf->maxhp;
lf->maxhp = ratio * lf->maxhp; lf->hp = ratio * lf->maxhp;
limit(&(lf->hp), 1, lf->maxhp); limit(&(lf->hp), 1, lf->maxhp);
} }
if (thisisplayer) statdirty = B_TRUE; if (thisisplayer) statdirty = B_TRUE;
@ -3135,7 +3135,12 @@ void die(lifeform_t *lf) {
copyflag(corpse->flags, lf->flags, F_CANCAST); copyflag(corpse->flags, lf->flags, F_CANCAST);
copyflag(corpse->flags, lf->flags, F_CANWILL); copyflag(corpse->flags, lf->flags, F_CANWILL);
copyflag(corpse->flags, lf->flags, F_JOB); copyflag(corpse->flags, lf->flags, F_JOB);
// race subspecies flags, so that we can have mosnters which eat
// only certain kinds of corpses
copyflag(corpse->flags, lf->flags, F_AVIAN);
copyflag(corpse->flags, lf->flags, F_CANINE);
copyflag(corpse->flags, lf->flags, F_EQUINE);
copyflag(corpse->flags, lf->flags, F_FELINE);
f = hasflag(corpse->flags, F_CORPSEOF); f = hasflag(corpse->flags, F_CORPSEOF);
if (f) { if (f) {
@ -8356,10 +8361,28 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
char jobstring[BUFLEN]; char jobstring[BUFLEN];
char the[6]; char the[6];
char lname[BUFLEN]; char lname[BUFLEN];
race_t *lfrace;
flag_t *f; flag_t *f;
enum LFSIZE size,racesize; enum LFSIZE size,racesize;
int dobehaviour = B_TRUE; int dobehaviour = B_TRUE;
enum SKILLLEVEL lorelev;
if (gamemode == GM_GAMESTARTED) {
lorelev = getlorelevel(player, lf->race->raceclass->id);
} else {
lorelev = PR_MASTER;
}
if (lfhasflag(lf, F_LYCANTHROPE)) {
// lycanthropes appear as human unless you know better
if (lorelev >= PR_ADEPT) {
lfrace = lf->race;
} else {
lfrace = findrace(R_HUMAN);
}
} else {
lfrace = lf->race;
}
// 'the' or 'your' ? // 'the' or 'your' ?
f = lfhasflag(lf, F_NAME); f = lfhasflag(lf, F_NAME);
@ -8368,7 +8391,7 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
strcpy(lname, f->text); strcpy(lname, f->text);
} else if (lfhasflag(lf, F_UNIQUE)) { } else if (lfhasflag(lf, F_UNIQUE)) {
strcpy(the, ""); strcpy(the, "");
strcpy(lname, lf->race->name); strcpy(lname, lfrace->name);
} else { } else {
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
strcpy(the, "your "); strcpy(the, "your ");
@ -8377,33 +8400,35 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
} }
f = lfhasflag(lf, F_NAMED); f = lfhasflag(lf, F_NAMED);
if (f) { // ie. "the xat named blah" if (f) { // ie. "the xat named blah"
strcpy(lname, lf->race->name); strcpy(lname, lfrace->name);
strcat(lname, " named "); strcat(lname, " named ");
strcat(lname, f->text); strcat(lname, f->text);
} else { // ie. "the xat" } else { // ie. "the xat"
strcpy(lname, lf->race->name); strcpy(lname, lfrace->name);
} }
} }
// construct description string // construct description string
strcpy(descstring, ""); strcpy(descstring, "");
// has their size changed? // if you lorelev is high enough, you can tell when the race is larger or smaller than
f = hasflag(lf->race->flags, F_SIZE); // they should be.
if (f) { if (lorelev >= PR_BEGINNER) {
racesize = f->val[0]; f = hasflag(lfrace->flags, F_SIZE);
} else { if (f) {
racesize = SZ_HUMAN; // default racesize = f->val[0];
} } else {
size = getlfsize(lf); racesize = SZ_HUMAN; // default
if (size != racesize) { }
strcat(descstring, getsizetext(size)); size = getlfsize(lf);
strcat(descstring, " "); if (size != racesize) {
strcat(descstring, getsizetext(size));
strcat(descstring, " ");
}
} }
// need a certain amount of race knowledge to recognise ai traits // need a certain amount of race knowledge to recognise ai traits
if (getlorelevel(player, lf->race->raceclass->id) < PR_SKILLED) { if (lorelev < PR_SKILLED) {
dobehaviour = B_FALSE; dobehaviour = B_FALSE;
} }
// frozen/headless trump behavioural descriptions like "insane" // frozen/headless trump behavioural descriptions like "insane"
@ -8426,7 +8451,7 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
// construct job string // construct job string
strcpy(jobstring, ""); strcpy(jobstring, "");
if (showall || isplayer(lf) || (getlorelevel(player, lf->race->raceclass->id) >= PR_BEGINNER)) { if (showall || isplayer(lf) || (lorelev >= PR_BEGINNER)) {
if (!lfhasflag(lf, F_NOJOBTEXT) && !lfhasflag(lf, F_NAME) && !lfhasflag(lf, F_UNIQUE)) { if (!lfhasflag(lf, F_NOJOBTEXT) && !lfhasflag(lf, F_NAME) && !lfhasflag(lf, F_UNIQUE)) {
if (getjob(lf)) { if (getjob(lf)) {
snprintf(jobstring, BUFLEN, " %s", getjobname(lf)); snprintf(jobstring, BUFLEN, " %s", getjobname(lf));
@ -8483,6 +8508,29 @@ char *getlfnamea(lifeform_t *lf, char *buf) {
} }
char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis, int showall) { char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis, int showall) {
race_t *lfrace;
enum SKILLLEVEL lorelev;
if (gamemode == GM_GAMESTARTED) {
lorelev = getlorelevel(player, lf->race->raceclass->id);
} else {
lorelev = PR_MASTER;
}
switch (lf->race->id) {
case R_WERERAT:
case R_WEREWOLF:
if (lorelev >= PR_ADEPT) {
lfrace = lf->race;
} else {
lfrace = findrace(R_HUMAN);
}
break;
default:
lfrace = lf->race;
break;
}
if (isplayer(lf)) { if (isplayer(lf)) {
snprintf(buf, BUFLEN, "you"); snprintf(buf, BUFLEN, "you");
} else { } else {
@ -8497,7 +8545,7 @@ char *real_getlfnamea(lifeform_t *lf, char *buf, int usevis, int showall) {
if (ispetof(lf, player)) { if (ispetof(lf, player)) {
strcpy(the, "your "); strcpy(the, "your ");
} else { } else {
if (isvowel(lf->race->name[0])) { if (isvowel(lfrace->name[0])) {
strcpy(the, "an "); strcpy(the, "an ");
} else { } else {
strcpy(the, "a "); strcpy(the, "a ");
@ -9513,39 +9561,44 @@ object_t *getweapon(lifeform_t *lf) {
// this function MIGHT allocat op! // this function MIGHT allocat op!
int getweapons(lifeform_t *lf, object_t **wep, flag_t **damflag, int *lastweaponidx, obpile_t **op, int *nweps) { int getweapons(lifeform_t *lf, object_t **wep, flag_t **damflag, int *lastweaponidx, obpile_t **op, int *nweps) {
int gotweapon = B_FALSE; int gotweapon = B_FALSE;
flag_t *retflag[MAXCANDIDATES],*f; flag_t *retflag[MAXCANDIDATES],*f,*forcewep;
int nretflags,i; int nretflags,i;
// first use our weapon... // first use our weapon...
*nweps = 0;
wep[*nweps] = getweapon(lf);
if (wep[*nweps]) {
if (damflag) damflag[*nweps] = hasflag(wep[*nweps]->flags, F_DAM);
if (lastweaponidx) *lastweaponidx = 0;
(*nweps)++;
gotweapon = B_TRUE;
}
// if we are skilled at twoweaponing, we can attack with our second weapon *nweps = 0;
// as well, with a possible accuracy penalty depending on our skill level.
if (getskill(lf, SK_TWOWEAPON)) { forcewep = lfhasflag(lf, F_FORCEATTACK);
wep[*nweps] = getsecmeleeweapon(lf); if (!forcewep) {
wep[*nweps] = getweapon(lf);
if (wep[*nweps]) { if (wep[*nweps]) {
if ((*nweps >= 1) && (wep[*nweps] == wep[(*nweps)-1])) { if (damflag) damflag[*nweps] = hasflag(wep[*nweps]->flags, F_DAM);
// can't be the same as first one if (lastweaponidx) *lastweaponidx = 0;
} else { (*nweps)++;
if (damflag) damflag[*nweps] = hasflag(wep[*nweps]->flags, F_DAM); gotweapon = B_TRUE;
if (lastweaponidx) *lastweaponidx = *nweps; }
(*nweps)++;
gotweapon = B_TRUE; // if we are skilled at twoweaponing, we can attack with our second weapon
// as well, with a possible accuracy penalty depending on our skill level.
if (getskill(lf, SK_TWOWEAPON)) {
wep[*nweps] = getsecmeleeweapon(lf);
if (wep[*nweps]) {
if ((*nweps >= 1) && (wep[*nweps] == wep[(*nweps)-1])) {
// can't be the same as first one
} else {
if (damflag) damflag[*nweps] = hasflag(wep[*nweps]->flags, F_DAM);
if (lastweaponidx) *lastweaponidx = *nweps;
(*nweps)++;
gotweapon = B_TRUE;
}
} }
} }
} } // end if !forcewep
// then use all our innate attacks.. // then use all our innate attacks..
getflags(lf->flags, retflag, &nretflags, F_HASATTACK, F_NONE); getflags(lf->flags, retflag, &nretflags, F_HASATTACK, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
f = retflag[i]; f = retflag[i];
if (f->id == F_HASATTACK) { if (!forcewep || (f->val[0] == forcewep->val[0])) {
objecttype_t *ot; objecttype_t *ot;
if (!(*op)) { if (!(*op)) {
@ -16235,11 +16288,20 @@ int readytotrain(lifeform_t *lf) {
} }
int recruit(lifeform_t *lf) { int recruit(lifeform_t *lf) {
enum ALIGNMENT pa,lfa;
// alignments must match, otherwire VERY hard to make them join!
pa = getalignment(player);
lfa = getalignment(lf);
int rv = B_FALSE; int rv = B_FALSE;
if (lfhasflag(lf, F_NOHIRE)) { if (lfhasflag(lf, F_NOHIRE)) {
// refusing to join at all. // refusing to join at all.
sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL); sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL);
rv = B_TRUE; rv = B_TRUE;
} else if ( ((pa == AL_GOOD) && (lfa == AL_EVIL)) ||
((pa == AL_EVIL) && (lfa == AL_GOOD)) ) {
sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL);
rv = B_TRUE;
} else { } else {
int dohire = B_FALSE; int dohire = B_FALSE;
int askingprice = -1; int askingprice = -1;
@ -16259,6 +16321,7 @@ int recruit(lifeform_t *lf) {
// since you have to be at least speech=4(skilled) to ask someone to // since you have to be at least speech=4(skilled) to ask someone to
// join, add +8 to difficulty (pr_skilled * 2) // join, add +8 to difficulty (pr_skilled * 2)
difficulty = 25 + 8 + ((gettr(player) - gettr(lf))*2); difficulty = 25 + 8 + ((gettr(player) - gettr(lf))*2);
if (real_skillcheck(player, SC_SPEECH, difficulty, 0, &result)) { if (real_skillcheck(player, SC_SPEECH, difficulty, 0, &result)) {
minmult = 10; minmult = 10;
maxmult = 20; maxmult = 20;
@ -16970,11 +17033,30 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t
rv = say(lf, buf, volume); rv = say(lf, buf, volume);
break; break;
case SP_RECRUIT_ASKPRICE: case SP_RECRUIT_ASKPRICE:
snprintf(buf, BUFLEN, "My services will cost you $%d.",val0); switch (rnd(1,8)) {
case 1: snprintf(buf, BUFLEN, "My services will cost you $%d.", val0); break;
case 2: snprintf(buf, BUFLEN, "$%d and you have yourself a deal.", val0); break;
case 3: snprintf(buf, BUFLEN, "Okay. How does $%d sound?", val0); break;
case 4: snprintf(buf, BUFLEN, "I'll do it for $%d.", val0); break;
case 5: snprintf(buf, BUFLEN, "Let's see... $%d should do it.", val0); break;
case 6: snprintf(buf, BUFLEN, "My fee is $%d. Still interested?", val0); break;
case 7: snprintf(buf, BUFLEN, "I don't work for free. $%d.", val0); break;
case 8: snprintf(buf, BUFLEN, "$%d and your cause is mine.", val0); break;
}
rv = say(lf, buf, volume); rv = say(lf, buf, volume);
break; break;
case SP_RECRUIT_DECLINE: case SP_RECRUIT_DECLINE:
rv = say(lf, "No, I regretfully decline your offer.", volume); switch (rnd(1,8)) {
case 1: snprintf(buf, BUFLEN, "No, I regretfully decline your offer."); break;
case 2: snprintf(buf, BUFLEN, "You dare ask me for help?"); break;
case 3: snprintf(buf, BUFLEN, "I will never help you."); break;
case 4: snprintf(buf, BUFLEN, "No."); break;
case 5: snprintf(buf, BUFLEN, "Me? Help you?."); break;
case 6: snprintf(buf, BUFLEN, "Ahem. I think not."); break;
case 7: snprintf(buf, BUFLEN, "I don't think that would be a good idea."); break;
case 8: snprintf(buf, BUFLEN, "Sorry, but no."); break;
}
rv = say(lf, buf, volume);
break; break;
case SP_RECRUIT_DECLINE_CANTPAY: case SP_RECRUIT_DECLINE_CANTPAY:
rv = say(lf, "...which I see you cannot afford.", volume); rv = say(lf, "...which I see you cannot afford.", volume);
@ -17417,8 +17499,15 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
killflag(f); killflag(f);
nkilled++; nkilled++;
} else if ((f->lifetime > 0) && (f->id != F_POLYMORPHED)) { } else if ((f->lifetime > 0) && (f->id != F_POLYMORPHED)) {
killflag(f); // kill most temporary flags, with exceptions
nkilled++; switch (f->id) {
case F_FLEEFROM:
break;
default:
killflag(f);
nkilled++;
break;
}
} }
} }

119
map.c
View File

@ -142,12 +142,18 @@ void addhomeobs(lifeform_t *lf, int dolevelobs) {
amt = rnd(f->val[0],f->val[1]); amt = rnd(f->val[0],f->val[1]);
for (i = 0; i < amt; i++) { for (i = 0; i < amt; i++) {
cell_t *c; cell_t *c;
// pick new EMPTY random spot // pick new EMPTY random spot. try rooms first.
c = getrandomcell(lf->cell->map); c = getrandomroomcell(lf->cell->map, ANYROOM, WE_WALKABLE);
while (!cellwalkable(NULL, c, NULL)) { if (!c) {
// if no rooms, get any walkable cell.
c = getrandomcell(lf->cell->map); c = getrandomcell(lf->cell->map);
while (!cellwalkable(NULL, c, NULL)) {
c = getrandomcell(lf->cell->map);
}
}
if (c) {
o = addob(c->obpile, f->text);
} }
o = addob(c->obpile, f->text);
} }
} }
@ -1236,6 +1242,39 @@ int adjcellokforreachability(cell_t *c, int srcroomid, int dir, int wantfilled)
return B_FALSE; return B_FALSE;
} }
int cellmatchescondition(cell_t *c, int wecond) {
int ok = B_FALSE;
if (wecond == WE_EMPTY) {
// make sure it's empty
if (isempty(c)) {
ok = B_TRUE;
}
} else if (wecond == WE_WALKABLE) {
if (cellwalkable(NULL, c, NULL)) {
ok = B_TRUE;
}
} else if (wecond == WE_PORTAL) {
if (cellwalkable(NULL, c, NULL) && !hasenterableobject(c) ) {
if (!hasobwithflag(c->obpile, F_DOOR)) {
ok = B_TRUE;
}
}
} else if (wecond == WE_NOTWALL) {
if ((!c->type->solid) && !hasobwithflag(c->obpile, F_IMPASSABLE)) {
//if (!c->type->solid) {
ok = B_TRUE;
}
} else if (wecond == WE_NOLF) {
if (!c->lf) ok = B_TRUE;
} else if (wecond == WE_SOLID) {
if (c->type->solid) ok = B_TRUE;
} else {
// always ok
ok = B_TRUE;
}
return ok;
}
// returns B_TRUE, B_FALSE or B_MAYBE // returns B_TRUE, B_FALSE or B_MAYBE
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom) { int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom) {
int db = B_FALSE; int db = B_FALSE;
@ -2873,9 +2912,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
if (db) dblog("--> Will add %d pillars",numpillars); if (db) dblog("--> Will add %d pillars",numpillars);
for (n = 0; n < numpillars;n++ ) { for (n = 0; n < numpillars;n++ ) {
//dblog("----> Adding pillar %d/%d",n+1,numpillars); //dblog("----> Adding pillar %d/%d",n+1,numpillars);
c = getrandomroomcell(map, i); c = getrandomroomcell(map, i, WE_EMPTY);
if (c && isempty(c) && !countobs(c->obpile, B_TRUE)) { if (c && !countobs(c->obpile, B_TRUE)) {
setcelltype(c, solidcell); setcelltype(c, solidcell);
} }
} }
@ -2897,10 +2936,9 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
int nmonsters = 0; int nmonsters = 0;
done = B_FALSE; done = B_FALSE;
while (!done) { while (!done) {
c = getrandomroomcell(map, i); c = getrandomroomcell(map, i, WE_WALKABLE);
// if nothing there // if nothing there
if (c && cellwalkable(NULL, c, NULL)) { if (c) {
int obchance; int obchance;
int nadded = 0; int nadded = 0;
@ -3418,7 +3456,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
break; break;
case RT_OBJECT: case RT_OBJECT:
if (db) dblog(" adding forced regionthing object: %s", thing[i]->what); if (db) dblog(" adding forced regionthing object: %s", thing[i]->what);
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM, WE_WALKABLE);
if (!c) c = getrandomcell(map); if (!c) c = getrandomcell(map);
c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL); c = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_DONTNEED, NULL, NULL);
addob(c->obpile, thing[i]->what); addob(c->obpile, thing[i]->what);
@ -3967,7 +4005,7 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
// also ensure it's not over water. // also ensure it's not over water.
c = NULL; c = NULL;
while (!c || (countadjwalls(c) == 0) || getcellwaterdepth(c, NULL)) { while (!c || (countadjwalls(c) == 0) || getcellwaterdepth(c, NULL)) {
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM, WE_NONE);
assert(c); assert(c);
} }
o = addobfast(c->obpile, OT_GRATINGROOF); o = addobfast(c->obpile, OT_GRATINGROOF);
@ -4659,13 +4697,13 @@ int linkexits(map_t *m, int roomid) {
assert(roomidx != -1); assert(roomidx != -1);
// does this roomid actually exist?? // does this roomid actually exist??
c = getrandomroomcell(m, roomid); c = getrandomroomcell(m, roomid, WE_NONE);
if (!c) return B_FALSE; if (!c) return B_FALSE;
if (db) { if (db) {
char buf[BUFLEN]; char buf[BUFLEN];
vault_t *v; vault_t *v;
c = getrandomroomcell(m, roomid); c = getrandomroomcell(m, roomid, WE_NONE);
v = getcellvault(c); v = getcellvault(c);
snprintf(buf, BUFLEN, "*** linkexits for roomid %d (%s) [%d,%d-%d,%d]", roomid, snprintf(buf, BUFLEN, "*** linkexits for roomid %d (%s) [%d,%d-%d,%d]", roomid,
v ? v->id : "novault", v ? v->id : "novault",
@ -5195,8 +5233,8 @@ void finalisemap(map_t *map, object_t *entryob) {
flag_t *f; flag_t *f;
// first dungeon level. just one exit stairs // first dungeon level. just one exit stairs
c = NULL; c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { while (!c || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
} }
o = addobfast(c->obpile, upstairtype); o = addobfast(c->obpile, upstairtype);
if (entryob) { if (entryob) {
@ -5223,8 +5261,8 @@ void finalisemap(map_t *map, object_t *entryob) {
// up stairs on all other levels // up stairs on all other levels
for (i = 0; i < nupstairsneeded; i++) { for (i = 0; i < nupstairsneeded; i++) {
c = NULL; c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { while (!c || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
if (!c) { if (!c) {
// ANY cell at all, doesn't have to be a room. // ANY cell at all, doesn't have to be a room.
c = getrandomcell(map); c = getrandomcell(map);
@ -5248,8 +5286,8 @@ void finalisemap(map_t *map, object_t *entryob) {
if ((downstairtype != OT_NONE) && (map->depth < map->region->rtype->maxdepth)) { if ((downstairtype != OT_NONE) && (map->depth < map->region->rtype->maxdepth)) {
for (i = 0; i < ndownstairsneeded; i++) { for (i = 0; i < ndownstairsneeded; i++) {
c = NULL; c = NULL;
while (!c || !isempty(c) || countobs(c->obpile, B_TRUE)) { while (!c || countobs(c->obpile, B_TRUE)) {
c = getrandomroomcell(map, ANYROOM); c = getrandomroomcell(map, ANYROOM, WE_EMPTY);
if (!c) { if (!c) {
// ANY cell at all, doesn't have to be a room. // ANY cell at all, doesn't have to be a room.
c = getrandomcell(map); c = getrandomcell(map);
@ -5329,7 +5367,7 @@ void finalisemap(map_t *map, object_t *entryob) {
if (roomlightchance) { if (roomlightchance) {
for (i = 0; i < map->nrooms; i++) { for (i = 0; i < map->nrooms; i++) {
if (pctchance(roomlightchance)) { if (pctchance(roomlightchance)) {
c = getrandomroomcell(map, i); c = getrandomroomcell(map, i, WE_WALKABLE);
addob(c->obpile, roomlightob); addob(c->obpile, roomlightob);
} }
} }
@ -5474,6 +5512,13 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
addhomeobs(lf, B_TRUE); addhomeobs(lf, B_TRUE);
// if monster can shapeshift, it will sometimes start in its alternate form.
if (cancast(lf, OT_S_SHAPESHIFT, NULL)) {
if (onein(4)) {
castspell(lf, OT_S_SHAPESHIFT, lf, NULL, lf->cell, NULL, NULL);
}
}
/* /*
getflags(lf->flags, retflag, &nretflags, F_LIFEOB, F_NONE); getflags(lf->flags, retflag, &nretflags, F_LIFEOB, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
@ -6018,34 +6063,8 @@ cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LO
enum OBTYPE *badoid; enum OBTYPE *badoid;
int ok = B_FALSE; int ok = B_FALSE;
numwithlof++; numwithlof++;
if (wantempty == WE_EMPTY) {
// make sure it's empty ok = cellmatchescondition(new, wantempty);
if (isempty(new)) {
ok = B_TRUE;
}
} else if (wantempty == WE_WALKABLE) {
if (cellwalkable(NULL, new, NULL)) {
ok = B_TRUE;
}
} else if (wantempty == WE_PORTAL) {
if (cellwalkable(NULL, new, NULL) && !hasenterableobject(new) ) {
if (!hasobwithflag(new->obpile, F_DOOR)) {
ok = B_TRUE;
}
}
} else if (wantempty == WE_NOTWALL) {
if ((!new->type->solid) && !hasobwithflag(new->obpile, F_IMPASSABLE)) {
//if (!new->type->solid) {
ok = B_TRUE;
}
} 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;
}
// obs we dont want? // obs we dont want?
if (dontwantob) { if (dontwantob) {
@ -6149,7 +6168,7 @@ int getrandomdirexcept(int dirtype, int exception) {
return dir; return dir;
} }
cell_t *getrandomroomcell(map_t *map, int roomid) { cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty) {
int npossible = 0; int npossible = 0;
int selidx; int selidx;
int x,y; int x,y;
@ -6175,7 +6194,7 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
} }
} }
if (ok) { if (ok && cellmatchescondition(c, wantempty)) {
poss[npossible] = c; poss[npossible] = c;
npossible++; npossible++;
} }

3
map.h
View File

@ -16,6 +16,7 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in
void breakwall(cell_t *c); void breakwall(cell_t *c);
int cellhaslos(cell_t *c1, cell_t *dest); int cellhaslos(cell_t *c1, cell_t *dest);
int cellisfixedvaultwall(cell_t *c); int cellisfixedvaultwall(cell_t *c);
int cellmatchescondition(cell_t *c, int wecond);
int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom); int cellokforreachability(cell_t *startcell, cell_t *c, int srcroomid, int dir, int wantfilled, int *insameroom);
void clearcell(cell_t *c); void clearcell(cell_t *c);
void clearcell_exceptflags(cell_t *c, ...); void clearcell_exceptflags(cell_t *c, ...);
@ -120,7 +121,7 @@ cell_t *getrandomcell(map_t *map);
cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id); cell_t *getrandomcelloftype(map_t *map, enum CELLTYPE id);
int getrandomdir(int dirtype); int getrandomdir(int dirtype);
int getrandomdirexcept(int dirtype, int exception); int getrandomdirexcept(int dirtype, int exception);
cell_t *getrandomroomcell(map_t *map, int roomid); cell_t *getrandomroomcell(map_t *map, int roomid, int wantempty);
void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells); void getroomcells(map_t *m, int roomid, cell_t **retcell, int *ncells);
int getslipperyness(cell_t *c, object_t **slipob); int getslipperyness(cell_t *c, object_t **slipob);
cell_t *getstairdestination(object_t *o, int *madenewmap); cell_t *getstairdestination(object_t *o, int *madenewmap);

View File

@ -942,7 +942,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
targetmap = addmap(); targetmap = addmap();
createmap(targetmap, dlev, c->map->region, NULL, D_NONE, NULL); createmap(targetmap, dlev, c->map->region, NULL, D_NONE, NULL);
} }
targetcell = getrandomroomcell(targetmap, ANYROOM); targetcell = getrandomroomcell(targetmap, ANYROOM, WE_WALKABLE);
if (!targetcell) targetcell = getrandomcell(targetmap); if (!targetcell) targetcell = getrandomcell(targetmap);
while (!cellwalkable(NULL, targetcell, NULL)) { while (!cellwalkable(NULL, targetcell, NULL)) {
targetcell = getrandomadjcell(targetcell, WE_WALKABLE, B_ALLOWEXPAND); targetcell = getrandomadjcell(targetcell, WE_WALKABLE, B_ALLOWEXPAND);
@ -1634,6 +1634,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum
cf->val[1] = sizetonutrition(rf->val[0]); cf->val[1] = sizetonutrition(rf->val[0]);
} }
} }
// fill in animal subspecies
copyflag(o->flags, corpserace->flags, F_AVIAN);
copyflag(o->flags, corpserace->flags, F_CANINE);
copyflag(o->flags, corpserace->flags, F_EQUINE);
copyflag(o->flags, corpserace->flags, F_FELINE);
} else if (o->type->id == OT_MAP) { } else if (o->type->id == OT_MAP) {
region_t *srcregion; region_t *srcregion;
regiontype_t *dstrt = NULL; regiontype_t *dstrt = NULL;

30
spell.c
View File

@ -2067,9 +2067,9 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
// find a random empty cell here // find a random empty cell here
entry = getrandomroomcell(newmap, ANYROOM); entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
while (!cellwalkable(target, entry, NULL)) { while (!cellwalkable(target, entry, NULL)) {
entry = getrandomroomcell(newmap, ANYROOM); entry = getrandomroomcell(newmap, ANYROOM, WE_WALKABLE);
} }
// link the map to this lf // link the map to this lf
@ -2121,6 +2121,9 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else if (!lfhasflag(user, F_FLYING)) { } else if (!lfhasflag(user, F_FLYING)) {
if (isplayer(user)) msg("You are not flying, therefore cannot swoop."); if (isplayer(user)) msg("You are not flying, therefore cannot swoop.");
return B_TRUE; return B_TRUE;
} else if (!lfhasflagval(user, F_HASATTACK, OT_CLAWS, NA, NA, NULL)) {
if (isplayer(user)) msg("You need claws to perform a swoop attack.");
return B_TRUE;
} }
if (!targcell) { if (!targcell) {
@ -2189,7 +2192,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
// attack // attack
addflag(user->flags, F_FORCEATTACK, OT_CLAWS, NA, NA, "fromuseability");
attackcell(user, targcell, B_TRUE); attackcell(user, targcell, B_TRUE);
f = lfhasflagval(user, F_FORCEATTACK, OT_CLAWS, NA, NA, "fromuseability");
if (f) killflag(f);
// teleport back to initial pos // teleport back to initial pos
movelf(user, origcell); movelf(user, origcell);
@ -4891,7 +4897,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// determine type of mosnter // determine type of mosnter
if (getforcedspellrace(caster, spellid, buf)) { if (getforcedspellrace(caster, spellid, buf, NULL)) {
} else if ((power >= 7) && isplayer(caster)) { } else if ((power >= 7) && isplayer(caster)) {
// ask what kind of monster // ask what kind of monster
askstring("Create what kind of monster", '?', buf, BUFLEN, NULL); askstring("Create what kind of monster", '?', buf, BUFLEN, NULL);
@ -4952,13 +4958,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
ch = askchar("Teleport to the new vault", "yn","y", B_TRUE, B_FALSE); ch = askchar("Teleport to the new vault", "yn","y", B_TRUE, B_FALSE);
if (ch == 'y') { if (ch == 'y') {
int ntries = 0; int ntries = 0;
c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1); c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
if (!c || !cellwalkable(caster, c, NULL)) { if (!c || !cellwalkable(caster, c, NULL)) {
if (++ntries >= 10) { if (++ntries >= 10) {
msg("Oops, couldn't find a free space."); msg("Oops, couldn't find a free space.");
return B_FALSE; return B_FALSE;
} }
c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1); c = getrandomroomcell(caster->cell->map, caster->cell->map->nrooms-1, WE_WALKABLE);
} }
teleportto(caster, c, B_TRUE); teleportto(caster, c, B_TRUE);
return B_FALSE; return B_FALSE;
@ -8980,7 +8986,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else if ((spellid == OT_S_POLYMORPH) || (spellid == OT_S_SHAPESHIFT)) { } else if ((spellid == OT_S_POLYMORPH) || (spellid == OT_S_SHAPESHIFT)) {
race_t *r = NULL; race_t *r = NULL;
if (caster && (frompot || (spellid == OT_S_SHAPESHIFT))) { if (caster && (frompot || (spellid == OT_S_SHAPESHIFT))) {
target = caster; target = caster;
} else { } else {
@ -9007,7 +9012,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
//if ((caster == target) && getforcedspellrace(caster, spellid, buf)) { //if ((caster == target) && getforcedspellrace(caster, spellid, buf)) {
if (getforcedspellrace(target, spellid, buf)) { if (getforcedspellrace(target, spellid, buf, NULL)) {
r = findracebyname(buf); r = findracebyname(buf);
} else { } else {
if (spellid == OT_S_POLYMORPH) { if (spellid == OT_S_POLYMORPH) {
@ -10812,6 +10817,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
(spellid == OT_S_HECTASSERVANT) || (spellid == OT_S_HECTASSERVANT) ||
(spellid == OT_S_SUMMONDEMON)) { (spellid == OT_S_SUMMONDEMON)) {
int lifetime, nwant,ngot,successrate; int lifetime, nwant,ngot,successrate;
int tempcount = 0;
enum LFSIZE wantsize; enum LFSIZE wantsize;
enum RACECLASS wantrc; enum RACECLASS wantrc;
enum RACE wantrace = R_NONE; enum RACE wantrace = R_NONE;
@ -10887,7 +10893,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// override with forced race? // override with forced race?
if (caster && getforcedspellrace(caster, spellid, racename)) { if (caster && getforcedspellrace(caster, spellid, racename, &tempcount)) {
race_t *r; race_t *r;
r = findracebyname(racename); r = findracebyname(racename);
if (r) { if (r) {
@ -10896,6 +10902,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
wantsize = SZ_ANY; wantsize = SZ_ANY;
} }
} }
// override count
if (tempcount > 0) {
nwant = tempcount;
}
if (!pctchance(successrate)) { if (!pctchance(successrate)) {
fizzle(caster); fizzle(caster);
@ -11842,7 +11852,7 @@ enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school) {
return firstspell; return firstspell;
} }
char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr) { char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr, int *count) {
flag_t *f; flag_t *f;
// forced? // forced?
f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL); f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL);
@ -11850,7 +11860,7 @@ char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr) {
f = lfhasflagval(lf, F_CANCAST, spellid, NA, NA, NULL); f = lfhasflagval(lf, F_CANCAST, spellid, NA, NA, NULL);
} }
if (f) { if (f) {
texttospellopts(f->text, "race:", racestr, NULL); texttospellopts(f->text, "race:", racestr, "count:", count, NULL);
if (strlen(racestr)) { if (strlen(racestr)) {
return racestr; return racestr;
} }

View File

@ -9,7 +9,7 @@ enum SPELLSCHOOL findspellschoolbyname(char *buf);
void fizzle(lifeform_t *caster); void fizzle(lifeform_t *caster);
//int getiqreq(enum OBTYPE oid); //int getiqreq(enum OBTYPE oid);
enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school); enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school);
char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr); char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr, int *count);
int getmpcost(lifeform_t *lf, enum OBTYPE oid); int getmpcost(lifeform_t *lf, enum OBTYPE oid);
int getmrdiff(enum OBTYPE spellid, int power); int getmrdiff(enum OBTYPE spellid, int power);
enum OBTYPE getrandomspell(int maxlev); enum OBTYPE getrandomspell(int maxlev);

76
text.c
View File

@ -2304,6 +2304,7 @@ int texttospellopts(char *text, ... ) {
int nfilled = 0; int nfilled = 0;
char *validname[] = { char *validname[] = {
"pw:", "pw:",
"count:",
"dam:", "dam:",
"needgrab:", "needgrab:",
"range:", "range:",
@ -2313,6 +2314,7 @@ int texttospellopts(char *text, ... ) {
}; };
int argdefault[] = { int argdefault[] = {
0, 0,
1,
-1, // string -1, // string
B_FALSE, B_FALSE,
0, 0,
@ -2321,6 +2323,7 @@ int texttospellopts(char *text, ... ) {
-99, // last -99, // last
}; };
char argtype[] = { char argtype[] = {
'i',
'i', 'i',
's', 's',
'b', 'b',
@ -2336,50 +2339,51 @@ int texttospellopts(char *text, ... ) {
wantname = va_arg(args, char *); wantname = va_arg(args, char *);
if (wantname) writeto = va_arg(args, void *); if (wantname) writeto = va_arg(args, void *);
while (wantname) { // process this one while (wantname) { // process this one
int foundidx = -1,i; if (writeto) {
int foundidx = -1,i;
// validate 'wantname' - must match one of 'validname[]'
for (i = 0; validname[i]; i++) { // validate 'wantname' - must match one of 'validname[]'
if (streq(validname[i], wantname)) { for (i = 0; validname[i]; i++) {
foundidx = i; if (streq(validname[i], wantname)) {
break; foundidx = i;
break;
}
} }
} assert(foundidx != -1);
assert(foundidx != -1);
// blank our dest buffer // blank our dest buffer
if (argtype[foundidx] == 'i') { if (argtype[foundidx] == 'i') {
*((int *)writeto) = argdefault[foundidx]; *((int *)writeto) = argdefault[foundidx];
} else if (argtype[foundidx] == 'b') { } else if (argtype[foundidx] == 'b') {
*((int *)writeto) = argdefault[foundidx]; *((int *)writeto) = argdefault[foundidx];
} else if (argtype[foundidx] == 's') { } else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, ""); strcpy((char *)writeto, "");
} }
// look for 'wantname' within 'text' // look for 'wantname' within 'text'
for (p = text ; *p ; p++) { for (p = text ; *p ; p++) {
if (!strncmp(p, wantname, strlen(wantname)) ) { // found it! if (!strncmp(p, wantname, strlen(wantname)) ) { // found it!
char localval[BUFLEN]; char localval[BUFLEN];
char *valfull; char *valfull;
// extract value from text // extract value from text
// p will point to "pw:xxx;" // p will point to "pw:xxx;"
strcpy(localval, p + strlen(wantname)); // localval is "xxx;" strcpy(localval, p + strlen(wantname)); // localval is "xxx;"
valfull = strtok(localval, ";"); // valfull is "xxx" valfull = strtok(localval, ";"); // valfull is "xxx"
if (valfull) { if (valfull) {
// if it's there, write the value into 'writeto' // if it's there, write the value into 'writeto'
if (argtype[foundidx] == 'i') { if (argtype[foundidx] == 'i') {
*((int *)writeto) = atoi(valfull); *((int *)writeto) = atoi(valfull);
} else if (argtype[foundidx] == 'b') { } else if (argtype[foundidx] == 'b') {
*((int *)writeto) = atoi(valfull) ? B_TRUE : B_FALSE; *((int *)writeto) = atoi(valfull) ? B_TRUE : B_FALSE;
} else if (argtype[foundidx] == 's') { } else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, valfull); strcpy((char *)writeto, valfull);
}
nfilled++;
} }
nfilled++;
} }
} }
} }
// get next one // get next one
wantname = va_arg(args, char *); wantname = va_arg(args, char *);
if (wantname) writeto = va_arg(args, void *); if (wantname) writeto = va_arg(args, void *);