#include #include #include #include #include #include #include "ai.h" #include "attack.h" #include "defs.h" #include "flag.h" #include "god.h" #include "io.h" #include "lf.h" #include "map.h" #include "move.h" #include "nexus.h" #include "objects.h" #include "spell.h" #include "text.h" extern int statdirty; extern WINDOW *mainwin; extern map_t *firstmap; extern map_t *heaven; extern race_t *firstrace, *lastrace; extern raceclass_t *firstraceclass, *lastraceclass; extern job_t *firstjob, *lastjob; extern skill_t *firstskill, *lastskill; extern objecttype_t *objecttype; extern lifeform_t *player; extern condset_t ccwalkable; lifeform_t *godlf[MAXGODS]; int ngodlfs = 0; void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { lifeform_t *god; int piety; char buf[BUFLEN]; enum PIETYLEV plev,oldplev; int dosay = B_FALSE; // don't please/anger gods while enraged. if (lfhasflag(player, F_RAGE)) return; if (lfhasflag(player, F_WINNER)) return; god = findgod(rid); if (hasequippedobid(player->pack, OT_AMU_PIETY)) { amt /= 2; limit(&amt, 1, NA); } oldplev = getpietylev(rid, NULL, NULL); modpiety(rid, -amt); piety = getpiety(rid); plev = getpietylev(rid, NULL, NULL); // if you have never prayed to this god before, finish now. if (!lfhasflag(god, F_PIETY)) { return; } // if you HAVE prayed to this god before, something bad will probably happen. switch (why) { case GA_ATTACKALLY: godsay(rid, B_TRUE, "How dare you attack an ally!"); break; case GA_ATTACKHELPLESS: godsay(rid, B_TRUE, "You would attack one who is helpless?"); break; case GA_ATTACKOBJECT: if (rid == R_GODTHIEVES) { godsay(rid, B_TRUE, "What are you, a common thug?"); break; } else if (rid == R_GODNATURE) { godsay(rid, B_TRUE, "You dare destroy my creations?"); break; } else { godsay(rid, B_TRUE, "You dare desecrate my symbols?"); break; } case GA_ASSAULT: if (rid == R_GODDEATH) { godsay(rid, B_TRUE, "You dare attack one of my servants?"); break; } else { godsay(rid, B_TRUE, "You dare attack an innocent?"); break; } case GA_COWARD: godsay(rid, B_TRUE, "Coward!"); break; case GA_EAT: godsay(rid, B_TRUE, "That is NOT acceptable for consumption!"); break; case GA_GODSTONE: switch (god->race->id) { case R_GODPURITY: sprintf(buf, "That is not yours to touch, mortal!"); break; case R_GODTHIEVES: sprintf(buf, "You dare to steal MY property?"); break; case R_GODDEATH: sprintf(buf, "A fleshling thinks they can challenge the lord of death?"); break; case R_GODFIRE: sprintf(buf, "THIIIEEEFFF!"); break; case R_GODLIFE: sprintf(buf, "NO! You have stolen the very essense of life!"); break; case R_GODMERCY: sprintf(buf, "NO!"); break; case R_GODNATURE: sprintf(buf, "You threaten the destruction of everything!"); break; case R_GODBATTLE: sprintf(buf, "Knave! Your theft constitutes a declaration of war!"); break; case R_GODMAGIC: sprintf(buf, "One does not comprehend the danger of One's find!"); break; default: break; } godsay(rid, B_TRUE, buf); break; case GA_HERESY: if (rid == R_GODFIRE) { godsay(rid, B_TRUE, "HERESY!"); } else if (rid == R_GODMAGIC) { godsay(rid, B_TRUE, "One's mundanity is offensive!"); } else { godsay(rid, B_TRUE, "Heresy!"); } break; case GA_MERCY: godsay(rid, B_TRUE, "You allowed my sacrifice to escape!"); break; case GA_MONEY: godsay(rid, B_TRUE, "Where is your sense of greed?!"); break; case GA_MURDER: godsay(rid, B_TRUE, "You have taken a life!"); break; case GA_PEACEHOUR: godsay(rid, B_TRUE, "You dare violate the sanctity of Glorana's Peace?"); break; break; case GA_PRAY: dosay = B_TRUE; break; case GA_POISON: godsay(rid, B_TRUE, "I do not condone the use of poison!"); break; case GA_RACE: godsay(rid, B_TRUE, "Your form offends me!"); break; case GA_SPELL: if (rid == R_GODBATTLE) { godsay(rid, B_TRUE, "A true warrior does not resort to magic!"); break; } else if (rid == R_GODFIRE) { godsay(rid, B_TRUE, "NO COLD MAGIC!"); break; } else if (rid == R_GODDEATH) { godsay(rid, B_TRUE, "The stink of your vile magic offends me!"); break; } else if (rid == R_GODLIFE) { godsay(rid, B_TRUE, "I will not tolerate such evil magics!"); break; } else { godsay(rid, B_TRUE, "Your magic offends me!"); break; } } // announce switch (plev) { case PL_ENRAGED: godsay(rid,dosay, "Witness the wrath of a god!"); break; case PL_FURIOUS: godsay(rid,dosay, "You go too far, mortal!"); break; case PL_ANGRY: godsay(rid,dosay, "You have angered me, mortal!"); break; case PL_INDIFFERENT: // ie. not angry yet... godsay(rid, dosay, "You are testing my patience, mortal!"); break; default: // ie. still happy break; } // bad stuff if (piety <= 0) { void *poss[MAXCANDIDATES]; object_t *o; flag_t *f; int isflag[MAXCANDIDATES]; int nposs = 0; enum ATTRIB a; // lose at least one god gift for (o = player->pack->first ; o ; o = o->next) { if (hasflagval(o->flags, F_GODGIFT, rid, NA, NA, NULL)) { poss[nposs] = o; isflag[nposs] = B_FALSE; nposs++; } } for (f = player->flags->first ; f ; f = f->next) { if ((f->lifetime == FROMGODGIFT) && (f->obfrom == god->race->id)) { poss[nposs] = f; isflag[nposs] = B_TRUE; nposs++; } } if (nposs) { int sel; msg("\"You are unworthy of my gifts, mortal!\""); sel = rnd(0,nposs-1); if (isflag[sel]) { killflag((flag_t *)poss[sel]); } else { obdie((object_t *)poss[sel]); } } // then... if (plev == PL_ANGRY) { int i,n; flag_t *retflag[MAXCANDIDATES]; int nretflags; lifeform_t *l; // minor bad stuff switch (rid) { case R_GODBATTLE: // rust your armour for (o = player->pack->first ; o ; o = o->next) { if (isarmour(o) && (o->type->material->id == MT_METAL)) { poss[nposs++] = o; } } if (nposs) { o = poss[rnd(0,nposs-1)]; msg("\"Let your armour reflect your actions!\""); makewet(o, R_TRUSTY); } else { o = getweapon(player); if (o) { msg("\"Let your weapon reflect your actions!\""); makeduller(o, 2); } } break; case R_GODDEATH: castspell(god, OT_S_PAIN, player, NULL, player->cell, NULL, NULL); castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell, NULL, NULL); // all undead in sight become hostile for (l = player->cell->map->lf ; l ; l = l->next) { if (!isplayer(l) && isundead(l) && cansee(l, player)) { if (getallegiance(l) != AL_HOSTILE) { aiattack(l, player, PERMENANT); } } } break; case R_GODFIRE: msg("\"Fire will burn away your sins!\""); dospelleffects(NULL, OT_S_FLAMEPILLAR, 4, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); break; case R_GODLIFE: msg("\"Your body shall be slow to recover from wounds...\""); // life spells will fail break; case R_GODMAGIC: msg("\"You can live without my gifts for a while...\""); losemp(player, player->mp); // get random spell getflags(player->flags, retflag, &nretflags, F_CANCAST, F_NONE); nposs = 0; for (i = 0; i < nretflags; i++) { if (retflag[i]->lifetime != FROMJOB) { poss[nposs++] = retflag[i]; } } if (nposs) { f = poss[rnd(0,nposs-1)]; killflag(f); } break; case R_GODNATURE: msg("\"You have transgressed against nature!\""); dospelleffects(NULL, OT_S_ENTANGLE, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); // note: you will also rot food on touch until god is appeased. // see touch(). break; case R_GODMERCY: // lower one attribute msg("\"Be glad that I am feeling merciful, mortal!\""); a = rnd(0,MAXATTS-1); modattr(player, a, -1); break; case R_GODPURITY: // remove blessings nposs = 0; for (o = player->pack->first ; o ; o = o->next) { if (isblessed(o)) { poss[nposs++] = o; } } if (nposs) { msg("\"Your actions do not befit the bearer of blessed objects!\""); n = rnd(1,3); if (nposs < n) n = nposs; for (i = 0; i < n; i++) { o = (object_t *)poss[rnd(0,nposs-1)]; while (!isblessed(o)) { // pick again... o = (object_t *)poss[rnd(0,nposs-1)]; } curseob(o); } } else { // don't have any blessed objects. msg("\"Perhaps you need some time without material wealth...\""); dospelleffects(NULL, OT_S_GUSTOFWIND, 10, NULL, NULL, player->cell, B_UNCURSED, NULL, B_TRUE, NULL); } break; case R_GODTHIEVES: // take a random object msg("\"Yoink!\""); castspell(god, OT_S_CONFISCATE, player, NULL, player->cell, NULL, NULL); break; default: break; } } else if (plev == PL_FURIOUS) { object_t *o; lifeform_t *l; int n,i,nretcells; cell_t *retcell[MAXRETCELLS]; int rollagain = B_TRUE; // major bad stuff switch (god->race->id) { case R_GODBATTLE: switch (rnd(1,3)) { case 1: // bad weapon msg("\"A fool deserves a fool's weapon!\""); // forcibly drop player's weapon o = getweapon(player); if (o) { killflagsofid(o->flags, F_EQUIPPED); drop(o, o->amt); } o = addob(player->pack, "cursed -1 stick"); if (o) { identify(o); weild(player, o); } break; case 2: // bad armour msg("\"A fool deserves a fool's armour!\""); // remove all player's armour dospelleffects(god, OT_S_INSTANTDISROBE, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); // give them cursed armour o = addob(player->pack, "cursed -5 cotton shirt"); if (o) { resizeobject(o, getlfsize(player)); identify(o); wear(player, o); } break; case 3: // summon monsters msg("\"Fight for your life, knave!\""); summonlfs(player, player->cell, R_NONE, RC_HUMANOID, SZ_HUMAN, AL_NONE, 8, PERMENANT, B_FALSE); break; } break; case R_GODDEATH: castspell(god, OT_S_PAIN, player, NULL, player->cell, NULL, NULL); castspell(god, OT_S_DRAINLIFE, player, NULL, player->cell, NULL, NULL); // all undead in sight become hostile for (l = player->cell->map->lf ; l ; l = l->next) { if (!isplayer(l) && isundead(l) && cansee(l, player)) { if (getallegiance(l) != AL_HOSTILE) { aiattack(l, player, PERMENANT); } } } switch (rnd(1,2)) { case 1: msg("\"This will teach you some humility, mortal!\""); if (getattr(player, A_IQ) > getattr(player, A_STR)) { castspell(god, OT_S_FEEBLEMIND, player, NULL, player->cell, NULL, NULL); } else { castspell(god, OT_S_WEAKEN, player, NULL, player->cell, NULL, NULL); } break; case 2: // summon undead msg("\"Destroy him, my pets!\""); summonlfs(god, player->cell, R_NONE, RC_UNDEAD, SZ_ANY, AL_EVIL, 3, PERMENANT, B_FALSE); break; } break; case R_GODFIRE: msg("\"Burn, infidel!\""); dospelleffects(NULL, OT_S_FLAMEPILLAR, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); getradiuscells(player->cell, 1, DT_COMPASS, B_FALSE, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 0); for (i = 0; i < nretcells; i++) { if (!retcell[i]->type->solid) { addobfast(retcell[i]->obpile, OT_FIRELARGE); } } break; case R_GODLIFE: msg("\"I withdraw my gifts from you!\""); // lower max hp by 10 player->maxhp -= 10; limit(&(player->maxhp), 1, NA); if (player->hp > player->maxhp) player->hp = player->maxhp; statdirty = B_TRUE; // player can now never heal break; case R_GODTHIEVES: o = getweapon(player); msg("\"Allow me to lighten your load a little...\""); if (o) { // take player's weapon castspell(god, OT_S_CONFISCATE, player, o, player->cell, NULL, NULL); } else { // take 3 objects int i; for (i = 0; i < 3; i++) { castspell(god, OT_S_CONFISCATE, player, NULL, player->cell, NULL, NULL); } } break; case R_GODMAGIC: rollagain = B_TRUE; while (rollagain) { flag_t *retflag[MAXCANDIDATES]; int nretflags; rollagain = B_FALSE; switch (rnd(1,3)) { case 1: // lose all spells msg("\"I forbid you my gifts!\""); nposs = 0; getflags(player->flags, retflag, &nretflags, F_CANCAST, F_NONE); nposs = 0; for (i = 0; i < nretflags; i++) { if (retflag[i]->lifetime != FROMJOB) { killflag(retflag[i]); } } break; case 2: // spells usually fail msg("\"You will find my gifts far less reliable in future!\""); addtempflag(player->flags, F_MISCASTCHANCE, 85, NA, NA, NULL, 200); break; case 3: // become a newt if (ispolymorphed(player)) { rollagain = B_TRUE; } else { msg("\"Maybe this will teach you some humility!\""); polymorphto(player, R_NEWT, 20); } break; } } // end while rollagain break; case R_GODMERCY: msg("\"Even my mercy has its limits!\""); // age age(player, 15); // lower every attribute by one for (a = 0; a < MAXATTS; a++) { modattr(player, a, -1); } break; case R_GODNATURE: msg("\"You have violated the cardinal laws of nature!\""); dospelleffects(NULL, OT_S_ENTANGLE, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); switch (rnd(1,3)) { case 1: dospelleffects(NULL, OT_S_CLOUDKILL, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); break; case 2: dospelleffects(NULL, OT_S_HAILSTORM, 10, NULL, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); break; case 3: msg("\"Destroy him, my pets!\""); summonlfs(god, player->cell, R_SAWGRASS, RC_ANY, SZ_ANY, AL_GOOD, 8, PERMENANT, B_FALSE); break; } break; case R_GODPURITY: switch (rnd(1,2)) { case 1: // break objects msg("\"Time for a lesson in materialism!\""); nposs = 0; for (o = player->pack->first ; o ; o = o->next) { if (hasflag(o->flags, F_DAMAGABLE) && !hasflag(o->flags, F_DEAD)) { poss[nposs++] = o; } } n = rnd(1,3); if (nposs < n) n = nposs; for (i = 0; i < n; i++) { char obname[BUFLEN]; o = (object_t *)poss[rnd(0,nposs-1)]; // damage it getobname(o, obname, o->amt); msg("Your %s %s struck by divine force!", OB1(o, "is", "are"), noprefix(obname)); takedamage(o, rnd(10,40), DT_DIRECT, NULL); } break; case 2: // summon holy creautes msg("\"Destroy him, my pets!\""); summonlfs(god, player->cell, R_NONE, RC_ANY, SZ_ANY, AL_GOOD, 3, PERMENANT, B_FALSE); break; } break; default: break; } } else if (plev == PL_ENRAGED) { // god attacks! godappears(god->race->id, NULL); aiattack(god, player, PERMENANT); } } checkgodbonus(rid,plev, oldplev); } // anger the god if you are worshipping them. // returns TRUE if someone got angry int angergodmaybe(enum RACE rid, int amt, enum GODANGERREASON why) { lifeform_t *god; if (lfhasflag(player, F_WINNER)) return B_FALSE; god = findgod(rid); if (lfhasflag(god, F_PRAYEDTO)) { angergod(rid, amt, why); return B_TRUE; } return B_FALSE; } void askforworship(enum RACE rid) { lifeform_t *god; char yn; if (lfhasflag(player, F_NOPRAY)) return; // make sure the player knows about it! killtransitoryflags(player->flags, F_BLIND); killtransitoryflags(player->flags, F_DEAF); god = godappears(rid, NULL); if (!god) return; addflag(player->flags, F_GODOFFERDONE, B_TRUE, NA, NA, NULL); say(god, getflagtext(god->flags, F_GODASK1), SV_TALK); more(); msg("\"%s\"", getflagtext(god->flags, F_GODASK2)); more(); yn = '?'; while (yn == '?') { char buf[BUFLEN]; snprintf(buf, BUFLEN, "Will you accept %s%s offer?", god->race->name, isplural(god->race->name) ? "'" : "'s"); yn = askchar(buf, "yn?", "n", B_TRUE, B_FALSE); if (yn == '?') { describegod(god); } else if (yn == 'y') { // should never be true, but check just in case... if (!godprayedto(rid)) { addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL); } // always get a gift, but announce it first. say(god, getflagtext(god->flags, F_GODGIFTTEXT), SV_TALK); more(); godgiftmaybe(rid, B_TRUE, B_FALSE); // increment piety so that it doesn't remain around the border. modpiety(rid, PIETYPRAYLOSS); } else { // ie. no msg("\"%s\"", getflagtext(god->flags, F_GODDECLINE)); more(); } } // make god vanish castspell(god, OT_S_PLANESHIFT, god, NULL, god->cell, NULL, NULL); } void checkgodbonus(enum RACE rid, enum PIETYLEV newlev, enum PIETYLEV oldlev) { flag_t *retflag[MAXCANDIDATES]; int nretflags,i; enum PIETYLEV plev; lifeform_t *god; int first = B_TRUE; if (!godprayedto(rid)) return; if (newlev == oldlev) return; god = findgod(rid); plev = getpietylev(rid, NULL, NULL); getflags(god->flags, retflag, &nretflags, F_GODBONUS, F_NONE); for (i = 0; i < nretflags; i++) { if (newlev < oldlev) { if ((retflag[i]->val[0] > newlev) && (retflag[i]->val[0] <= oldlev)) { removegodbonus(rid, retflag[i], first); first = B_FALSE; } } else if (newlev > oldlev) { // piety increased if ((retflag[i]->val[0] <= newlev) && (retflag[i]->val[0] > oldlev)) { givegodbonus(rid, retflag[i], first); first = B_FALSE; } } } // non-auto-announced ones... if (newlev > oldlev) { if ((rid == R_GODMERCY) && (newlev == PL_ECSTATIC)) { godsay(rid, B_FALSE, "My mercy shall be with you!"); } } } void dooffer(void) { object_t *o, *nexto; lifeform_t *god; flag_t *retflag[MAXCANDIDATES]; int nretflags,pietyplus = 0; int dowoodsangry = B_FALSE; int success = B_FALSE; char splatterob[BUFLEN]; strcpy(splatterob, ""); if (lfhasflag(player, F_RAGE)) { msg("You are too enraged to offer a sacrifice!"); return; } // which god? god = askgod("To whom will you sacrifice?", B_TRUE, B_FALSE); if (!god) { msg("Cancelled."); return; } getflags(god->flags, retflag, &nretflags, F_SACRIFICEOB, F_SACRIFICEOBCLASS, F_SACRIFICEOBWITHFLAG, F_SACRIFICEOBBLESSED, F_SACRIFICEOBMAGIC, F_NONE); if (nretflags == 0) { msg("%s does not accept sacrifices.", god->race->name); return; } // anything here to offer? for (o = player->cell->obpile->first ; o ; o = nexto) { int i; nexto = o->next; if (hasflag(o->flags, F_NOSACRIFICE)) continue; // does the god want this? getflags(god->flags, retflag, &nretflags, F_SACRIFICEOB, F_SACRIFICEOBCLASS, F_SACRIFICEOBWITHFLAG, F_SACRIFICEOBBLESSED, F_SACRIFICEOBMAGIC, F_NONE); for (i = 0; i < nretflags; i++) { int ok = B_FALSE; int thispiety = 0; flag_t *f; f = retflag[i]; if ((f->id == F_SACRIFICEOB) && (f->val[0] == o->type->id)) { int validcorpse = B_FALSE; if (f->val[1] == NA) { validcorpse = B_TRUE; } else { flag_t *ff; ff = hasflag(o->flags, F_CORPSEOF); if (ff) { race_t *r; r = findrace(ff->val[0]); if (r->raceclass->id == f->val[1]) { validcorpse = B_TRUE; } } } // special case - amberon only accepts evil corpses if (validcorpse && (god->race->id == R_GODPURITY) && (o->type->id == OT_CORPSE)) { flag_t *ff; ff = hasflag(o->flags, F_ALIGNMENT); if (!ff || (ff->val[0] != AL_EVIL)) { validcorpse = B_FALSE; } } if (validcorpse) { ok = B_TRUE; thispiety = f->val[2]; } } else if ((f->id == F_SACRIFICEOBCLASS) && (f->val[0] == o->type->obclass->id)) { ok = B_TRUE; thispiety = f->val[2]; // will be overridden late though, if val[0] is OC_MONEY } else if ((f->id == F_SACRIFICEOBWITHFLAG) && hasflag(o->flags, f->val[0])) { ok = B_TRUE; thispiety = f->val[2]; } else if ((f->id == F_SACRIFICEOBBLESSED) && (f->val[0] == o->blessed) && (o->blessknown == B_TRUE)) { ok = B_TRUE; thispiety = f->val[2]; } else if ((f->id == F_SACRIFICEOBMAGIC) && ismagical(o)) { ok = B_TRUE; thispiety = f->val[2]; } if (thispiety) { if (hasobmod(o, findobmod(OM_MASTERWORK))) { thispiety *= 2; } else if (hasobmod(o, findobmod(OM_MASTERWORK))) { thispiety /= 2; limit(&thispiety, 1, NA); } } // god of thieves only accepts untouched stuff if (ok && (god->race->id == R_GODTHIEVES)) { if (!hasflag(o->flags, F_UNTOUCHED)) { ok = B_FALSE; thispiety = 0; } } if (ok) { char *p; char obname[BUFLEN]; cell_t *newcell = NULL; // gold/gems are treated differently if (o->type->id == OT_GOLD) { thispiety = (getobvalue(o) / 2); } else if (hasflag(o->flags, F_GEM)) { thispiety = (getobvalue(o) / 50); //if (pctchance(getobvalue(o))) { //} else { // thispiety = 0; // } } // special effect sacrificing flora to ekrub makes it turn into a // butterfly if ((god->race->id == R_GODNATURE) && (o->type->obclass->id == OC_FLORA)) { newcell = getrandomadjcell(player->cell, &ccwalkable, B_NOEXPAND); } if (haslos(player, player->cell)) { getobname(o, obname, ALL); if ((god->race->id == R_GODNATURE) && (o->type->obclass->id == OC_FLORA) && !newcell) { // couldn't create a butterfly p = strdup("OB IS carried away on a gust of wind."); } else { p = strdup(f->text); } strrep(&p, "OB", obname, NULL); if (o->amt == 1) { strrep(&p, "IS", "is", NULL); strrep(&p, "#S", "s", NULL); } else { strrep(&p, "IS", "are", NULL); strrep(&p, "#S", "", NULL); } msg("%s", p); free(p); } if ((god->race->id == R_GODNATURE) && (o->type->obclass->id == OC_FLORA) && newcell) { addmonster(newcell, R_BUTTERFLY, NULL, B_FALSE, 1, B_FALSE, B_NOEXTRA, NULL); } if (o->type->obclass->id == OC_FLORA) { cell_t *loc; loc = getoblocation(o); if (loc->map->region->rtype->id == BH_WOODS) { dowoodsangry = B_TRUE; } } removeob(o, ALL); pietyplus += thispiety; // special effect if (god->race->id == R_GODBATTLE) { strcpy(splatterob, "splash of blood"); } break; } } // end for each f_sacrificexxx flag } // end foreach ob if (pietyplus) { pleasegod(god->race->id, pietyplus); if (strlen(splatterob)) { addob(player->cell->obpile, splatterob); addobsinradius(player->cell, 1, DT_COMPASS, splatterob, B_TRUE, B_NOCENTRE, NULL, NULL, NULL, NULL); } if (god->race->id == R_GODFIRE) { dospelleffects(player, OT_S_FLAMEBURST, 1, NULL, NULL, player->cell, B_UNCURSED, NULL, B_FALSE, NULL); } } else if (!success) { nothinghappens(); } taketime(player, getactspeed(player)); if (dowoodsangry) { magicwoods_angry(player); } } lifeform_t *findgod(enum RACE rid) { lifeform_t *lf; // search heaven first for (lf = heaven->lf ; lf ; lf = lf->next) { if (lf->race->id == rid) return lf; } // now search other maps lf = findlfunique(rid); return lf; } char *getgodname(enum RACE rid, char *buf) { lifeform_t *god; god = findgod(rid); if (god) { sprintf(buf, "%s", god->race->name); } else { sprintf(buf, "(unknowngod)"); } return buf; } enum RACE getopposinggod(enum RACE rid) { switch (rid) { //case R_GODPURITY: return R_GODCHAOS; //case R_GODCHAOS: return R_GODPURITY; case R_GODDEATH: return R_GODLIFE; case R_GODLIFE: return R_GODDEATH; case R_GODMERCY: return R_GODTHIEVES; case R_GODTHIEVES: return R_GODMERCY; case R_GODBATTLE: return R_GODMAGIC; case R_GODMAGIC: return R_GODBATTLE; case R_GODNATURE: return R_GODFIRE; case R_GODFIRE: return R_GODNATURE; default: break; } return R_NONE; } enum OBTYPE getopposinggodstone(enum RACE rid) { objecttype_t *ot; for (ot = objecttype ; ot ; ot = ot->next) { if (ot->obclass->id != OC_GODSTONE) continue; if (hasflagval(ot->flags, F_LINKGOD, getopposinggod(rid), NA, NA, NULL)) return ot->id; } return OT_NONE; } int getpiety(enum RACE rid) { lifeform_t *god; flag_t *f; god = findgod(rid); f = lfhasflag(god, F_PIETY); if (f) { return f->val[0]; } else { // ie. haven't prayed to them before. return 100; } return 0; } // return the highest piety value which will result in the given level. int getpietycutoff(enum PIETYLEV pl) { switch (pl) { case PL_ENRAGED: return -200; case PL_FURIOUS: return -100; case PL_ANGRY: return -1; case PL_TOLERATED: return 99; case PL_INDIFFERENT: return 199; case PL_PLEASED: return 299; case PL_DELIGHTED: return 399; case PL_ECSTATIC: return 1000; } // default return 0; } enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness) { int piety; /// figure out piety bracket // min = -200 // max = 400 // range = 600 piety = getpiety(rid); if (piety <= -200) { // -200 - -100 if (col) *col = C_ORANGE; if (happiness) strcpy(happiness, "Enraged"); return PL_ENRAGED; } else if (piety <= -100) { // -199 - -100 if (col) *col = C_RED; if (happiness) strcpy(happiness, "Furious"); return PL_FURIOUS; } else if (piety < 0) { // -99 - 0 if (col) *col = C_YELLOW; if (happiness) strcpy(happiness, "Angry"); return PL_ANGRY; } else if (piety <= 99) { // 0 - 99 if (col) *col = C_DARKYELLOW; if (happiness) strcpy(happiness, "Tolerated"); return PL_TOLERATED; } else if (piety <= 199) { // 100 - 199 if (col) *col = C_GREY; if (happiness) strcpy(happiness, "Neutral"); return PL_INDIFFERENT; } else if (piety <= 299) { // 200 - 299 if (col) *col = C_GREEN; if (happiness) strcpy(happiness, "Pleased"); return PL_PLEASED; } else if (piety <= 399) { // 300 - 399 if (col) *col = C_LIGHTGREEN; if (happiness) strcpy(happiness, "Delighted"); return PL_DELIGHTED; } else { // 400+ if (col) *col = C_LIGHTCYAN; if (happiness) strcpy(happiness, "Ecstatic"); return PL_ECSTATIC; } return PL_INDIFFERENT; } int getprayedgods(lifeform_t **retgod, int *nretgods) { int i; *nretgods = 0; for (i = 0; i < ngodlfs; i++) { if (lfhasflag(godlf[i], F_PRAYEDTO)) { retgod[*nretgods] = godlf[i]; (*nretgods)++; } } return *nretgods; } lifeform_t *getrandomgod(void) { if (ngodlfs == 0) { return NULL; } return godlf[rnd(0,ngodlfs-1)]; } // get a random god which player has prayed to lifeform_t *getrandomprayedgod(void) { int nposs; lifeform_t *poss[MAXGODS]; getprayedgods(poss, &nposs); if (nposs == 0) { return NULL; } return poss[rnd(0,nposs-1)]; } enum OBTYPE getrelatedgodstone(enum RACE rid) { objecttype_t *ot; for (ot = objecttype ; ot ; ot = ot->next) { if (ot->obclass->id != OC_GODSTONE) continue; if (hasflagval(ot->flags, F_LINKGOD, rid, NA, NA, NULL)) return ot->id; } return OT_NONE; } void givegodbonus(enum RACE rid, flag_t *bf, int announce) { flag_t *f; lifeform_t *god; int targ[3], arg = NA; enum PIETYLEV bonuslev; enum GODBONUS bonusid; god = findgod(rid); if (!god) return; // god announcement. if (announce) { godsay(rid, B_TRUE, getflagtext(god->flags, F_GODBONUSTEXT)); more(); } // increment piety so that it doesn't keep bouncing around the border. modpiety(rid, PIETYPRAYLOSS); addtempflag(player->flags, F_NOPIETYLOSS, rid, NA, NA, NULL,rnd(50,100)); // parse regular rags parsegodbonusargs(bf, &bonuslev, &bonusid, &arg, targ); // now do something... switch (bonusid) { case GB_DTIMMUNE: if (!lfhasflagval(player, F_DTIMMUNE, arg, NA, NA, NULL)) { f = addtempflag(player->flags, F_DTIMMUNE, arg, NA, NA, NULL, FROMGODPIETY); f->obfrom = rid; } break; case GB_DTRESIST: if (!lfhasflagval(player, F_DTRESIST, arg, NA, NA, NULL)) { f = addtempflag(player->flags, F_DTRESIST, arg, NA, NA, NULL, FROMGODPIETY); f->obfrom = rid; } break; case GB_FLAG: if (!lfhasflagval(player, arg, targ[0], targ[1], targ[2], NULL)) { f = addtempflag(player->flags, arg, targ[0], targ[1], targ[2], NULL, FROMGODPIETY); f->obfrom = rid; // extra text for flags which aren't announced if (arg == F_SKILLCHECKMOD) { switch (targ[0]) { case SC_STEALTH: godsay(rid, B_FALSE, "Henceforce the shadows will cloak you!"); break; case SC_OPENLOCKS: godsay(rid, B_FALSE, "Locks will open at your touch!"); break; case SC_SEARCH: godsay(rid, B_FALSE, "That which is hidden shall be revealed!"); break; default: break; } } else if (arg == F_MINCRITCHANCE) { godsay(rid, B_FALSE, "You shall inflict grevious injuries on your foes!"); break; } } break; case GB_CANWILL: if (!lfhasflagval(player, F_CANWILL, arg, NA, NA, NULL)) { f = addtempflag(player->flags, F_CANWILL, arg, targ[0], targ[0], NULL, FROMGODPIETY); f->obfrom = rid; } break; case GB_MAGICBOOST: f = addtempflag(player->flags, F_MAGICBOOST, arg, NA, NA, NULL, FROMGODPIETY); f->obfrom = rid; break; case GB_FIREBODY: if (player->material->id != MT_FIRE) { player->material = findmaterial(MT_FIRE); msg("^gYour body bursts into flames!"); } break; } } int prayedtoany(void) { int i; for (i = 0; i < ngodlfs; i++) { if (godlf[i] && godprayedto(godlf[i]->race->id)) { return B_TRUE; } } return B_FALSE; } void removegodbonus(enum RACE rid, flag_t *bf, int announce) { int targ[3], arg = NA; enum PIETYLEV bonuslev; enum GODBONUS bonusid; lifeform_t *god; god = findgod(rid); if (!god) return; // god announcement. if (announce) { godsay(rid, B_TRUE, getflagtext(god->flags, F_GODNOBONUSTEXT)); more(); } // parse regular rags parsegodbonusargs(bf, &bonuslev, &bonusid, &arg, targ); // now do something... switch (bonusid) { case GB_DTRESIST: killflagsofval(ALL, player->flags, F_DTRESIST, arg, NA, NA, FROMGODPIETY, rid); break; case GB_DTIMMUNE: killflagsofval(ALL, player->flags, F_DTIMMUNE, arg, NA, NA, FROMGODPIETY, rid); break; case GB_FLAG: killflagsofval(ALL, player->flags, arg, targ[0], targ[1], targ[2], FROMGODPIETY, rid); break; case GB_CANWILL: killflagsofval(ALL, player->flags, F_CANWILL, arg, NA, NA, FROMGODPIETY, rid); break; case GB_MAGICBOOST: // special case: just remove ONE of these. killflagsofval(1, player->flags, F_MAGICBOOST, arg, NA, NA, FROMGODPIETY, rid); break; case GB_FIREBODY: if (player->material->id == MT_FIRE) { // TODO: what if player is polymorphed? player->material = player->race->material; msg("Your body is no longer aflame."); } break; } } lifeform_t *godappears(enum RACE rid, cell_t *where) { lifeform_t *god; char killedname[BUFLEN],godname[BUFLEN]; god = findgod(rid); real_getlfname(god, godname, NULL, B_NOSHOWALL, B_REALRACE); strcpy(killedname, ""); if (!where) { condset_t cs; // somewhere next to the player. where = real_getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, player); if (!where) { // try somewhere nearby even if it's not walkable. initcond(&cs); addcond(&cs, CC_IMPASSABLE, B_FALSE, NA); where = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, player); } if (!where) { // try somewhere adjacent even if it's not walkable and has no line of fire to player. initcond(&cs); addcond(&cs, CC_IMPASSABLE, B_FALSE, NA); where = real_getrandomadjcell(player->cell, &cs, B_ALLOWEXPAND, LOF_DONTNEED, NULL, player); } if (!where) { // still nowhere? get anywhere adjacent. where = real_getrandomadjcell(player->cell, NULL, B_ALLOWEXPAND, LOF_DONTNEED, NULL, player); } if (!where) { // still nowhere? fail. msg("You briefly feel the presence of %s.", godname); return NULL; } } // solid cell? if (issolid(where)) { // clear it. msg("%s %s disappears!", needan(where->type->name) ? "An" : "A", where->type->name); clearcell(where); setcelltype(where, where->map->habitat->emptycelltype); } // now see if anyone is there. if (where->lf) { // kill them. getlfname(where->lf, killedname); killlf(where->lf); teleportto(god, where, B_TRUE); if (haslos(player, where) && strlen(killedname)) { msg("%s transforms into %s!", killedname, godname); } } else { teleportto(god, where, B_TRUE); // visual effect for some gods switch (god->race->id) { case R_GODBATTLE: // bloodsplatter addob(god->cell->obpile, "splash of blood"); addobsinradius(god->cell, 2, DT_COMPASS, "splash of blood", B_TRUE, B_INCLUDECENTRE, NULL, NULL, NULL, NULL); break; case R_GODLIFE: //light addob(god->cell->obpile, "bright light"); addobsinradius(god->cell, 2, DT_COMPASS, "bright light", B_TRUE, B_INCLUDECENTRE, NULL, NULL, NULL, NULL); break; case R_GODFIRE: // fire addob(god->cell->obpile, "large fire"); break; default: break; } } return god; } void god_usepoison_response(void) { int i; flag_t *f; for (i = 0; i < ngodlfs; i++) { if (godlf[i]) { f = lfhasflag(godlf[i], F_GODPOISON); if (f) { if (f->val[0]) { pleasegodmaybe(godlf[i]->race->id, f->val[1]); } else { angergodmaybe(godlf[i]->race->id, f->val[1], GA_POISON); } } } } } int godblocked(enum RACE rid) { lifeform_t *opposegod,*god; enum RACE opposeid; god = findgod(rid); // forcibly blocked? if (lfhasflag(god, F_GODBLOCKED)) { return B_TRUE; } // already prayed to the opposing god? opposeid = getopposinggod(rid); opposegod = findgod(opposeid); if (opposegod && lfhasflag(opposegod, F_PRAYEDTO)) { return B_TRUE; } return B_FALSE; } // maybe get a gift int godgiftmaybe(enum RACE rid, int fromtemple, int announce) { lifeform_t *god; int piety,gotgift = B_FALSE; enum PIETYLEV plev; int chance; flag_t *timerflag; god = findgod(rid); piety = getpiety(rid); plev = getpietylev(rid, NULL, NULL); if (fromtemple) { chance = 100; } else if (plev >= PL_PLEASED) { // ie. >= 200 // ie. 200 -> 4% // ie. 500 -> 10% //chance = piety / 50; chance = piety / 100; } else { chance = 0; } // check whether gift timer is ready timerflag = lfhasflag(god, F_GIFTTIMER); assert(timerflag); if (timerflag && (timerflag->val[0] > 0)) { timerflag->val[0]--; return B_FALSE; } if (pctchance(chance)) { // if this is true, you get a gift. char obtogive[BUFLEN]; int rollagain = B_TRUE; enum SPELLSCHOOL school; gotgift = B_TRUE; killflagsofid(player->flags, F_ASLEEP); if (announce) { // god announcement. godsay(rid, B_TRUE, getflagtext(god->flags, F_GODGIFTTEXT)); more(); } strcpy(obtogive, ""); switch (god->race->id) { case R_GODBATTLE: while (rollagain) { rollagain = B_FALSE; switch (rnd(1,2)) { case 1: snprintf(obtogive, BUFLEN, "excellent appropriate branded weapon"); break; case 2: snprintf(obtogive, BUFLEN, "excellent appropriate branded armour"); break; } } break; case R_GODDEATH: while (rollagain) { flag_t *f; object_t *wep; rollagain = B_FALSE; switch (rnd(2,6)) { /* case 1: if (lfhasflag(player, F_SEEINDARK)) { rollagain = B_TRUE; } else { msg("\"Henceforth the night shall be your ally!\""); f = addtempflag(player->flags, F_SEEINDARK, 4, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; */ case 2: snprintf(obtogive, BUFLEN, "cursed appropriate branded weapon"); break; case 3: // poison your weapon wep = getweapon(player); if (wep && canbepoisoned(wep->type->id)) { applyobmod(wep, findobmod(OM_POISONED)); msg("A layer of venom covers your weapon!"); } else { rollagain = B_TRUE; } break; case 4: // resistant/immune to necrotic if (lfhasflagval(player, F_DTRESIST, DT_NECROTIC, NA, NA, NULL)) { if (lfhasflagval(player, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL)) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_DTIMMUNE, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } } else { f = addtempflag(player->flags, F_DTRESIST, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; case 5: // become a vampire if (player->race->id == R_VAMPIRE) { rollagain = B_TRUE; } else { int orighp; int origatt[MAXATTS]; enum ATTRIB a; msg("\"Go forth and kill in my name!\""); msg("You transform into a vampire!"); // special polymorph - we won't change some stats. orighp = player->maxhp; for (a = 0; a < MAXATTS; a++) { origatt[a] = player->att[a]; } // change the race. setrace(player, R_VAMPIRE, B_FALSE); // ie. don't set origrace! // restore stats player->maxhp = orighp; player->hp = orighp; for (a = 0; a < MAXATTS; a++) { player->att[a] = origatt[a]; } statdirty = B_TRUE; drawscreen(); } break; case 6: // necromancy spells if (!getskill(player, SK_SS_DEATH)) { giveskill(player, SK_SS_DEATH); } else { snprintf(obtogive, BUFLEN, "spellbook of necromancy"); } break; } } break; case R_GODFIRE: while (rollagain) { object_t *wep; wep = getweapon(player); rollagain = B_FALSE; switch (rnd(1,3)) { case 1: // weapon gains burning if (wep) { if (!hasobmod(wep, findobmod(OM_FLAMING))) { applyobmod(wep, findobmod(OM_FLAMING)); } else if (!hasflag(wep->flags, F_HASBRAND)) { char obname[BUFLEN]; // already burning. gains pyromania addflag(wep->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL); getobname(wep, obname, 1); msg("Your %s glows with a brilliant heat!", noprefix(obname)); } else { // already has pyromania. rollagain = B_TRUE; } } else { rollagain = B_TRUE; } break; case 2: // fire resist/immune if (lfhasflagval(player, F_DTRESIST, DT_FIRE, NA, NA, NULL)) { if (lfhasflagval(player, F_DTIMMUNE, DT_FIRE, NA, NA, NULL)) { rollagain = B_TRUE; } else { flag_t *f; f = addtempflag(player->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } } else { flag_t *f; f = addtempflag(player->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; case 3: // fire-related spellbook, or fire magic skill if (getskill(player, SK_SS_FIRE)) { snprintf(obtogive, BUFLEN, "spellbook of Fire Magic"); } else { flag_t *f; f = giveskill(player, SK_SS_FIRE); if (f) { f->obfrom = god->race->id; } else { rollagain = B_TRUE; } } break; case 4: // grant immolation power if (lfhasflagval(player, F_CANWILL, OT_S_IMMOLATE, NA, NA, NULL)) { rollagain = B_TRUE; } else { flag_t *f; f = addflag(player->flags, F_CANWILL, OT_S_IMMOLATE, 20, 20, "pw:10;"); f->obfrom = god->race->id; } break; } } break; case R_GODLIFE: while (rollagain) { object_t *wep; flag_t *f; wep = getweapon(player); rollagain = B_FALSE; switch (rnd(1,4)) { case 1: // regeneration if (lfhasflag(player, F_REGENERATES)) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_REGENERATES, 1, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; case 2: // learn first aid skill f = giveskill(player, SK_FIRSTAID); if (f) { f->obfrom = god->race->id; } else { rollagain = B_TRUE; } break; case 3: // life-related spellbook, or life magic skill if (getskill(player, SK_SS_LIFE)) { snprintf(obtogive, BUFLEN, "spellbook of Life Magic"); } else { flag_t *f; f = giveskill(player, SK_SS_LIFE); if (f) { f->obfrom = god->race->id; } else { rollagain = B_TRUE; } } break; case 4: // increase max hp player->maxhp += rollhitdice(player, B_TRUE); statdirty = B_TRUE; msg("\"I have increased your tolerance to injury!\""); break; } } break; case R_GODMAGIC: while (rollagain) { rollagain = B_FALSE; switch (rnd(1,3)) { case 1: // spellbook for a known school school = getrandomspellschool(player, B_TRUE); if (school == SS_NONE) { rollagain = B_TRUE; } else { snprintf(obtogive, BUFLEN, "spellbook of %s", getschoolname(school)); } break; case 2: // manual for an unknown spell school school = getrandomspellschool(player, B_FALSE); if (school == SS_NONE) { rollagain = B_TRUE; } else { enum SKILL skid; skill_t *sk; skid = getschoolskill(school); sk = findskill(skid); snprintf(obtogive, BUFLEN, "manual of %s", sk->name); } break; case 3: msg("\"I grant you additional magical reserves!\""); player->maxmp += rnd(4,6); statdirty = B_TRUE; break; } } break; case R_GODMERCY: while (rollagain) { flag_t *f; rollagain = B_FALSE; switch (rnd(1,3)) { case 1: snprintf(obtogive, BUFLEN, "3-4 potions of restoration"); break; case 2: if (hasob(player->pack, OT_RING_MIRACLES)) { rollagain = B_TRUE; } else { snprintf(obtogive, BUFLEN, "ring of miracles"); } break; case 3: // sixth sense if (lfhasflag(player, F_SIXTHSENSE)) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_SIXTHSENSE, B_TRUE, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; } } break; case R_GODNATURE: while (rollagain) { flag_t *f; object_t *o; objecttype_t *ot; rollagain = B_FALSE; switch (rnd(1,6)) { case 1: // resist/immune poison if (lfhasflag(player, F_DISEASEIMMUNE)) { if (lfhasflagval(player, F_DTIMMUNE, DT_POISON, NA, NA, NULL)) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_DTIMMUNE, DT_POISON, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } } else { f = addtempflag(player->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; case 2: // resist/immune cold if (lfhasflagval(player, F_DTRESIST, DT_COLD, NA, NA, NULL)) { if (lfhasflagval(player, F_DTIMMUNE, DT_COLD, NA, NA, NULL)) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } } else { f = addtempflag(player->flags, F_DTRESIST, DT_COLD, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; case 3: // good ranged weapon if (getskill(player, SK_RANGED)) { char obname[BUFLEN]; condset_t cs; initcondv(&cs, CC_HASSIZE, B_TRUE, getlfsize(player), CC_WEPSK, B_TRUE, SK_RANGED, CC_OBCLASS, B_TRUE, OC_WEAPON, CC_NONE); if (real_getrandomob(NULL, obname, 25, NA, RR_NONE, B_TRUE, &cs)) { snprintf(obtogive, BUFLEN, "excellent %s", obname); } else { rollagain = B_TRUE; } } else { rollagain = B_TRUE; } break; case 4: // ammo o = getfirearm(player); if (o) { ot = getrandomammofor(o, B_FALSE); snprintf(obtogive, BUFLEN, "%d excellent %s", rnd(20,30), ot->name); } else { rollagain = B_TRUE; } break; case 5: // calm animals ability if (lfhasflagval(player, F_CANWILL, OT_S_CALMANIMALS, NA, NA, NULL)) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_CANWILL, OT_S_CALMANIMALS, NA, NA, "pw:10;", FROMGODGIFT); f->obfrom = god->race->id; } break; case 6: if (lfhasflagval(player, F_CANWILL, OT_S_SHAPESHIFT, NA, NA, "pw:1;race:hawk;")) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_CANWILL, OT_S_SHAPESHIFT, 50, 50, "pw:1;race:hawk;", FROMGODGIFT); f->obfrom = god->race->id; } break; } } break; case R_GODPURITY: if (!hasob(player->pack, OT_POT_RESTORATION)) { snprintf(obtogive, BUFLEN, "2-3 blessed potions of restoration"); } else { while (rollagain) { flag_t *f; rollagain = B_FALSE; switch (rnd(1,3)) { case 1: snprintf(obtogive, BUFLEN, "2-3 blessed potions of water"); break; case 2: snprintf(obtogive, BUFLEN, "wand of turn undead"); break; case 3: // holy aura if (lfhasflag(player, F_HOLYAURA)) { rollagain = B_TRUE; } else { f = addtempflag(player->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; f = addtempflag(player->flags, F_HOLYAURA, NA, NA, NA, NULL, FROMGODGIFT); f->obfrom = god->race->id; } break; } } } break; case R_GODTHIEVES: while (rollagain) { object_t *wep; rollagain = B_FALSE; wep = getweapon(player); if (wep && !hasflag(wep->flags, F_HASBRAND)) { char obname[BUFLEN]; brand_t *br; flag_t *f; getobname(wep,obname,1); // announce msg("Your %s vibrates, and you suddenly thirst for vengeance!", noprefix(obname)); f = addflag(wep->flags, F_REVENGE, B_TRUE, NA, NA, NULL); f->known = B_TRUE; br = findbrand(BR_REVENGE); copyflags(wep->flags, br->flags, FROMBRAND); addflag(wep->flags, F_HASBRAND, BR_REVENGE, NA, NA, NULL); } else { switch (rnd(1,7)) { case 1: if (getskill(player, SK_TECHUSAGE) >= gettechlevel(OT_LOCKHACKER)) { snprintf(obtogive, BUFLEN, "lock hacker"); } else { snprintf(obtogive, BUFLEN, "3-6 blessed lockpicks"); } break; case 2: if (onein(6)) { snprintf(obtogive, BUFLEN, "large bag of holding"); } else { snprintf(obtogive, BUFLEN, "bag of holding"); } break; case 3: snprintf(obtogive, BUFLEN, "safebox"); break; case 4: snprintf(obtogive, BUFLEN, "wand of opening"); break; case 5: snprintf(obtogive, BUFLEN, "wand of invisibility"); break; case 6: snprintf(obtogive, BUFLEN, "3-6 potions of invisibility"); break; case 7: snprintf(obtogive, BUFLEN, "leather boots of stealth"); break; } } } break; default: break; } // end switch if (strlen(obtogive)) { object_t *o; o = addob(player->cell->obpile, obtogive); if (o) { char buf[BUFLEN]; // make sure armour fits if (hasflag(o->flags, F_MULTISIZE)) { resizeobject(o, getlfsize(player)); } addflag(o->flags, F_GODGIFT, god->race->id, NA, NA, NULL); if (haslos(player, player->cell)) { getobname(o, buf, o->amt); msg("%s appear%s!", buf, OBS1(o)); } else { msg("You hear something hitting the ground."); } } } // since you got a gift, have to wait before getting another one. /* if (!fromtemple) { modpiety(rid, -50); } */ timerflag->val[0] = timerflag->val[1]; timerflag->val[1] = pctof(150,timerflag->val[1]); } // end if (pctchance enough to get a gift) return gotgift; } int godisangry(enum RACE rid) { if (getpiety(rid) < 0) { return B_TRUE; } return B_FALSE; } int godprayedto(enum RACE rid) { lifeform_t *god; god = findgod(rid); if (hasflag(god->flags, F_PRAYEDTO)) { return B_TRUE; } return B_FALSE; } void godsay(enum RACE rid, int says, char *format, ...) { lifeform_t *god; char godname[BUFLEN], buf[BUFLEN]; char voiceverb[BUFLEN]; va_list args; va_start(args, format); vsnprintf( buf, BUFLEN, format, args ); va_end(args); god = findgod(rid); real_getlfname(god, godname, NULL, B_NOSHOWALL, B_REALRACE); switch (rid) { case R_GODBATTLE: strcpy(voiceverb, "rings out from the heavens"); break; case R_GODDEATH: strcpy(voiceverb, "grates against your mind"); break; case R_GODFIRE: strcpy(voiceverb, "burns into your mind"); break; case R_GODLIFE: strcpy(voiceverb, "chimes out from the heavens"); break; case R_GODMAGIC: strcpy(voiceverb, "enters your thoughts"); break; case R_GODMERCY: strcpy(voiceverb, "washes over you"); break; case R_GODNATURE: if (godisangry(rid)) { strcpy(voiceverb, "arrives with a buffeting wind"); } else { strcpy(voiceverb, "arrives with a gentle breeze"); } break; case R_GODTHIEVES: strcpy(voiceverb, "whispers in your ear"); break; case R_GODPURITY: default: strcpy(voiceverb, "booms out from the heavens"); break; } if (says) { msg("%s%s voice %s:", godname, getpossessive(godname), voiceverb); more(); } msg("\"%s\"", buf); } void godstone_pickup_effects(lifeform_t *god, lifeform_t *opposegod, object_t *o) { int x,y; // opposing god appears godappears(opposegod->race->id, NULL); msg("%s says:", opposegod->race->name); more(); cls(); wmove(mainwin, 0, 0); // tells you you can become the new god of xxx // or give the stone to them, for a reward //tells you about the portal on the surface switch (opposegod->race->id) { case R_GODBATTLE: wprintw(mainwin, "\"Soldier. What you have just appropriated is the legendary\n"); wprintw(mainwin, "Godstone of Magic. As you well know, the existence of magic\n"); wprintw(mainwin, "has unfairly changed the outcome of many a battle. It causes\n"); wprintw(mainwin, "even the most hardened veteran to tremble in the face of the\n"); wprintw(mainwin, "weak and infirm. This goes against everything that is proper.\n"); wprintw(mainwin, "Now that the Godstone has been captured, there is a singular\n"); wprintw(mainwin, "opportunity to end this travesty.\n\n"); wprintw(mainwin, "Claim the stone in the name of armies everywhere, stand before\n"); wprintw(mainwin, "the Goddess of Magic, and issue your challenge. Strike her down,\n"); wprintw(mainwin, "and with her strike down the imbalances of magic itself!\n\n"); wprintw(mainwin, "Do not take any chances. If for any reason the success of your\n"); wprintw(mainwin, "primary mission should become uncertain, your contingency plan is\n"); wprintw(mainwin, "to immediately escort the stone safely to me. Such a dangerous\n"); wprintw(mainwin, "weapon must not fall into the hands of enemies, and only in\n"); wprintw(mainwin, "my possession can we be sure of its safety.\n\n"); wprintw(mainwin, "Your first waypoint is the portal atop the dungeon. This will\n"); wprintw(mainwin, "lead to the Realm of Gods, where both of your objectives can be\n"); wprintw(mainwin, "achieved.\"\n"); break; case R_GODDEATH: wprintw(mainwin, "\"Heh, heh, heh.\n\n"); wprintw(mainwin, "You, mortal, have just found the Godstone of Life.\n"); wprintw(mainwin, "It is the source of all Glorana's power... and could also be used to murder\n"); wprintw(mainwin, "her and take that power... if one had sufficient courage.\n\n"); wprintw(mainwin, "As you are a mere fleshling however, I will offer you a deal. Simply\n"); wprintw(mainwin, "deliver the Godstone to me, and in return I will forgo my claim on your\n"); wprintw(mainwin, "life. Your flesh will never wither. Your strength will never fade.\n"); wprintw(mainwin, "Death will never claim you.\n\n"); wprintw(mainwin, "Whatever your choice, travel to the surface and you will find a portal\n"); wprintw(mainwin, "to the Realm of Gods. Enter through, and claim your prize!\"\n\n"); break; case R_GODFIRE: wprintw(mainwin, "\"NATURE STONE!!!!\n\n"); wprintw(mainwin, "YOU WILL BRING IT! YOU WILL BRING IT AND KLIKIRAK WILL DESTROY!\n"); wprintw(mainwin, "OR... STONE KILL EKRUB. YES! YOU WILL USE. YOU FIND\n"); wprintw(mainwin, "HER. YOU USE STONE. STONE HELP BURN NATURE GODDESS!\n\n"); wprintw(mainwin, "YOU GO UPWARD. UPWARD GOES TO FOREST. PORTAL IN FOREST.\n"); wprintw(mainwin, "PORTAL TO TREE WOMAN. YOU KILL TREE WOMAN. OR YOU FIND KLIKIRAK,\n"); wprintw(mainwin, "YOU GIVE STONE TO KLIKIRAK.\n\n"); wprintw(mainwin, "YES. YES. YYYEESSS!!\"\n"); break; case R_GODLIFE: wprintw(mainwin, "\"BEWARE, CHILD! That is the Godstone of Death!\n\n"); wprintw(mainwin, "But wait... you seem unaffected by its power. Common wisdom\n"); wprintw(mainwin, "holds that the stone destroys all who touch it. Since this is\n"); wprintw(mainwin, "clearly untrue however... could it be that Hecta has fooled us\n"); wprintw(mainwin, "all? That the God of Death does indeed possess a weakness?\"\n\n"); wprintw(mainwin, "Lumara's pulsating form wavers for a moment, seemingly unsure.\n\n"); wprintw(mainwin, "\"It must be. And if this stone is truly the source of Hecta's\n"); wprintw(mainwin, "power, then destroying it... that would mean and end to death!\n"); wprintw(mainwin, "Life could last forever - all could be immortal, rathern just\n"); wprintw(mainwin, "a select few! It must be done - if you can bring me the\n"); wprintw(mainwin, "Godstone it will take but a few moments and the meaning of life\n"); wprintw(mainwin, "will be forever altered. Hecta will likely try to stop you.\n"); wprintw(mainwin, "Avoid him if you can... but should that not prove possible, the\n"); wprintw(mainwin, "the stone should at least grant you a slim chance of survival.\n"); wprintw(mainwin, "It might even be powerful enough for you to triumph...\n\n"); wprintw(mainwin, "But let us not dwell on that. Find the portal to my realm on\n"); wprintw(mainwin, "the surface, and take the first step towards eternal life!\"\n"); break; case R_GODMAGIC: wprintw(mainwin, "\"One has made a monumental discovery!\n\n"); wprintw(mainwin, "One my now comprehend, but the level of magic within the cosmos\n"); wprintw(mainwin, "has been waning. One's find is the source of this - an artifact\n"); wprintw(mainwin, "so imbued with the essense of physical conflict that its very\n"); wprintw(mainwin, "existence has disrupted the energies of imagination so vital to magic.\n"); wprintw(mainwin, "While One's path is of course One's own to decide, I would counsel you\n"); wprintw(mainwin, "to consider two alternative courses of action.\n\n"); wprintw(mainwin, "If you are able to bring the stone before me, the universe could be\n"); wprintw(mainwin, "forever enlightened. I could unlock infinite magical potential within\n"); wprintw(mainwin, "every living being, from the tiniest insect to the very stars themselves.\n\n"); wprintw(mainwin, "If One craves danger and adventure, One could also use the stone to confront\n"); wprintw(mainwin, "the God of Battle himself. Its power may just be sufficient to best the\n"); wprintw(mainwin, "Battlelord, and doing so would open the doors for One's own ascension.\n\n"); wprintw(mainwin, "One should consider these words wisely, and make One's choice.\"\n"); break; case R_GODMERCY: wprintw(mainwin, "\"HALT! By touching the Godstone of Vengeance, you have commited a\n"); wprintw(mainwin, "unspeakable sin! By rights your action should condemn you for\n"); wprintw(mainwin, "eternity. However...\"\n\n"); wprintw(mainwin, "Yumi's grave expression softens.\n\n"); wprintw(mainwin, "\"I embody mercy, and all sins can be forgiven. In this case, the road\n"); wprintw(mainwin, "to your redemption is tied with the deed itself. Bring the stone to me.\n"); wprintw(mainwin, "Perform this penance and not only will you be forgiven, but you will ensure\n"); wprintw(mainwin, "that your mistake is never again repeated for all eternity. The God of\n"); wprintw(mainwin, "Revenge will be neutralised, his influence ended.\n\n"); wprintw(mainwin, "Mercy however, extends even to the divine. I would not doom Felix to a\n"); wprintw(mainwin, "life of misery, his very essence ripped away. Should you possess the\n"); wprintw(mainwin, "power, the Godstone could be used to grant Felix the peaceful sleep\n"); wprintw(mainwin, "of death. For a tormented soul such as his, this would truly be a mercy.\n\n"); wprintw(mainwin, "Either way, your atonement begins now. Travel up to the surface, and enter\n"); wprintw(mainwin, "the magic portal. Complete your task in the Realm of Gods and all will be\n"); wprintw(mainwin, "forgiven.\"\n"); break; case R_GODNATURE: wprintw(mainwin, "\"%s! You hold the Godstone of Rage!\n\n", toupper(player->race->name[0]), (player->race->name + 1)); wprintw(mainwin, "Long have I sought this ancient artifact - it is from this stone that the\n"); wprintw(mainwin, "insane God of Fire draws his destructive power.\n"); wprintw(mainwin, "If you can just deliver this stone to me, Klikirak's reign could be ended!\n\n"); wprintw(mainwin, "Or even better...\"\n\n"); wprintw(mainwin, "Ekrub pauses for a moment.\n\n"); wprintw(mainwin, "As a being of creation I cannot affect the Fire God directly, but with the"); wprintw(mainwin, "power of the stone, you could. If you can confront and defeat him, I vow"); wprintw(mainwin, "to support you.\n\n"); wprintw(mainwin, "Within my forest on the surface, there is a portal to the Realm of Gods."); wprintw(mainwin, "Use it, and bring the Godstone!\"\n"); break; case R_GODTHIEVES: wprintw(mainwin, "\"Oho, what have you there? That stone, my friend, is none other than\n"); wprintw(mainwin, "the Godstone of Mercy itself! Oh sure, there are those rumours of\n"); wprintw(mainwin, "its protective powers, but what people don't know is that it's also\n"); wprintw(mainwin, "the direct source of power for Yumi, the Mercy Goddess.\n"); wprintw(mainwin, "Now, were someone to hold that stone... well, they'd be in prime\n"); wprintw(mainwin, "position to give the high and might lady of forgiveness a taste of\n"); wprintw(mainwin, "good old fashioned Revenge.\n\n"); wprintw(mainwin, "Of course you don't need to bother with all that. Just bring the stone\n"); wprintw(mainwin, "to me and I'll do the rest. There's a portal up on the surface, all\n"); wprintw(mainwin, "you need to do is step through, track me down, and hand over that little\n"); wprintw(mainwin, "trinket. Piece of cake!\"\n"); break; case R_GODPURITY: wprintw(mainwin, "\"Mortal! You hold an ancient artifact of immense power!\n"); wprintw(mainwin, "In your hands is the accursed Godstone of Chaos. For\n"); wprintw(mainwin, "centuries I have tracked this vile object, but somehow\n"); wprintw(mainwin, "the energies of the mortal world are keeping it from me.\n\n"); wprintw(mainwin, "This single stone is the source of all impurity in the universe.\n"); wprintw(mainwin, "Now all you need to do is deliver it to me, and it can be\n"); wprintw(mainwin, "unmade. In fact with the Godstone possessed by another,\n"); wprintw(mainwin, "the Chaos God's power may well have been waned far enough\n"); wprintw(mainwin, "for him to be confronted directly.\n\n"); wprintw(mainwin, "Travel to the Realm of Gods mortal, and come to me with the\n"); wprintw(mainwin, "stone. If you find and destroy the Chaos god on the way, all"); wprintw(mainwin, "the better. Chaos and impurity MUST be ended!\"\n"); break; default: break; } getyx(mainwin, y, x); centre(mainwin,C_WHITE, y, "[Press any key]"); getch(); restoregamewindows(); // identify the godstone identify(o); // make sure related god's anger will trigger one bad effect. if (!godprayedto(god->race->id)) { addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL); } // related god screams and gets furios/enraged at you. // (you lose prayedto if you have it?) if (getpietylev(god->race->id, NULL, NULL) == PL_FURIOUS) { // becomes enraged setpiety(god->race->id, getpietycutoff(PL_ENRAGED)); } else { // becomes furious setpiety(god->race->id, getpietycutoff(PL_FURIOUS)); } angergod(god->race->id, 0, GA_GODSTONE); killflagsofid(god->flags, F_PRAYEDTO); addflag(god->flags, F_GODBLOCKED, B_TRUE, NA, NA, NULL); } void modpiety(enum RACE rid, int amt) { lifeform_t *god; flag_t *f; god = findgod(rid); if (godblocked(god->race->id)) return; f = lfhasflag(god, F_PIETY); if (!f) return; f->val[0] += amt; limit(&f->val[0], PIETY_MIN, PIETY_MAX); } void parsegodbonusargs(flag_t *bf, enum PIETYLEV *bonuslev, enum GODBONUS *bonusid, int *arg, int *targ) { int i; char *p, buf[BUFLEN]; *bonuslev = bf->val[0]; *bonusid = bf->val[1]; *arg = bf->val[2]; // parse text args for (i = 0; i < 3; i++) targ[i] = NA; p = readuntil(buf, bf->text, ','); i = 0; while (p && (i < 3)) { if (streq(buf, "NA")) targ[i] = NA; else targ[i] = atoi(buf); i++; p = readuntil(buf, p, ','); } } void pleasegod(enum RACE rid, int amt) { lifeform_t *lf; char lfname[BUFLEN]; enum PIETYLEV oldplev,newplev; // don't please/anger gods while enraged. if (lfhasflag(player, F_RAGE)) return; // if you haven't praeyd to anyone yet, piety // gain is boosted heaps. /* if (!prayedtoany()) { switch (rid) { case R_GODTHIEVES: amt *= 4; break; default: break; } } */ lf = findgod(rid); real_getlfname(lf, lfname, NULL, B_NOSHOWALL, B_REALRACE); dblog("pleasing %s by %d\n", lfname, amt); oldplev = getpietylev(rid, NULL, NULL); modpiety(rid, amt); newplev = getpietylev(rid, NULL, NULL); // announce if (hasflag(lf->flags, F_PRAYEDTO)) { if (!isasleep(player)) { switch (rid) { case R_GODBATTLE: msg("You feel triumphant."); break; case R_GODDEATH: msg("You feel a thrill of unholy ecstasy."); break; case R_GODFIRE: msg("A searing heat runs through your blood."); break; case R_GODLIFE: if (isasleep(player)) { msg("You dream of a choir singing."); } else if (isdeaf(player)) { msg("You have a feeling of holiness."); } else { msg("You hear a distance choir singing."); } break; case R_GODMAGIC: msg("You feel Lumara's presense nearby."); break; case R_GODNATURE: msg("You feel in tune with nature."); break; case R_GODMERCY: msg("You feel a sense of serenity."); break; case R_GODPURITY: msg("You feel righteous."); break; case R_GODTHIEVES: msg("You feel a guilty pleasure."); break; default: msg("You feel like %s approves of your actions.", lfname); break; } } godgiftmaybe(rid, B_FALSE, B_TRUE); // checkgodbonus(rid,newplev, oldplev); } if (!prayedtoany() && !lfhasflag(player, F_GODOFFERDONE)) { if ((newplev > oldplev) && (newplev >= PL_PLEASED)) { if ((rid == R_GODDEATH) && (getalignment(player) == AL_GOOD)) { } else if ((rid == R_GODLIFE) && (getalignment(player) == AL_EVIL)) { } else { askforworship(rid); } } } } void pleasegodmaybe(enum RACE rid, int amt) { enum PIETYLEV modplev; int chance; if (lfhasflag(player, F_WINNER)) return; modplev = abs(getpietylev(rid, NULL, NULL)); if (!prayedtoany()) { chance = 1; } else { // the angrier or more happy the god gets, the harder it // is to please them. // ie. INDIFFERENT = 1 in 1 (always) // ie. PLEASED/TOLERATED = 1 in 2 // ie. DELIGHTED/ANGRY = 1 in 3 // ie. ECSTATIC/FURIOUS = 1 in 4 // ie. ENRAGED = 1 in 5 chance = modplev + 1; if (hasequippedobid(player->pack, OT_AMU_PIETY)) { chance--; limit(&chance, 1, NA); } } if (onein(chance)) { pleasegod(rid, amt); } } int prayto(lifeform_t *lf, lifeform_t *god) { int piety,i,x,y; char assisttext[BUFLEN]; enum PIETYLEV plev; int newgod; enum ALIGNMENT changealign = AL_NONE; taketime(lf, getactspeed(lf)); if (godblocked(god->race->id)) { msg("%s doesn't respond.", god->race->name); return B_TRUE; } if (lfhasflagval(god, F_HATESRACECLASS, lf->race->raceclass->id, NA, NA, NULL) || lfhasflagval(god, F_HATESRACE, lf->race->id, NA, NA, NULL)) { angergod(god->race->id, 50, GA_RACE); return B_TRUE; } // this will return 100 if we haven't prayed to this // god before piety = getpiety(god->race->id); if (godisangry(god->race->id)) { // get even more angry angergod(god->race->id, PIETYPRAYLOSS, GA_PRAY); return B_FALSE; } if (piety <= 99) { // piety between 0 and 99 = ignored //godsay(god->race->id, "Stop pestering me!"); msg("%s ignores you.", god->race->name); angergod(god->race->id, 0, GA_PRAY); modpiety(god->race->id, -30); return B_FALSE; } // if we get here, piety is >= 100. // you get some help... plev = getpietylev(god->race->id, NULL, NULL); if ((god->race->id == R_GODDEATH) && (getalignment(player) == AL_GOOD)) { char yn; godsay(god->race->id, B_TRUE, "You really wish to walk the path of evil, fleshling?"); yn = askchar("Change alignment to Evil?", "yn?", "n", B_TRUE, B_FALSE); if (yn == 'y') { godsay(god->race->id, B_FALSE, "So be it, foolish mortal."); changealign = AL_EVIL; } else { godsay(god->race->id, B_FALSE, "Coward!"); return B_FALSE; } } else if ((god->race->id == R_GODLIFE) && (getalignment(player) == AL_EVIL)) { char yn; godsay(god->race->id, B_TRUE, "Are you sure you wish to forsake your evil ways?"); yn = askchar("Change alignment to Good?", "yn?", "n", B_TRUE, B_FALSE); if (yn == 'y') { godsay(god->race->id, B_FALSE, "Be welcome, then!"); changealign = AL_GOOD; } else { godsay(god->race->id, B_FALSE, "If you reconsider, pray to me."); return B_FALSE; } } if (!prayedtoany()) { // special msg for first time. switch (god->race->id) { case R_GODBATTLE: strcpy(assisttext, "Welcome aboard, soldier!"); break; case R_GODTHIEVES: strcpy(assisttext, "Be welcome, brother of the night."); break; case R_GODDEATH: strcpy(assisttext, "Serve me well, fleshling... or suffer the consequences."); break; case R_GODFIRE: switch (rnd(1,2)) { case 1: strcpy(assisttext, "BURN!"); break; case 2: strcpy(assisttext, "DESTROY!"); break; } break; case R_GODLIFE: strcpy(assisttext, "Hold life forever sacred!"); break; case R_GODMERCY: strcpy(assisttext, "Welcome my child... remember mercy always."); break; case R_GODNATURE: strcpy(assisttext, "Accept Nature's aid, and aid it in return."); break; case R_GODMAGIC: strcpy(assisttext, "One's curiosity will be satisfied!"); break; case R_GODPURITY: default: strcpy(assisttext, "Remain pure, mortal - and reap the rewards."); break; } } else { switch (god->race->id) { case R_GODBATTLE: strcpy(assisttext, "Message received, soldier!"); break; case R_GODTHIEVES: strcpy(assisttext, "What mischief have you gotten yourself into, then?"); break; case R_GODDEATH: strcpy(assisttext, "You desire a favour, fleshling?"); break; case R_GODFIRE: switch (rnd(1,2)) { case 1: strcpy(assisttext, "BURN!"); break; case 2: strcpy(assisttext, "DESTROY!"); break; } break; case R_GODLIFE: strcpy(assisttext, "You prayer is answered!"); break; case R_GODMERCY: strcpy(assisttext, "I hear your prayer, child."); break; case R_GODNATURE: strcpy(assisttext, "Nature hears your call!"); break; case R_GODMAGIC: strcpy(assisttext, "One calls upon the eldritch powers..."); break; case R_GODPURITY: default: strcpy(assisttext, "You appear in need of assistance, mortal!"); break; } } godsay(god->race->id, B_TRUE, assisttext); if (changealign != AL_NONE) { setalignment(player, changealign); msg("^BYour alignment has changed to %s!", getalignmentname(changealign)); more(); msg("^B(you will receive -15%% XP for the next 1001 turns)"); addtempflag(player->flags, F_LEARNBOOST, -15, NA, NA, NULL, 1001); } // at this point, remember that we have now prayed to // this god. ie. player is expected to follow the god's rules. if (!hasflag(god->flags, F_PRAYEDTO)) { addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL); newgod = B_TRUE; } if (god) { lifeform_t *l; int dist; int donesomething = B_FALSE,n; cell_t *c; object_t *o; switch (god->race->id) { case R_GODBATTLE: dist = isinbattle(player, B_INCLUDEDISTANT, B_FALSE); if (dist) { int redo = B_TRUE; object_t *o; // knock back nearby enemies if (dist == 1) { if (plev >= 0) { int power; power = 1+(plev*3); dospelleffects(god, OT_S_FORCESPHERE, power, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); } } if (getstamina(player) <= pctof(25, getmaxstamina(player))) { setstamina(player, getmaxstamina(player)); msg("\"Time for your second wind!\""); } while (redo) { redo = B_FALSE; switch (rnd(1,4)) { case 1: // bless weapon msg("\"Fight in my name!\""); o = getweapon(player); if (o && !isblessed(o)) { blessob(o); } else { redo = B_TRUE; } break; case 2: // bezerk if (lfhasflag(player, F_RAGE)) { redo = B_TRUE; } else { msg("\"Rage like a badger!\""); player->stamina = getmaxstamina(player); abilityeffects(player, OT_A_RAGE, player->cell, player, NULL); } break; case 3: // msg("\"I will guide your blade!\""); dospelleffects(god, OT_S_TRUESTRIKE, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); break; case 4: // msg("\"Your blows will be as lightning!\""); dospelleffects(god, OT_S_HASTE, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); break; } // end switch }// end while redo } else { // not in battle... int done = B_FALSE; object_t *o,*wep; wep = getweapon(player); if (uncurse_one_equipped(lf, "\"Be free of your curse!\"")){ done = B_TRUE; } if (!done) { // try to repair armour or undull weapons i = 0; for (o = lf->pack->first ; o ; o = o->next) { if (isequipped(o)) { if (isdamaged(o) || (getobbonus(o, B_FALSE) < 0)) { dospelleffects(lf, OT_S_MENDING, 10, NULL, o, NULL, B_BLESSED, NULL, B_FALSE, NULL); i++; } } } if (i) { msg("\"Keep fighting, warrior!\""); done = B_TRUE; } } if (!done) { int redo = B_TRUE; while (redo) { redo = B_FALSE; switch (rnd(1,2)) { case 1: // detect life msg("\"Seek out battle in my name!\""); dospelleffects(god, OT_S_DETECTLIFE, 10, lf, NULL, lf->cell, B_BLESSED, NULL, B_TRUE, NULL); break; case 2: // bless weapon msg("\"Fight in my name!\""); o = getweapon(player); if (o && !isblessed(o)) { blessob(o); } else { redo = B_TRUE; } break; } // end switch }// end while redo } } break; case R_GODPURITY: msg("\"Witness the holy radiance of purity!\""); c = getrandomadjcell(lf->cell, &ccwalkable, B_ALLOWEXPAND); if (c) { dospelleffects(god, OT_S_LIGHT, 10, NULL, NULL, c, B_BLESSED, NULL, B_TRUE, NULL); } // uncurse ALL equipped obs for (o = lf->pack->first ; o ; o = o->next) { if (iscursed(o) && isequipped(o)) { blessob(o); } } // cure poison if (ispoisoned(lf)) { dospelleffects(god, OT_S_CUREPOISON, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL); } // fix drained stats restoredrainedstats(lf); if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { int i,nretflags; flag_t *retflag[MAXCANDIDATES]; // smite evil or exorcise for (l = lf->cell->map->lf ; l ; l = l->next) { if ((getraceclass(l) == RC_DEMON) || (getalignment(l) == AL_EVIL)) { if (haslof(lf->cell, l->cell, LOF_WALLSTOP, NULL)) { if (getraceclass(l) == RC_DEMON) { // exorcise them castspell(god, OT_S_EXORCISE, l, NULL, l->cell, NULL, NULL); } else { // smite them castspell(god, OT_S_SMITEEVIL, l, NULL, l->cell, NULL, NULL); } } } } // remove all temporary bad status effects getflags(player->flags, retflag, &nretflags, F_BLIND, F_CONFUSED, F_DEAF, F_CAFFEINATED, F_DRUNK, F_FROZEN, F_GRABBEDBY, F_NAUSEATED, F_PAIN, F_POISONED, F_SLOWACT, F_SLOWMOVE, F_SLOWACTMOVE, F_NONE); for (i = 0; i < nretflags; i++) { if (istransitoryflag(retflag[i])) { killflag(retflag[i]); } } } else { object_t *wep; flag_t *f; int donesomething = B_FALSE; // restore original lifeform shape if (!donesomething) { f = lfhasflag(lf, F_ORIGRACE); if (f) { setrace(lf, f->val[0], B_TRUE); donesomething = B_TRUE; } } // restore to original lifeform size if (!donesomething) { f = hasflag(lf->race->flags, F_SIZE); if (f && (getlfsize(lf) != f->val[0])) { resizelf(lf, f->val[0], B_TRUE); donesomething = B_TRUE; } } // purify your food if (!donesomething) { if (!dospelleffects(god, OT_S_PURIFYFOOD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL)) { donesomething = B_TRUE; } } // bless your weapon if (!donesomething) { wep = getweapon(player); if (wep && !isblessed(wep)) { blessob(wep); donesomething = B_TRUE; } } // bless 1-3 random obs if (!donesomething) { int nposs = 0, n; object_t *o,*poss[MAXCANDIDATES]; nposs = 0; n = rnd(1,3); // num to bless for (o = player->pack->first ; o ; o = o->next) { if (!isblessed(o) && !hasflag(o->flags, F_NOBLESS)) { poss[nposs++] = o; } } if (nposs < n) n = nposs; for (i = 0; i < n; i++) { o = poss[rnd(0,nposs-1)]; while (isblessed(o)) { o = poss[rnd(0,nposs-1)]; } blessob(o); donesomething = B_TRUE; } } } break; case R_GODDEATH: if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { msg("\"Behold, the power of death!\""); n = OT_NONE; switch (rnd(0,1)) { case 0: n = OT_S_FLAYFLESH; break; case 1: n = OT_S_HECTASSERVANT; break; } for (i = 1; i < lf->nlos; i++) { lifeform_t *who; who = lf->los[i]->lf; if (who && !areallies(lf, who)) { if (isundead(who)) { makepeaceful(who, god); } else if (gettr(who) <= 5) { // instakill who->lastdamtype = DT_NECROTIC; setlastdam(who, "Hecta's finger of death."); who->hp = 0; } else if (n != OT_NONE) { if (n == OT_S_HECTASSERVANT) { c = getrandomadjcell(player->cell, &ccwalkable, B_ALLOWEXPAND); if (c) { castspell(god, n, player, NULL, c, NULL, NULL); } n = OT_S_DRAINLIFE; } else { dospelleffects(god, n, 20, who, NULL, who->cell, B_UNCURSED, NULL, B_FALSE, NULL); } break; } } } // animate dead dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); } else { // restore mana or stamina if (lf->mp < getmaxmp(lf)) { gainmp(lf, getmaxmp(lf)); msg("An unholy energy revitalises your mind!"); } else if (getstamina(player) <= getmaxstamina(player)) { setstamina(player, getmaxstamina(player)); msg("An unholy energy revitalises your muscles!"); } // animate dead dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); if (rnd(1,2) == 1) { // kill trees / decay wooden objects around you dospelleffects(god, OT_S_DECAYFIELD, 10, NULL, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL); } } break; case R_GODFIRE: // restore frozen weapons o = getweapon(player); if (o && (o->material->id == MT_ICE) && (o->material != o->type->material)) { changemat(o, o->type->material->id); } // enlarge any nearby fires dospelleffects(NULL, OT_S_PYROMANIA, 10, player, NULL, player->cell, B_BLESSED, NULL, B_TRUE, NULL); // set all nearby non-cosmetic objects on fire i = 0; for (y = 0; y < player->cell->map->h; y++) { for (x = 0; x < player->cell->map->w; x++) { cell_t *c; c = getcellat(player->cell->map, x, y); if (c && cellhaslos(c, player->cell)) { if (c->lf && (c->lf != player)) { dospelleffects(NULL, OT_S_FLAMEPILLAR, 10, NULL, NULL, c, B_BLESSED, NULL, B_TRUE, NULL); } else if (countnoncosmeticobs(c->obpile, B_FALSE, B_FALSE)) { addobfast(c->obpile, OT_FIRESMALL); i++; } } } } if (i) { msg("Nearby objects erupt in flames!"); more(); } break; case R_GODLIFE: if (ispoisoned(lf)) { castspell(god, OT_S_CUREPOISON, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } if (gethungerlevel(gethungerval(player)) >= H_PECKISH) { dospelleffects(NULL, OT_S_SATEHUNGER, 10, player, NULL, player->cell, B_UNCURSED, NULL, B_FALSE, NULL); donesomething = B_TRUE; } if (lf->mp < (getmaxmp(lf)/2)) { gainmp(lf, getmaxmp(lf)/2); donesomething = B_TRUE; } if (lfhasflag(lf, F_INJURY)) { castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } if (lf->hp < lf->maxhp) { gainhp(lf, lf->maxhp); donesomething = B_TRUE; statdirty = B_TRUE; } if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { // turn undead castspell(god, OT_S_TURNUNDEAD, lf, NULL, NULL, NULL, NULL); if (plev >= PL_INDIFFERENT) { int pow; pow = plev + 1; limit(&pow, 1, getspellmaxpower(OT_S_HEAVENARM)); dospelleffects(NULL, OT_S_HEAVENARM, pow, player, NULL, player->cell, B_UNCURSED, NULL, B_FALSE, NULL); donesomething = B_TRUE; } } // will bless player's water if nothing else done. if (!donesomething && (plev >= PL_PLEASED)) { object_t *o; for (o = player->pack->first ; o ; o = o->next) { if (o->type->id == OT_POT_WATER) { if (!isblessed(o)) { blessob(o); } else if (!o->blessknown) { dospelleffects(god, OT_S_IDENTIFY, 10, NULL, o, NULL, B_UNCURSED, NULL, B_FALSE, NULL); } } } } if (donesomething) { msg("\"Rejoice in life!\""); } break; case R_GODTHIEVES: if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { lifeform_t *l; int donesomething = B_FALSE; if (islowhp(lf)) { // teleport away msg("\"Nothing like a quick getaway!\""); dospelleffects(NULL, OT_S_DISPERSAL, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL); donesomething = B_TRUE; } else { int redo = B_TRUE; while (redo) { redo = B_FALSE; switch (rnd(1,2)) { case 1: // steal from your enemies for (l = lf->cell->map->lf ; l ; l = l->next) { if ((l != lf) && areenemies(l, lf) && cansee(l, lf)) { object_t *wep; // confiscate their weapon wep = getweapon(l); if (wep) { if (!donesomething) { msg("\"I'll take that...\""); donesomething = B_TRUE; } castspell(god, OT_S_CONFISCATE, l, wep, l->cell, NULL, NULL); } } } break; case 2: if (lfhasflag(lf, F_INVISIBLE)) { redo = B_TRUE; } else { // invisibility msg("\"Can't hurt what you can't see...\""); addtempflag(lf->flags, F_INVISIBLE, B_TRUE, NA, NA, NULL, 20); } break; } } } if (!donesomething) { // teleport away msg("\"Nothing like a quick getaway!\""); dospelleffects(NULL, OT_S_DISPERSAL, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_FALSE, NULL); } } else { int redo = B_TRUE; object_t *possob[MAXPILEOBS]; int npossob,i,first; object_t *o; // unlock doors and remove impassable objects first = B_TRUE; for (i = 0; i < player->nlos; i++) { cell_t *c; object_t *o,*nexto; c = player->los[i]; for (o = c->obpile->first ; o ; o = nexto) { nexto = o->next; if (killflagsofid(o->flags, F_LOCKED) || killflagsofid(o->flags, F_SECRET)) { if (first) { msg("\"Access granted!\""); first = B_FALSE; } noise(c, NULL, NC_OTHER, SV_TALK, "the click of a lock.", NULL); } else if (isimpassableob(o, lf, SZ_ANY)) { if (first) { msg("\"Access granted!\""); first = B_FALSE; } removeob(o, ALL); noise(c, NULL, NC_OTHER, SV_TALK, "the sucking of air.", NULL); } } } // uncurse one equipped ob if (uncurse_one_equipped(lf, "\"Curses, schmurses!\"")){ redo = B_FALSE; } while (redo) { redo = B_FALSE; switch (rnd(1,2)) { case 1: msg("\"Allow me to reveal your surroundings...\""); dospelleffects(god, OT_S_MAPPING, 5, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); dospelleffects(god, OT_S_REVEALHIDDEN, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); break; case 2: // identify objects npossob = 0; for (o = lf->pack->first ; o ; o = o->next) { if (!isknown(o)) { possob[npossob++] = o; } } if (npossob) { char oldname[BUFLEN],newname[BUFLEN]; o = possob[rnd(0,npossob-1)]; getobname(o,oldname,o->amt); identify(o); getobname(o,newname,o->amt); msg("\"%s %s you are carrying %s %s!\"", (o->amt == 1) ? "That" : "Those", noprefix(oldname), (o->amt == 1) ? "is" : "are", newname); } else { redo = B_TRUE; } break; } // end switch }// end while redo } break; case R_GODMAGIC: if (player->mp <= (getmaxmp(player)/2)) { gainmp(lf, getmaxmp(lf)); msg("\"One's magical reserves have been filled!\""); } else { object_t *toid[MAXPILEOBS],*touncurse[MAXPILEOBS]; int idnum = 0, uncursenum = 0; int done = B_FALSE; // uncurse one equipped ob if (uncurse_one_equipped(lf, "\"One's curse is lifted.\"")){ done = B_TRUE; } if (!done) { // any unid'd scrolls/books? for (o = player->pack->first ; o ; o = o->next) { if ((o->type->obclass->id == OC_SCROLL) || (o->type->obclass->id == OC_BOOK)) { if (!isknown(o)) { toid[idnum++] = o; } if (isequipped(o) && iscursed(o)) { touncurse[uncursenum++] = o; } } } if (idnum) { msg("\"One is granted the favour of knowledge!\""); o = toid[rnd(0,idnum-1)]; dospelleffects(god, OT_S_IDENTIFY, 10, NULL, o, NULL, B_UNCURSED, NULL, B_FALSE, NULL); } else if (uncursenum) { msg("\"One is granted the favour of redemption!\""); o = touncurse[rnd(0,uncursenum-1)]; uncurseob(o, NULL); } else { if (lf->mp < getmaxmp(lf)) { // just regain mana. gainmp(lf, getmaxmp(lf)); msg("\"One's magical reserves have been filled!\""); } else { lf->maxmp++; msg("\"One's magical capacity has been increased!\""); } } } } break; case R_GODMERCY: if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { lifeform_t *l; int donesomething = B_FALSE; int preventstoning = B_FALSE; int preventparalysis = B_FALSE; // if something nearby could stone/petrify you, confer temporary immunity. for (l = lf->cell->map->lf ; l ; l = l->next) { if ((l != lf) && areenemies(l, lf) && cansee(l, lf)) { obpile_t *op = NULL; int nweps = 0; object_t *wep[MAXCANDIDATES]; flag_t *damflag[MAXCANDIDATES]; int lastweaponidx; if (l->race->id == R_COCKATRICE) { preventstoning = B_TRUE; } getweapons(l, B_MELEEONLY, wep, damflag, &lastweaponidx, &op, &nweps); for (i = 0; i < nweps; i++) { if (hasflagval(wep[i]->flags, F_HITCONFER, F_PARALYZED, NA, NA, NULL)) { preventparalysis = B_TRUE; break; } } if (op) killobpile(op); } } if (preventstoning || preventparalysis) { addtempflag(player->flags, F_DTIMMUNE, DT_PETRIFY, NA, NA, NULL, rnd(40,50)); donesomething = B_TRUE; } // sleep on all enemies if (!donesomething) { for (l = lf->cell->map->lf ; l ; l = l->next) { if ((l != lf) && areenemies(l, lf) && cansee(l, lf)) { castspell(god, OT_S_SLEEP, l, NULL, l->cell, NULL, NULL); donesomething = B_TRUE; } } } } else { if (ispoisoned(lf)) { msg("\"Let thy body be purged of toxins.\""); castspell(god, OT_S_CUREPOISON, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } if (gethungerlevel(gethungerval(player)) >= H_PECKISH) { msg("\"Let thy stomach be satisfied.\""); castspell(god, OT_S_SATEHUNGER, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } if (islowhp(lf)) { msg("\"Let thy wounds be healed.\""); castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } } // uncurse one equipped ob uncurse_one_equipped(lf, "\"Let thy curse be ended!\""); break; case R_GODNATURE: if (isinbattle(lf, B_INCLUDEDISTANT, B_FALSE)) { lifeform_t *l; int donesomething = B_FALSE; int redo = B_TRUE; while (redo) { redo = B_FALSE; switch (rnd(1,3)) { case 1: msg("\"My children will bind your enemies!\""); // entangle your enemies for (l = lf->cell->map->lf ; l ; l = l->next) { if ((l != lf) && areenemies(l, lf) && cansee(l, player)) { dospelleffects(NULL, OT_S_ENTANGLE, 10, NULL, NULL, l->cell, B_BLESSED, NULL, B_TRUE, NULL); } } break; case 2: // summon plants msg("\"My children will aid you!\""); summonlfs(player, player->cell, R_NONE, RC_PLANT, SZ_ANY, AL_NONE, 5, PERMENANT, B_TRUE); break; case 3: // lightning msg("\"The powers of the sky will smite your foes!\""); for (l = lf->cell->map->lf ; l ; l = l->next) { if ((l != lf) && areenemies(l, lf) && cansee(l, player)) { dospelleffects(god, OT_S_CALLLIGHTNING, 10, NULL, NULL, l->cell, B_BLESSED, NULL, B_TRUE, NULL); } } break; } } // fighting a dragon? for (i = 0; i < lf->nlos; i++) { if (lf->los[i]->lf && (getraceclass(lf->los[i]->lf) == RC_DRAGON)) { godappears(god->race->id, NULL); aiattack(god, lf->los[i]->lf, PERMENANT); donesomething = B_TRUE; break; } } } else {// not in battle int donesomething = B_FALSE; flag_t *f; // fix any poison potions dospelleffects(god, OT_S_PURIFYFOOD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE, NULL); if (ispoisoned(lf)) { msg("\"I will cure your poison...\""); castspell(god, OT_S_CUREPOISON, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } if (!donesomething && (gethungerlevel(gethungerval(player)) >= H_PECKISH)) { msg("\"I will cure your hunger...\""); castspell(god, OT_S_SATEHUNGER, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } if (!donesomething && islowhp(lf)) { msg("\"I will heal your injuries...\""); castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL); donesomething = B_TRUE; } if (!donesomething) { // out of ammo? object_t *gun; gun = getfirearm(lf); if (gun && !getammo(gun) && !getrandomammo(lf)) { objecttype_t *ot; ot = getrandomammofor(gun, B_FALSE); if (ot) { char obtogive[BUFLEN],ammoname[BUFLEN]; char gunname[BUFLEN]; object_t *ammo; f = hasflag(gun->flags, F_AMMOCAPACITY); snprintf(obtogive, BUFLEN, "%d %s of seeking", f->val[0], ot->name); ammo = addob(gun->contents, obtogive); identify(ammo); getobname(ammo, ammoname, ammo->amt); getobname(gun, gunname, 1); msg("%s appear%s in your %s!", ammoname, OBS1(ammo), noprefix(gunname)); donesomething = B_TRUE; } } } if (!donesomething) { // mend one random armour object_t *poss[MAXCANDIDATES]; int nposs = 0; for (o = lf->pack->first ; o ; o = o->next) { if (isequipped(o) && isarmour(o) && isdamaged(o)) { poss[nposs++] = o; } } if (nposs) { o = poss[rnd(0,nposs-1)]; dospelleffects(lf, OT_S_MENDING, 10, NULL, o, NULL, B_BLESSED, NULL, B_FALSE, NULL); donesomething = B_TRUE; } } if (!donesomething) { // bless armour object_t *poss[MAXCANDIDATES]; int nposs = 0; for (o = lf->pack->first ; o ; o = o->next) { if (isequipped(o) && isarmour(o) && (o->blessed == B_UNCURSED)) { poss[nposs++] = o; } } if (nposs) { o = poss[rnd(0,nposs-1)]; msg("\"Nature's power will protect you...\""); blessob(o); } donesomething = B_TRUE; } } break; default: break; } } // new god effects if (newgod) { switch (god->race->id) { case R_GODTHIEVES: makelearnable(lf, SK_THIEVERY); makelearnable(lf, SK_LOCKPICKING); break; default: break; } } if (god->race->id == R_GODNATURE) { object_t *oo; oo = addob(lf->cell->obpile, "flower"); if (oo) { if (haslos(player, lf->cell)) { msg("A beautiful flower grows from the ground."); } addflag(oo->flags, F_NOSACRIFICE, B_TRUE, NA, NA, NULL); } } // if (!godgiftmaybe(god->race->id, B_FALSE)) { // if you didn't get a gift, lower piety for this god modpiety(god->race->id, -PIETYPRAYLOSS); // } // lower piety for other related gods for (i = 0; i < ngodlfs; i++) { if (godlf[i] != god) { modpiety(godlf[i]->race->id, -25); } } return B_FALSE; } void setpiety(enum RACE rid, int amt) { lifeform_t *god; flag_t *f; god = findgod(rid); f = lfhasflag(god, F_PIETY); if (!f) return; f->val[0] = amt; limit(&f->val[0], PIETY_MIN, PIETY_MAX); } // uncurse one equipped ob // returns true if we do somethign int uncurse_one_equipped(lifeform_t *lf, char *text) { object_t *possob[MAXPILEOBS],*o; int npossob; npossob = 0; for (o = lf->pack->first ; o ; o = o->next) { if (iscursed(o) && isequipped(o)) { possob[npossob++] = o; } } if (npossob) { o = possob[rnd(0,npossob-1)]; if (text) { msg(text); } blessob(o); return B_TRUE; } return B_FALSE; }