- [+] bones file error:" the lazy minotaur"
- [+] parserace needs to cope with lazy etc. - [+] make enum BEHAVIOUR - [+] make behaviour_t - [+] id - [+] name - [+] flags - [+] killbehaviours() - [+] addbehaviour() calls to define them - [+] cleanup callsk illbehaviours - [+] givebehaviour(lf, enum behaviour) - [+] getrandombehaviour() - [+] instead of checking f_behaviour->text, use findbehaviour(f->behaviour->val[0])->name - [+] parserace should handle these and populate wantflags appropriately. - [+] add disease incubation times (instead of getting them right away) - [+] OT_A_TRIP should be a lot harder on anything with more than 2 legs - [+] monster fleeing up/down stairs should anger hecta - [+] reduce short bow damage. - [+] add composite bow (between short & long) - [+] need magic/silver weapons to hurt MT_MAGIC things - [+] spirits should no lnoger be made of "MAGIC" - make them something else. flesh will do. - [+] in attack.c, noncorporeal check should also check for silver / magic weapons - [+] describe noncorporeal in io.c if knowledge is high enough. - [+] new spell casttype: ct_sounbased. deafness protects. - [+] Banshee (7hd, spirit, death keen at night) - blue / red 'p' - [+] death keen = sonic damage"midnight dirge" - [+] but only at night. - [+] harpy: 7hd - orange 'A' - [+] charm (via sound, so sonic prevents) - [+] 50% chance of bone club - [+] bite, claw
This commit is contained in:
parent
984999d912
commit
53ada31364
3
ai.c
3
ai.c
|
@ -2475,6 +2475,9 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
|
|||
if ((ot->id == OT_S_BLINDNESS) && isblind(victim)) {
|
||||
specificcheckok = B_FALSE;
|
||||
}
|
||||
if (ot->id == OT_S_DEATHKEEN) {
|
||||
if (!isnighttime()) specificcheckok = B_FALSE;
|
||||
}
|
||||
if ((ot->id == OT_S_DANCINGFLAME) || (ot->id == OT_S_CLEANSINGFIRE)) {
|
||||
int i;
|
||||
int found = B_FALSE;
|
||||
|
|
2
attack.c
2
attack.c
|
@ -824,7 +824,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
|
|||
if (lfhasflag(victim, F_NONCORPOREAL) &&
|
||||
!lfhasflag(lf, F_NONCORPOREAL) ) {
|
||||
// using a magical or blessed weapon? if so you're ok.
|
||||
if (wep && (ismagical(wep) || isblessed(wep)) ) {
|
||||
if (wep && (ismagical(wep) || isblessed(wep) || (wep->material->id == MT_SILVER)) ) {
|
||||
} else {
|
||||
weppassthrough = B_TRUE;
|
||||
hit = B_FALSE;
|
||||
|
|
204
data.c
204
data.c
|
@ -10,6 +10,7 @@
|
|||
#include "objects.h"
|
||||
#include "spell.h"
|
||||
|
||||
extern behaviour_t *firstbehaviour,*lastbehaviour;
|
||||
extern command_t *firstcommand,*lastcommand;
|
||||
extern option_t *firstoption,*lastoption;
|
||||
extern map_t *firstmap;
|
||||
|
@ -81,6 +82,34 @@ option_t *addoption(enum OPTION id, char *text, int def) {
|
|||
return a;
|
||||
}
|
||||
|
||||
behaviour_t *addbehaviour(enum BEHAVIOUR id, char *name) {
|
||||
behaviour_t *a;
|
||||
|
||||
assert(!findbehaviour(id));
|
||||
|
||||
// add to the end of the list
|
||||
if (firstbehaviour == NULL) {
|
||||
firstbehaviour = malloc(sizeof(behaviour_t));
|
||||
a = firstbehaviour;
|
||||
a->prev = NULL;
|
||||
} else {
|
||||
// go to end of list
|
||||
a = lastbehaviour;
|
||||
a->next = malloc(sizeof(behaviour_t));
|
||||
a->next->prev = a;
|
||||
a = a->next;
|
||||
}
|
||||
lastbehaviour = a;
|
||||
a->next = NULL;
|
||||
|
||||
// set props
|
||||
a->id = id;
|
||||
a->name = strdup(name);
|
||||
a->flags = addflagpile(NULL, NULL);
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
command_t *addcommand(enum COMMAND id, char ch, char *desc) {
|
||||
command_t *a;
|
||||
|
||||
|
@ -2969,6 +2998,13 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 4, NA, NULL);
|
||||
// l5
|
||||
addot(OT_S_DEATHKEEN, "midnight dirge", "Emits a dreadful wailing keen which instantly slays any who hear it.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell will only function at night.");
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 5, NA, NULL);
|
||||
addot(OT_S_HECTASSERVANT, "hecta's hand", "Summons an enormous skeletal hand to drag foes to their doom. BEWARE: the hand will attack anything living, including the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
|
||||
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
||||
|
@ -7689,6 +7725,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_ATTREQ, A_STR, 50, 60, "10");
|
||||
addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OBATTACKDELAY, 110, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_CANBEDIFFMAT, MT_BONE, 33, NA, NULL);
|
||||
addot(OT_GREATCLUB, "great club", "An enormous, very heavy, blunt instrument to hit things with.", MT_STONE, 15, OC_WEAPON, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_CAVE, 50, NA, NULL);
|
||||
|
@ -7813,7 +7850,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_RARITY, H_SWAMP, 100, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 2, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_DART, NA, NA, NULL);
|
||||
|
@ -7828,14 +7865,28 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_RARITY, H_CAVE, 100, RR_COMMON, NULL);
|
||||
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOCAPACITY, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RELOADTURNS, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTREQ, A_STR, 45, NA, NULL);
|
||||
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addot(OT_COMPOSITEBOW, "composite bow", "A short bow, smaller than a longbow but more powerful than a shortbow.", MT_WOOD, 7, OC_WEAPON, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL);
|
||||
addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL);
|
||||
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 6, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOCAPACITY, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RELOADTURNS, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTREQ, A_STR, 45, NA, NULL);
|
||||
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ATTREQ, A_STR, 65, NA, NULL);
|
||||
|
||||
addot(OT_CROSSBOW, "crossbow", "A standard crossbow. Very powerful, but slow to reload and needs high strength to use.", MT_WOOD, 8, OC_WEAPON, SZ_MEDIUM);
|
||||
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
|
||||
|
@ -7844,7 +7895,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 10, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 6, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_BOLT, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOCAPACITY, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RELOADTURNS, 2, NA, NA, NULL);
|
||||
|
@ -7857,7 +7908,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 7, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_BOLT, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOCAPACITY, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RELOADTURNS, 1, NA, NA, NULL);
|
||||
|
@ -7869,7 +7920,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 8, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 8, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOCAPACITY, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RELOADTURNS, 1, NA, NA, NULL);
|
||||
|
@ -7898,7 +7949,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_TWOHANDED, SZ_HUMAN, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 20, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 2, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_BULLET, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOCAPACITY, 2, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RELOADTURNS, 3, NA, NA, NULL);
|
||||
|
@ -7910,7 +7961,7 @@ void initobjects(void) {
|
|||
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_FIRESPEED, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RANGE, 4, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOOB, OT_STONE, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_AMMOCAPACITY, 1, NA, NA, NULL);
|
||||
addflag(lastot->flags, F_RELOADTURNS, 1, NA, NA, NULL);
|
||||
|
@ -8069,6 +8120,28 @@ void initrace(void) {
|
|||
skill_t *sk;
|
||||
int i;
|
||||
|
||||
// behaviours
|
||||
addbehaviour(BH_INSANE, "insane");
|
||||
addflag(lastbehaviour->flags, F_TERRITORIAL, 2, NA , NA, NULL);
|
||||
addbehaviour(BH_HUNGRY, "hungry");
|
||||
addflag(lastbehaviour->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS , NA, NULL);
|
||||
addbehaviour(BH_TIMID, "timid");
|
||||
// givebehaviour() will also halve morale
|
||||
addflag(lastbehaviour->flags, F_FLEEONDAM, B_TRUE, NA , NA, NULL);
|
||||
addbehaviour(BH_DRUGGED, "drugged");
|
||||
// givebehaviour() will also remove fleeonxxx flags
|
||||
addflag(lastbehaviour->flags, F_NOFLEE, B_TRUE, NA , NA, NULL);
|
||||
addbehaviour(BH_DRUNK, "drunk");
|
||||
// givebehaviour() will add f_drunk rnd(2,5)
|
||||
addbehaviour(BH_DETERMINED, "determined");
|
||||
addflag(lastbehaviour->flags, F_FOLLOWTIME, (DEF_AIFOLLOWTIME*2), NA, NA, NULL);
|
||||
addbehaviour(BH_LAZY, "lazy");
|
||||
addflag(lastbehaviour->flags, F_FOLLOWTIME, (DEF_AIFOLLOWTIME/4), NA, NA, NULL);
|
||||
addbehaviour(BH_MUSCLED, "muscled");
|
||||
// givebehaviour() will modify maxhp
|
||||
addbehaviour(BH_SCRAWNY, "scrawny");
|
||||
// givebehaviour() will modify maxhp
|
||||
|
||||
// unique monsters
|
||||
addrace(R_JAILER, "jailer", 110, '@', C_MAGENTA, MT_FLESH, RC_HUMANOID, "Jailers are generally known for their surplus of brawn and utter lack of brains. This one is no different.");
|
||||
setbodytype(lastrace, BT_HUMANOID);
|
||||
|
@ -9237,7 +9310,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_CANCAST, OT_S_PARALYZE, NA, NA, "pw:2;");
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 8, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "gazes");
|
||||
addflag(lastrace->flags, F_CASTTYPE, CT_GAZE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTTYPE, OT_NONE, CT_GAZE, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_EXPERT, NA, NULL);
|
||||
|
@ -9476,9 +9549,10 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_CANCAST, OT_S_PLANTWALK, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANCAST, OT_S_CHARM, NA, NA, "pw:1;");
|
||||
addflag(lastrace->flags, F_CASTCHANCE, 70, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTTYPE, OT_S_CHARM, CT_GAZE, NA, NULL);
|
||||
//addflag(lastrace->flags, F_CANCAST, OT_S_SLEEP, 10, 10, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_PLANTWALK, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_CHARM, NA, B_APPENDYOU, "beckons");
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_CHARM, NA, B_APPENDYOU, "smiles seductively and beckons");
|
||||
addflag(lastrace->flags, F_WANTSOBFLAG, F_GEM, B_COVETS, NA, NULL);
|
||||
addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "shouts^a shout");
|
||||
|
@ -9591,7 +9665,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_CASTCHANCE, 50, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANCAST, OT_S_DISPERSAL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANCAST, OT_S_GRAVBOOST, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTTYPE, CT_GAZE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTTYPE, OT_NONE, CT_GAZE, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "gazes");
|
||||
addflag(lastrace->flags, F_TREMORSENSE, 5, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SEEINDARK, UNLIMITED, NA, NA, NULL);
|
||||
|
@ -9628,7 +9702,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "bellows^a bellow");
|
||||
addflag(lastrace->flags, F_CANCAST, OT_S_STUN, 5, 5, "pw:1;");
|
||||
addflag(lastrace->flags, F_CASTTYPE, CT_GAZE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTTYPE, OT_NONE, CT_GAZE, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_STUN, NA, B_APPENDYOU, "gazes");
|
||||
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL);
|
||||
|
@ -10244,6 +10318,7 @@ void initrace(void) {
|
|||
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);
|
||||
addbodypart(lastrace, BP_WINGS, 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);
|
||||
|
@ -10286,6 +10361,7 @@ void initrace(void) {
|
|||
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);
|
||||
addbodypart(lastrace, BP_WINGS, 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, "");
|
||||
|
@ -10611,6 +10687,7 @@ void initrace(void) {
|
|||
addrace(R_MANTICORE, "manticore", 80, 'm', C_RED, MT_FLESH, RC_MAGIC, "Horrific beasts with the body of a lion, bat-like winds and a human head. The tip of their tail contains a mass of iron spikes.");
|
||||
setbodytype(lastrace, BT_QUADRAPED);
|
||||
addbodypart(lastrace, BP_TAIL, NULL);
|
||||
addbodypart(lastrace, BP_WINGS, 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);
|
||||
|
@ -13139,6 +13216,42 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_WALKVERB, NA, NA, NA, "hop");
|
||||
|
||||
addrace(R_HARPY, "harpy", 60, 'A', C_ORANGE, MT_FLESH, RC_HUMANOID, "Hideous humanoid females, with the lower body and wings of a vulture."); // 'A' for Avian
|
||||
setbodytype(lastrace, BT_HUMANOID);
|
||||
addbodypart(lastrace, BP_WINGS, NULL);
|
||||
setbodypartname(lastrace, BP_HANDS, "talons");
|
||||
setbodypartname(lastrace, BP_RIGHTFINGER, "right claw");
|
||||
setbodypartname(lastrace, BP_LEFTFINGER, "left claw");
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_RARE, NULL);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_GTAVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_LOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, 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, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MAXATTACKS, 2, 2, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
|
||||
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 6, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain");
|
||||
addflag(lastrace->flags, F_AVIAN, 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_STARTOB, 50, NA, NA, "bone club");
|
||||
addflag(lastrace->flags, F_CANCAST, OT_S_CHARM, 15, 15, "pw:5;");
|
||||
addflag(lastrace->flags, F_CASTTYPE, OT_S_CHARM, CT_SOUNDBASED, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_CHARM, NA, B_APPENDYOU, "sings a seductive song");
|
||||
|
||||
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;
|
||||
|
@ -13796,7 +13909,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^slithering");
|
||||
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 2, NA, "hisses^hissing");
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "spits");
|
||||
addflag(lastrace->flags, F_CASTTYPE, CT_EYESPIT, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTTYPE, OT_NONE, CT_EYESPIT, NA, NULL);
|
||||
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_BLINDNESS, 4, 4, "pw:3;range:2;");
|
||||
|
@ -14213,7 +14326,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addrace(R_WORMGLUT, "glutwyrm", 25, 'W', C_MAGENTA, MT_FLESH, RC_DRAGON, "Gigantic wyrms who have become so obese over the centuries that they have evolved without wings. They swallow their prey whole, slowly digesting their still living bodies.");
|
||||
addrace(R_WORMGLUT, "glutwyrm", 25, 'W', C_MAGENTA, MT_FLESH, RC_DRAGON, "Gigantic wyrms who have become so obese over the centuries that they have evolved to be wingless. They swallow their prey whole, slowly digesting their still living bodies.");
|
||||
addbodypart(lastrace, BP_HEAD, NULL);
|
||||
addbodypart(lastrace, BP_TAIL, NULL);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
|
@ -15529,6 +15642,37 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_EATCONFER, F_DTRESIST, DT_COLD, NA, "15");
|
||||
|
||||
addrace(R_BANSHEE, "banshee", 50, 'p', C_BLUE, MT_FLESH, RC_UNDEAD, "A floating phantom, with wild unbrushed hair.");
|
||||
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_IQ, AT_HIGH, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_AVERAGE, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CON, AT_LOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_WIS, AT_LOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_CHA, AT_VLOW, NA, NULL);
|
||||
addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL);
|
||||
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_VERYRARE, NULL);
|
||||
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_HITDICE, 7, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_TR, 7, 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_HASATTACK, OT_TOUCHNECROTIC, 8, NA, NULL);
|
||||
addflag(lastrace->flags, F_CANWILL, OT_S_DEATHKEEN, 100, 100, NULL);
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_DEATHKEEN, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_DTIMMUNE, DT_ELECTRIC, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_INDUCEFEAR, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SEEINDARK, 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_NONCORPOREAL, B_TRUE, NA, NA, NULL);
|
||||
|
||||
addrace(R_GHAST, "ghast", 50, 'Z', C_BOLDGREEN, MT_FLESH, RC_UNDEAD, "A more slender and ghost-like form of ghoul. Ghasts are cunning and deadly, and possess a paralyzing touch.");
|
||||
setbodytype(lastrace, BT_HUMANOID);
|
||||
setbodypartname(lastrace, BP_HANDS, "claws");
|
||||
|
@ -15559,7 +15703,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL);
|
||||
|
||||
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
|
||||
addrace(R_GHOST, "ghost", 50, 'p', C_GREY, MT_FLESH, 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);
|
||||
addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL);
|
||||
|
@ -15691,7 +15835,7 @@ void initrace(void) {
|
|||
addflag(lastrace->flags, F_HITCONFERVALS, P_ROT, 3, NA, NULL); // strong!
|
||||
addflag(lastrace->flags, F_CANCAST, OT_S_FEAR, 50, 50, "pw:3;");
|
||||
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FEAR, NA, B_APPENDYOU, "gazes");
|
||||
addflag(lastrace->flags, F_CASTTYPE, CT_GAZE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_CASTTYPE, OT_NONE, CT_GAZE, NA, NULL);
|
||||
addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
|
||||
addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL);
|
||||
|
@ -16306,7 +16450,7 @@ void initskills(void) {
|
|||
addskilldesc(SK_FIRSTAID, PR_INEPT, "- Determines how long poison effects will last.", B_FALSE);
|
||||
addskilldesc(SK_FIRSTAID, PR_NOVICE, "+2 hit points per level.", B_FALSE);
|
||||
addskilldesc(SK_FIRSTAID, PR_BEGINNER, "+4 hit points per level.", B_FALSE);
|
||||
addskilldesc(SK_FIRSTAID, PR_BEGINNER, "You now notice the onset of poison.", B_TRUE);
|
||||
addskilldesc(SK_FIRSTAID, PR_BEGINNER, "You now recognise the onset of poison or sickness.", B_TRUE);
|
||||
addskilldesc(SK_FIRSTAID, PR_ADEPT, "+6 hit points per level.", B_FALSE);
|
||||
addskilldesc(SK_FIRSTAID, PR_ADEPT, "^gYou can now recognise when poison is potentially fatal.^n", B_TRUE);
|
||||
addskilldesc(SK_FIRSTAID, PR_SKILLED, "+8 hit points per level.", B_FALSE);
|
||||
|
@ -16619,6 +16763,32 @@ void killoption(option_t *w) {
|
|||
}
|
||||
}
|
||||
|
||||
void killbehaviour(behaviour_t *b) {
|
||||
behaviour_t *nextone, *lastone;
|
||||
|
||||
// free mem
|
||||
if (b->name) free(b->name);
|
||||
killflagpile(b->flags);
|
||||
|
||||
// remove from list
|
||||
nextone = b->next;
|
||||
if (nextone != NULL) {
|
||||
nextone->prev = b->prev;
|
||||
} else { /* last */
|
||||
lastbehaviour = b->prev;
|
||||
}
|
||||
|
||||
if (b->prev == NULL) {
|
||||
/* first */
|
||||
nextone = b->next;
|
||||
free(firstbehaviour);
|
||||
firstbehaviour = nextone;
|
||||
} else {
|
||||
lastone = b->prev;
|
||||
free (lastone->next );
|
||||
lastone->next = nextone;
|
||||
}
|
||||
}
|
||||
|
||||
void killcommand(command_t *cmd) {
|
||||
command_t *nextone, *lastone;
|
||||
|
|
2
data.h
2
data.h
|
@ -2,6 +2,7 @@
|
|||
|
||||
void addbonustext(flagpile_t *fp, enum FLAG fid, char *text);
|
||||
option_t *addoption(enum OPTION id, char *text, int def);
|
||||
behaviour_t *addbehaviour(enum BEHAVIOUR id, char *name);
|
||||
command_t *addcommand(enum COMMAND id, char c, char *desc);
|
||||
void initcommands(void);
|
||||
void initjobs(void);
|
||||
|
@ -10,6 +11,7 @@ void initoptions(void);
|
|||
void initrace(void);
|
||||
void initraceclasses(void);
|
||||
void initskills(void);
|
||||
void killbehaviour(behaviour_t *b);
|
||||
void killcommand(command_t *cmd);
|
||||
void killoption(option_t *o);
|
||||
void make_basic_shop(flagpile_t *fp);
|
||||
|
|
35
defs.h
35
defs.h
|
@ -322,6 +322,19 @@
|
|||
|
||||
#define MAXDIR_MAP 15
|
||||
|
||||
enum BEHAVIOUR {
|
||||
BH_NONE = 0,
|
||||
BH_INSANE,
|
||||
BH_HUNGRY,
|
||||
BH_TIMID,
|
||||
BH_DRUGGED,
|
||||
BH_DRUNK,
|
||||
BH_DETERMINED,
|
||||
BH_LAZY,
|
||||
BH_MUSCLED,
|
||||
BH_SCRAWNY,
|
||||
};
|
||||
|
||||
// relative directions
|
||||
enum RELATIVEDIR {
|
||||
RD_FORWARDS,
|
||||
|
@ -489,7 +502,8 @@ enum COLOUR {
|
|||
enum CASTTYPE {
|
||||
CT_NORMAL = 0,
|
||||
CT_GAZE,
|
||||
CT_EYESPIT
|
||||
CT_EYESPIT,
|
||||
CT_SOUNDBASED,
|
||||
};
|
||||
|
||||
enum DRAINTYPE {
|
||||
|
@ -1123,6 +1137,7 @@ enum RACE {
|
|||
R_DOGWAR,
|
||||
R_ELEPHANT,
|
||||
R_GYRFALCON,
|
||||
R_HARPY,
|
||||
R_HAWK,
|
||||
R_HAWKYOUNG,
|
||||
R_HAWKBLOOD,
|
||||
|
@ -1191,6 +1206,7 @@ enum RACE {
|
|||
R_LINGTRAPPER,
|
||||
R_QUASIT,
|
||||
// undead
|
||||
R_BANSHEE,
|
||||
R_GHAST,
|
||||
R_GHOST,
|
||||
R_GHOUL,
|
||||
|
@ -1514,6 +1530,7 @@ enum OBTYPE {
|
|||
OT_S_BLIGHT,
|
||||
OT_S_COMMANDUNDEAD,
|
||||
OT_S_CURSE,
|
||||
OT_S_DEATHKEEN,
|
||||
OT_S_DRAINLIFE,
|
||||
OT_S_FEAR,
|
||||
OT_S_FLAYFLESH,
|
||||
|
@ -2162,6 +2179,7 @@ enum OBTYPE {
|
|||
// projectile weapons
|
||||
OT_BLOWGUN,
|
||||
OT_BOW,
|
||||
OT_COMPOSITEBOW,
|
||||
OT_CROSSBOW,
|
||||
OT_CROSSBOWHAND,
|
||||
OT_LONGBOW,
|
||||
|
@ -2243,6 +2261,7 @@ enum DEPTH {
|
|||
};
|
||||
|
||||
enum NOISETYPE {
|
||||
N_DEATHKEEN,
|
||||
N_GETANGRY,
|
||||
N_WALK,
|
||||
N_FLY,
|
||||
|
@ -2835,8 +2854,7 @@ enum FLAG {
|
|||
// if you won by becoming a god, v1 = godid
|
||||
// if you won by becoming a demigod, v1 = godid
|
||||
// text = copied F_GODFLAG text from god.
|
||||
F_BEHAVIOUR, // textual field describing special behaviour for this
|
||||
// lf
|
||||
F_BEHAVIOUR, // v0 = enum behaviour.
|
||||
F_RNDSPELLCOUNT, // this monster starts with v0 random spells.
|
||||
// needs to also have either f_rndspellschool OR
|
||||
// f_rndspellposs.
|
||||
|
@ -3300,8 +3318,8 @@ enum FLAG {
|
|||
F_CONFUSED, // move randomly about
|
||||
F_DEAF, // cannot hear
|
||||
F_NEEDOBFORSPELLS, // lf can only cast spells if it has object v0
|
||||
F_CASTTYPE, // lf uses enum CASTTYPE v0 for spells
|
||||
// optional v1 is colour for casttype-based animations
|
||||
F_CASTTYPE, // lf uses enum CASTTYPE v1 for spellid v0. (ot_none=all)
|
||||
// optional v2 is colour for casttype-based animations
|
||||
// (ie. spit spells)
|
||||
F_CAFFEINATED, // can't sleep.
|
||||
F_CANEATRAW, // lf can eat raw food with no issues
|
||||
|
@ -3822,6 +3840,13 @@ enum COMMAND {
|
|||
};
|
||||
|
||||
|
||||
typedef struct behaviour_s {
|
||||
enum BEHAVIOUR id;
|
||||
char *name;
|
||||
struct flagpile_s *flags;
|
||||
struct behaviour_s *next, *prev;
|
||||
} behaviour_t;
|
||||
|
||||
typedef struct npcname_s {
|
||||
char *name;
|
||||
int valid;
|
||||
|
|
13
io.c
13
io.c
|
@ -1613,11 +1613,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
|
|||
case F_POISONED:
|
||||
pt = findpoisontype(f->val[0]);
|
||||
if (isplayer(lf)) {
|
||||
if (streq(pt->desc, "Sick")) {
|
||||
if (streq(pt->desc, "Sick") || (pt->id == P_FOOD) || (pt->id == P_FOODBAD)) {
|
||||
msg("^%cYou have contracted %s.", getlfcol(lf, CC_VBAD), pt->name);
|
||||
} else {
|
||||
msg("^%cYou are sick with %s.", getlfcol(lf, CC_VBAD), pt->name);
|
||||
}
|
||||
more();
|
||||
} else {
|
||||
msg("^%c%s looks very sick.", getlfcol(lf, CC_VBAD), lfname);
|
||||
}
|
||||
|
@ -2266,15 +2267,6 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
|
|||
case F_FRIENDLY:
|
||||
msg("%s no longer looks quite so friendly!", lfname);
|
||||
break;
|
||||
case F_INCUBATING:
|
||||
if (isplayer(lf)) {
|
||||
poisontype_t *pt;
|
||||
pt = findpoisontype(f->val[0]);
|
||||
if (pt) {
|
||||
msg("^%cYour body has fought off %s.", getlfcol(lf, CC_GOOD), pt->name);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case F_POISONED:
|
||||
msg("^%c%s %s less sick now.^n", getlfcol(lf, CC_VGOOD), lfname, isplayer(lf) ? "feel" : "looks");
|
||||
donesomething = B_TRUE;
|
||||
|
@ -7174,6 +7166,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
|
|||
case F_LEVITATING: if (lorelev >= PR_NOVICE) sprintf(buf, "Can levitate at will"); break;
|
||||
case F_MEDITATES: if (lorelev >= PR_ADEPT) sprintf(buf, "Meditates to retain awareness while sleeping."); break;
|
||||
case F_MPMOD: if (f->val[0] > 0) sprintf(buf, "+%d Mana", f->val[0]); break;
|
||||
case F_NONCORPOREAL: if (lorelev >= PR_NOVICE) sprintf(buf, "Only affected by blessed, magic or silver weapons"); break;
|
||||
case F_NOSLEEP: if (lorelev >= PR_BEGINNER) sprintf(buf, "Does not sleep"); break;
|
||||
case F_PHALANX: if (lorelev >= PR_ADEPT) sprintf(buf, "Gains extra defence when in a pack."); break;
|
||||
case F_PHOTOMEM: sprintf(buf, "Photographic memory"); break;
|
||||
|
|
205
lf.c
205
lf.c
|
@ -32,6 +32,7 @@ extern int enteringmap;
|
|||
extern map_t *firstmap;
|
||||
extern race_t *firstrace, *lastrace;
|
||||
extern raceclass_t *firstraceclass, *lastraceclass;
|
||||
extern behaviour_t *firstbehaviour, *lastbehaviour;
|
||||
extern job_t *firstjob, *lastjob;
|
||||
extern skill_t *firstskill, *lastskill;
|
||||
extern poisontype_t *firstpoisontype,*lastpoisontype;
|
||||
|
@ -835,6 +836,7 @@ int caneat(lifeform_t *lf, object_t *o) {
|
|||
|
||||
|
||||
int canhaverandombehaviour(lifeform_t *lf) {
|
||||
if (lfhasflag(lf, F_BEHAVIOUR)) return B_FALSE;
|
||||
if (isundead(lf)) return B_FALSE;
|
||||
if (isgod(lf)) return B_FALSE;
|
||||
if (getraceclass(lf) == RC_HUMANOID) {
|
||||
|
@ -1609,11 +1611,14 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
int power;
|
||||
int spellblessed = B_UNCURSED;
|
||||
objecttype_t *sp;
|
||||
enum CASTTYPE casttype = CT_NORMAL;
|
||||
|
||||
|
||||
if (fromob) {
|
||||
spellblessed = fromob->blessed;
|
||||
power = getobspellpower(fromob, lf);
|
||||
} else {
|
||||
flag_t *ctf;
|
||||
spellblessed = B_UNCURSED;
|
||||
power = getspellpower(lf, sid);
|
||||
// check whether we _can_ cast it.
|
||||
|
@ -1682,6 +1687,14 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
return B_TRUE;
|
||||
}
|
||||
}
|
||||
ctf = lfhasflagval(lf, F_CASTTYPE, sid, NA, NA, NULL);
|
||||
if (!ctf) {
|
||||
ctf = lfhasflagval(lf, F_CASTTYPE, OT_NONE, NA, NA, NULL);
|
||||
}
|
||||
if (ctf) {
|
||||
casttype = ctf->val[1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
sp = findot(sid);
|
||||
|
@ -1808,7 +1821,14 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
|
||||
// announce
|
||||
if (!isplayer(lf) && !fromob) {
|
||||
int doannounce = B_FALSE;
|
||||
|
||||
if (cansee(player, lf)) {
|
||||
doannounce = B_TRUE;
|
||||
} else if ((casttype == CT_SOUNDBASED) && canhear(player, lf->cell, SV_TALK)) {
|
||||
doannounce = B_TRUE;
|
||||
}
|
||||
if (doannounce) {
|
||||
char lfname[BUFLEN];
|
||||
char whattosay[BUFLEN];
|
||||
getlfname(lf, lfname);
|
||||
|
@ -1851,23 +1871,28 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
|
||||
// eye protection will stop some spells!
|
||||
if (targcell && targcell->lf) {
|
||||
flag_t *casttype;
|
||||
lifeform_t *victim;
|
||||
victim = targcell->lf;
|
||||
casttype = lfhasflag(lf, F_CASTTYPE);
|
||||
if (casttype) {
|
||||
object_t *protob = NULL;
|
||||
switch (casttype->val[0]) {
|
||||
case CT_EYESPIT:
|
||||
protob = getarmour(victim, BP_EYES);
|
||||
break;
|
||||
case CT_GAZE:
|
||||
protob = eyesshaded(victim);
|
||||
break;
|
||||
default:
|
||||
protob = NULL;
|
||||
break;
|
||||
}
|
||||
int protected = B_FALSE;
|
||||
object_t *protob = NULL;
|
||||
switch (casttype) {
|
||||
case CT_EYESPIT:
|
||||
protob = getarmour(victim, BP_EYES);
|
||||
if (protob) protected = B_TRUE;
|
||||
break;
|
||||
case CT_GAZE:
|
||||
protob = eyesshaded(victim);
|
||||
if (protob) protected = B_TRUE;
|
||||
break;
|
||||
case CT_SOUNDBASED:
|
||||
if (isdeaf(victim)) protected = B_TRUE;
|
||||
break;
|
||||
default:
|
||||
protob = NULL;
|
||||
protected = B_FALSE;
|
||||
break;
|
||||
}
|
||||
if (protected) {
|
||||
if (protob) {
|
||||
if (isplayer(victim)) {
|
||||
char gbuf[BUFLEN];
|
||||
|
@ -1879,8 +1904,16 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
|
|||
getlfname(victim, lfname);
|
||||
msg("%s%s %s protects it.", lfname, getpossessive(lfname), noprefix(gbuf) );
|
||||
}
|
||||
return B_FALSE;
|
||||
} else {
|
||||
if (isplayer(victim)) {
|
||||
msg("You are unaffected.");
|
||||
} else if (cansee(player, victim)) {
|
||||
char lfname[BUFLEN];
|
||||
getlfname(victim, lfname);
|
||||
msg("%s is unaffected.", lfname);
|
||||
}
|
||||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2549,6 +2582,24 @@ int countinnateattacks(lifeform_t *lf) {
|
|||
}
|
||||
|
||||
|
||||
int countlegs(lifeform_t *lf) {
|
||||
enum BODYPART bp;
|
||||
int legs = 0;
|
||||
for (bp = 0; bp <= MAXBODYPARTS; bp++) {
|
||||
if (hasbp(lf, bp)) {
|
||||
switch (bp) {
|
||||
case BP_LEGS:
|
||||
case BP_FRONTLEGS:
|
||||
case BP_BACKLEGS:
|
||||
legs += 2;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return legs;
|
||||
}
|
||||
|
||||
int countnearbyallies(lifeform_t *lf) {
|
||||
lifeform_t *l;
|
||||
int count = 0;
|
||||
|
@ -5341,6 +5392,14 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) {
|
|||
}
|
||||
}
|
||||
|
||||
behaviour_t *findbehaviour(enum BEHAVIOUR bid) {
|
||||
behaviour_t *b;
|
||||
for (b = firstbehaviour ; b ; b = b->next) {
|
||||
if (b->id == bid) return b;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
job_t *findjob(enum JOB jobid) {
|
||||
job_t *j;
|
||||
for (j = firstjob ; j ; j = j->next) {
|
||||
|
@ -5613,7 +5672,8 @@ int flee(lifeform_t *lf) {
|
|||
if (isplayer(thisone)) {
|
||||
pleasegodmaybe(R_GODMERCY, 5);
|
||||
if ((lf->lastdamlf == player->id) || cansee(player, lf)) {
|
||||
// ie. only if the player
|
||||
// ie. only if the player saw them run away, or has already
|
||||
// attacked them.
|
||||
angergodmaybe(R_GODDEATH, 10, GA_MERCY);
|
||||
}
|
||||
}
|
||||
|
@ -5684,6 +5744,15 @@ int flee(lifeform_t *lf) {
|
|||
if (stairs && !lfhasflag(lf, F_NOSTAIRS)) {
|
||||
if (db) dblog("%s - trying to flee via %s", lfname, stairs->type->name);
|
||||
if (!usestairs(lf, stairs, B_TRUE, B_TRUE)) {
|
||||
// success
|
||||
if (isplayer(fleefrom)) {
|
||||
pleasegodmaybe(R_GODMERCY, 5);
|
||||
if ((lf->lastdamlf == player->id) || cansee(player, lf)) {
|
||||
// ie. only if the player saw them run away, or has already
|
||||
// attacked them.
|
||||
angergodmaybe(R_GODDEATH, 10, GA_MERCY);
|
||||
}
|
||||
}
|
||||
return B_TRUE;
|
||||
}
|
||||
if (db) dblog("%s - failed to flee via %s", lfname, stairs->type->name);
|
||||
|
@ -7833,6 +7902,11 @@ int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, flag_t *noiseflag,
|
|||
}
|
||||
return B_FALSE;
|
||||
}
|
||||
} else if (nid == N_DEATHKEEN) {
|
||||
if (volume) *volume = SV_TALK;
|
||||
if (heartext) strcpy(heartext, "the dread wailing of death!");
|
||||
if (seetext) strcpy(seetext, "wails with the power of death!");
|
||||
return B_FALSE;
|
||||
} else if (nid == N_SONICBOLT) {
|
||||
if (volume) *volume = 5;
|
||||
if (heartext) strcpy(heartext, "a ear-splitting burst of sound!");
|
||||
|
@ -8543,8 +8617,12 @@ char *real_getlfname(lifeform_t *lf, char *buf, lifeform_t *usevis, int showall,
|
|||
if (dobehaviour) {
|
||||
f = lfhasflag(lf, F_BEHAVIOUR);
|
||||
if (f) {
|
||||
strcat(descstring, f->text);
|
||||
strcat(descstring, " ");
|
||||
behaviour_t *b;
|
||||
b = findbehaviour(f->val[0]);
|
||||
if (b) {
|
||||
strcat(descstring, b->name);
|
||||
strcat(descstring, " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8961,6 +9039,29 @@ object_t *getrandomarmour(lifeform_t *lf, lifeform_t *attacker) {
|
|||
return o;
|
||||
}
|
||||
|
||||
enum BEHAVIOUR getrandombehaviour(void) {
|
||||
behaviour_t *b;
|
||||
int numb = 0,sel;
|
||||
enum BEHAVIOUR selb = BH_NONE;
|
||||
for (b = firstbehaviour ; b ; b = b->next) {
|
||||
numb++;
|
||||
}
|
||||
sel = rnd(0,numb-1);
|
||||
numb = 0;
|
||||
for (b = firstbehaviour ; b ; b = b->next) {
|
||||
if (numb == sel) {
|
||||
selb = b->id;
|
||||
break;
|
||||
}
|
||||
numb++;
|
||||
}
|
||||
if (selb == BH_NONE) {
|
||||
// should never happen!
|
||||
assert("getrandombehaviour() failed!" == 0);
|
||||
}
|
||||
return selb;
|
||||
}
|
||||
|
||||
// pick a random major body part
|
||||
// ie. head, body, arms/hands, legs, wings, tail
|
||||
enum BODYPART getrandomcorebp(lifeform_t *lf, lifeform_t *attacker) {
|
||||
|
@ -9758,6 +9859,39 @@ long getxpforlev(int level) {
|
|||
return needxp;
|
||||
}
|
||||
|
||||
void givebehaviour(lifeform_t *lf, enum BEHAVIOUR bid) {
|
||||
behaviour_t *b;
|
||||
flag_t *f;
|
||||
b = findbehaviour(bid);
|
||||
if (!b) return;
|
||||
addflag(lf->flags, F_BEHAVIOUR, bid, NA, NA, NULL);
|
||||
copyflags(lf->flags, b->flags, FROMRACE);
|
||||
switch (bid) {
|
||||
case BH_TIMID:
|
||||
f = lfhasflag(lf, F_MORALE);
|
||||
if (f) {
|
||||
f->val[0] /= 2;
|
||||
}
|
||||
break;
|
||||
case BH_DRUGGED:
|
||||
killflagsofid(lf->flags, F_FLEEONDAM);
|
||||
killflagsofid(lf->flags, F_FLEEONHPPCT);
|
||||
break;
|
||||
case BH_DRUNK:
|
||||
addflag(lf->flags, F_DRUNK, rnd(2,5), NA, NA, NULL);
|
||||
case BH_MUSCLED:
|
||||
lf->maxhp = pctof(rnd(125,200), lf->maxhp); // 25-100% more hp
|
||||
lf->hp = lf->maxhp;
|
||||
break;
|
||||
case BH_SCRAWNY:
|
||||
lf->maxhp = pctof(rnd(50,75), lf->maxhp); // 25-50% less hp
|
||||
limit(&(lf->maxhp), 1, NA);
|
||||
lf->hp = lf->maxhp;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void givejob(lifeform_t *lf, enum JOB jobid) {
|
||||
job_t *j;
|
||||
flag_t *f;
|
||||
|
@ -11601,11 +11735,13 @@ flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int
|
|||
}
|
||||
|
||||
// returns radius of light produces
|
||||
int lfproduceslight(lifeform_t *lf) {
|
||||
int lfproduceslight(lifeform_t *lf, object_t **fromwhat) {
|
||||
int temp = 0;
|
||||
int radius = 0;
|
||||
object_t *o;
|
||||
|
||||
if (fromwhat) *fromwhat = NULL;
|
||||
|
||||
// lf producing light itself?
|
||||
sumflags(lf->flags, F_PRODUCESLIGHT, &temp, NULL, NULL);
|
||||
if (temp) radius = temp;
|
||||
|
@ -11616,6 +11752,7 @@ int lfproduceslight(lifeform_t *lf) {
|
|||
temp = obproduceslight(o);
|
||||
if (temp > radius) {
|
||||
radius = temp;
|
||||
if (fromwhat) *fromwhat = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15585,7 +15722,8 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
|
|||
if (isdead(noisemaker)) {
|
||||
msg("The dying %s %s.", noprefix(lfname), realseetext);
|
||||
} else {
|
||||
msg("%s %s.", lfname, realseetext);
|
||||
msg("%s %s%s", lfname, realseetext,
|
||||
(realseetext[strlen(realseetext)-1] == '!') ? "" : ".");
|
||||
}
|
||||
rv = B_TRUE;
|
||||
}
|
||||
|
@ -15785,6 +15923,7 @@ enum NOISECLASS noisetypetoclass(enum NOISETYPE nt) {
|
|||
case N_FLY:
|
||||
return NC_MOVEMENT;
|
||||
case N_SONICBOLT:
|
||||
case N_DEATHKEEN:
|
||||
case N_WARCRY:
|
||||
return NC_SPELLEFFECT;
|
||||
default:
|
||||
|
@ -16061,16 +16200,18 @@ void poison(lifeform_t *lf, int howlong, enum POISONTYPE ptype, int power, char
|
|||
if (ii->val[2] < 1) ii->val[2] = 1;
|
||||
if (getskill(lf, SK_FIRSTAID) >= PR_BEGINNER) {
|
||||
ii->known = B_TRUE;
|
||||
msg("You feel %s coming on more quickly.", pt->name);
|
||||
msg("^BYou feel %s coming on more quickly.", pt->name);
|
||||
}
|
||||
} else {
|
||||
char ftext[BUFLEN];
|
||||
sprintf(ftext, "%d^%s", power, fromwhat);
|
||||
ii = addflag(lf->flags, F_INCUBATING, ptype, power, pt->incubationtime, ftext);
|
||||
ii = addflag(lf->flags, F_INCUBATING, ptype, pt->incubationtime, howlong, ftext);
|
||||
ii->obfrom = srcrace ? srcrace->id : NA;
|
||||
if (getskill(lf, SK_FIRSTAID) >= PR_BEGINNER) {
|
||||
ii->known = B_TRUE;
|
||||
msg("You feel %s coming on.", pt->name);
|
||||
msg("^BYou feel %s coming on.", pt->name);
|
||||
} else {
|
||||
ii->known = B_FALSE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -19485,8 +19626,9 @@ void startlfturn(lifeform_t *lf) {
|
|||
} else if (f->val[0] == P_MIGRAINE) {
|
||||
// sleeping will avoid all migraine effects
|
||||
if (!asleep && !ko) {
|
||||
object_t *lamp = NULL;
|
||||
int amt;
|
||||
amt = lfproduceslight(lf);
|
||||
amt = lfproduceslight(lf, &lamp);
|
||||
if (amt) {
|
||||
int dam;
|
||||
// note: amt will be doubled due to light vulnerability,
|
||||
|
@ -19495,7 +19637,13 @@ void startlfturn(lifeform_t *lf) {
|
|||
limit(&dam, 1, NA);
|
||||
losehp(lf, amt, DT_LIGHT, NULL, "a migraine");
|
||||
if (isplayer(lf)) {
|
||||
msg("Your head explodes in pain at your light!");
|
||||
char obname[BUFLEN];
|
||||
if (lamp) {
|
||||
getobname(lamp, obname, lamp->amt);
|
||||
} else {
|
||||
strcpy(obname, "a body"); // noprefix will strip the 'a '
|
||||
}
|
||||
msg("Your head explodes in pain at the light from your %s!", noprefix(obname));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21440,6 +21588,11 @@ int validateraces(void) {
|
|||
goterror = B_TRUE;
|
||||
}
|
||||
|
||||
if (strstr(r->desc, "wings") && !hasbp(lf, BP_WINGS)) {
|
||||
printf("ERROR in race '%s' - description refers to wings but race has no bp_wings.\n", r->name);
|
||||
goterror = B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
if (!hasflag(r->flags, F_SIZE)) {
|
||||
printf("ERROR in race '%s' - missing F_SIZE.\n", r->name);
|
||||
|
|
6
lf.h
6
lf.h
|
@ -79,6 +79,7 @@ void copycorpseflags(flagpile_t *dst, flagpile_t *src);
|
|||
int continuedigging(lifeform_t *lf);
|
||||
int continuerepairing(lifeform_t *lf, flag_t *repairflag);
|
||||
int countinnateattacks(lifeform_t *lf);
|
||||
int countlegs(lifeform_t *lf);
|
||||
int countnearbyallies(lifeform_t *lf);
|
||||
int countnearbyhurtallies(lifeform_t *lf);
|
||||
int countplantsinsight(lifeform_t *lf);
|
||||
|
@ -104,6 +105,7 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce);
|
|||
int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong);
|
||||
int fall_from_air(lifeform_t *lf);
|
||||
void fightback(lifeform_t *lf, lifeform_t *attacker);
|
||||
behaviour_t *findbehaviour(enum BEHAVIOUR bid);
|
||||
job_t *findjob(enum JOB jobid);
|
||||
job_t *findjobbyname(char *name);
|
||||
lifeform_t *findlf(map_t *m, int lfid);
|
||||
|
@ -241,6 +243,7 @@ enum POISONSEVERITY getpoisonseverity(enum POISONTYPE ptype);
|
|||
int getraceclass(lifeform_t *lf);
|
||||
int getracerarity(map_t *map, enum RACE rid, enum RARITY *rr);
|
||||
object_t *getrandomarmour(lifeform_t *lf, lifeform_t *attacker);
|
||||
enum BEHAVIOUR getrandombehaviour(void);
|
||||
enum BODYPART getrandomcorebp(lifeform_t *lf, lifeform_t *attacker);
|
||||
race_t *getrandomcorpserace(cell_t *c);
|
||||
job_t *getrandomjob(int onlyplayerjobs);
|
||||
|
@ -269,6 +272,7 @@ object_t *getweapon(lifeform_t *lf);
|
|||
int getweapons(lifeform_t *lf, int meleeonly, object_t **wep, flag_t **damflag, int *lastweaponidx, obpile_t **op, int *nweps);
|
||||
enum SKILLLEVEL getweaponskill(lifeform_t *lf, object_t *o);
|
||||
long getxpforlev(int level);
|
||||
void givebehaviour(lifeform_t *lf, enum BEHAVIOUR bid);
|
||||
void givejob(lifeform_t *lf, enum JOB jobid);
|
||||
void givesubjob(lifeform_t *lf, enum SUBJOB sj);
|
||||
int givemoney(lifeform_t *from, lifeform_t *to, int amt);
|
||||
|
@ -293,7 +297,7 @@ flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid);
|
|||
flag_t *lfhasflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, char *text);
|
||||
flag_t *lfhasknownflag(lifeform_t *lf, enum FLAG fid);
|
||||
flag_t *lfhasknownflagval(lifeform_t *lf, enum FLAG fid, int val0, int val1, int val2, /*@null@*/ char *text);
|
||||
int lfproduceslight(lifeform_t *lf);
|
||||
int lfproduceslight(lifeform_t *lf, object_t **fromwhat);
|
||||
int lockpick(lifeform_t *lf, cell_t *targcell, object_t *target, object_t *device);
|
||||
void loseobflags(lifeform_t *lf, object_t *o, int kind);
|
||||
int hasbp(lifeform_t *lf, enum BODYPART bp);
|
||||
|
|
89
map.c
89
map.c
|
@ -23,6 +23,7 @@ int enteringmap = B_FALSE;
|
|||
extern habitat_t *firsthabitat,*lasthabitat;
|
||||
extern job_t *firstjob;
|
||||
extern map_t *firstmap,*lastmap;
|
||||
extern behaviour_t *firstbehaviour,*lastbehaviour;
|
||||
extern region_t *firstregion,*lastregion;
|
||||
extern regionoutline_t *firstregionoutline,*lastregionoutline;
|
||||
extern regiontype_t *firstregiontype,*lastregiontype;
|
||||
|
@ -223,6 +224,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
flagpile_t *wantflags = NULL;
|
||||
enum JOB wantjob = J_NONE;
|
||||
enum SUBJOB wantsubjob = SJ_NONE;
|
||||
enum BEHAVIOUR wantbehaviour = BH_NONE;
|
||||
|
||||
if (nadded) *nadded = 0;
|
||||
|
||||
|
@ -249,7 +251,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
} else {
|
||||
|
||||
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
|
||||
rid = parserace(racename, wantflags, &wantjob, &wantsubjob);
|
||||
rid = parserace(racename, wantflags, &wantjob, &wantsubjob, &wantbehaviour);
|
||||
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
|
||||
|
||||
if (rid == R_RANDOM) {
|
||||
|
@ -394,7 +396,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
}
|
||||
}
|
||||
|
||||
finalisemonster(lf, NULL, wantflags, 0);
|
||||
finalisemonster(lf, NULL, wantflags, wantbehaviour, 0);
|
||||
|
||||
// NOTE: because the initial maps (world, heaven, dungeon lev1) are created BEFORE the player,
|
||||
// monsters on these maps will not have their hostility adjusted!
|
||||
|
@ -465,7 +467,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
newlf->born = B_FALSE;
|
||||
|
||||
|
||||
finalisemonster(newlf, lf, wantflags, idx);
|
||||
finalisemonster(newlf, lf, wantflags, idx, BH_NONE);
|
||||
|
||||
newlf->born = B_TRUE;
|
||||
|
||||
|
@ -506,7 +508,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
adjcell = real_getrandomadjcell(c, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, NULL);
|
||||
if (!adjcell) break;
|
||||
|
||||
newrid = parserace(f->text, NULL, NULL, NULL);
|
||||
newrid = parserace(f->text, NULL, NULL, NULL, NULL);
|
||||
newr = findrace(newrid);
|
||||
if (!newr) break;
|
||||
|
||||
|
@ -515,7 +517,8 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int randomjobok
|
|||
|
||||
if (nadded) (*nadded)++;
|
||||
|
||||
finalisemonster(newlf, lf, wantflags, 0);
|
||||
// wantbehaviour only applies to initial monster
|
||||
finalisemonster(newlf, lf, wantflags, 0, BH_NONE);
|
||||
|
||||
newlf->born = B_TRUE;
|
||||
}
|
||||
|
@ -2039,7 +2042,7 @@ void calclight(map_t *map) {
|
|||
|
||||
// has lightproducing lf? (ie.hasflag f_produceslight)
|
||||
if (c->lf) {
|
||||
radius = lfproduceslight(c->lf);
|
||||
radius = lfproduceslight(c->lf, NULL);
|
||||
if (radius) {
|
||||
makelitradius(c, radius, L_TEMP, -1);
|
||||
}
|
||||
|
@ -5463,7 +5466,7 @@ void finalisemap(map_t *map, object_t *entryob) {
|
|||
|
||||
}
|
||||
|
||||
void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags, int idx) {
|
||||
void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags, enum BEHAVIOUR wantbehaviour, int idx) {
|
||||
flag_t *f;
|
||||
enum FLAG noflag[MAXCANDIDATES];
|
||||
int nnoflags = 0,i;
|
||||
|
@ -5506,56 +5509,10 @@ void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags,
|
|||
}
|
||||
|
||||
// random monster behaviours
|
||||
if (canhaverandombehaviour(lf) && onein(6)) {
|
||||
switch (rnd(0,8)) {
|
||||
case 0: // insane
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "insane");
|
||||
addflag(lf->flags, F_TERRITORIAL, 2, NA, NA, NULL); // attack anything within 1 cells
|
||||
break;
|
||||
case 1: // hungry
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "hungry");
|
||||
addflag(lf->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL);
|
||||
break;
|
||||
case 2: // timid
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "timid");
|
||||
f = lfhasflag(lf, F_MORALE);
|
||||
if (f) {
|
||||
f->val[0] /= 2;
|
||||
} else {
|
||||
addflag(lf->flags, F_FLEEONDAM, B_TRUE, NA, NA, NULL);
|
||||
}
|
||||
break;
|
||||
case 3: // drugged
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "drugged");
|
||||
killflagsofid(lf->flags, F_FLEEONDAM);
|
||||
killflagsofid(lf->flags, F_FLEEONHPPCT);
|
||||
addflag(lf->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
|
||||
break;
|
||||
case 4: // drunk
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "drunk");
|
||||
addflag(lf->flags, F_DRUNK, rnd(2,5), NA, NA, NULL);
|
||||
break;
|
||||
case 5: // determined
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "determined");
|
||||
addflag(lf->flags, F_FOLLOWTIME, (DEF_AIFOLLOWTIME*2), NA, NA, NULL);
|
||||
break;
|
||||
case 6: // lazy
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "lazy");
|
||||
addflag(lf->flags, F_FOLLOWTIME, (DEF_AIFOLLOWTIME/4), NA, NA, NULL);
|
||||
break;
|
||||
case 7: // extra hp
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "muscled");
|
||||
lf->maxhp = pctof(rnd(125,200), lf->maxhp); // 25-100% more hp
|
||||
lf->hp = lf->maxhp;
|
||||
break;
|
||||
case 8: // less hp
|
||||
addflag(lf->flags, F_BEHAVIOUR, NA, NA, NA, "scrawny");
|
||||
lf->maxhp = pctof(rnd(50,75), lf->maxhp); // 25-50% less hp
|
||||
limit(&(lf->maxhp), 1, NA);
|
||||
lf->hp = lf->maxhp;
|
||||
break;
|
||||
}
|
||||
if ((wantbehaviour == BH_NONE) && canhaverandombehaviour(lf) && onein(6)) {
|
||||
wantbehaviour = getrandombehaviour();
|
||||
}
|
||||
givebehaviour(lf, wantbehaviour);
|
||||
|
||||
if (wantflags) {
|
||||
copyflags(lf->flags, wantflags, NA);
|
||||
|
@ -7392,17 +7349,20 @@ int orthdir(int compassdir) {
|
|||
return D_NONE;
|
||||
}
|
||||
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum SUBJOB *wantsubjob) {
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum SUBJOB *wantsubjob, enum BEHAVIOUR *wantbehaviour) {
|
||||
int donesomething;
|
||||
char *p,*suff;
|
||||
job_t *j;
|
||||
char named[BUFLEN];
|
||||
char *localname;
|
||||
char *namestart;
|
||||
behaviour_t *b;
|
||||
|
||||
// get params
|
||||
donesomething = B_TRUE;
|
||||
|
||||
if (wantbehaviour) *wantbehaviour = BH_NONE;
|
||||
|
||||
|
||||
// take a local copy so we can strip suffixes off it
|
||||
if (strstarts(name, "the ")) {
|
||||
|
@ -7425,8 +7385,23 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum S
|
|||
if (wantflags) addflag(wantflags, F_ASLEEP, NA, ST_ASLEEP, NA, NULL);
|
||||
donesomething = B_TRUE;
|
||||
}
|
||||
if (wantbehaviour && (*wantbehaviour != BH_NONE)) {
|
||||
} else {
|
||||
// try removing prefixes for behaviours
|
||||
for (b = firstbehaviour ; b; b = b->next) {
|
||||
char lookfor[BUFLEN];
|
||||
sprintf(lookfor, "%s ", b->name);
|
||||
if (strstarts(p, lookfor)) {
|
||||
p += strlen(lookfor);
|
||||
if (wantbehaviour) *wantbehaviour = b->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// try removing suffixes for "named xxx"
|
||||
strcpy(named, "");
|
||||
suff = strends(localname, " named ");
|
||||
|
|
4
map.h
4
map.h
|
@ -87,7 +87,7 @@ void expand_cave(map_t *map, int numpasses);
|
|||
void explodesinglecell(cell_t *c, int dam, int killwalls, object_t *o, cell_t *centre);
|
||||
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce);
|
||||
void finalisemap(map_t *map, object_t *entryob);
|
||||
void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags, int idx);
|
||||
void finalisemonster(lifeform_t *lf, lifeform_t *leader, flagpile_t *wantflags, enum BEHAVIOUR wantbehaviour, int idx);
|
||||
celltype_t *findcelltype(enum CELLTYPE cid);
|
||||
celltype_t *findcelltypebyname(char *name);
|
||||
habitat_t *findhabitat(enum HABITAT id);
|
||||
|
@ -167,7 +167,7 @@ void markroomwalls(map_t *m, room_t *r);
|
|||
void mapentereffects(map_t *m);
|
||||
void moveobtoclearcell(object_t *o);
|
||||
int orthdir(int compassdir);
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum SUBJOB *wantsubjob);
|
||||
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum SUBJOB *wantsubjob, enum BEHAVIOUR *wantbehaviour);
|
||||
int remove_deadends(map_t *m, int howmuch);
|
||||
void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph);
|
||||
void setcellknown(cell_t *cell, int forcelev);
|
||||
|
|
2
move.c
2
move.c
|
@ -1280,7 +1280,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
|
|||
|
||||
if (gamemode == GM_GAMESTARTED) {
|
||||
// update light
|
||||
if ((isplayer(lf) && changedlev) || lfproduceslight(lf)) {
|
||||
if ((isplayer(lf) && changedlev) || lfproduceslight(lf, NULL)) {
|
||||
calclight(lf->cell->map);
|
||||
setlosdirty(lf);
|
||||
}
|
||||
|
|
3
nexus.c
3
nexus.c
|
@ -28,6 +28,7 @@ objecttype_t *objecttype = NULL,*lastobjecttype = NULL;
|
|||
brand_t *firstbrand = NULL,*lastbrand = NULL;
|
||||
obmod_t *firstobmod = NULL,*lastobmod = NULL;
|
||||
celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
|
||||
behaviour_t *firstbehaviour = NULL,*lastbehaviour = NULL;
|
||||
command_t *firstcommand = NULL,*lastcommand = NULL;
|
||||
race_t *firstrace = NULL,*lastrace = NULL;
|
||||
raceclass_t *firstraceclass = NULL,*lastraceclass = NULL;
|
||||
|
@ -661,6 +662,8 @@ void cleanup(void) {
|
|||
free(npcname);
|
||||
// free hidden names
|
||||
while (firsthiddenname) killhiddenname(firsthiddenname);
|
||||
// behaviours
|
||||
while (firstbehaviour) killbehaviour(firstbehaviour);
|
||||
//WriteMemLeak();
|
||||
}
|
||||
|
||||
|
|
|
@ -2375,6 +2375,7 @@ void adjustdammaterial(int *dam, enum DAMTYPE damtype, enum MATERIAL mat) {
|
|||
if (mat == MT_MAGIC) {
|
||||
switch (damtype) {
|
||||
case DT_DIRECT:
|
||||
case DT_MAGIC:
|
||||
case DT_NONE:
|
||||
break;
|
||||
default:
|
||||
|
|
43
spell.c
43
spell.c
|
@ -1808,7 +1808,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
}
|
||||
losehp(target, roll(damstr), DT_SONIC, user, "a bolt of sound");
|
||||
}
|
||||
|
||||
} else if (abilid == OT_A_SPRINT) {
|
||||
flag_t *f;
|
||||
f = lfhasflag(user, F_SPRINTING);
|
||||
|
@ -2331,6 +2330,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
} else if (abilid == OT_A_TRIPLF) {
|
||||
object_t *wep;
|
||||
int skillmod = 0;
|
||||
int legs;
|
||||
// ask for direction
|
||||
if (!targcell) {
|
||||
char dirch;
|
||||
|
@ -2365,6 +2365,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
return B_TRUE;
|
||||
}
|
||||
|
||||
legs = countlegs(target);
|
||||
|
||||
if (legs == 0) {
|
||||
if (isplayer(user)) msg("You can't trip something which has no legs!");
|
||||
return B_TRUE;
|
||||
}
|
||||
|
||||
|
||||
getlfname(target, targetname);
|
||||
|
||||
|
@ -2380,7 +2387,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
|
|||
skillmod = getskill(user, SK_UNARMED);
|
||||
}
|
||||
|
||||
if (skillcheckvs(user, SC_DEX, skillmod, target, SC_SLIP, 0)) {
|
||||
if (skillcheckvs(user, SC_DEX, skillmod, target, SC_SLIP, (legs > 2) ? 5 : 0)) {
|
||||
if (cansee(player, user)) {
|
||||
msg("^w%s trip%s %s.",username, isplayer(user) ? "" : "s", targetname);
|
||||
}
|
||||
|
@ -3555,12 +3562,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
|
||||
// special: spit attacks need an animation
|
||||
casttype = lfhasflag(caster, F_CASTTYPE);
|
||||
if (casttype && (casttype->val[0] == CT_EYESPIT)) {
|
||||
if (casttype && (casttype->val[1] == CT_EYESPIT)) {
|
||||
enum COLOUR col;
|
||||
if (casttype->val[1] == NA) {
|
||||
if (casttype->val[2] == NA) {
|
||||
col = C_GREEN;
|
||||
} else {
|
||||
col = casttype->val[1];
|
||||
col = casttype->val[2];
|
||||
}
|
||||
anim(caster->cell, targcell, '}', col);
|
||||
}
|
||||
|
@ -5417,6 +5424,28 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
needredraw = B_TRUE;
|
||||
drawscreen();
|
||||
}
|
||||
} else if (spellid == OT_S_DEATHKEEN) {
|
||||
if (!isnighttime()) {
|
||||
fizzle(caster);
|
||||
return B_TRUE;
|
||||
}
|
||||
if (isplayer(caster)) {
|
||||
msg("You wail with the power of death!");
|
||||
}
|
||||
noise(caster->cell, NULL, NC_OTHER, SV_TALK, "the dread wail of a banshee", NULL);
|
||||
makenoise(caster, N_DEATHKEEN);
|
||||
|
||||
// all in range must pass a magic resistance check or die
|
||||
for (target = caster->cell->map->lf ; target ; target = target->next) {
|
||||
if (target != caster) {
|
||||
if (canhear(target, caster->cell, SV_TALK)) {
|
||||
if (spellresisted(target, caster, spellid, power, seenbyplayer, B_TRUE)) {
|
||||
} else {
|
||||
losehp(target, target->hp, DT_SONIC, caster, "a banshee's wail");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (spellid == OT_S_DETECTAURA) {
|
||||
if (isplayer(caster)) {
|
||||
object_t *o;
|
||||
|
@ -5668,6 +5697,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
} else if (spellid == OT_S_DETECTPOISON) {
|
||||
if (isplayer(caster)) {
|
||||
int npoisoned = 0;
|
||||
int selfpoisoned = B_FALSE;
|
||||
int n,i;
|
||||
flag_t *retflag[MAXCANDIDATES];
|
||||
int nretflags;
|
||||
|
@ -5679,6 +5709,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
pt = findpoisontype(f->val[0]);
|
||||
msg("You detect %s in your body.", pt->name);
|
||||
f->known = B_TRUE;
|
||||
selfpoisoned = B_TRUE;
|
||||
}
|
||||
|
||||
for (n = 0; n < caster->nlos; n++) {
|
||||
|
@ -5739,7 +5770,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
|
|||
}
|
||||
}
|
||||
if (!npoisoned) {
|
||||
msg("You can't detect any poison nearby.");
|
||||
msg("You can't detect any %spoison nearby.", selfpoisoned ? "other " : "");
|
||||
}
|
||||
} // end if isplayer
|
||||
} else if (spellid == OT_S_DETONATE) {
|
||||
|
|
Loading…
Reference in New Issue