1051 lines
27 KiB
C
1051 lines
27 KiB
C
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#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 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;
|
|
|
|
lifeform_t *godlf[MAXGODS];
|
|
int ngodlfs = 0;
|
|
|
|
void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
|
|
lifeform_t *god;
|
|
int piety;
|
|
int dosay = B_FALSE;
|
|
|
|
god = findgod(rid);
|
|
|
|
modpiety(rid, -amt);
|
|
piety = getpiety(rid);
|
|
|
|
// 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 {
|
|
godsay(rid, B_TRUE, "You dare destroy my symbols?"); break;
|
|
}
|
|
case GA_ASSAULT:
|
|
godsay(rid, B_TRUE, "You dare attack one of my innocent servants?"); break;
|
|
case GA_EAT:
|
|
godsay(rid, B_TRUE, "That is NOT acceptable for consumption!"); break;
|
|
case GA_HERESY:
|
|
godsay(rid, B_TRUE, "Heresy!"); break;
|
|
case GA_MERCY:
|
|
godsay(rid, B_TRUE, "You allowed your foe to escape!"); break;
|
|
case GA_MONEY:
|
|
godsay(rid, B_TRUE, "Giving away money offends me..."); break;
|
|
case GA_MURDER:
|
|
godsay(rid, B_TRUE, "You have taken a life!"); 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_SPELL:
|
|
godsay(rid, B_TRUE, "Your magic offends me!"); break;
|
|
}
|
|
|
|
// announce
|
|
if (piety > 0) { // not angry yet.
|
|
godsay(rid, dosay, "You are testing my patience, mortal!");
|
|
} else if (piety > -100) { // minor bad stuff
|
|
godsay(rid,dosay, "You have angered me, mortal!");
|
|
} else if (piety > -200) { // major bad stuff
|
|
godsay(rid,dosay, "You go too far, mortal!");
|
|
} else { // god will attack
|
|
godsay(rid,dosay, "You will regret that!");
|
|
}
|
|
|
|
// 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 (piety > -100) {
|
|
int i,n;
|
|
lifeform_t *l;
|
|
// minor bad stuff
|
|
switch (rid) {
|
|
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_GODTHIEVES:
|
|
// take a random object
|
|
msg("\"Yoink!\"");
|
|
castspell(god, OT_S_CONFISCATE, player, NULL, player->cell, NULL, NULL);
|
|
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);
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (piety > -200) {
|
|
object_t *o;
|
|
lifeform_t *l;
|
|
int n,i;
|
|
// major bad stuff
|
|
switch (god->race->id) {
|
|
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_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_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_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, roll("2d4"), DT_DIRECT);
|
|
}
|
|
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 {
|
|
// god attacks!
|
|
godappears(god->race->id, NULL);
|
|
aiattack(god, player, PERMENANT);
|
|
}
|
|
}
|
|
}
|
|
|
|
// anger the god if you are worshippin them.
|
|
void angergodmaybe(enum RACE rid, int amt, enum GODANGERREASON why) {
|
|
lifeform_t *god;
|
|
god = findgod(rid);
|
|
if (lfhasflag(god, F_PRAYEDTO)) {
|
|
angergod(rid, amt, why);
|
|
}
|
|
}
|
|
|
|
void dooffer(void) {
|
|
object_t *o, *nexto;
|
|
lifeform_t *god;
|
|
flag_t *retflag[MAXCANDIDATES];
|
|
int nretflags,pietyplus = 0;
|
|
// which god?
|
|
god = askgod("To whom will you sacrifice?", B_TRUE);
|
|
if (!god) {
|
|
msg("Cancelled.");
|
|
return;
|
|
}
|
|
getflags(god->flags, retflag, &nretflags, F_SACRIFICEOB, F_SACRIFICEOBCLASS, F_SACRIFICEOBWITHFLAG, F_SACRIFICEOBBLESSED, 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;
|
|
// does the god want this?
|
|
getflags(god->flags, retflag, &nretflags, F_SACRIFICEOB, F_SACRIFICEOBCLASS, F_SACRIFICEOBWITHFLAG, F_SACRIFICEOBBLESSED, 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)) {
|
|
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];
|
|
} 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)) {
|
|
ok = B_TRUE;
|
|
thispiety = f->val[2];
|
|
}
|
|
if (ok) {
|
|
char *p;
|
|
char obname[BUFLEN];
|
|
|
|
// override piety sometimes
|
|
if (god->race->id == R_GODTHIEVES) {
|
|
// 100 value = 1 piety.
|
|
// NOTE: this could be exploited by constantly sacrificing
|
|
// 1 gold at a time!
|
|
if ((o->type->id == OT_GOLD) || hasflag(o->flags, F_GEM)) {
|
|
thispiety = (getobvalue(o) / 100) + 1;
|
|
}
|
|
}
|
|
|
|
if (haslos(player, player->cell)) {
|
|
getobname(o, obname, ALL);
|
|
p = strdup(f->text);
|
|
p = strrep(p, "OB", obname, NULL);
|
|
if (o->amt == 1) {
|
|
p = strrep(p, "IS", "is", NULL);
|
|
p = strrep(p, "#S", "s", NULL);
|
|
} else {
|
|
p = strrep(p, "IS", "are", NULL);
|
|
p = strrep(p, "#S", "", NULL);
|
|
}
|
|
msg("%s", p);
|
|
free(p);
|
|
}
|
|
removeob(o, ALL);
|
|
pietyplus += thispiety;
|
|
break;
|
|
}
|
|
} // end for each f_sacrificexxx flag
|
|
} // end foreach ob
|
|
|
|
if (pietyplus) {
|
|
pleasegod(god->race->id, pietyplus);
|
|
} else {
|
|
nothinghappens();
|
|
}
|
|
taketime(player, getactspeed(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;
|
|
}
|
|
|
|
enum RACE getopposinggod(enum RACE rid) {
|
|
switch (rid) {
|
|
case R_GODPURITY: return R_GODTHIEVES;
|
|
case R_GODTHIEVES: return R_GODPURITY;
|
|
case R_GODDEATH: return R_GODMERCY;
|
|
case R_GODMERCY: return R_GODDEATH;
|
|
default: break;
|
|
}
|
|
return R_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;
|
|
}
|
|
|
|
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_BROWN;
|
|
if (happiness) strcpy(happiness, "Tolerated");
|
|
return PL_TOLERATED;
|
|
} else if (piety <= 199) { // 100 - 199
|
|
if (col) *col = C_GREY;
|
|
if (happiness) strcpy(happiness, "Indifferent");
|
|
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_BOLDGREEN;
|
|
if (happiness) strcpy(happiness, "Delighted");
|
|
return PL_DELIGHTED;
|
|
} else { // 400+
|
|
if (col) *col = C_BOLDCYAN;
|
|
if (happiness) strcpy(happiness, "Ecstatic");
|
|
return PL_ECSTATIC;
|
|
}
|
|
return PL_INDIFFERENT;
|
|
}
|
|
|
|
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 i,nposs = 0;
|
|
lifeform_t *god,*poss[MAXGODS];
|
|
for (i = 0; i < ngodlfs; i++) {
|
|
god = godlf[i];
|
|
if (lfhasflag(god, F_PRAYEDTO)) {
|
|
poss[nposs++] = god;
|
|
}
|
|
}
|
|
if (nposs == 0) {
|
|
return NULL;
|
|
}
|
|
return poss[rnd(0,nposs-1)];
|
|
}
|
|
|
|
lifeform_t *godappears(enum RACE rid, cell_t *where) {
|
|
lifeform_t *god;
|
|
char killedname[BUFLEN],godname[BUFLEN];
|
|
god = findgod(rid);
|
|
real_getlfname(god, godname, B_FALSE, B_FALSE);
|
|
strcpy(killedname, "");
|
|
if (!where) {
|
|
// somewhere next to the player.
|
|
where = getrandomadjcell(player->cell, WE_WALKABLE, B_FALSE);
|
|
if (!where) {
|
|
where = getrandomadjcell(player->cell, B_FALSE, B_FALSE);
|
|
}
|
|
}
|
|
|
|
// now see if anyone is there.
|
|
if (where->lf) {
|
|
// kill them.
|
|
getlfname(where->lf, killedname);
|
|
killlf(where->lf);
|
|
if (where->type->solid) {
|
|
setcelltype(where, where->habitat->emptycelltype);
|
|
}
|
|
teleportto(god, where, B_TRUE);
|
|
if (haslos(player, where) && strlen(killedname)) {
|
|
msg("%s transforms into %s!", killedname, godname);
|
|
}
|
|
|
|
} else {
|
|
teleportto(god, where, B_TRUE);
|
|
}
|
|
|
|
return god;
|
|
}
|
|
|
|
int godblocked(enum RACE rid) {
|
|
lifeform_t *opposegod;
|
|
enum RACE opposeid;
|
|
// 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) {
|
|
lifeform_t *god;
|
|
int piety,gotgift = B_FALSE;
|
|
int chance;
|
|
god = findgod(rid);
|
|
piety = getpiety(rid);
|
|
|
|
if (fromtemple) {
|
|
chance = 100;
|
|
} else if (piety >= 200) {
|
|
// ie. 200 -> 4%
|
|
// ie. 500 -> 10%
|
|
chance = piety / 50;
|
|
} else {
|
|
chance = 0;
|
|
}
|
|
|
|
if (pctchance(chance)) { // if this is true, you get a gift.
|
|
char obtogive[BUFLEN];
|
|
int rollagain = B_TRUE;
|
|
gotgift = B_TRUE;
|
|
|
|
killflagsofid(player->flags, F_ASLEEP);
|
|
|
|
godsay(god->race->id, B_TRUE, "I bestow a gift upon you, mortal!");
|
|
strcpy(obtogive, "");
|
|
switch (god->race->id) {
|
|
case R_GODPURITY:
|
|
while (rollagain) {
|
|
int n,nposs,i;
|
|
object_t *poss[MAXCANDIDATES],*o;
|
|
flag_t *f;
|
|
object_t *wep;
|
|
rollagain = B_FALSE;
|
|
switch (rnd(1,6)) {
|
|
case 1:
|
|
snprintf(obtogive, BUFLEN, "2-4 blessed potions of water");
|
|
break;
|
|
case 2:
|
|
snprintf(obtogive, BUFLEN, "blessed great weapon");
|
|
break;
|
|
case 3:
|
|
snprintf(obtogive, BUFLEN, "wand of turn undead");
|
|
break;
|
|
case 4: // bless your weapon
|
|
wep = getweapon(player);
|
|
if (wep && !isblessed(wep)) {
|
|
blessob(wep);
|
|
} else {
|
|
rollagain = B_TRUE;
|
|
}
|
|
break;
|
|
case 5: // 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;
|
|
case 6: // bless 1-3 obs
|
|
nposs = 0;
|
|
n = rnd(1,3); // num to bless
|
|
for (o = player->pack->first ; o ; o = o->next) {
|
|
if (!isblessed(o)) {
|
|
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);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case R_GODDEATH:
|
|
while (rollagain) {
|
|
flag_t *f;
|
|
object_t *wep;
|
|
rollagain = B_FALSE;
|
|
switch (rnd(1,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, "3-5 cursed potions of water");
|
|
break;
|
|
case 3:
|
|
snprintf(obtogive, BUFLEN, "cursed branded weapon");
|
|
break;
|
|
case 4: // 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 5: // 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_DTIMMUNE, DT_NECROTIC, NA, NA, NULL, FROMGODGIFT);
|
|
f->obfrom = god->race->id;
|
|
}
|
|
break;
|
|
case 6:
|
|
if (player->race->id == R_VAMPIRE) {
|
|
rollagain = B_TRUE;
|
|
} else {
|
|
msg("\"Go forth and kill in my name!\"");
|
|
setrace(player, R_VAMPIRE, B_TRUE); // ie. don't set origrace!
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case R_GODTHIEVES:
|
|
while (rollagain) {
|
|
rollagain = B_FALSE;
|
|
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;
|
|
case R_GODMERCY:
|
|
while (rollagain) {
|
|
flag_t *f;
|
|
rollagain = B_FALSE;
|
|
switch (rnd(1,4)) {
|
|
case 1:
|
|
snprintf(obtogive, BUFLEN, "3 vials of ambrosia");
|
|
break;
|
|
case 2:
|
|
snprintf(obtogive, BUFLEN, "ring of regeneration");
|
|
break;
|
|
case 3:
|
|
snprintf(obtogive, BUFLEN, "ring of miracles");
|
|
break;
|
|
case 4: // immune to disease / 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;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
} // end switch
|
|
|
|
if (strlen(obtogive)) {
|
|
object_t *o;
|
|
o = addob(player->cell->obpile, obtogive);
|
|
if (o) {
|
|
char buf[BUFLEN];
|
|
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, lower piety a little.
|
|
//setpiety(rid, 101);
|
|
if (!fromtemple) {
|
|
modpiety(rid, -50);
|
|
}
|
|
} // 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;
|
|
}
|
|
|
|
void godsay(enum RACE rid, int says, char *format, ...) {
|
|
lifeform_t *god;
|
|
char godname[BUFLEN], buf[BUFLEN];
|
|
va_list args;
|
|
|
|
va_start(args, format);
|
|
vsnprintf( buf, BUFLEN, format, args );
|
|
va_end(args);
|
|
|
|
god = findgod(rid);
|
|
real_getlfname(god, godname, B_FALSE, B_FALSE);
|
|
|
|
if (says) {
|
|
msg("%s%s voice booms out from the heavens:", godname, getpossessive(godname)); more();
|
|
}
|
|
msg("\"%s\"", buf);
|
|
}
|
|
|
|
void modpiety(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);
|
|
}
|
|
|
|
void pleasegod(enum RACE rid, int amt) {
|
|
lifeform_t *lf;
|
|
char lfname[BUFLEN];
|
|
lf = findgod(rid);
|
|
real_getlfname(lf, lfname, B_FALSE, B_FALSE);
|
|
|
|
modpiety(rid, amt);
|
|
|
|
// announce
|
|
if (hasflag(lf->flags, F_PRAYEDTO)) {
|
|
if (!isasleep(lf)) {
|
|
switch (rid) {
|
|
case R_GODDEATH:
|
|
msg("You feel a thrill of unholy ecstasy.");
|
|
break;
|
|
case R_GODMERCY:
|
|
msg("You feel a sense of peace.");
|
|
break;
|
|
case R_GODPURITY:
|
|
msg("You hear a distant choir singing.");
|
|
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);
|
|
}
|
|
}
|
|
|
|
void pleasegodmaybe(enum RACE rid, int amt) {
|
|
enum PIETYLEV modplev;
|
|
int chance;
|
|
modplev = abs(getpietylev(rid, NULL, NULL));
|
|
|
|
// 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 (onein(chance)) {
|
|
pleasegod(rid, amt);
|
|
}
|
|
}
|
|
|
|
int prayto(lifeform_t *lf, lifeform_t *god) {
|
|
int piety,i;
|
|
|
|
taketime(lf, getactspeed(lf));
|
|
|
|
if (godblocked(god->race->id)) {
|
|
msg("%s ignores you.", god->race->name);
|
|
return B_TRUE;
|
|
}
|
|
|
|
// this will return 100 if we haven't prayed to this
|
|
// god before
|
|
piety = getpiety(god->race->id);
|
|
|
|
// 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);
|
|
}
|
|
|
|
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!");
|
|
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...
|
|
godsay(god->race->id, B_TRUE, "You appear in need of assistance, mortal!");
|
|
switch (god->race->id) {
|
|
lifeform_t *l;
|
|
int donesomething = B_FALSE;
|
|
cell_t *c;
|
|
object_t *o;
|
|
object_t *oposs[MAXPILEOBS];
|
|
int noposs = 0, n;
|
|
case R_GODPURITY:
|
|
msg("\"Witness the holy radiance of purity!\"");
|
|
c = getrandomadjcell(lf->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
|
if (c) {
|
|
dospelleffects(god, OT_S_LIGHT, 10, NULL, NULL, c, B_BLESSED, NULL, B_TRUE);
|
|
}
|
|
// get list of cursed obs
|
|
noposs = 0;
|
|
for (o = lf->pack->first ; o ; o = o->next) {
|
|
if (iscursed(o)) {
|
|
oposs[noposs++] = o;
|
|
}
|
|
}
|
|
if (noposs) {
|
|
o = oposs[rnd(0,noposs-1)];
|
|
blessob(o);
|
|
}
|
|
// smite evil
|
|
for (l = lf->cell->map->lf ; l ; l = l->next) {
|
|
if (getalignment(l) == AL_EVIL) {
|
|
if (haslof(lf->cell, l->cell, LOF_WALLSTOP, NULL)) {
|
|
// smite them
|
|
castspell(god, OT_S_SMITEEVIL, l, NULL, l->cell, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
// turn undead
|
|
castspell(god, OT_S_TURNUNDEAD, lf, NULL, NULL, NULL, NULL);
|
|
|
|
break;
|
|
case R_GODDEATH:
|
|
msg("\"Behold, the power of death!\"");
|
|
c = NULL;
|
|
n = OT_NONE;
|
|
switch (rnd(0,4)) {
|
|
case 0: n = OT_S_PAIN; break;
|
|
case 1: n = OT_S_DRAINLIFE; break;
|
|
case 2: n = OT_S_BLINDNESS; break;
|
|
case 3: n = OT_S_FLAYFLESH; break;
|
|
case 4: n = OT_S_HECTASSERVANT;
|
|
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
|
|
break;
|
|
}
|
|
if (n == OT_S_HECTASSERVANT) {
|
|
if (c) {
|
|
castspell(god, n, player, NULL, c, NULL, NULL);
|
|
n = OT_NONE;
|
|
} else {
|
|
n = OT_S_DRAINLIFE;
|
|
}
|
|
}
|
|
|
|
if (n != OT_NONE) {
|
|
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);
|
|
} else {
|
|
castspell(god, n, who, NULL, who->cell, NULL, NULL);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dospelleffects(god, OT_S_ANIMATEDEAD, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
|
|
break;
|
|
case R_GODTHIEVES:
|
|
if (isinbattle(lf)) {
|
|
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);
|
|
} else {
|
|
// steal from your enemies
|
|
for (l = lf->cell->map->lf ; l ; l = l->next) {
|
|
if ((l != lf) && lfhasflagval(l, F_TARGETLF, lf->id, NA, NA, NULL)) {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
} else {
|
|
int i,first = B_TRUE;
|
|
msg("\"Allow me to reveal your surroundings...\"");
|
|
dospelleffects(god, OT_S_MAPPING, 5, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
|
|
dospelleffects(god, OT_S_REVEALHIDDEN, 10, lf, NULL, lf->cell, B_UNCURSED, NULL, B_TRUE);
|
|
// unlock doors
|
|
for (i = 0; i < player->nlos; i++) {
|
|
cell_t *c;
|
|
object_t *o;
|
|
c = player->los[i];
|
|
if (c != player->cell) {
|
|
o = hascloseddoor(c);
|
|
if (o && hasflag(o->flags, F_LOCKED)) {
|
|
if (first) {
|
|
msg("\"Access granted!\"");
|
|
first = B_FALSE;
|
|
}
|
|
killflagsofid(o->flags, F_LOCKED);
|
|
noise(c, NULL, NC_OTHER, SV_TALK, "the click of a lock.", NULL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case R_GODMERCY:
|
|
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) || !donesomething) {
|
|
msg("\"Let thy wounds be healed.\"");
|
|
castspell(god, OT_S_HEALINGMAJ, player, NULL, player->cell, NULL, NULL);
|
|
donesomething = B_TRUE;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
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);
|
|
}
|