From 3e7380a5b6e0f0a7a68ec1473cd8485f41b32917 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Wed, 5 Oct 2011 22:08:13 +0000 Subject: [PATCH] - [+] if you put a water object onto dirt, it should become a mud object instead. - [+] dynamic morale - [+] whenever you fail a moral check, your moral gets a bit lower - [+] opposite if you pass it. - [+] make morale checks depend more on morale - [+] after you flee, become timid - [+] in io.c, show current morale if lorelev is high enough. "looks scared/timid/confident" - [+] implement f_timid: - [+] (will only move into melee range if it is behind you) * [+] checks: - [+] monsters can't attack while prone. always jsut stand up. - [+] call initiatemove even when atatcking - [+] bug: monsters not gaining abilities frmo skills - [+] bug when creating monsters with jobs: "xx looks foolish" etc - [+] tohit penalty for small monster hitting flying or levitating things (lower penalty for levitating) * [+] if you are flying and get hit, you drop to the ground? - [+] make feign death code better for mosnters - [+] moving should cose STAMREGEN points (ie don't regenerate stamina if you move) - [+] maybe: when you finish sprinting, drop stamina to -2 - [+] until it gets back, you can't move at all - [+] bug: stuck in moveto(), after walking up stairs to a new levle - [+] happened again right after "The young wolf starts sprinting! The young wolf flees down the staircase." - [+] was getting stuck in donextturn because we weren't on the plaeyr's map - taketime was returning. - [+] shield bash skill - [+] gain it at shieldlev beginner - [+] costs stamina - [+] pass a skill check based on shield skill and shield value to stun enemy - [+] only works if shield has hardness - [+] only works if you're the same size or larger than the opponent - [+] damages your shield (1d3 hp ?) --- ai.c | 51 +++++-- attack.c | 68 ++++++++- data.c | 103 +++++++++++-- data/hiscores.db | Bin 7168 -> 7168 bytes defs.h | 6 +- flag.c | 1 + io.c | 20 ++- lf.c | 264 ++++++++++++++++++++------------ lf.h | 13 +- move.c | 358 +++++++++++++++++++++++++------------------- nexus.c | 7 +- objects.c | 29 +++- objects.h | 1 + spell.c | 101 ++++++++++++- vaults/dirtroom.vlt | 16 ++ 15 files changed, 743 insertions(+), 295 deletions(-) create mode 100644 vaults/dirtroom.vlt diff --git a/ai.c b/ai.c index ddce9bc..7d7e56a 100644 --- a/ai.c +++ b/ai.c @@ -130,6 +130,11 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) { db = B_TRUE; } + if (db) { + dblog(".oO { looking for attack spells/abils }"); + } + + f = lfhasflag(lf, F_NEEDOBFORSPELLS); if (f && !hasob(lf->pack, f->val[0])) { if (db) dblog(".oO { Cannot cast spell, I don't have my spellcast object }"); @@ -550,7 +555,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { // how far away is my target ? dist = getcelldist(lf->cell, target->cell); // how far away do i _want_ to be? - getwantdistance(lf,&wantdistmin,&wantdistmax, wantattack); + getwantdistance(lf,target, &wantdistmin,&wantdistmax, wantattack); // reset F_TARGET lifetime to full. if (targetflag) { @@ -591,7 +596,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) { // random chance of casting a spell f = lfhasflag(lf, F_CASTCHANCE); if (f) spellchance = f->val[0]; - else spellchance = 15; + else spellchance = 30; if (pctchance(spellchance)) { spell = aigetattackspell(lf, target); @@ -1017,7 +1022,7 @@ void aiturn(lifeform_t *lf) { } /////////////////////////////////////////////// - // emergencies + // emergencies / fixing up /////////////////////////////////////////////// if (iqb >= AT_AVERAGE) { if (celldangerous(lf, lf->cell, B_TRUE, NULL)) { @@ -1028,6 +1033,20 @@ void aiturn(lifeform_t *lf) { } } + // flying monsters not flying? + if (!isprone(lf)) { + if (hasflag(lf->race->flags, F_FLYING) && !lfhasflag(lf, F_FLYING)) { + copyflag(lf->flags, lf->race->flags, F_FLYING); + taketime(lf, getmovespeed(lf)); + return; + } + if (hasflag(lf->race->flags, F_LEVITATING) && !lfhasflag(lf, F_LEVITATING)) { + copyflag(lf->flags, lf->race->flags, F_LEVITATING); + taketime(lf, getmovespeed(lf)); + return; + } + } + /////////////////////////////////////////////// // housekeeping - weapon changes, drop/pickup, @@ -1129,11 +1148,14 @@ void aiturn(lifeform_t *lf) { } } - // feigning death with enemies in sight? + // feigning death with enemies in sight, and hurt? if (lfhasflag(lf, F_FEIGNINGDEATH) && !safetorest(lf)) { - // just wait... - taketime(lf, getactspeed(lf)); - return; + if (isbleeding(lf)) { + if (db) dblog(".oO { i am feigning death and bleeding (hp=%d/%d), skipping turn. }",lf->hp,lf->maxhp); + // just wait... + rest(lf, B_TRUE); + return; + } } // hurt gods planeshift away @@ -1774,7 +1796,9 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG specificcheckok = B_FALSE; } if (ot->id == OT_A_HEAVYBLOW) { - if (!getweapon(lf)) { + object_t *w; + w = getweapon(lf); + if (!w || !isheavyweapon(w)) { specificcheckok = B_FALSE; } } @@ -1802,6 +1826,11 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG if ((ot->id == OT_S_PARALYZE) && lfhasflag(victim, F_PARALYZED)) { specificcheckok = B_FALSE; } + if (ot->id == OT_A_SHIELDBASH) { + if (!getshield(lf)) { + specificcheckok = B_FALSE; + } + } if ((ot->id == OT_S_SLEEP) && lfhasflag(victim, F_ASLEEP)) { specificcheckok = B_FALSE; } @@ -1814,8 +1843,10 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG if ((ot->id == OT_S_SMITEEVIL) && (getalignment(victim) != AL_EVIL)) { specificcheckok = B_FALSE; } - if ((ot->id == OT_A_SPRINT) && (lfhasflag(lf, F_SPRINTING) || !getstamina(lf))) { - specificcheckok = B_FALSE; + if (ot->id == OT_A_SPRINT) { + if (lfhasflag(lf, F_SPRINTING) || !getstamina(lf) || (getstamina(lf) <= (getmaxstamina(lf)/2))) { + specificcheckok = B_FALSE; + } } if ((ot->id == OT_A_STEAL) || (ot->id == OT_S_CONFISCATE)) { if (!countobs(victim->pack, B_FALSE)) { diff --git a/attack.c b/attack.c index 931f027..2521eb5 100644 --- a/attack.c +++ b/attack.c @@ -183,7 +183,6 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { stoprunning(lf); - // anyone there? if so just attack. if (c->lf) { if (!force && isplayer(lf) && !areenemies(lf,c->lf) && (getraceclass(c->lf) != RC_PLANT)) { @@ -210,6 +209,23 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { attackedpeaceful = B_TRUE; } + // player walked into someone who was feigning death? + if (isplayer(lf) && lfhasflag(c->lf, F_FEIGNINGDEATH) && !force) { + char vicname[BUFLEN]; + killflagsofid(c->lf->flags, F_FEIGNINGDEATH); + getlfname(c->lf, vicname); + capitalise(vicname); + if (cansee(lf, c->lf)) { + msg("Hey! %s was just feigning death!", vicname); + } else { + msg("You bump into someone!"); + } + killflagsofid(c->lf->flags, F_PRONE); + // still counts as a move! + taketime(lf, getmovespeed(lf)); + return B_FALSE; + } + attacktype = AT_LF; attacktarget = c->lf; @@ -508,8 +524,10 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { } } - // lose a bit of stamina - modstamina(lf, -getattackstamloss(lf)); + if (isplayer(lf)) { + // lose a bit of stamina + modstamina(lf, -getattackstamloss(lf)); + } // stop sprinting stopsprinting(lf); @@ -904,7 +922,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) if (lfhasflag(victim, F_FEIGNINGDEATH)) { killflagsofid(victim->flags, F_FEIGNINGDEATH); } else if (!fatal && !isplayer(victim) && cancast(victim, OT_A_FEIGNDEATH, NULL)) { - if (onein(6) || isbleeding(victim)) { + if (onein(2) || isbleeding(victim)) { // do it! useability(victim, OT_A_FEIGNDEATH, lf, lf->cell); feigneddeath = B_TRUE; @@ -1163,6 +1181,21 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) } } + // if victim was flying and took >= 25% of its hit points, it drops to the ground. + if (isphysicaldam(damtype[i]) && (dam[i] >= pctof(25, lf->maxhp))) { + int willfall = B_FALSE,willinjure = B_FALSE,n; + getflags(victim->flags, retflag, &nretflags, F_FLYING, F_LEVITATING, F_NONE); + for (n = 0; n < nretflags; n++) { + if (!istransitoryflag(retflag[n]) || (retflag[n]->lifetime == FROMRACE)) { + if (retflag[n]->id == F_FLYING) willinjure = B_TRUE; + willfall = B_TRUE; + killflag(retflag[n]); + } + } + if (willfall) fall(victim, NULL, B_TRUE); + if (willinjure) injure(victim, getrandomcorebp(victim), DT_BASH); + } + // if victim can still move... if (hasfreeaction(victim)) { fightback(victim, lf); @@ -1520,7 +1553,9 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, int d if (onein(2)) { // drop your weapon! o = getweapon(victim); - if (o) drop(o, ALL); + if (o) { + drop(o, ALL); + } break; } case BP_LEGS: @@ -2199,9 +2234,12 @@ int isphysicaldam(enum DAMTYPE damtype) { return B_FALSE; } -// 'howmuch' is the numerical amount to adjust 'val' by for every size bracket +// 'howmuch' is the amount to adjust 'val' by for every size bracket // difference. // +// how can be M_PCT (adjust by this val% per size bracket) +// how can be M_VAL (adjust by this number per size bracket) +// // if lf is bigger than victim, ADD howmuch. // if lf is smaller than victim, SUBTRACT howmuch. void modifyforsize(int *val, lifeform_t *lf, lifeform_t *victim, int howmuch, enum MODTYPE how) { @@ -2271,6 +2309,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) } else if (critical && *critical) { gothit = B_TRUE; } else { + enum LFSIZE sizetoreach = SZ_ANY; // actually roll... acc = getlfaccuracy(lf, wep); @@ -2286,6 +2325,23 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical) acc -= 50; } + // harder to hit flying/levitating enemies, unless you are + // large (ie. tall) enough to reach them. + // if you are smaller than "sizetoreach", you get a penalty + switch (isairborne(victim)) { + case F_FLYING: + sizetoreach = SZ_HUGE; + break; + case F_LEVITATING: + sizetoreach = SZ_HUMAN; + break; + default: sizetoreach = SZ_ANY; break; + } + if (sizetoreach != SZ_ANY) { + acc -= (15*(sizetoreach - getlfsize(lf))); + } + + // modify for defender's evasion if (isprone(victim) || !cansee(victim, lf)) { ev = 0; diff --git a/data.c b/data.c index 995fac4..de7c9e9 100644 --- a/data.c +++ b/data.c @@ -2950,6 +2950,11 @@ void initobjects(void) { addflag(lastot->flags, F_STAMCOST, 5, NA, NA, NULL); addot(OT_A_REPAIR, "repair equipment", "Repair damage done to your equipment.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addot(OT_A_SHIELDBASH, "shield bash", "Attempt to stun your opponent by bashing them with your shield.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); + addflag(lastot->flags, F_STAMCOST, 2, NA, NA, NULL); + addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); addot(OT_A_SONICBOLT, "sonic bolt", "Emit a damaging burst of sound, targetted at a particular location.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -5056,12 +5061,12 @@ void initobjects(void) { addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction"); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); - addot(OT_SHILLELAGH, "shillelagh", "An small club, lightweight yet surprisingly effective. Irish in origin.", MT_WOOD, 2, OC_WEAPON, SZ_MEDIUM); + addot(OT_SHILLELAGH, "shillelagh", "An small cudgel with a strap, lightweight yet surprisingly effective. Irish in origin.", MT_WOOD, 2, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d4+1"); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL); - addot(OT_STICK, "stick", "A sturdy wooden stick.", MT_WOOD, 0.5, OC_WEAPON, SZ_SMALL); + addot(OT_STICK, "stick", "A sturdy wooden stick. It's brown and sticky.", MT_WOOD, 0.5, OC_WEAPON, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, NULL); addflag(lastot->flags, F_DAM, DT_BASH, NA, NA, "1d2"); @@ -5782,6 +5787,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "claws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_COCKATRICE, "cockatrice", 5, 'c', C_YELLOW, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_VHIGH, NA, NULL); @@ -5830,6 +5836,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:1d6;"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;"); addflag(lastrace->flags, F_CASTCHANCE, 70, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_DARKMANTLE, "darkmantle", 70, 'U', C_BLUE, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -5877,6 +5884,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_SPELLSPEED, SP_VERYSLOW, NA, NA, NULL); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + 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); @@ -5891,7 +5899,6 @@ void initrace(void) { addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); - addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); addrace(R_GIANTHILL, "hill giant", 160, 'H', C_GREY, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -5925,6 +5932,7 @@ void initrace(void) { addflag(lastrace->flags, F_FLEEONHPPCT, 50, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_GIANTFIRE, "fire giant", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -5957,6 +5965,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_GIANTFIREFC, "fire giant forgecaller", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GIANTFIRE; @@ -5993,6 +6002,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 15, NA, NA, NULL); addrace(R_GIANTFIRETITAN, "fire titan", 160, 'H', C_RED, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -6023,6 +6033,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); // TODO: storm giant // TODO: storm titan @@ -6056,6 +6067,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_GNOLLHM, "gnoll huntmaster", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GNOLL; @@ -6090,6 +6102,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 12, NA, NA, NULL); addrace(R_GNOLLMR, "gnoll marauder", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GNOLL; @@ -6123,6 +6136,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 12, NA, NA, NULL); addrace(R_GOBLIN, "goblin", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -6153,7 +6167,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTJOB, 25, J_ROGUE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); - + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addrace(R_GOBLINWAR, "goblin warrior", 30, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GOBLIN; @@ -6183,6 +6197,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_GOBLINSHOOTER, "goblin sharpshooter", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GOBLIN; @@ -6215,6 +6230,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addrace(R_GOBLINHEXER, "goblin hexer", 20, 'g', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_GOBLIN; @@ -6246,6 +6262,7 @@ void initrace(void) { addflag(lastrace->flags, F_MINIONS, 90, 1, 2, "goblin"); addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -6278,6 +6295,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_HOBGOBLINWAR, "hobgoblin warrior", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_HOBGOBLIN; @@ -6312,6 +6330,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 7, NA, NA, NULL); // TODO: hobgoblin archer // TODO: hobgoblin warcaster @@ -6342,6 +6361,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "shouts^a shout"); addflag(lastrace->flags, F_SEEINDARK, 2, NA, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addrace(R_TROGLODYTE, "troglodyte", 20, 'z', C_GREY, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -6368,6 +6388,7 @@ void initrace(void) { addflag(lastrace->flags, F_STENCH, 3, 3, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addrace(R_LEPRECHAUN, "leprechaun", 35, 'n', C_GREEN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6390,6 +6411,7 @@ void initrace(void) { addflag(lastrace->flags, F_WANTS, OT_GOLD, B_COVETS, NA, NULL); addflag(lastrace->flags, F_DODGES, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_EXTRALUCK, 2, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addrace(R_LIZARDMAN, "lizardman", 100, 'z', C_GREEN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -6415,6 +6437,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_S_POISONBOLT, 5, 5, "pw:5;"); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_MINOTAUR, "minotaur", 130, 'H', C_BROWN, MT_FLESH, RC_HUMANOID); @@ -6569,6 +6592,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_ORCWARRIOR, "orc warrior", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID); lastrace->baseid = R_ORC; @@ -6602,6 +6626,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 12, NA, NA, NULL); addrace(R_ORK, "ork", 90, 'o', C_BROWN, MT_FLESH, RC_HUMANOID); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "orc corpse"); @@ -6631,6 +6656,7 @@ void initrace(void) { addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_PEGASUS, "pegasus", 130, 'Q', C_GREY, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL); @@ -6719,6 +6745,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTHIDDENPCT, 60, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 20, NA, NA, NULL); addrace(R_SHADOWCAT, "shadowcat", 5, 'f', C_BLUE, MT_FLESH, RC_MAGIC); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -6735,7 +6762,7 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 8, NA, NA, NULL); addflag(lastrace->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL); addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "cloud of smoke"); - addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); @@ -6768,6 +6795,7 @@ void initrace(void) { addflag(lastrace->flags, F_DIESPLATTER, 3, NA, NA, "splash of acid"); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, 5, NA, NA, NULL); addrace(R_SPRITEFIRE, "fire sprite", 5, 'n', C_RED, MT_FIRE, RC_MAGIC); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "small fire"); @@ -6791,7 +6819,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTSKILL, SK_SS_FIRE, PR_BEGINNER, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC); @@ -6816,7 +6844,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTSKILL, SK_SS_COLD, PR_ADEPT, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL); addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); @@ -6859,6 +6887,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "snorts^a snort"); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); // fish addrace(R_CRAB, "giant crab", 150, ';', C_ORANGE, MT_FLESH, RC_AQUATIC); @@ -6884,6 +6913,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOARMOURON, BP_LEFTFINGER, NA, NA, NULL); addflag(lastrace->flags, F_NOARMOURON, BP_HANDS, NA, NA, NULL); addflag(lastrace->flags, F_NOARMOURON, BP_FEET, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_MERLOCH, "merloch", 250, 'm', C_ORANGE, MT_FLESH, RC_AQUATIC); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6912,6 +6942,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOARMOURON, BP_LEFTFINGER, NA, NA, NULL); addflag(lastrace->flags, F_NOARMOURON, BP_HANDS, NA, NA, NULL); addflag(lastrace->flags, F_NOARMOURON, BP_FEET, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addrace(R_PIRANHA, "piranha", 0.5, ';', C_GREEN, MT_FLESH, RC_AQUATIC); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); @@ -6932,6 +6963,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_LEFTFINGER, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d2"); + addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addrace(R_PIRANHAKING, "king piranha", 1, ';', C_GREEN, MT_FLESH, RC_AQUATIC); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6952,6 +6984,7 @@ void initrace(void) { addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, NA, NA, "1d6"); addflag(lastrace->flags, F_CANWILL, OT_A_CHARGE, NA, NA, "range:5;"); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_EELELEC, "electric eel", 120, ';', C_CYAN, MT_FLESH, RC_AQUATIC); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6971,6 +7004,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_LEFTFINGER, NA, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_ZAPPER, NA, NA, "1d6"); addflag(lastrace->flags, F_DTIMMUNE, DT_ELECTRIC, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addrace(R_EELGIANT, "giant eel", 150, ';', C_BLUE, MT_FLESH, RC_AQUATIC); addflag(lastrace->flags, F_NEEDSWATER, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -6990,7 +7024,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOBODYPART, BP_LEFTFINGER, 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:2d6;"); - + addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); // plants addrace(R_CACTUS, "cactus", 30, 'F', C_YELLOW, MT_PLANT, RC_PLANT); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); @@ -7091,6 +7125,7 @@ void initrace(void) { addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addrace(R_BATMUTATED, "mutated bat", 3, 'B', C_MAGENTA, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL); @@ -7114,6 +7149,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_BATVAMPIRE, "vampire bat", 6, 'B', C_BLUE, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL); @@ -7139,6 +7175,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_FLY, 1, NA, "^flapping wings"); addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_BEAR, "black bear", 150, 'q', C_BLUE, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); @@ -7164,6 +7201,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_BEARGRIZZLY, "grizzly bear", 200, 'q', C_YELLOW, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_BEAR; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7192,6 +7230,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_BEARCUB, "bear cub", 60, 'q', C_BROWN, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_BEAR; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7215,6 +7254,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addrace(R_ANT, "giant ant", 20, 'a', C_BROWN, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7237,6 +7277,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_ANTS, "giant soldier ant", 25, 'a', C_BROWN, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7261,6 +7302,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_MINIONS, 50, 1, 3, "giant worker ant"); addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 12, NA, NA, NULL); addrace(R_ANTLION, "giant antlion", 30, 'a', C_YELLOW, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_ANT; addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7285,6 +7327,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 4, NA, "roars^a roars"); addflag(lastrace->flags, F_ENHANCESMELL, 4, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 14, NA, NA, NULL); addrace(R_CHICKEN, "chicken", 0.5, 'c', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); @@ -7303,6 +7346,8 @@ void initrace(void) { addflag(lastrace->flags, F_SEEINDARK, 1, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 2, NA, "squarks^squarking"); addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^clucking"); + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); + addflag(lastrace->flags, F_TIMID, B_TRUE, NA, NA, NULL); addrace(R_DOG, "dog", 35, 'd', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RNDHOSTILE, 10, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -7329,6 +7374,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addrace(R_DOGBLINK, "blink dog", 35, 'd', C_BLUE, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_ALIGNMENT, AL_GOOD, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7356,6 +7402,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addrace(R_DOGDEATH, "death hound", 40, 'd', C_MAGENTA, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 2, 6, NA, ""); @@ -7386,6 +7433,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 15, NA, NA, NULL); addrace(R_DOGWAR, "war hound", 40, 'd', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NUMAPPEAR, 1, 4, NA, ""); @@ -7411,6 +7459,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_HAWKYOUNG, "young hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL); // 'A' for Avian lastrace->baseid = R_HAWK; @@ -7439,6 +7488,7 @@ void initrace(void) { addflag(lastrace->flags, F_LEVRACE, 4, R_HAWK, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain"); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addrace(R_HAWK, "hawk", 1, 'A', C_GREY, MT_FLESH, RC_ANIMAL); // 'A' for Avian lastrace->baseid = R_HAWK; @@ -7463,11 +7513,11 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, NA, NA, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 3, NA, NA, NULL); - addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 4, NA, NA, NULL); addflag(lastrace->flags, F_LEVRACE, 8, R_HAWKBLOOD, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain"); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 6, NA, NA, NULL); addrace(R_HAWKBLOOD, "blood hawk", 1, 'A', C_RED, MT_FLESH, RC_ANIMAL); // 'A' for Avian lastrace->baseid = R_HAWK; @@ -7493,8 +7543,8 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SWOOP, NA, NA, NULL); addflag(lastrace->flags, F_SWOOPRANGE, 5, NA, NA, NULL); addflag(lastrace->flags, F_SEEINDARK, 6, NA, NA, NULL); - addflag(lastrace->flags, F_MORALE, 7, NA, NA, NULL); addflag(lastrace->flags, F_NOISETEXT, N_LOWHP, 3, NA, "screeches in pain^screeches of pain"); + addflag(lastrace->flags, F_MORALE, 8, NA, NA, NULL); addrace(R_HAWKFROST, "frost hawk", 1, 'A', C_CYAN, MT_FLESH, RC_ANIMAL); // 'A' for Avian addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7546,6 +7596,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_SUCKBLOOD, NA, NA, "dam:0d1+4;"); addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL); addflag(lastrace->flags, F_ENHANCESMELL, 5, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 20, NA, NA, NULL); addrace(R_NEWT, "giant newt", 4, ':', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -7566,6 +7617,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addrace(R_PORCUPINE, "giant porcupine", 10, 'r', C_GREY, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HATESRACE, R_ANT, NA, NA, NULL); @@ -7584,6 +7636,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); 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_MORALE, 8, NA, NA, NULL); addrace(R_RAT, "giant rat", 3, 'r', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); @@ -7607,6 +7660,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "claws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addrace(R_SNAKE, "brown snake", 3, 's', C_BROWN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -7634,6 +7688,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SNAKECARPET, "carpet snake", 3, 's', C_GREY, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -7658,6 +7713,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SNAKETREE, "tree snake", 3, 's', C_GREEN, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -7684,6 +7740,7 @@ void initrace(void) { addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SNAKECOBRABLACK, "black cobra", 3, 's', C_BLUE, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -7711,6 +7768,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SNAKECOBRAGOLDEN, "golden cobra", 3, 's', C_YELLOW, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -7739,6 +7797,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_S_BLINDNESS, 4, 4, "pw:3;range:2;"); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SNAKECONSTRICTOR, "constrictor", 3, 's', C_MAGENTA, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_COLDBLOOD, B_TRUE, NA, NA, NULL); @@ -7766,6 +7825,7 @@ void initrace(void) { addflag(lastrace->flags, F_CANWILL, OT_A_CRUSH, NA, NA, "dam:2d6;"); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SNAKEWATER, "water snake", 3, 's', C_BLUE, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_AQUATIC, B_TRUE, NA, NA, NULL); @@ -7793,6 +7853,7 @@ void initrace(void) { addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SPIDER, "giant spider", 5, 'S', C_GREY, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -7819,6 +7880,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HEAD, NA, NA, "cephalothorax"); addflag(lastrace->flags, F_BODYPARTNAME, BP_BODY, NA, NA, "abdomen"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SPIDERFUNNELWEB, "giant funnelweb", 5, 'S', C_MAGENTA, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_SPIDER; addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); @@ -7848,6 +7910,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HEAD, NA, NA, "cephalothorax"); addflag(lastrace->flags, F_BODYPARTNAME, BP_BODY, NA, NA, "abdomen"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_SPIDERREDBACK, "giant redback", 5, 'S', C_RED, MT_FLESH, RC_ANIMAL); lastrace->baseid = R_SPIDER; addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); @@ -7877,6 +7940,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HEAD, NA, NA, "cephalothorax"); addflag(lastrace->flags, F_BODYPARTNAME, BP_BODY, NA, NA, "abdomen"); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_WOLFYOUNG, "young wolf", 10, 'd', C_GREY, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -7904,6 +7968,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL); addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -7931,6 +7996,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "paws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 7, NA, NA, NULL); // insects addrace(R_BUTTERFLY, "butterfly", 0.01, 'i', C_YELLOW, MT_FLESH, RC_ANIMAL); @@ -7952,6 +8018,8 @@ void initrace(void) { addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); + addflag(lastrace->flags, F_TIMID, B_TRUE, NA, NA, NULL); addrace(R_GIANTFLY, "giant fly", 1, 'i', C_GREY, MT_FLESH, RC_INSECT); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); @@ -7977,6 +8045,8 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_CORPSE, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_ATTACKRANGE, 1, 2, NA, NULL); // just buzz around + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addrace(R_GIANTBLOWFLY, "giant blowfly", 2, 'i', C_GREY, MT_FLESH, RC_INSECT); lastrace->baseid = R_GIANTFLY; addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); @@ -8003,6 +8073,8 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); addflag(lastrace->flags, F_WANTS, OT_CORPSE, B_COVETS, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_ATTACKRANGE, 1, 2, NA, NULL); // just buzz around + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addrace(R_STIRGE, "stirge", 10, 'i', C_BROWN, MT_FLESH, RC_INSECT); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -8029,6 +8101,7 @@ void initrace(void) { addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "claws"); addflag(lastrace->flags, F_BODYPARTNAME, BP_RIGHTFINGER, NA, NA, "right foreclaw"); addflag(lastrace->flags, F_BODYPARTNAME, BP_LEFTFINGER, NA, NA, "left foreclaw"); + addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addrace(R_CENTIPEDE, "giant centipede", 3, 'w', C_GREEN, MT_FLESH, RC_INSECT); addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); @@ -8052,6 +8125,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_WALK, 1, NA, "^scuttling"); addflag(lastrace->flags, F_TREMORSENSE, 3, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addrace(R_GLOWBUG, "glowbug", 1, 'i', C_WHITE, MT_FLESH, RC_INSECT); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -8076,6 +8150,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOISETEXT, N_FLY, 2, NA, "^buzzing"); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); // demons addrace(R_DRETCH, "dretch", 30, '&', C_BROWN, MT_FLESH, RC_DEMON); @@ -8420,10 +8495,11 @@ void initrace(void) { } else if (r->raceclass->id == RC_DEMON) { addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_MATVULN, MT_SILVER, 200, NA, NULL); + addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); } else if (r->raceclass->id == RC_GOD) { addflag(r->flags, F_PIETY, 100, NA, NA, NULL); addflag(r->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addflag(r->flags, F_MORALE, 10, NA, NA, NULL); + addflag(r->flags, F_MORALE, 30, NA, NA, NULL); addflag(r->flags, F_BREATHWATER, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); @@ -8431,7 +8507,6 @@ void initrace(void) { addflag(r->flags, F_DTIMMUNE, DT_POISONGAS, NA, NA, NULL); addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL); addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL); - addflag(r->flags, F_MORALE, 40, NA, NA, NULL); } else if (r->raceclass->id == RC_MAGIC) { addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); } else if (r->raceclass->id == RC_PLANT) { @@ -8441,8 +8516,10 @@ void initrace(void) { addflag(r->flags, F_DTVULN, DT_COLD, NA, NA, NULL); addflag(r->flags, F_DTVULN, DT_DECAY, NA, NA, NULL); addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL); + addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); } else if (r->raceclass->id == RC_SLIME) { addflag(lastrace->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); } else if (r->raceclass->id == RC_UNDEAD) { addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); @@ -8452,6 +8529,7 @@ void initrace(void) { addflag(r->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL); addflag(r->flags, F_DTVULN, DT_HOLY, NA, NA, NULL); addflag(r->flags, F_SEEINDARK, B_TRUE, NA, NA, NULL); + addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); } // fill in missins alignments @@ -8548,6 +8626,7 @@ void initskills(void) { addskilldesc(SK_SHIELDS, PR_INEPT, "- Without this skill, shield accuracy penalties are tripled.", B_FALSE); addskilldesc(SK_SHIELDS, PR_NOVICE, "^gShield accuracy penalties are reduced by 5%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gShield accuracy penalties are reduced by 10%.^n", B_FALSE); + addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gYou gain the 'shield bash' ability.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_ADEPT, "^gShield accuracy penalties are reduced by 15%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_SKILLED, "^gShield accuracy penalties are reduced by 20%.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_EXPERT, "^gShield accuracy penalties are reduced by 25%.^n", B_FALSE); diff --git a/data/hiscores.db b/data/hiscores.db index c09383cc6491a14e095c25ee66ddee774bfdf1ad..f042e0fdbc865f2066557474ac1992c7d34ac971 100644 GIT binary patch delta 149 zcmZp$Xt0szOgWzk;}w~je$wn)SS_M@svQ)78X0AUSL6McA%i%W^t*Pi~#THB((ql delta 61 zcmV-D0K)%(IDj~i8v%8(9OwrFNdl9T2MCj~arptWlL~PS76}3u00Yhgl>=M@CIasQ Tw*r3xP68LPas2_a7aHjSRlySZ diff --git a/defs.h b/defs.h index 34f055d..983246f 100644 --- a/defs.h +++ b/defs.h @@ -107,7 +107,7 @@ #define B_BIG (-1) // Limits -#define MAXCANDIDATES 200 +#define MAXCANDIDATES 400 // must be >= max # of spells/abilities #define MAXCHOICES 400 #define MAXDEPTH 25 // max dungeon depth #define MAXDIR_ORTH 4 @@ -295,6 +295,7 @@ enum RELATIVEDIR { #define HUNGERCONST 500 #define STAMREGEN (0.3) // base amount of stamina to regain each turn +#define STAMTOATTACK ((float)STAMREGEN+0.2) // base amount of stamina to attack // Time periods #define TM_DRUNKTIME (10) // how long it takes for alcohol to wear off @@ -1287,6 +1288,7 @@ enum OBTYPE { OT_A_PRAY, OT_A_RAGE, OT_A_REPAIR, + OT_A_SHIELDBASH, OT_A_SONICBOLT, OT_A_SPRINT, OT_A_STUDYSCROLL, @@ -2062,6 +2064,7 @@ enum FLAG { // lifeform flags / lf flags / monster flags F_ALIGNMENT, // v0 = al_good, al_neutral, al_evil. default neutral. F_PIETY, // for god lifeforms - tracks player's piety with them + F_MOVED, // lf purposely moved in their last turn. F_PRAYEDTO, // player has prayed to this god before. F_GAVEMONEY, // v0 tracks how much money we gave away this turn // used for r_godgreed anger effects. @@ -2329,6 +2332,7 @@ enum FLAG { F_MORALE, // gain +v0 in morale checks. F_SPOTTED, // you have spotted hiding lf id v0. you lsoe this if they // go out of sight. + F_TIMID, // monster will only move close if behind its target. // special attack flags F_AIMEDSTRIKE, // next attack is an aimed strike F_COMBOSTRIKE, // lf is performing a combination strike diff --git a/flag.c b/flag.c index 7b0fbbc..143584f 100644 --- a/flag.c +++ b/flag.c @@ -381,6 +381,7 @@ int flagcausesredraw(lifeform_t *lf, enum FLAG fid) { case F_DETECTOBS: case F_ENHANCESMELL: case F_FASTMOVE: + case F_FEIGNINGDEATH: case F_HIDING: case F_INVISIBLE: case F_PRODUCESLIGHT: diff --git a/io.c b/io.c index 7e99a06..5bc0ad5 100644 --- a/io.c +++ b/io.c @@ -9791,14 +9791,32 @@ void showlfstats(lifeform_t *lf, int showall) { // traits based on the monster's bevaviour. // only known if you've studied this creature type a bit. if (showall || (lorelev >= PR_BEGINNER)) { - // sleeping habits + // morale and sleeping habits if (!isplayer(lf)) { + int morale; + char moralebuf[BUFLEN]; if (lfhasflag(lf, F_NOCTURNAL)) { mvwprintw(mainwin, y, 0, "It normally sleeps during the day."); y++; } if (lfhasflag(lf, F_DIURNAL)) { mvwprintw(mainwin, y, 0, "It normally sleeps during the night."); y++; } + morale = getmorale(lf); + if (morale >= 30) { + strcpy(moralebuf, "commanding"); + } else if (morale >= 20) { + strcpy(moralebuf, "fearless"); + } else if (morale >= 10) { + strcpy(moralebuf, "bold"); + } else if (morale >= 5) { + strcpy(moralebuf, "confident"); + } else if (morale >= 0) { + strcpy(moralebuf, "hesitant"); + } else { + strcpy(moralebuf, "nervous"); + } + mvwprintw(mainwin, y, 0, "It looks %s.", moralebuf); y++; + } // eating habits if (lfhasflag(lf, F_CARNIVORE)) { diff --git a/lf.c b/lf.c index abf957e..558e9ec 100644 --- a/lf.c +++ b/lf.c @@ -3368,8 +3368,10 @@ int fall(lifeform_t *lf, lifeform_t *fromlf, int announce) { if (isdead(lf)) return B_TRUE; if (isprone(lf)) return B_TRUE; - if (lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET)) { - return B_TRUE; + if (!isairborne(lf)) { + if ((lfhasflag(lf, F_STABILITY) || !hasbp(lf, BP_FEET))) { + return B_TRUE; + } } getlfname(lf,lfname); @@ -3450,7 +3452,7 @@ void fightback(lifeform_t *lf, lifeform_t *attacker) { addflag(lf->flags, F_NOHIRE, B_TRUE, NA, NA, NULL); } - if (willflee(lf)) { + if (mightflee(lf)) { scare(lf, attacker, PERMENANT, 0); } else { lifeform_t *l; @@ -3809,6 +3811,11 @@ void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose) { // stop targetting anyone or going anywhere loseaitargets(lf); + + // if no morale left, become timid for twice the flee time + if (!getmorale(lf)) { + addtempflag(lf->flags, F_TIMID, NA, NA, NA, NULL, (howlong == PERMENANT) ? howlong : (howlong*2)); + } } int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong) { @@ -4544,7 +4551,7 @@ int getattackspeed(lifeform_t *lf) { float getattackstamloss(lifeform_t *lf) { object_t *w; float loss; - loss = ((float)STAMREGEN+0.2); + loss = STAMTOATTACK; w = getweapon(lf); if (w) { @@ -5494,6 +5501,13 @@ int getmiscastchance(lifeform_t *lf) { return chance; } +int getmorale(lifeform_t *lf) { + flag_t *f; + f = hasflag(lf->flags, F_MORALE); + if (f) return f->val[0]; + return 0; +} + int getnightvisrange(lifeform_t *lf) { int range = 0; // default flag_t *f; @@ -6194,6 +6208,23 @@ int getstamina(lifeform_t *lf) { return (int)floor(lf->stamina); } +float getstamregen(lifeform_t *lf) { + float regenrate = STAMREGEN; + if (lfhasflagval(lf, F_INJURY, IJ_WINDPIPECRUSHED, NA, NA, NULL)) { + regenrate = 0.2; // override everything else + } else { + if (lfhasflag(lf, F_ASLEEP)) { + regenrate = pctof(200, regenrate); + } + if (ispoisoned(lf)) { + regenrate = pctof(50, regenrate); + } + } + limitf(®enrate, 0, NA); + return regenrate; +} + + char *getplayername(char *buf) { flag_t *f; f = hasflag(player->flags, F_NAME); @@ -6934,7 +6965,7 @@ int getturnspeed(lifeform_t *lf) { } -void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking) { +void getwantdistance(lifeform_t *lf, lifeform_t *victim, int *min, int *max, int attacking) { flag_t *f; // default - run into them *min = 0; @@ -6945,6 +6976,17 @@ void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking) { *min = f->val[0]; *max = f->val[1]; } + // if you're timid, it means you will only go close if you are + // behind them. + if (victim && lfhasflag(lf, F_TIMID)) { + // if not already adjacent... + if (getcelldist(lf->cell,victim->cell) >= 2) { + if ((*min < 2) && !isbehind(lf, victim)) { + *min = 2; + if (*max < *min) *max = *min; + } + } + } } else { // default - stay with 1-3 cells *min = 1; @@ -6955,6 +6997,7 @@ void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking) { *max = f->val[1]; } } + } @@ -7296,13 +7339,13 @@ void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype) { } -int giveskill(lifeform_t *lf, enum SKILL id) { - flag_t *f, *newf; +flag_t *giveskill(lifeform_t *lf, enum SKILL id) { + flag_t *f = NULL, *newf; skill_t *sk; sk = findskill(id); if (!sk) { - return B_TRUE; + return NULL; } f = lfhasflagval(lf, F_HASSKILL, id, NA, NA, NULL); @@ -7329,13 +7372,19 @@ int giveskill(lifeform_t *lf, enum SKILL id) { // remember that these from from a SKILL, so that // they are invalidated if we get polymorphed. if (id == SK_ATHLETICS) { - newf = addflag(lf->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); - newf->lifetime = FROMSKILL; + newf = hasflagval(lf->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); + if (!newf) { + newf = addflag(lf->flags, F_CANWILL, OT_A_SPRINT, NA, NA, NULL); + newf->lifetime = FROMSKILL; + } } else if (id == SK_COOKING) { makeknown(OT_POT_WATER); } else if (id == SK_LORE_ARCANA) { - newf = addflag(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL); - newf->lifetime = FROMSKILL; + newf = hasflagval(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL); + if (!newf) { + newf = addflag(lf->flags, F_CANWILL, OT_A_INSPECT, NA, NA, NULL); + newf->lifetime = FROMSKILL; + } } else if (id == SK_METALWORK) { newf = hasflagval(lf->flags, F_CANWILL, OT_A_REPAIR, NA, NA, NULL); if (!newf) { @@ -7388,6 +7437,11 @@ int giveskill(lifeform_t *lf, enum SKILL id) { lf->losdirty = B_TRUE; if (isplayer(lf)) needredraw = B_TRUE; } + } else if (id == SK_SHIELDS) { + if (f->val[1] == PR_BEGINNER) { + newf = addflag(lf->flags, F_CANWILL, OT_A_SHIELDBASH, NA, NA, NULL); + newf->lifetime = FROMSKILL; + } } else if (id == SK_SPELLCASTING) { if (f->val[1] == PR_SKILLED) { newf = hasflagval(lf->flags, F_CANWILL, OT_A_STUDYSCROLL, NA, NA, NULL); @@ -7467,24 +7521,18 @@ int giveskill(lifeform_t *lf, enum SKILL id) { drawstatus(); } - return B_FALSE; + return f; } -int giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev) { - flag_t *f; +flag_t *giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev) { + flag_t *f = NULL; f = lfhasflagval(lf, F_HASSKILL, id, NA, NA, NULL); - if (!f) { - // give one rank of the skill - giveskill(lf, id); - f = lfhasflagval(lf, F_HASSKILL, id, NA, NA, NULL); + while (!f || (f->val[1] < slev)) { + // give another rank + f = giveskill(lf, id); + if (!f) break; } - - if (f) { - f->val[1] = slev; - } else { - assert(1 == 0); - } - return B_FALSE; + return f; } // give start objects from a particular flagpile @@ -8562,16 +8610,16 @@ int haslos_fast(lifeform_t *viewer, cell_t *dest) { return B_FALSE; } -int isairborne(lifeform_t *lf) { +enum FLAG isairborne(lifeform_t *lf) { if (!lf) return B_FALSE; if (lfhasflag(lf, F_FLYING)) { - return B_TRUE; + return F_FLYING; } else if (lfhasflag(lf, F_LEVITATING)) { - return B_TRUE; + return F_LEVITATING; } else if (lfhasflag(lf, F_ICESLIDE)) { - return B_TRUE; + return F_LEVITATING; } - return B_FALSE; + return F_NONE; } int isaquatic(lifeform_t *lf) { @@ -10656,6 +10704,37 @@ int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o) { return B_TRUE; } +// will the lf flee after taking damage? +int mightflee(lifeform_t *lf) { + flag_t *f; + enum ATTRBRACKET iqb; + + if (hasflag(lf->flags, F_NOFLEE)) { + return B_FALSE; + } + + if (hasflag(lf->flags, F_FLEEONDAM)) { + return B_TRUE; + } + + f = hasflag(lf->flags, F_FLEEONHPPCT); + if (f) { + if (gethppct(lf) <= f->val[0]) { + return B_TRUE; + } + } + + iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL); + if (iqb >= AT_AVERAGE) { + if (!skillcheck(lf, SC_MORALE, (100 - gethppct(lf))/2, 0)) { + return B_TRUE; + } + } + + return B_FALSE; +} + + int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) { if (isplayer(lf)) { @@ -10679,7 +10758,7 @@ int modattr(lifeform_t *lf, enum ATTRIB attr, int amt) { // enforce limits limit(&lf->att[attr], 0, 18); - if ((gamemode == GM_GAMESTARTED) && (amt != 0) && (isplayer(lf) || cansee(player, lf))) { + if (lf->born && (gamemode == GM_GAMESTARTED) && (amt != 0) && (isplayer(lf) || cansee(player, lf))) { char lfname[BUFLEN], verb[BUFLEN], adverb[BUFLEN]; getlfname(lf, lfname); if (isplayer(lf)) strcpy(verb, "feel"); @@ -10842,6 +10921,21 @@ float modifybystat(float num, lifeform_t *lf, enum ATTRIB att) { return newnum; } +void modmorale(lifeform_t *lf, int howmuch) { + flag_t *mf; + mf = hasflag(lf->flags, F_MORALE); + if (mf) { + mf->val[0] += howmuch; + if (mf->val[0] <= 0) { + killflag(mf); + } + } else { + if (howmuch > 0) { + addflag(lf->flags, F_MORALE, howmuch, NA, NA, NULL); + } + } +} + void modstamina(lifeform_t *lf, float howmuch) { float orig; orig = getstamina(lf); @@ -11118,8 +11212,10 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume, if (!ispeaceful(l) || onein(6)) { char lfname[BUFLEN]; turntoface(l, c); - getlfname(l, lfname); - msg("%s turns to face you.", lfname); + if (!lfhasflag(l, F_FEIGNINGDEATH)) { + getlfname(l, lfname); + msg("%s turns to face you.", lfname); + } } } } @@ -11486,6 +11582,7 @@ void precalclos_new(lifeform_t *lf) { assert(nendcells < MAXVISLIMIT); // look in the lf's field of vision arc + //for (ang = 0; ang < 360; ang += 30) { for (nn = 0; nn < nendcells; nn++) { int keepgoing = B_TRUE; @@ -12063,9 +12160,8 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t // returns TRUE if something happened int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { - int nfailures = 0; - int i; - int penalty = 0; + int nfailures = 0,nsuccesses = 0,penalty = 0,i; + int nchecks; if (!scarer) return B_FALSE; // immune to fear? @@ -12098,18 +12194,29 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { } } } - // modify by charisma: -3 to 3 scarerbonus += (getstatmod(lf, A_CHA) / 15); - // three checks - nfailures = 0; - for (i = 0; i < 3; i++) { + // if you have morale left, you make 3 checks. chance of not fleeing at all. + // if you DONT have morale left, the first check always fails. + if (getmorale(lf)) { + nfailures = 0; + nchecks = 3; + } else { + nfailures = 1; + nchecks = 2; + // two checks - first one always fails. + } + for (i = 0; i < nchecks; i++) { if (!skillcheckvs(lf, SC_MORALE, -penalty, scarer, SC_MORALE, scarerbonus)) { nfailures++; } } + nsuccesses = 3 - nfailures; + + // modify morale + modmorale(lf, nsuccesses - nfailures); if (nfailures == 1) { // cower @@ -12577,11 +12684,9 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r case SC_LEARNMAGIC: attrib = (getattr(lf, A_IQ) / 2) + (getskill(lf, SK_SPELLCASTING)/2) + lf->level; break; - case SC_MORALE: // based on level/hitdice and size. - attrib = (lf->hp / 4); - attrib += ((float)getlfsize(lf) * 1.5); - f = lfhasflag(lf, F_MORALE); - if (f) attrib += f->val[0]; + case SC_MORALE: // based on morale, level/hitdice and size. + attrib = getmorale(lf) + gethitdice(lf); + attrib += getlfsize(lf); break; case SC_SLIP: case SC_FALL: @@ -12689,7 +12794,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r break; } } else if (ct == SC_MORALE) { - othermod += (getstatmod(lf, A_WIS) / 10); // ie. -5 to 5 + othermod += (getstatmod(lf, A_WIS) / 30); // ie. -1 to 1 } else if (ct == SC_OPENLOCKS) { enum SKILLLEVEL slev; slev = getskill(lf, SK_LOCKPICKING); @@ -13109,25 +13214,14 @@ void startlfturn(lifeform_t *lf) { } if (lossamt) modstamina(lf, -lossamt); } else { - if (getstamina(lf) < getmaxstamina(lf)) { - float regenrate = STAMREGEN; - if (lfhasflagval(lf, F_INJURY, IJ_WINDPIPECRUSHED, NA, NA, NULL)) { - regenrate = 0.2; // override everything else - } else { - if (lfhasflag(lf, F_ASLEEP)) { - regenrate = pctof(200, regenrate); - } - if (ispoisoned(lf)) { - regenrate = pctof(50, regenrate); - } + // if we didn't move last turn, regenerate stamina. + if (!killflagsofid(lf->flags, F_MOVED)) { + if (getstamina(lf) < getmaxstamina(lf)) { + modstamina(lf, getstamregen(lf)); } - limitf(®enrate, 0, NA); - - modstamina(lf, regenrate); } } - // god piety gets restored over time if (isplayer(lf)) { for (i = 0; i < ngodlfs; i++) { @@ -14887,6 +14981,8 @@ int validateraces(void) { int i; cell_t fakecell; map_t fakemap; + flag_t *retflag[MAXCANDIDATES]; + int nretflags; // generate xp list genxplist(); @@ -14949,24 +15045,30 @@ int validateraces(void) { } } else if (f->id == F_STARTATT) { if (strlen(f->text) && (f->val[1] != NA)) { - printf("ERROR in race '%s' - F_STARTATT has both text range and val1.", r->name); + printf("ERROR in race '%s' - F_STARTATT has both text range and val1.\n", r->name); goterror = B_TRUE; } } else if (f->id == F_NOISETEXT) { if (f->val[0] == N_FLY) { if (!hasflag(r->flags, F_FLYING) && !hasflag(r->flags, F_LEVITATING)) { - printf("ERROR in race '%s' - has NOISETEXT N_FLY but isn't flying.", r->name); + printf("ERROR in race '%s' - has NOISETEXT N_FLY but isn't flying.\n", r->name); goterror = B_TRUE; } } if (f->val[1] == NA) { - printf("ERROR in race '%s' - has NOISETEXT but no volume.", r->name); - goterror = B_TRUE; + printf("ERROR in race '%s' - has NOISETEXT but no volume.\n", r->name); + goterror = B_TRUE; } } - } + } // end foreach flag + + getflags(lf->flags, retflag, &nretflags, F_MORALE, F_NONE); + if (nretflags > 1) { + printf("ERROR in race '%s' - has multiple F_MORALE flags.\n", r->name); + goterror = B_TRUE; + } // xp check... calcxp(lf); @@ -15827,33 +15929,5 @@ int willburden(lifeform_t *lf, object_t *o, int howmany) { return B_FALSE; } -// will the lf flee after taking damage? -int willflee(lifeform_t *lf) { - enum ATTRBRACKET iqb; - flag_t *f; - - - if (hasflag(lf->flags, F_NOFLEE)) { - return B_FALSE; - } - - if (hasflag(lf->flags, F_FLEEONDAM)) { - return B_TRUE; - } - - iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL); - if ((iqb >= AT_GTAVERAGE) && isbleeding(lf)) { - return B_TRUE; - } - - f = hasflag(lf->flags, F_FLEEONHPPCT); - if (f) { - if (gethppct(lf) <= f->val[0]) { - return B_TRUE; - } - } - - return B_FALSE; -} diff --git a/lf.h b/lf.h index 7cf7bb5..75898e7 100644 --- a/lf.h +++ b/lf.h @@ -148,6 +148,7 @@ enum LFCONDITION getlfcondition(lifeform_t *lf); enum SKILLLEVEL getmaxskilllevel(lifeform_t *lf, enum SKILL skid); int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions); int getmiscastchance(lifeform_t *lf); +int getmorale(lifeform_t *lf); int getnightvisrange(lifeform_t *lf); char *getlfconditionname(enum LFCONDITION cond); object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp); @@ -184,6 +185,7 @@ object_t *getsecmeleeweapon(lifeform_t *lf); object_t *getshield(lifeform_t *lf); int getspellspeed(lifeform_t *lf); int getstamina(lifeform_t *lf); +float getstamregen(lifeform_t *lf); char *getplayername(char *buf); char *getplayernamefull(char *buf); int getpoisondamchance(enum POISONTYPE ptype); @@ -214,15 +216,15 @@ char *getskillname(enum SKILL id ); char *getskilllevelname(enum SKILLLEVEL sl); int getthrowspeed(int str); int getturnspeed(lifeform_t *lf); -void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking); +void getwantdistance(lifeform_t *lf, lifeform_t *victim, int *min, int *max, int attacking); object_t *getweapon(lifeform_t *lf); enum SKILLLEVEL getweaponskill(lifeform_t *lf, object_t *o); long getxpforlev(int level); void givejob(lifeform_t *lf, enum JOB jobid); int givemoney(lifeform_t *from, lifeform_t *to, int amt); void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype); -int giveskill(lifeform_t *lf, enum SKILL id); -int giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev); +flag_t *giveskill(lifeform_t *lf, enum SKILL id); +flag_t *giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev); void givestartobs(lifeform_t *lf, object_t *targob, flagpile_t *fp); void givestartskills(lifeform_t *lf, flagpile_t *fp); map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs); @@ -246,7 +248,7 @@ int haslof(cell_t *src, cell_t *dest, enum LOFTYPE loftype, cell_t **newdest); int haslos(lifeform_t *viewer, cell_t *dest); int haslos_fast(lifeform_t *viewer, cell_t *dest); void interrupt(lifeform_t *lf); -int isairborne(lifeform_t *lf); +enum FLAG isairborne(lifeform_t *lf); int isaquatic(lifeform_t *lf); int isbehind(lifeform_t *lf, lifeform_t *otherlf); int isbleeding(lifeform_t *lf); @@ -304,9 +306,11 @@ void makepeaceful(lifeform_t *lf); lifeform_t *makezombie(object_t *o); void mayusespellschool(flagpile_t *fp, enum SPELLSCHOOL ss, enum FLAG how); int meetsattreq(lifeform_t *lf, flag_t *f, object_t *o); +int mightflee(lifeform_t *lf); int modattr(lifeform_t *lf, enum ATTRIB attr, int amt); void modhunger(lifeform_t *lf, int amt); float modifybystat(float num, lifeform_t *lf, enum ATTRIB att); +void modmorale(lifeform_t *lf, int howmuch); void modstamina(lifeform_t *lf, float howmuch); int needstorest(lifeform_t *lf, char *validchars); int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nt, int volume, char *text, char *seetext); @@ -377,5 +381,4 @@ int wear(lifeform_t *lf, object_t *o); int weild(lifeform_t *lf, object_t *o); int willbleedfrom(lifeform_t *lf, enum BODYPART bp); int willburden(lifeform_t *lf, object_t *o, int howmany); -int willflee(lifeform_t *lf); //int youhear(cell_t *c, char *text); diff --git a/move.c b/move.c index 006b7c6..5a9765c 100644 --- a/move.c +++ b/move.c @@ -428,7 +428,7 @@ int diropposite(int dir) { int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) { int dir; int tries = 0; - int moveok; + int moveok,rv; enum ERROR why; // find a valid direction @@ -470,7 +470,12 @@ int dorandommove(lifeform_t *lf, int badmovesok, int restonfail) { } } } - return trymove(lf, dir, B_TRUE, B_FALSE); + rv = trymove(lf, dir, B_TRUE, B_FALSE); + if (rv && restonfail) { + // ie move failed + rest(lf, B_TRUE); + } + return rv; } @@ -1910,7 +1915,25 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { object_t *o, *nexto; char buf[BUFLEN]; flag_t *f; + int attacking = B_FALSE; + if (cell && cell->lf && !canswapwith(lf, cell->lf)) attacking = B_TRUE; + + // too tired? (if we're attacking, leave the 'too tired' message to + // the attack code) + if (!attacking && !getstamina(lf)) { + if (isplayer(lf)) { + msg("You are too tired to move!"); + } else { + // this doesn't count as an action for the player, but it + // does for monsters + taketime(lf, getmovespeed(lf)); + } + reason = E_OK; + return B_TRUE; + } + + // checks which only happen if we're MOVING (ie not attacking) // demon in pentagram if ((getraceclass(lf) == RC_DEMON) && hasob(lf->cell->obpile, OT_PENTAGRAM)) { if (isplayer(lf)) { @@ -1926,176 +1949,199 @@ int initiatemove(lifeform_t *lf, cell_t *cell, int *didmsg) { } // gravboosted - if (lfhasflag(lf, F_GRAVBOOSTED)) { - // make a saving throw to move - if (!skillcheck(lf, SC_STR, 25, 0)) { - if (isplayer(lf)) { - msg("You try to %s but are unable to %s!", - isprone(lf) ? "stand" : "move", - isprone(lf) ? "lift your arms" : "lift your feet"); - if (didmsg) *didmsg = B_TRUE; - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s tries to %s but is unable to %s!", lfname, - isprone(lf) ? "stand" : "move", - isprone(lf) ? "get up" : "lift its feet"); - if (didmsg) *didmsg = B_TRUE; - } - reason = E_OK; - taketime(lf, getmovespeed(lf)); - return B_TRUE; - } - } - - // sticky objects in current cell? - for (o = lf->cell->obpile->first ; o ; o = nexto) { - nexto = o->next; - - f = obrestrictsmovement(o, lf); - if (f) { - char lfname[BUFLEN]; - int diff; - int checkmod = 0; - int getsweaker; - - if ((o->type->id == OT_WEB) && isairborne(lf)) { - checkmod -= 5; - } - - getlfname(lf,lfname); - getobname(o, buf, o->amt); - - // for stacks of sticky objects, each one after the first adds - // quarter its difficuly. ie: - // 1 x object with f_sticky:20, difficult is 20 - // 2 x object with f_sticky:20, difficult is 25 - // 3 x object with f_sticky:20, difficult is 30 - // etc - // can you break free? - diff = f->val[0]; - if (o->amt > 1) { - diff = (o->amt - 1) * ((float)f->val[0] / 4.0); - } - getsweaker = f->val[1]; - if (skillcheck(lf, SC_STR, diff, checkmod)) { + if (!attacking) { + if (lfhasflag(lf, F_GRAVBOOSTED)) { + // make a saving throw to move + if (!skillcheck(lf, SC_STR, 25, 0)) { if (isplayer(lf)) { - msg("You tear free from %s!", buf); + msg("You try to %s but are unable to %s!", + isprone(lf) ? "stand" : "move", + isprone(lf) ? "lift your arms" : "lift your feet"); if (didmsg) *didmsg = B_TRUE; } else if (cansee(player, lf)) { - msg("%s tears free from %s!", lfname, buf); + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s tries to %s but is unable to %s!", lfname, + isprone(lf) ? "stand" : "move", + isprone(lf) ? "get up" : "lift its feet"); if (didmsg) *didmsg = B_TRUE; } - killob(o); - continue; - } else { - // failed - object gets a little less sticky - if (isplayer(lf)) { - msg("You struggle in %s!", buf); - if (didmsg) *didmsg = B_TRUE; - } else if (cansee(player, lf)) { - msg("%s struggles in %s!", lfname, buf); - if (didmsg) *didmsg = B_TRUE; - } - - if (getsweaker) { - takedamage(o, 1, DT_DIRECT); - } - - taketime(lf, getmovespeed(lf)); - reason = E_OK; - return B_TRUE; + taketime(lf, getmovespeed(lf)); + return B_TRUE; + } + } + + // sticky objects in current cell? + for (o = lf->cell->obpile->first ; o ; o = nexto) { + nexto = o->next; + + f = obrestrictsmovement(o, lf); + if (f) { + char lfname[BUFLEN]; + int diff; + int checkmod = 0; + int getsweaker; + + if ((o->type->id == OT_WEB) && isairborne(lf)) { + checkmod -= 5; + } + + getlfname(lf,lfname); + getobname(o, buf, o->amt); + + // for stacks of sticky objects, each one after the first adds + // quarter its difficuly. ie: + // 1 x object with f_sticky:20, difficult is 20 + // 2 x object with f_sticky:20, difficult is 25 + // 3 x object with f_sticky:20, difficult is 30 + // etc + // can you break free? + diff = f->val[0]; + if (o->amt > 1) { + diff = (o->amt - 1) * ((float)f->val[0] / 4.0); + } + getsweaker = f->val[1]; + if (skillcheck(lf, SC_STR, diff, checkmod)) { + if (isplayer(lf)) { + msg("You tear free from %s!", buf); + if (didmsg) *didmsg = B_TRUE; + } else if (cansee(player, lf)) { + msg("%s tears free from %s!", lfname, buf); + if (didmsg) *didmsg = B_TRUE; + } + killob(o); + continue; + } else { + // failed - object gets a little less sticky + if (isplayer(lf)) { + msg("You struggle in %s!", buf); + if (didmsg) *didmsg = B_TRUE; + } else if (cansee(player, lf)) { + msg("%s struggles in %s!", lfname, buf); + if (didmsg) *didmsg = B_TRUE; + } + + if (getsweaker) { + takedamage(o, 1, DT_DIRECT); + } + + taketime(lf, getmovespeed(lf)); + + reason = E_OK; + return B_TRUE; + } } } } // are we on the ground? - if (isprone(lf)) { - int howlong; - float quartermax; - int units; + if (isprone(lf) && (!isplayer(lf) || !attacking)) { + int willstand = B_FALSE; if (isplayer(lf)) { - msg("You stand up."); - } else if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf, lfname); - msg("%s stands up.",lfname); + if (!attacking) { + // player can attack from the ground + willstand = B_TRUE; + } + } else { + // monsters always stand up + willstand = B_TRUE; } - killflagsofid(lf->flags, F_PRONE); - killflagsofid(lf->flags, F_FEIGNINGDEATH); - // time to get up depends on armour - // 1*movespeed for every 1/4 of maxcarryweight being worn. - quartermax = getmaxcarryweight(lf) / 4; - units = (getequippedweight(lf) / quartermax)+1; - howlong = getmovespeed(lf)*units; - taketime(lf, howlong); + + if (willstand) { + if (isplayer(lf)) { + msg("You stand up."); + } else if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf, lfname); + msg("%s stands up.",lfname); + } + killflagsofid(lf->flags, F_PRONE); + killflagsofid(lf->flags, F_FEIGNINGDEATH); + + reason = E_OK; - reason = E_OK; - return B_TRUE; + // monsters don't take time to stand up if they were feigning death! + if (!isplayer(lf) && lfhasflag(lf, F_FEIGNINGDEATH)) { + return B_FALSE; + } else { + int howlong; + float quartermax; + int units; + // time to get up depends on armour + // 1*movespeed for every 1/4 of maxcarryweight being worn. + quartermax = getmaxcarryweight(lf) / 4; + units = (getequippedweight(lf) / quartermax)+1; + howlong = getmovespeed(lf)*units; + taketime(lf, howlong); + } + return B_TRUE; + } } // slipping on something before moving? - if (!isairborne(lf)) { - int slip; - object_t *slipob; + if (!attacking) { + if (!isairborne(lf)) { + int slip; + object_t *slipob; - if (!lfhasflag(lf, F_SNEAK)) { - slip = getslipperyness(lf->cell, &slipob); - if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { - if (!slipon(lf, slipob)) { - if (didmsg) *didmsg = B_TRUE; - // don't move - reason = E_OK; - return B_TRUE; - } - } + if (!lfhasflag(lf, F_SNEAK)) { + slip = getslipperyness(lf->cell, &slipob); + if (slip && !skillcheck(lf, SC_SLIP, slip, 0)) { + if (!slipon(lf, slipob)) { + if (didmsg) *didmsg = B_TRUE; + // don't move + reason = E_OK; + return B_TRUE; + } + } + } } - } - // check for cursed objects in new cell + animals - // do this AFTER checking if we will move, so that - // they will actually try the move and fail (this lets - // the player find out about the cursed object). - // - // note however that if a monster is chasing a player (ie - // has F_TARGET,player) then they will simply avoid the cursed - // object rather than failing the movement. - if (cell) { - for (o = cell->obpile->first ; o ; o = nexto) { - nexto = o->next; - if (!isplayer(lf)) { - if ((o->blessed == B_CURSED) && (getraceclass(lf) == RC_ANIMAL) && !isairborne(lf)) { - if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf,lfname); - getobname(o, buf, o->amt); - msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); - o->blessknown = B_TRUE; - if (didmsg) *didmsg = B_TRUE; + // check for cursed objects in new cell + animals + // do this AFTER checking if we will move, so that + // they will actually try the move and fail (this lets + // the player find out about the cursed object). + // + // note however that if a monster is chasing a player (ie + // has F_TARGET,player) then they will simply avoid the cursed + // object rather than failing the movement. + if (cell) { + for (o = cell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (!isplayer(lf)) { + if ((o->blessed == B_CURSED) && (getraceclass(lf) == RC_ANIMAL) && !isairborne(lf)) { + if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf,lfname); + getobname(o, buf, o->amt); + msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); + o->blessknown = B_TRUE; + if (didmsg) *didmsg = B_TRUE; + } + taketime(lf, getmovespeed(lf)); + reason = E_OK; + // avoid this object in future + snprintf(buf, BUFLEN, "%ld",o->id); + addflag(lf->flags, F_AVOIDOB, B_CURSED, NA, NA, buf); + return B_TRUE; + } else if (lfhasflagval(lf, F_AVOIDOBTYPE, o->type->id, NA, NA, NULL)) { + if (cansee(player, lf)) { + char lfname[BUFLEN]; + getlfname(lf,lfname); + getobname(o, buf, o->amt); + msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); + o->blessknown = B_TRUE; + if (didmsg) *didmsg = B_TRUE; + } + taketime(lf, getmovespeed(lf)); + reason = E_OK; + // avoid this object in future + snprintf(buf, BUFLEN, "%ld",o->id); + addflag(lf->flags, F_AVOIDOB, NA, NA, NA, buf); + return B_TRUE; } - taketime(lf, getmovespeed(lf)); - reason = E_OK; - // avoid this object in future - snprintf(buf, BUFLEN, "%ld",o->id); - addflag(lf->flags, F_AVOIDOB, B_CURSED, NA, NA, buf); - return B_TRUE; - } else if (lfhasflagval(lf, F_AVOIDOBTYPE, o->type->id, NA, NA, NULL)) { - if (cansee(player, lf)) { - char lfname[BUFLEN]; - getlfname(lf,lfname); - getobname(o, buf, o->amt); - msg("%s %s away from %s!", lfname, isplayer(lf) ? "shy" : "shies", buf); - o->blessknown = B_TRUE; - if (didmsg) *didmsg = B_TRUE; - } - taketime(lf, getmovespeed(lf)); - reason = E_OK; - // avoid this object in future - snprintf(buf, BUFLEN, "%ld",o->id); - addflag(lf->flags, F_AVOIDOB, NA, NA, NA, buf); - return B_TRUE; } } } @@ -2309,6 +2355,14 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { return B_TRUE; } + // for the player, moving means that we don't regenerate stamina. + // this is the equivilant of losing the same amount of stamina which we + // would regenerate, only it avoids constantly redrawing the status + // bar every single move. + if (isplayer(lf)) { + addflag(lf->flags, F_MOVED, B_TRUE, NA, NA, NULL); + } + reason = E_OK; // remember last dir we walked @@ -2542,6 +2596,10 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) { } break; case E_LFINWAY: + if (initiatemove(lf, cell, &dontclearmsg)) { + // failed? + return B_TRUE; + } if (canswapwith(lf, cell->lf)) { lifeform_t *lfinway; // otherwise swap locations. diff --git a/nexus.c b/nexus.c index 097d9cd..0b4013b 100644 --- a/nexus.c +++ b/nexus.c @@ -777,6 +777,11 @@ void donextturn(map_t *map) { } } } + + // moved into a new map? stop turn. + if (who->cell->map != map) { + break; + } } if (hasflag(player->flags, F_ASLEEP)) { @@ -784,7 +789,7 @@ void donextturn(map_t *map) { } if (!isdead(who)) endlfturn(who); - } // end 'if who' + } // end 'if (who)' // check for death etc diff --git a/objects.c b/objects.c index 84c1421..1a7e521 100644 --- a/objects.c +++ b/objects.c @@ -855,6 +855,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes // we now have the objecttype! //////////////////////////////////// + if ((gamemode != GM_LOADING) && hasflag(ot->flags, F_ONEPERCELL)) { if (hasob(where, ot->id)) { if (db) dblog("DB: trying to add >1 ONEPERCELL object to a cell. (%s) bailing out.", ot->name); @@ -863,6 +864,13 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes } } + // water ob onto dirt -> mud + if ((ot->material->id == MT_WATER) && where->where) { + if (where->where->type->id == CT_DIRT) { + ot = findot(OT_MUDPOOL); + } + } + // override blessed status from flags... f = hasflag(ot->flags, F_STARTBLESSED); if (f) { @@ -1736,14 +1744,8 @@ objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material, void adjustdamhardness(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat) { // now check for hardness if (isphysicaldam(damtype)) { - material_t *m; - m = findmaterial(mat); - if (m) { - flag_t *f; - f = hasflag(m->flags, F_HARDNESS); - if (f && (*dam < f->val[0])) { - *dam = 0; - } + if (*dam < gethardness(mat)) { + *dam = 0; } } } @@ -2937,6 +2939,17 @@ void fragments(cell_t *centre, char *what, int speed, int howfar) { } } +int gethardness(enum MATERIAL matid) { + material_t *m; + m = findmaterial(matid); + if (m) { + flag_t *f; + f = hasflag(m->flags, F_HARDNESS); + if (f) return f->val[0]; + } + return 0; +} + void genhiddennames(void) { objecttype_t *ot; flag_t *f; diff --git a/objects.h b/objects.h index 7d42ea3..cf0c886 100644 --- a/objects.h +++ b/objects.h @@ -90,6 +90,7 @@ char *getfillingname(int nutrition); int getfirearmrange(object_t *o); int getfirearmspeed(object_t *o); glyph_t *getglyph(object_t *o); +int gethardness(enum MATERIAL matid); char *genhiddenname(enum OBCLASS id); char *gethiddenname(object_t *o); int getobattackdelay(object_t *o); diff --git a/spell.c b/spell.c index d8ec83d..50b3393 100644 --- a/spell.c +++ b/spell.c @@ -450,7 +450,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef if (target) { char targname[BUFLEN]; getlfname(target, targname); - msg("%s kill%s %s.", targname, isplayer(target) ? "" : "s", username); + if (isplayer(target)) { + msg("^gYou kill %s!", username); + } else { + msg("%s kills %s.", targname, username); + } } else { msg("%s dies.", username); } @@ -939,6 +943,88 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef // TODO: make this like eating/resting/etc ? taketime(user, getactspeed(user)); + } else if (abilid == OT_A_SHIELDBASH) { + object_t *shield; + char dirch; + flag_t *f; + int badshield = B_FALSE; + int shpenalty,mod; + char shname[BUFLEN], tname[BUFLEN]; + + if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { + if (isplayer(user)) msg("You lack the stability for a shield bash while swimming."); + return B_TRUE; + } + + shield = getshield(user); + if (!shield || !isshield(shield)) { + badshield = B_TRUE; + } + + if (badshield) { + if (isplayer(user)) msg("You need a shield equipped to perform a shield bash!"); + return B_TRUE; + } + getobname(shield, shname, 1); + + + f = hasflagval(shield->flags, F_EQUIPCONFER, F_SHIELDPENALTY, NA, NA, NULL); + if (f) { + shpenalty = adjustshieldpenalty(user, f->val[1]); + } else { + shpenalty = 0; + } + if (shpenalty) { + if (isplayer(user)) msg("Your %s is too cumbersome to bash with.",shname); + return B_TRUE; + } + + + // ask for direction + if (!targcell) { + dirch = askchar("Shield bash in which direction (- to cancel)", "yuhjklbn.-","-", B_FALSE); + if (dirch == '.') { + // yourself! + targcell = user->cell; + } else { + int dir; + dir = chartodir(dirch); + if (dir == D_NONE) { + if (isplayer(user)) msg("Cancelled."); + return B_TRUE ; + } else { + targcell = getcellindir(user->cell, dir); + } + } + } + + target = targcell->lf; + if (!target) { + if (isplayer(user)) msg("There is nobody there to attack!"); + return B_TRUE; + } + getlfname(target, tname); + + if (isplayer(user)) { + msg("You bash %s with your %s!",tname, noprefix(shname)); + } else if (cansee(player, user)) { + msg("%s bashes %s with %s!",username, tname, shname); + } + + + // only works if shield is hard + if (gethardness(shield->material->id)) { + // success depends on shield skill, relative lf size, target's evasion + mod = 0; + modifyforsize(&mod, user, target, 5, M_VAL); + if (mod > 0) mod = 0; + if (skillcheck(user, SC_SHIELDBLOCK, 5 + getevasion(target), mod)) { + stun(target, 2); + } + } + + // shield gets damaged + takedamage(shield, roll("1d3"), DT_DIRECT); } else if (abilid == OT_A_SONICBOLT) { int volume; @@ -1391,10 +1477,12 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef getchoicestr(&prompt, B_FALSE, B_TRUE); sk = (skill_t *)prompt.result; if (sk) { + enum SKILLLEVEL firstlev,wantlev; int i; ch = 'a'; + firstlev = getskill(user, sk->id) + 1; initprompt(&prompt, "How much will you learn this skill?"); - for (i = getskill(user, sk->id) + 1 ; i <= PR_MASTER; i++) { + for (i = firstlev ; i <= PR_MASTER; i++) { snprintf(buf, BUFLEN, "%s",getskilllevelname(i)); addchoice(&prompt, ch++, buf, buf, NULL, NULL); } @@ -1402,11 +1490,12 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef msg("You have already mastered this skill!"); return B_TRUE; } - getchoice(&prompt); + ch = getchoice(&prompt); + wantlev = firstlev + (ch - 'a'); - while (strcmp(getskilllevelname(getskill(user, sk->id)), prompt.choice[prompt.selection].text)) { - giveskill(user, sk->id); - } + //while (strcmp(getskilllevelname(getskill(user, sk->id)), prompt.choice[prompt.selection].text)) { + giveskilllev(user, sk->id, wantlev); + //} } else { msg("Cancelled."); } diff --git a/vaults/dirtroom.vlt b/vaults/dirtroom.vlt new file mode 100644 index 0000000..9574e1a --- /dev/null +++ b/vaults/dirtroom.vlt @@ -0,0 +1,16 @@ +@id:dirtroom +@map +random(2,2) +@end + +@legend +@end + +@flags +goesin:dungeon +autodoors:25 +autopop +fill(1,1,-2,-2) cell:dirt +rarity:common +@end +