- [+] delvers should always want money for info, unless you are a

delver too.
- [+] mirror image (mental)
    - [+] varpower
    - [+] makes power 'clone' lfs who look the same as caster
        - [+] ie. same race.
        - [+] also same job/armour/weps?
        - [+] add f_noxp
        - [+] add f_nocorpse
        - [+] add f_summonedby so they vanish when the caster dies
        - [+] add f_phantasm
            - [+] vanish after _power_ hits,
            - [+] attacks do 0 damage
            - [+] don't announce innefectual attacks
            - [+] dont cast spells or use abilities
        - [+] petify() them if made by the player
            - [+] force them to stay close.
        - [+] in io.c or getlfname, show "[clone]" if it has f_phantasm
              and was created by player
    - [+]  mosnters try to attack them.
    - [+] once one gets hit enough times, it disappears
    - [+] if the caster dies or changes level, they disappear.
    - [+] can't talk to them
    - [+] their obejcts vanish when they die
    - [+] don't talk
- [+] make Yumi more about forgiving silly mistakes and avoiding
      instakills
    - [+] remove liking of healing
    - [+] remove like of healing spells
    - [+] takes a long time to anger.
    - [+] aviod traps (bamf you away before they trigger)
    - [+] prayers:
        - [+] resist stoning (pray while appropriate creatures around)
        - [+] resist paralysis (pray while appropriate creatures around)
        - [+] sleep on enemies
    - [+] passive powers:
        - [+] always warn as if wisdom is high (passive) 
        - [+] always save when killed right after using stairs
              (passive) "well, that seemed unfair."
    - [+] gift:
        - [+] auto sixth sense
        - [+] potions of restoration
        - [+] ring of miracles
- [+] shouldn't be able to Offer while enraged.
- [+] don't lose stamina while caffeinated
- [+] new vault: pit with walkway around it
- [+] bug: when worshipping yumi you get "you kill xxx" but they're
      still alive
    - [+] ... but they're still alive!
    - [+] ... for yumi, move KO chance from losehp() to attacklf().
    - [+] do the check BEFORE setting 'fatal'
    - [+] pass forceko to losehp_real
- [+] bug: adjustdamhardness should only trigger when ismeleedam() is
      true, not isphysicaldam()
- [+] greatly reduce motel cost
- [+] change order in attack.c: apply damage THEN announce, to deal
      with KO
    - [+] do it.
    - [+] test KO code.
    - [+] then check that feign death still works
- [+] demonskin vest should be flammable or vulnerable to fire.
- [+] time to get up should depend on size.
    - [+] less than human: shortnone
    - [+] human: normal
    - [+] larger than human: longer
- [+] expert unarmed now gives you 'flip'
- [+] reduce damage done by low-level monsters
- [+] change resoration into a spell
    - [+] implement
    - [+] test
- [+] new spell: ressurection
    - [+] corpses need to remember their lf's level
    - [+] test
- [+] godstone of life - revives/restores all
- [+] rename "confiscate" to "yoink", and make it take a random object
      at power 1, selected at power 2
- [+] gods should attack player if they are Enraged or Furious
- [+] is STR calc to see if you can push a boulder still working?
- [+] change to wizards:
    - [+] start at novice in all magic skills (but don't gain initial
          spells)
- [+] killing undead should please glorana LOTS. because it's hard to
      gain piety with her otherwise.
- [+] restoration spells/potion should hurt undead
- [+] healing spells/potions should hurt undead
- [+] immolate shouldnt work if there is aleady a fire tehre.
CODE FOR WINNING THE GAME:
- [+] get at least one godstone
- [+] exit the dungeon
- [+] find the portal to the realm of gods
- [+] opposing god should appear once you pick up a godstone, and tell
      you what to do next.
    - [+] "come to the realm of gods and use it to destroy (related
          god)"
    - [+] "or if you lack the courage, give it to me!"
    - [+] "you will find a portal on the surface"
- [+] use the portal to teleport to realm of gods
- [+] implement text for all gods...
- [+] god text in wt_god - should say 'but you werent meant to replace
      them!'
- [+] EITHER:
    - [+] challenge and defeat the god related to this godstone (more
          points. "Crowned the god of xxx.")
        - [+] TEST
    - [+] offer the godstone to the godstone's opposing god  (less
          points, "Ascended to demigod-hood.")
        - [+] implement
        - [+] TEST
GODSTONES:
- [+] klikirak: rage
    - [+] done
    - [+]  (make this one have fire effects too)
- [+] glorana: life
- [+] Felix shouldn't be able to yoink the godstone off you!
- [+] Write up the rest of the Godstone finding text.....
    - [+] magic
    - [+] battle
    - [+] life
    - [+] mercy
- [+] you can't hurt gods unless you
    - [+] a) have their godstone
    - [+] b) are in the realm of gods
This commit is contained in:
Rob Pearce 2012-02-17 05:16:45 +00:00
parent 30006c4cac
commit 067cd92f37
18 changed files with 1566 additions and 312 deletions

21
ai.c
View File

@ -160,6 +160,10 @@ enum OBTYPE aigetattackspell(lifeform_t *lf, lifeform_t *victim) {
if (db) { if (db) {
dblog(".oO { looking for attack spells/abils }"); dblog(".oO { looking for attack spells/abils }");
} }
if (lfhasflag(lf, F_PHANTASM)) {
if (db) dblog(".oO { no attack spell because i am a phantasm }");
return OT_NONE;
}
f = lfhasflag(lf, F_NEEDOBFORSPELLS); f = lfhasflag(lf, F_NEEDOBFORSPELLS);
@ -222,6 +226,11 @@ enum OBTYPE aigetfleespell(lifeform_t *lf) {
db = B_TRUE; db = B_TRUE;
} }
if (lfhasflag(lf, F_PHANTASM)) {
if (db) dblog(".oO { no flee spell because i am a phantasm }");
return OT_NONE;
}
f = lfhasflag(lf, F_FLEEFROM); f = lfhasflag(lf, F_FLEEFROM);
if (f) { if (f) {
fleefrom = findlf(lf->cell->map, f->val[0]); fleefrom = findlf(lf->cell->map, f->val[0]);
@ -788,7 +797,15 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
if (pctchance(chance)) { if (pctchance(chance)) {
flag_t *f; flag_t *f;
if (lfhasflag(lf, F_HATESALL) || lfhasflag(lf, F_RAGE)) { if ((getraceclass(lf) == RC_GOD) &&
(getpietylev(lf->race->id, NULL, NULL) <= PL_FURIOUS) &&
isplayer(who)) {
if (nhateposs < MAXCANDIDATES) {
if (db) dblog(".oO { i am an angry god - found player lfid %d (%s) ! }",
who->id, who->race->name);
hateposs[nhateposs++] = who;
}
} else if (lfhasflag(lf, F_HATESALL) || lfhasflag(lf, F_RAGE)) {
if (nhateposs < MAXCANDIDATES) { if (nhateposs < MAXCANDIDATES) {
if (db) dblog(".oO { hate everything - found lfid %d (%s) ! }",who->id, who->race->name); if (db) dblog(".oO { hate everything - found lfid %d (%s) ! }",who->id, who->race->name);
hateposs[nhateposs++] = who; hateposs[nhateposs++] = who;
@ -863,7 +880,7 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
} else { } else {
// god with no targets? // god with no targets?
if (lf->race->raceclass->id == RC_GOD) { if (lf->race->raceclass->id == RC_GOD) {
if (onein(6) && (lf->cell->map->habitat->id != H_HEAVEN)) { if (onein(3) && (lf->cell->map->habitat->id != H_HEAVEN)) {
if (db) dblog(".oO { planeshifting home }"); if (db) dblog(".oO { planeshifting home }");
// gods will planeshift away // gods will planeshift away
if (!castspell(lf, OT_S_PLANESHIFT, lf, NULL, lf->cell, NULL, NULL)) { if (!castspell(lf, OT_S_PLANESHIFT, lf, NULL, lf->cell, NULL, NULL)) {

134
attack.c
View File

@ -585,6 +585,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
char attackername[BUFLEN]; char attackername[BUFLEN];
char victimname[BUFLEN],victimbpname[BUFLEN]; char victimname[BUFLEN],victimbpname[BUFLEN];
int fatal = B_FALSE; int fatal = B_FALSE;
int waskod = B_FALSE;
int feigneddeath = B_FALSE; int feigneddeath = B_FALSE;
int deflected = B_FALSE; int deflected = B_FALSE;
int weppassthrough = B_FALSE; int weppassthrough = B_FALSE;
@ -737,7 +738,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
hit = rolltohit(lf, victim, wep, &critical); hit = rolltohit(lf, victim, wep, &critical);
if (critical) { if (critical && !lfhasflag(lf, F_PHANTASM)) {
object_t *armour; object_t *armour;
char noun[BUFLEN]; char noun[BUFLEN];
critpos = getrandomcorebp(victim, lf); critpos = getrandomcorebp(victim, lf);
@ -885,6 +886,11 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
dam[0] = (int) ( (float)dam[0] + loreadd ); dam[0] = (int) ( (float)dam[0] + loreadd );
} }
if (lfhasflag(lf, F_PHANTASM)) {
dam[0] = 0;
if (aidb) dblog(".oO { adjusting phantasm dam to 0 }");
}
if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0])); if (aidb) dblog(".oO { dealing %d %s damage }", dam[0], getdamname(damtype[0]));
ndam = 1; ndam = 1;
@ -956,6 +962,8 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
adjustdamlf(victim, &dam[i], damtype[i]); adjustdamlf(victim, &dam[i], damtype[i]);
//dblog("adjusted for lf to dam[%d] = %d",i,dam[i]); //dblog("adjusted for lf to dam[%d] = %d",i,dam[i]);
if (lfhasflag(lf, F_PHANTASM)) dam[0] = 0;
// armour doesn't reduce damage for backstabs or critical hits. // armour doesn't reduce damage for backstabs or critical hits.
// BUT in the case of a critical hit, the armour might get // BUT in the case of a critical hit, the armour might get
// damaged during criticalhit() // damaged during criticalhit()
@ -976,16 +984,22 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (lfhasflag(lf, F_QUIVERINGPALM)) { if (lfhasflag(lf, F_QUIVERINGPALM)) {
// make sure damage isn't fatal // make sure damage isn't fatal
// becquse we want them to explode
if (dam[i] >= victim->hp) { if (dam[i] >= victim->hp) {
dam[i] = victim->hp - 1; dam[i] = victim->hp - 1;
} }
} }
// will this hit be fatal? // at this point, will the damage be fatal? we need to know so we
// can determine whether monsters will use feign death ability.
// NOTE: whether or not the atatck is fatal is re-calculated again
// later on after damage is applied to ensure that the correct
// attack string is displayed ("you hit xxx" vs "you kill xxx").
if (dam[i] >= victim->hp) { if (dam[i] >= victim->hp) {
fatal = B_TRUE; fatal = B_TRUE;
} }
if (lfhasflag(lf, F_PHANTASM)) dam[0] = 0;
// monsters feigning death? // monsters feigning death?
if (lfhasflag(victim, F_FEIGNINGDEATH)) { if (lfhasflag(victim, F_FEIGNINGDEATH)) {
@ -998,30 +1012,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
} }
// announce it
if (!feigneddeath) {
if (isplayer(lf) || isplayer(victim) || cansee(player, lf) || cansee(player, victim)) {
construct_hit_string(lf, victim, attackername, victimname, victimbpname, wep, damtype[i], dam[i], victim->maxhp, i, backstab, critical, fatal, isunarmed, buf);
if (strlen(buf)) {
warn("%s", buf);
}
}
//if (!isplayer(lf) && !isplayer(victim)) {
noise(lf->cell, lf, NC_FIGHTING, SV_SHOUT, "fighting.", NULL);
//}
if (fatal) {
if (strstr(buf, "behead")) {
// we'll need to place the severed head object
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
}
if ((isplayer(lf) || cansee(player, victim)) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
// don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
}
}
}
if (willheal) { if (willheal) {
if (cansee(player, victim)) { if (cansee(player, victim)) {
flag_t *f; flag_t *f;
@ -1034,11 +1024,13 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (f) { if (f) {
f->known = B_TRUE; f->known = B_TRUE;
} }
gainhp(victim, dam[i]);
} }
gainhp(victim, dam[i]);
reduceamt = 0;
} else if (lfhasflag(lf, F_QUIVERINGPALM)) { } else if (lfhasflag(lf, F_QUIVERINGPALM)) {
// victim explodes! // victim explodes!
losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE, NULL, B_FALSE); losehp_real(victim, victim->hp, DT_EXPLOSIVE, lf, "a quivering palm strike", B_FALSE, NULL, B_FALSE, NULL);
reduceamt = 0;
} else { } else {
char attackername2[BUFLEN]; char attackername2[BUFLEN];
real_getlfname(lf, attackername2, B_FALSE, B_TRUE); real_getlfname(lf, attackername2, B_FALSE, B_TRUE);
@ -1067,21 +1059,58 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} else { } else {
strcpy(buf, attackername2); strcpy(buf, attackername2);
} }
losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, wep, B_FALSE); losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, wep, B_FALSE, &waskod);
}
// victim's armour loses hp // was it fatal ? override previously calculated value.
if (reduceamt && !critical) { if ((victim->hp <= 0) && !waskod) {
applyarmourdamage(victim, wep, dam[i], damtype[i], lf); fatal = B_TRUE;
// train armour } else {
practice(victim, SK_ARMOUR, 1); fatal = B_FALSE;
}
// announce it
if (!feigneddeath) {
if (isplayer(lf) || isplayer(victim) || cansee(player, lf) || cansee(player, victim)) {
construct_hit_string(lf, victim, attackername, victimname, victimbpname, wep, damtype[i], dam[i], victim->maxhp, i, backstab, critical, fatal, isunarmed, buf);
if (strlen(buf)) {
warn("%s", buf);
}
} }
if (backstab) { //if (!isplayer(lf) && !isplayer(victim)) {
practice(lf, SK_BACKSTAB, 1); //}
if (fatal) {
if (strstr(buf, "behead")) {
// we'll need to place the severed head object
addflag(victim->flags, F_BEHEADED, B_TRUE, NA, NA, NULL);
}
if ((isplayer(lf) || cansee(player, victim)) && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
if (!hasflag(victim->flags, F_PHANTASM)) {
// don't also say "the xx dies"
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
}
}
} }
} }
// make noise
noise(lf->cell, lf, NC_FIGHTING, SV_SHOUT, "fighting.", NULL);
// victim's armour loses hp
if (reduceamt && !critical) {
applyarmourdamage(victim, wep, dam[i], damtype[i], lf);
// train armour
practice(victim, SK_ARMOUR, 1);
}
if (backstab) {
practice(lf, SK_BACKSTAB, 1);
}
if (fatal || waskod) break; // stop now!
} // end foreach damtype } // end foreach damtype
if (waskod) {
loseconsciousness(victim, waskod, lf);
}
// other effects // other effects
if (!isdead(victim) && !blocked) { if (!isdead(victim) && !blocked) {
// special weapon effects, as long as you're not doing a heavy blow // special weapon effects, as long as you're not doing a heavy blow
@ -1112,7 +1141,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
char lfname[BUFLEN]; char lfname[BUFLEN];
dam = rolldie(f->val[0], f->val[1]) + f->val[2]; dam = rolldie(f->val[0], f->val[1]) + f->val[2];
real_getlfname(lf, lfname, B_FALSE, B_FALSE); real_getlfname(lf, lfname, B_FALSE, B_FALSE);
losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE, NULL, B_FALSE); losehp_real(victim, dam, DT_BITE, lf, lfname, B_FALSE, NULL, B_FALSE, NULL);
if (isplayer(victim) || cansee(player, victim)) { if (isplayer(victim) || cansee(player, victim)) {
msg("^%c%s bites %s!", isplayer(victim) ? 'b' : 'n', lfname, victimname); msg("^%c%s bites %s!", isplayer(victim) ? 'b' : 'n', lfname, victimname);
} }
@ -1138,7 +1167,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
if (nmatched >= f->val[2]) { if (nmatched >= f->val[2]) {
char damstring[BUFLEN]; char damstring[BUFLEN];
snprintf(damstring, BUFLEN, "%s pack", lfname); snprintf(damstring, BUFLEN, "%s pack", lfname);
losehp_real(victim, f->val[0], f->val[1], lf, damstring, B_TRUE, NULL, B_FALSE); losehp_real(victim, f->val[0], f->val[1], lf, damstring, B_TRUE, NULL, B_FALSE, NULL);
if (isplayer(victim) || cansee(player, victim)) { if (isplayer(victim) || cansee(player, victim)) {
msg("^%c%s pack attacks %s!", isplayer(victim) ? 'b' : 'c', lfname, victimname); msg("^%c%s pack attacks %s!", isplayer(victim) ? 'b' : 'c', lfname, victimname);
} }
@ -1208,7 +1237,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
attackername); attackername);
} }
snprintf(damstring, BUFLEN, "%s%s %s", victimname, getpossessive(victimname), noprefix(f->text)); snprintf(damstring, BUFLEN, "%s%s %s", victimname, getpossessive(victimname), noprefix(f->text));
losehp_real(lf, rdam, f->val[2], victim, damstring, B_TRUE, NULL, B_TRUE); losehp_real(lf, rdam, f->val[2], victim, damstring, B_TRUE, NULL, B_TRUE, NULL);
} }
} }
} }
@ -1492,7 +1521,6 @@ int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag) {
enum DAMTYPE damtype[100]; enum DAMTYPE damtype[100];
int ndam = 0; int ndam = 0;
char attackername[BUFLEN]; char attackername[BUFLEN];
char obname[BUFLEN];
int isunarmed = B_FALSE; int isunarmed = B_FALSE;
char buf[BUFLEN]; char buf[BUFLEN];
int i; int i;
@ -1530,8 +1558,10 @@ int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag) {
for (i = 0; i < ndam; i++) { for (i = 0; i < ndam; i++) {
char cellname[BUFLEN];
sprintf(cellname, "%s %s", needan(c->type->name) ? "an" : "a", c->type->name);
// announce the hit // announce the hit
construct_hit_string(lf, NULL, attackername, c->type->name, NULL, wep, damtype[i], dam[i], maxhp, i, B_FALSE, B_FALSE, B_FALSE, isunarmed, buf); construct_hit_string(lf, NULL, attackername, cellname, NULL, wep, damtype[i], dam[i], maxhp, i, B_FALSE, B_FALSE, B_FALSE, isunarmed, buf);
if (strlen(buf)) { if (strlen(buf)) {
msg("%s", buf); msg("%s", buf);
@ -1587,7 +1617,7 @@ int attackwall(lifeform_t *lf, cell_t *c, object_t *wep, flag_t *damflag) {
// ok // ok
} else { } else {
char buf[BUFLEN]; char buf[BUFLEN];
snprintf(buf, BUFLEN, "punching %s", obname); snprintf(buf, BUFLEN, "punching %s", cellname);
if ( losehp(lf, 1, DT_BASH, lf, buf)) { if ( losehp(lf, 1, DT_BASH, lf, buf)) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("^bOw!"); msg("^bOw!");
@ -1929,6 +1959,11 @@ int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) {
int i; int i;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags = 0; int nretflags = 0;
if (lf && lfhasflag(lf, F_PHANTASM)) {
return *dam;
}
// special case - EXTRADAM goes onto INITIAL dam[] if the same type, rather than // special case - EXTRADAM goes onto INITIAL dam[] if the same type, rather than
// adding a new one. // adding a new one.
getflags(lf->flags, retflag, &nretflags, F_EXTRADAM, F_NONE); getflags(lf->flags, retflag, &nretflags, F_EXTRADAM, F_NONE);
@ -1982,6 +2017,11 @@ int getextradamwep(object_t *wep, int *dam, enum DAMTYPE *damtype, int *ndam) {
lifeform_t *owner; lifeform_t *owner;
owner = wep->pile->owner; owner = wep->pile->owner;
if (owner && lfhasflag(owner, F_PHANTASM)) {
return *dam;
}
// enchanted weapons only deal magic damage if the user has remaining mp. // enchanted weapons only deal magic damage if the user has remaining mp.
if (owner && owner->mp) { if (owner && owner->mp) {
f = hasflag(wep->flags, F_ENCHANTED); f = hasflag(wep->flags, F_ENCHANTED);
@ -2066,6 +2106,12 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) {
int dam; int dam;
int bonusdam = 0; int bonusdam = 0;
flag_t *f; flag_t *f;
lifeform_t *owner;
owner = o->pile->owner;
if (owner && lfhasflag(owner, F_PHANTASM)) {
return 0;
}
if (damflag) { if (damflag) {
int min,max; int min,max;
@ -2096,8 +2142,6 @@ int getdamroll(object_t *o, lifeform_t *victim, flag_t *damflag) {
// special effects ? // special effects ?
f = hasflag(o->flags, F_BALANCE); f = hasflag(o->flags, F_BALANCE);
if (f) { if (f) {
lifeform_t *owner;
owner = o->pile->owner;
if (owner && victim) { if (owner && victim) {
float ratio; float ratio;
ratio = (float)owner->maxhp / (float)victim->maxhp; ratio = (float)owner->maxhp / (float)victim->maxhp;

106
data.c
View File

@ -829,6 +829,17 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_AIR, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_DEATH, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_DIVINATION, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_ENCHANTMENT, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_FIRE, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_COLD, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_GRAVITY, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_MODIFICATION, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_SUMMONING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_TRANSLOCATION, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_SS_WILD, PR_NOVICE, NA, NULL);
// learnable skills // learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
@ -838,17 +849,6 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_STAVES, PR_ADEPT, NA, NULL); // limit addflag(lastjob->flags, F_CANLEARN, SK_STAVES, PR_ADEPT, NA, NULL); // limit
addflag(lastjob->flags, F_CANLEARN, SK_THROWING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_THROWING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_AIR, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_DEATH, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_DIVINATION, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_ENCHANTMENT, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_FIRE, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_COLD, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_GRAVITY, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_MODIFICATION, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_SUMMONING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_TRANSLOCATION, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SS_WILD, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DEMONS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LORE_DEMONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL);
@ -1655,7 +1655,7 @@ void initobjects(void) {
addflag(lastot->flags, F_REPELBLESSED, B_BLESSED, B_CURSED, NA, NULL); addflag(lastot->flags, F_REPELBLESSED, B_BLESSED, B_CURSED, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_DFEATURE, SZ_LARGE); addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_EFFECT, SZ_LARGE);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_VERYRARE, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, RR_VERYRARE, NULL);
addflag(lastot->flags, F_GLYPH, C_BOLDGREEN, '^', NA, NULL); addflag(lastot->flags, F_GLYPH, C_BOLDGREEN, '^', NA, NULL);
addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, "portal"); addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, "portal");
@ -2058,6 +2058,8 @@ void initobjects(void) {
addflag(lastot->flags, F_RECHARGE, 1, NA, NA, NULL); addflag(lastot->flags, F_RECHARGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKGOD, R_GODPURITY, NA, NA, NULL);
addot(OT_GODSTONER, "Godstone of Rage", "An ancient artifact representing the power of anger.", MT_STONE, 3, OC_GODSTONE, SZ_SMALL); addot(OT_GODSTONER, "Godstone of Rage", "An ancient artifact representing the power of anger.", MT_STONE, 3, OC_GODSTONE, SZ_SMALL);
addflag(lastot->flags, F_GLYPH, C_RED, '*', NA, NULL); addflag(lastot->flags, F_GLYPH, C_RED, '*', NA, NULL);
addflag(lastot->flags, F_VALUE, 1000, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 1000, NA, NA, NULL);
@ -2065,6 +2067,17 @@ void initobjects(void) {
addflag(lastot->flags, F_RECHARGE, 1, NA, NA, NULL); addflag(lastot->flags, F_RECHARGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKGOD, R_GODFIRE, NA, NA, NULL);
addot(OT_GODSTONEL, "Godstone of Life", "An ancient artifact representing the power of life.", MT_STONE, 3, OC_GODSTONE, SZ_SMALL);
addflag(lastot->flags, F_GLYPH, C_WHITE, '*', NA, NULL);
addflag(lastot->flags, F_VALUE, 1000, NA, NA, NULL);
addflag(lastot->flags, F_CHARGES, 100, 100, NA, NULL);
addflag(lastot->flags, F_RECHARGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_REPLENISHABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKGOD, R_GODLIFE, NA, NA, NULL);
// flora // flora
addot(OT_FLOWER, "flower", "A colourful woodland flower.", MT_PLANT, 0.01, OC_FLORA, SZ_TINY); addot(OT_FLOWER, "flower", "A colourful woodland flower.", MT_PLANT, 0.01, OC_FLORA, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, ""); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_FREQUENT, "");
@ -2333,7 +2346,7 @@ void initobjects(void) {
addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, NULL); addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_EXPLODEONDAM, DT_FIRE, NA, NA, "2d4"); addflag(lastot->flags, F_EXPLODEONDAM, DT_FIRE, NA, NA, "2d4");
addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 15, NA, NA, NULL);
addot(OT_POT_COFFEE, "potion of coffee", "A caffeinated beverage prepared from coffee beans.", MT_GLASS, 1, OC_POTION, SZ_TINY); addot(OT_POT_COFFEE, "potion of coffee", "A caffeinated beverage prepared from coffee beans. Prevents your stamina from decreasing, but also prevents you from sleeping.", MT_GLASS, 1, OC_POTION, SZ_TINY);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL); addflag(lastot->flags, F_VALUE, 10, NA, NA, NULL);
addot(OT_POT_RUM, "potion of rum", "Strong liqour which is sure to make you tipsy. This will make you unsteady and lower your accuracy, but also let you ignore pain, minor damage, and many mental attacks.", MT_GLASS, 1, OC_POTION, SZ_TINY); addot(OT_POT_RUM, "potion of rum", "Strong liqour which is sure to make you tipsy. This will make you unsteady and lower your accuracy, but also let you ignore pain, minor damage, and many mental attacks.", MT_GLASS, 1, OC_POTION, SZ_TINY);
@ -2595,6 +2608,10 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MPCOST, 0, NA, NA, NULL); addflag(lastot->flags, F_MPCOST, 0, NA, NA, NULL);
// l2 // l2
addot(OT_S_ALCHEMY, "alchemy", "Converts any metal item into (^bpower * 10^n)% of its value in gold.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
addot(OT_S_PULLMETAL, "pull metal", "Pulls metal objects to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PULLMETAL, "pull metal", "Pulls metal objects to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
@ -3538,6 +3555,21 @@ void initobjects(void) {
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l5
addot(OT_S_RESTORATION, "restoration", "Restore nearly all the target's HP and MP, and remove almost all negative status effects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l6
addot(OT_S_RESSURECTION, "ressurection", "Restore one adjacent corpse to life.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_OBJECT, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
/////////////////// ///////////////////
// mental/psionic // mental/psionic
/////////////////// ///////////////////
@ -3581,6 +3613,12 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_MIRRORIMAGE, "mirror image", "Creates ^bpower^n illusionary clones of the caster to distract enemies. These clones cannot deal damage, and vanish when hit.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many clones are created, and how many hits they can sustain.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
// l3 // l3
addot(OT_S_PSYARMOUR, "psychic armour", "Mentally block incoming attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PSYARMOUR, "psychic armour", "Mentally block incoming attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The psychic armour's Armour Rating is ^bpower*4^n."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The psychic armour's Armour Rating is ^bpower*4^n.");
@ -3874,6 +3912,14 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_CONFISCATE, "yoink", "Transports one random object directly from the target to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level II, the target object can be selected.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 2, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_DISPERSAL, "dispersal", "Scatters everything in the target cell around the area.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_DISPERSAL, "dispersal", "Scatters everything in the target cell around the area.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
@ -3976,12 +4022,7 @@ void initobjects(void) {
addot(OT_S_WISHLIMITED, "limited wish", "Grants the caster a wish of their choice. Beware - casting this powerful spell will reduce the caster's hit points by 25%.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_WISHLIMITED, "limited wish", "Grants the caster a wish of their choice. Beware - casting this powerful spell will reduce the caster's hit points by 25%.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
addot(OT_S_CONFISCATE, "confiscate", "Takes any object from the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); // l6
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_GIFT, "gift", "Grants the target any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_GIFT, "gift", "Grants the target any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
@ -5543,6 +5584,8 @@ void initobjects(void) {
addflag(lastot->flags, F_CRITPROTECTION, 33, NA, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 33, NA, NA, NULL);
addot(OT_ARMOURDEMON, "demonskin vest", "Body armour created by flaying the flesh from a living demon, it retains its innate immunity to fire.", MT_FLESH, 7, OC_ARMOUR, SZ_MEDIUM); addot(OT_ARMOURDEMON, "demonskin vest", "Body armour created by flaying the flesh from a living demon, it retains its innate immunity to fire.", MT_FLESH, 7, OC_ARMOUR, SZ_MEDIUM);
killflagsofid(lastot->flags, F_FLAMMABLE);
killflagsofid(lastot->flags, F_DTVULN);
addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL);
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
@ -7825,7 +7868,6 @@ void initrace(void) {
addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, NA, 10, "OB explode#S in a shower of sparks!"); addflag(lastrace->flags, F_SACRIFICEOB, OT_CORPSE, NA, 10, "OB explode#S in a shower of sparks!");
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes/dislikes // likes/dislikes
addflag(lastrace->flags, F_GODPOISON, B_FALSE, 100, NA, NULL); addflag(lastrace->flags, F_GODPOISON, B_FALSE, 100, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead");
@ -7984,7 +8026,6 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_BLINKASS, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_BLINKASS, NA, NA, "pw:10;");
//addflag(lastrace->flags, F_CANWILL, OT_S_HUNGER, NA, NA, "pw:1;"); //addflag(lastrace->flags, F_CANWILL, OT_S_HUNGER, NA, NA, "pw:1;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes/dislikes // likes/dislikes
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "backstabbing"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "backstabbing");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "stealing items"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "stealing items");
@ -8076,7 +8117,6 @@ void initrace(void) {
} }
} }
addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_WISHLIMITED, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
// likes // likes
addflag(lastrace->flags, F_GODPOISON, B_TRUE, 3, NA, NULL); addflag(lastrace->flags, F_GODPOISON, B_TRUE, 3, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing (especially the good-aligned)"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing (especially the good-aligned)");
@ -8127,7 +8167,7 @@ void initrace(void) {
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "inflicting cold-based damage"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "inflicting cold-based damage");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "using cold-based magic"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "using cold-based magic");
// sacrifices // sacrifices
addflag(lastrace->flags, F_SACRIFICEOBWITHFLAG, F_FLAMMABLE, NA, 10, "OB IS consumed in a burst of fire!"); addflag(lastrace->flags, F_SACRIFICEOBWITHFLAG, F_FLAMMABLE, NA, 2, "OB IS consumed in a burst of fire!");
addrace(R_GODMAGIC, "Lumara", 55, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Lumara is the goddess of magic. She appears as a slender elderly woman, her expression wise with age."); addrace(R_GODMAGIC, "Lumara", 55, '@', C_BOLDMAGENTA, MT_FLESH, RC_GOD, "Lumara is the goddess of magic. She appears as a slender elderly woman, her expression wise with age.");
setbodytype(lastrace, BT_HUMANOID); setbodytype(lastrace, BT_HUMANOID);
@ -8207,7 +8247,6 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_SATEHUNGER, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_SATEHUNGER, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_DISPERSAL, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_DISPERSAL, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_SLEEP, NA, NA, "pw:10;"); addflag(lastrace->flags, F_CANWILL, OT_S_SLEEP, NA, NA, "pw:10;");
addflag(lastrace->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL); addflag(lastrace->flags, F_GODPOISON, B_FALSE, 25, NA, NULL);
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "allowing fleeing creatures to escape"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "allowing fleeing creatures to escape");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "knocking enemies unconscious"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "knocking enemies unconscious");
@ -9020,7 +9059,7 @@ void initrace(void) {
addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 5, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_HIGH, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_AGI, AT_HIGH, NA, NULL);
@ -9912,7 +9951,7 @@ void initrace(void) {
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, AT_LOW, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "snorts^a snort"); addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "snorts^a snort");
addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL);
addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL);
@ -10171,7 +10210,7 @@ void initrace(void) {
addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL); addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL); addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "0d4+2"); addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "0d4+2");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 1, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 1, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 1, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
@ -10736,7 +10775,8 @@ void initrace(void) {
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL); addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
addflag(lastrace->flags, F_FLEEONDAM, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_FLEEONDAM, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DTRESIST, DT_COLD, B_TRUE, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_FIRE, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_COLD, B_TRUE, NA, NULL);
addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 3, NA, NA, NULL);
@ -12161,7 +12201,7 @@ void initrace(void) {
addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL); addflag(lastrace->flags, F_EVASION, -10, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 5, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_AXES, NA, NULL); addflag(lastrace->flags, F_STARTOBWEPSK, 50, SK_AXES, NA, NULL);
addflag(lastrace->flags, F_STARTOB, 25, NA, NA, "buckler"); addflag(lastrace->flags, F_STARTOB, 25, NA, NA, "buckler");
@ -12554,7 +12594,8 @@ void initrace(void) {
addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL); addflag(r->flags, F_FLEEONHPPCT, 20, NA, NA, NULL);
addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL); addflag(r->flags, F_RESISTMAG, 15, NA, NA, NULL);
addflag(r->flags, F_MEDITATES, B_TRUE, NA, NA, NULL); addflag(r->flags, F_MEDITATES, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_SEEINDARK, 10, NA, NA, NULL); addflag(r->flags, F_SEEINDARK, 10, NA, NA, NULL);
addflag(r->flags, F_CANWILL, OT_S_PLANESHIFT, NA, NA, "pw:1;");
} else if (r->raceclass->id == RC_MAGIC) { } else if (r->raceclass->id == RC_MAGIC) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_PLANT) { } else if (r->raceclass->id == RC_PLANT) {
@ -12566,11 +12607,11 @@ void initrace(void) {
addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL); addflag(r->flags, F_FLAMMABLE, PERMENANT, NA, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_SLIME) { } else if (r->raceclass->id == RC_SLIME) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL); addflag(r->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL);
} else if (r->raceclass->id == RC_UNDEAD) { } else if (r->raceclass->id == RC_UNDEAD) {
addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL); addflag(r->flags, F_DISEASEIMMUNE, B_TRUE, NA, NA, NULL);
addflag(r->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); addflag(r->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL);
@ -12813,6 +12854,7 @@ void initskills(void) {
addskill(SK_UNARMED, "Unarmed Combat", "Helps you fight using your bare hands.", 50); addskill(SK_UNARMED, "Unarmed Combat", "Helps you fight using your bare hands.", 50);
addskilldesc(SK_UNARMED, PR_ADEPT, "^gYour unarmed attacks can now smash wooden objects.^n", B_TRUE); addskilldesc(SK_UNARMED, PR_ADEPT, "^gYour unarmed attacks can now smash wooden objects.^n", B_TRUE);
addskilldesc(SK_UNARMED, PR_SKILLED, "^gYou can now make melee attacks with your off-hand.^n", B_TRUE); addskilldesc(SK_UNARMED, PR_SKILLED, "^gYou can now make melee attacks with your off-hand.^n", B_TRUE);
addskilldesc(SK_UNARMED, PR_EXPERT, "^gYou gain the 'flip' ability.^n", B_FALSE);
// spell schools // spell schools
addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school.", 50); addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school.", 50);

Binary file not shown.

23
defs.h
View File

@ -468,6 +468,7 @@ enum GODANGERREASON {
GA_PRAY, // pestering through constant prayer GA_PRAY, // pestering through constant prayer
GA_RACE, // prayed while a hated race. GA_RACE, // prayed while a hated race.
GA_SPELL, // cast a spell from the wrong school GA_SPELL, // cast a spell from the wrong school
GA_GODSTONE, // picked up this god's godstone
}; };
enum NOISECLASS { enum NOISECLASS {
@ -620,6 +621,12 @@ enum GAMEMODE {
GM_CLEANUP, GM_CLEANUP,
}; };
enum WINGAMETYPE {
WT_NONE = 0,
WT_GOD,
WT_DEMIGOD,
};
enum ATTRIB { enum ATTRIB {
A_NONE = -1, A_NONE = -1,
A_STR = 0, A_STR = 0,
@ -1235,6 +1242,7 @@ enum OBTYPE {
OT_GOLD, OT_GOLD,
// godstones // godstones
OT_GODSTONEJ, OT_GODSTONEJ,
OT_GODSTONEL,
OT_GODSTONER, OT_GODSTONER,
// flora // flora
OT_FLOWER, OT_FLOWER,
@ -1354,6 +1362,7 @@ enum OBTYPE {
// -- allomancy // -- allomancy
OT_S_ABSORBMETAL, OT_S_ABSORBMETAL,
OT_S_ACCELMETAL, OT_S_ACCELMETAL,
OT_S_ALCHEMY,
OT_S_ANIMATEMETAL, OT_S_ANIMATEMETAL,
OT_S_EXPLODEMETAL, OT_S_EXPLODEMETAL,
OT_S_HEATMETAL, OT_S_HEATMETAL,
@ -1451,6 +1460,8 @@ enum OBTYPE {
OT_S_HEAVENARM, OT_S_HEAVENARM,
OT_S_HOLYAURA, OT_S_HOLYAURA,
OT_S_PROTEVIL, OT_S_PROTEVIL,
OT_S_RESTORATION,
OT_S_RESSURECTION,
OT_S_SMITEEVIL, OT_S_SMITEEVIL,
OT_S_SPEAKDEAD, OT_S_SPEAKDEAD,
OT_S_TURNUNDEAD, OT_S_TURNUNDEAD,
@ -1462,6 +1473,7 @@ enum OBTYPE {
OT_S_LETHARGY, OT_S_LETHARGY,
OT_S_LOWERMETAB, OT_S_LOWERMETAB,
OT_S_MINDSCAN, OT_S_MINDSCAN,
OT_S_MIRRORIMAGE,
OT_S_PACIFY, OT_S_PACIFY,
OT_S_PSYARMOUR, OT_S_PSYARMOUR,
OT_S_SLEEP, OT_S_SLEEP,
@ -2200,6 +2212,7 @@ enum FLAG {
F_NOSTEAL, // this object can't be stolen, blown away, etc. F_NOSTEAL, // this object can't be stolen, blown away, etc.
F_SALTED, // this corpse has been salted and will not decay. F_SALTED, // this corpse has been salted and will not decay.
F_CORPSEOF, // this is a corpse of montype val0. F_CORPSEOF, // this is a corpse of montype val0.
// v1 is its level when it died
// text is how it died. // text is how it died.
F_REVIVETIMER, // v0 = cur, v1 = max. v0 incremenets each tick. F_REVIVETIMER, // v0 = cur, v1 = max. v0 incremenets each tick.
// when v0 == v1, this object changes into lf of race // when v0 == v1, this object changes into lf of race
@ -2578,6 +2591,12 @@ enum FLAG {
// person. // person.
F_FOLLOWTIME, // v0 = how long will ai chase you for? defaults to F_FOLLOWTIME, // v0 = how long will ai chase you for? defaults to
// DEF_AIFOLLOWTIME. // DEF_AIFOLLOWTIME.
F_FOUNDGODSTONE, // this flag is added once the player picks up their
// first godstone, and a god appears.
F_WINNER, // player has won the game!
// if you won by becoming a god, v1 = godid
// if you won by becoming a demigod, v1 = godid
// text = copied F_GODFLAG text from god.
F_BEHAVIOUR, // textual field describing special behaviour for this F_BEHAVIOUR, // textual field describing special behaviour for this
// lf // lf
F_NOSMELL, // lf can't smell. not affected by stench, and F_NOSMELL, // lf can't smell. not affected by stench, and
@ -2609,6 +2628,7 @@ enum FLAG {
// then print this text. // then print this text.
F_TURNED, // lf turned this turn. F_TURNED, // lf turned this turn.
F_PRAYEDTO, // player has prayed to this god before. F_PRAYEDTO, // player has prayed to this god before.
F_GODBLOCKED, // player may NOT pray to this god
F_HPDRAIN, // lf loses v0 hit points eath turn. F_HPDRAIN, // lf loses v0 hit points eath turn.
// v1 = damtype // v1 = damtype
// text = killer damage string // text = killer damage string
@ -2839,6 +2859,8 @@ enum FLAG {
// this is cleared at start of turn. // this is cleared at start of turn.
F_TARGETCELL, // lf will go towards this place. val0=x,val1=y F_TARGETCELL, // lf will go towards this place. val0=x,val1=y
// optional: v2 = mr_lf or mr_ob. text=lf or ob id. // optional: v2 = mr_lf or mr_ob. text=lf or ob id.
F_PHANTASM, // this lf is a phantasm - can deal no damage, and
// uses v0 as a fake hp counter.
F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed F_STABBEDBY, // lf has been stabbed by lfid v0. can't be stabbed
// by them again until they go out of sight. // by them again until they go out of sight.
F_FLEEFROM, // lf will run away from this lf id F_FLEEFROM, // lf will run away from this lf id
@ -3110,6 +3132,7 @@ enum FLAG {
F_SLOWACTMOVE, // modifier for move and action speed F_SLOWACTMOVE, // modifier for move and action speed
F_XRAYVIS, //val0=num of walls we can see through F_XRAYVIS, //val0=num of walls we can see through
F_CANSEETHROUGHMAT, //val0=kind of material you can see through F_CANSEETHROUGHMAT, //val0=kind of material you can see through
F_CANSEETHROUGHLF, // larger lifeforms don't block los for us
F_SPRINTING, // you are sprinting. F_SPRINTING, // you are sprinting.
F_WINDSHIELD,// has a windshield protecting against missiles of speed F_WINDSHIELD,// has a windshield protecting against missiles of speed
// v0 or lower. // v0 or lower.

4
flag.c
View File

@ -935,7 +935,7 @@ void killflag(flag_t *f) {
// got away. // got away.
if (isplayer(fleefrom) && !cansee(lf, fleefrom)) { if (isplayer(fleefrom) && !cansee(lf, fleefrom)) {
for (i = 0; i < ngodlfs; i++) { for (i = 0; i < ngodlfs; i++) {
if (godlf[i]->race->id == R_GODMERCY) dopleasegod[i] += 5; if (godlf[i] && (godlf[i]->race->id == R_GODMERCY)) dopleasegod[i] += 5;
} }
} }
} }
@ -1062,7 +1062,7 @@ void killflag(flag_t *f) {
if (gamemode == GM_GAMESTARTED) { if (gamemode == GM_GAMESTARTED) {
for (i = 0; i < ngodlfs; i++) { for (i = 0; i < ngodlfs; i++) {
if (dopleasegod[i]) { if (godlf[i] && dopleasegod[i]) {
pleasegodmaybe(godlf[i]->race->id, dopleasegod[i]); pleasegodmaybe(godlf[i]->race->id, dopleasegod[i]);
} }
} }

259
god.c
View File

@ -20,6 +20,8 @@
extern int statdirty; extern int statdirty;
extern WINDOW *mainwin;
extern map_t *firstmap; extern map_t *firstmap;
extern map_t *heaven; extern map_t *heaven;
extern race_t *firstrace, *lastrace; extern race_t *firstrace, *lastrace;
@ -35,9 +37,12 @@ int ngodlfs = 0;
void angergod(enum RACE rid, int amt, enum GODANGERREASON why) { void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
lifeform_t *god; lifeform_t *god;
int piety; int piety;
char buf[BUFLEN];
enum PIETYLEV plev; enum PIETYLEV plev;
int dosay = B_FALSE; int dosay = B_FALSE;
if (lfhasflag(player, F_WINNER)) return;
god = findgod(rid); god = findgod(rid);
modpiety(rid, -amt); modpiety(rid, -amt);
@ -74,6 +79,21 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
godsay(rid, B_TRUE, "Coward!"); break; godsay(rid, B_TRUE, "Coward!"); break;
case GA_EAT: case GA_EAT:
godsay(rid, B_TRUE, "That is NOT acceptable for consumption!"); break; 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: case GA_HERESY:
if (rid == R_GODFIRE) { if (rid == R_GODFIRE) {
godsay(rid, B_TRUE, "HERESY!"); godsay(rid, B_TRUE, "HERESY!");
@ -472,6 +492,9 @@ void angergod(enum RACE rid, int amt, enum GODANGERREASON why) {
// anger the god if you are worshippin them. // anger the god if you are worshippin them.
void angergodmaybe(enum RACE rid, int amt, enum GODANGERREASON why) { void angergodmaybe(enum RACE rid, int amt, enum GODANGERREASON why) {
lifeform_t *god; lifeform_t *god;
if (lfhasflag(player, F_WINNER)) return;
god = findgod(rid); god = findgod(rid);
if (lfhasflag(god, F_PRAYEDTO)) { if (lfhasflag(god, F_PRAYEDTO)) {
angergod(rid, amt, why); angergod(rid, amt, why);
@ -485,6 +508,12 @@ void dooffer(void) {
int nretflags,pietyplus = 0; int nretflags,pietyplus = 0;
char splatterob[BUFLEN]; char splatterob[BUFLEN];
strcpy(splatterob, ""); strcpy(splatterob, "");
if (lfhasflag(player, F_RAGE)) {
msg("You are too enraged to offer a sacrifice!");
return;
}
// which god? // which god?
god = askgod("To whom will you sacrifice?", B_TRUE); god = askgod("To whom will you sacrifice?", B_TRUE);
if (!god) { if (!god) {
@ -633,6 +662,15 @@ enum RACE getopposinggod(enum RACE rid) {
return R_NONE; 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) { int getpiety(enum RACE rid) {
lifeform_t *god; lifeform_t *god;
flag_t *f; flag_t *f;
@ -647,6 +685,22 @@ int getpiety(enum RACE rid) {
return 0; 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) { enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness) {
int piety; int piety;
/// figure out piety bracket /// figure out piety bracket
@ -721,6 +775,16 @@ lifeform_t *getrandomprayedgod(void) {
return poss[rnd(0,nposs-1)]; 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;
}
lifeform_t *godappears(enum RACE rid, cell_t *where) { lifeform_t *godappears(enum RACE rid, cell_t *where) {
lifeform_t *god; lifeform_t *god;
char killedname[BUFLEN],godname[BUFLEN]; char killedname[BUFLEN],godname[BUFLEN];
@ -729,9 +793,9 @@ lifeform_t *godappears(enum RACE rid, cell_t *where) {
strcpy(killedname, ""); strcpy(killedname, "");
if (!where) { if (!where) {
// somewhere next to the player. // somewhere next to the player.
where = getrandomadjcell(player->cell, WE_WALKABLE, B_FALSE); where = real_getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_WALLSTOP, NULL, player);
if (!where) { if (!where) {
where = getrandomadjcell(player->cell, B_FALSE, B_FALSE); where = getrandomadjcell(player->cell, B_FALSE, B_NOEXPAND);
} }
} }
@ -773,8 +837,13 @@ void god_usepoison_response(void) {
} }
int godblocked(enum RACE rid) { int godblocked(enum RACE rid) {
lifeform_t *opposegod; lifeform_t *opposegod,*god;
enum RACE opposeid; enum RACE opposeid;
god = findgod(rid);
// forcibly blocked?
if (lfhasflag(god, F_GODBLOCKED)) {
return B_TRUE;
}
// already prayed to the opposing god? // already prayed to the opposing god?
opposeid = getopposinggod(rid); opposeid = getopposinggod(rid);
opposegod = findgod(opposeid); opposegod = findgod(opposeid);
@ -1322,6 +1391,187 @@ void godsay(enum RACE rid, int says, char *format, ...) {
msg("\"%s\"", buf); 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, "to the Realm of Gods, where both of your objectives can be\n");
wprintw(mainwin, "achieved.\"");
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,");
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!\"");
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");
wprintw(mainwin, "Yumi's grave expression softens.\n");
wprintw(mainwin, "\"I embody mercy, and all sins can be forgiven. In this case, the\n");
wprintw(mainwin, "road to your redemption is tied with the deed itself.\n\n");
wprintw(mainwin, "Bring the stone to me. Perform this penance and not only will you\n");
wprintw(mainwin, "be forgiven, but you will ensure that your mistake is never again\n");
wprintw(mainwin, "repeated for all eternity. The God of Revenge will be neutralised,");
wprintw(mainwin, "his influence ended.\n\n");
wprintw(mainwin, "Mercy however, extends even to the divine. I would not doom Felix\n");
wprintw(mainwin, "to a life of misery, his very essence ripped away. Should you\n");
wprintw(mainwin, "possess the power, the Godstone would be used to grant Felix the\n");
wprintw(mainwin, "peaceful sleep of death. For a tormented soul such as his, this\n");
wprintw(mainwin, "would truly be a mercy.\n\n");
wprintw(mainwin, "Either way, your atonement begins now. Travel up to the surface,\n");
wprintw(mainwin, "and enter the magic portal. Once you arrive in the Realm of Gods\n");
wprintw(mainwin, "and complete your task, all will be forgiven.\"");
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!\"");
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!\"");
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) { void modpiety(enum RACE rid, int amt) {
lifeform_t *god; lifeform_t *god;
flag_t *f; flag_t *f;
@ -1392,6 +1642,9 @@ void pleasegod(enum RACE rid, int amt) {
void pleasegodmaybe(enum RACE rid, int amt) { void pleasegodmaybe(enum RACE rid, int amt) {
enum PIETYLEV modplev; enum PIETYLEV modplev;
int chance; int chance;
if (lfhasflag(player, F_WINNER)) return;
modplev = abs(getpietylev(rid, NULL, NULL)); modplev = abs(getpietylev(rid, NULL, NULL));
// the angrier or more happy the god gets, the harder it // the angrier or more happy the god gets, the harder it

4
god.h
View File

@ -5,11 +5,14 @@ void angergodmaybe(enum RACE rid, int amt, enum GODANGERREASON why);
void dooffer(void); void dooffer(void);
lifeform_t *findgod(enum RACE rid); lifeform_t *findgod(enum RACE rid);
enum RACE getopposinggod(enum RACE rid); enum RACE getopposinggod(enum RACE rid);
enum OBTYPE getopposinggodstone(enum RACE rid);
int getpiety(enum RACE rid); int getpiety(enum RACE rid);
int getpietycutoff(enum PIETYLEV pl);
enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness); enum PIETYLEV getpietylev(enum RACE rid, enum COLOUR *col, char *happiness);
int getprayedgods(lifeform_t **retgod, int *nretgods); int getprayedgods(lifeform_t **retgod, int *nretgods);
lifeform_t *getrandomgod(void); lifeform_t *getrandomgod(void);
lifeform_t *getrandomprayedgod(void); lifeform_t *getrandomprayedgod(void);
enum OBTYPE getrelatedgodstone(enum RACE rid);
lifeform_t *godappears(enum RACE rid, cell_t *where); lifeform_t *godappears(enum RACE rid, cell_t *where);
void god_usepoison_response(void); void god_usepoison_response(void);
int godblocked(enum RACE rid); int godblocked(enum RACE rid);
@ -17,6 +20,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple);
int godisangry(enum RACE rid); int godisangry(enum RACE rid);
int godprayedto(enum RACE rid); int godprayedto(enum RACE rid);
void godsay(enum RACE rid, int says, char *format, ...); void godsay(enum RACE rid, int says, char *format, ...);
void godstone_pickup_effects(lifeform_t *god, lifeform_t *opposegod, object_t *o);
void modpiety(enum RACE rid, int amt); void modpiety(enum RACE rid, int amt);
void pleasegod(enum RACE rid, int amt); void pleasegod(enum RACE rid, int amt);
void pleasegodmaybe(enum RACE rid, int amt); void pleasegodmaybe(enum RACE rid, int amt);

411
io.c
View File

@ -29,6 +29,8 @@ WINDOW *gamewin;
WINDOW *msgwin; WINDOW *msgwin;
WINDOW *statwin; WINDOW *statwin;
extern enum WINGAMETYPE wintype;
int statdirty = B_TRUE; int statdirty = B_TRUE;
int inaskcoords = B_FALSE; // are we inside this function? int inaskcoords = B_FALSE; // are we inside this function?
@ -713,6 +715,12 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
break; break;
} }
// clone?
if (ispetof(c->lf, player) && lfhasflag(c->lf, F_PHANTASM)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "phantasm");
}
// obvious things // obvious things
if (isfleeing(c->lf)) { if (isfleeing(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
@ -1049,10 +1057,10 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
tempob = addob(c->obpile, obname); tempob = addob(c->obpile, obname);
} }
// show objects // show objects
o = doaskobject(c->obpile, "Describe which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); o = doaskobject(c->obpile, "Describe which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', NULL, MT_NOTHING, AO_NONE, F_NONE);
while (o) { while (o) {
describeob(o); describeob(o);
o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); o = doaskobject(c->obpile, "Describe which object", NULL, B_FALSE, B_FALSE, B_FALSE, '\0', NULL, MT_NOTHING, AO_NONE, F_NONE);
} }
if (tempob) killob(tempob); if (tempob) killob(tempob);
} }
@ -1187,6 +1195,11 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
return B_FALSE; return B_FALSE;
} }
// stop announcement when we add f_awareness at the end of the game.
if (lfhasflag(lf, F_WINNER)) {
return B_FALSE;
}
getlfname(lf, lfname); getlfname(lf, lfname);
if (isdead(player)) return B_FALSE; if (isdead(player)) return B_FALSE;
@ -2683,6 +2696,7 @@ lifeform_t *askgod(char *prompttext, int onlyprayed) {
flag_t *f; flag_t *f;
char godof[BUFLEN],buf[BUFLEN]; char godof[BUFLEN],buf[BUFLEN];
lf = godlf[i]; lf = godlf[i];
if (!lf) continue;
if (onlyprayed && !lfhasflag(lf, F_PRAYEDTO)) { if (onlyprayed && !lfhasflag(lf, F_PRAYEDTO)) {
continue; continue;
@ -2716,11 +2730,11 @@ object_t *askobject(obpile_t *op, char *prompt, int *count, char action, long o
if (op->owner && isplayer(op->owner)) { if (op->owner && isplayer(op->owner)) {
showlong = B_FALSE; showlong = B_FALSE;
} }
return doaskobject(op, prompt, count, showlong, B_TRUE, B_FALSE, action, NULL, opts, F_NONE); return doaskobject(op, prompt, count, showlong, B_TRUE, B_FALSE, action, NULL, MT_NOTHING, opts, F_NONE);
} }
object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, char action, long opts, enum FLAG withflag) { object_t *askobjectwithflag(obpile_t *op, char *prompt, int *count, char action, long opts, enum FLAG withflag) {
return doaskobject(op, prompt, count, B_TRUE, B_TRUE, B_FALSE, action, NULL, opts, withflag, F_NONE); return doaskobject(op, prompt, count, B_TRUE, B_TRUE, B_FALSE, action, NULL, MT_NOTHING, opts, withflag, F_NONE);
} }
int contains(enum OBCLASS *array, int nargs, enum OBCLASS want) { int contains(enum OBCLASS *array, int nargs, enum OBCLASS want) {
@ -2852,13 +2866,13 @@ void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int fi
} }
// varargs are: // varargs are a list of flags which we want:
// F_xxx // F_xxx
// F_xxx // F_xxx
// F_NONE // F_NONE
// //
// If you pass "sellshop", DONT also pass F_xxx. // If you pass "sellshop", DONT also pass F_xxx.
object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int forpickup, int showpoints, char action, object_t *sellshop, long opts, ...) { object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int forpickup, int showpoints, char action, object_t *sellshop, int wantmaterial, long opts, ...) {
int c,i; int c,i;
char defchar = '\0'; char defchar = '\0';
static char defaults[52] = {'\0'}; static char defaults[52] = {'\0'};
@ -2962,6 +2976,12 @@ object_t *doaskobject(obpile_t *op, char *prompt, int *count, int showlong, int
if (!canseeob(player, o)) ok = B_FALSE; if (!canseeob(player, o)) ok = B_FALSE;
if (ok) {
if ((wantmaterial != MT_NOTHING) && (o->material->id != wantmaterial)) {
ok = B_FALSE;
}
}
if (ok) { if (ok) {
// check for wanted flags // check for wanted flags
for (n = 0; n < nwantflags; n++) { for (n = 0; n < nwantflags; n++) {
@ -3860,6 +3880,7 @@ void docomms(lifeform_t *lf) {
int count; int count;
int alignmod = 0; int alignmod = 0;
object_t *o, *givenob = NULL; object_t *o, *givenob = NULL;
object_t *godstone = NULL;
if (!lf) { if (!lf) {
where = askcoords("Talk to who?", "Talk->", TT_MONSTER, player, UNLIMITED, LOF_DONTNEED, B_FALSE); where = askcoords("Talk to who?", "Talk->", TT_MONSTER, player, UNLIMITED, LOF_DONTNEED, B_FALSE);
if (where && where->lf && cansee(player, where->lf)) { if (where && where->lf && cansee(player, where->lf)) {
@ -3875,6 +3896,7 @@ void docomms(lifeform_t *lf) {
getlfname(lf, lfname); getlfname(lf, lfname);
snprintf(buf, BUFLEN, "What will you say to %s?",lfname); snprintf(buf, BUFLEN, "What will you say to %s?",lfname);
initprompt(&prompt, buf); initprompt(&prompt, buf);
prompt.maycancel = B_TRUE; prompt.maycancel = B_TRUE;
@ -3936,8 +3958,19 @@ void docomms(lifeform_t *lf) {
} }
// if you are allies, use 'trade items' instead // if you are allies, use 'trade items' instead
if (isadjacent(lf->cell, player->cell) && !areallies(player,lf) && !isgod(lf)) { if (isadjacent(lf->cell, player->cell) && !areallies(player,lf)) {
addchoice(&prompt, 'd', "(donate an item)", NULL, NULL, NULL); if (isgod(lf)) {
// may only donate the godstone
godstone = hasob(player->pack, getopposinggodstone(lf->race->id));
if (godstone) {
char buf[BUFLEN],obname[BUFLEN];
getobname(godstone, obname, 1);
sprintf(buf, "(offer %s)", obname);
addchoice(&prompt, 'd', buf, NULL, NULL, NULL);
}
} else {
addchoice(&prompt, 'd', "(donate an item)", NULL, NULL, NULL);
}
} }
/* /*
@ -3982,6 +4015,10 @@ void docomms(lifeform_t *lf) {
msg("%s doesn't respond.", lfname); msg("%s doesn't respond.", lfname);
break; break;
} }
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
if (lf == lf2) { if (lf == lf2) {
// won't attack itself // won't attack itself
@ -4008,6 +4045,10 @@ void docomms(lifeform_t *lf) {
msg("%s doesn't respond.", lfname); msg("%s doesn't respond.", lfname);
break; break;
} }
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
// find adjacent cell // find adjacent cell
c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND);
if (c) { if (c) {
@ -4015,9 +4056,15 @@ void docomms(lifeform_t *lf) {
} }
break; break;
case 'd': // donate case 'd': // donate
// ask what to give // giving godstone to a god?
snprintf(buf, BUFLEN, "What will you give to %s?",lfname); if (godstone) {
o = askobject(player->pack, buf, &count, '\0', AO_NONE); o = godstone;
count = 1;
} else {
// ask what to give
snprintf(buf, BUFLEN, "What will you give to %s?",lfname);
o = askobject(player->pack, buf, &count, '\0', AO_NONE);
}
if (o) { if (o) {
if (o->type->id == OT_GOLD) { if (o->type->id == OT_GOLD) {
char countbuf[BUFLEN]; char countbuf[BUFLEN];
@ -4093,6 +4140,17 @@ void docomms(lifeform_t *lf) {
} }
pleasegodmaybe(R_GODPURITY, 10); pleasegodmaybe(R_GODPURITY, 10);
pleasegodmaybe(R_GODMERCY, 20); pleasegodmaybe(R_GODMERCY, 20);
} else if (isgod(lf) && (givenob->type->obclass->id == OC_GODSTONE)) {
// in heaven?
if (lf->cell->map->habitat->id == H_HEAVEN) {
flag_t *gf;
gf = lfhasflag(lf, F_GODOF);
// you win!
addflag(player->flags, F_WINNER, WT_DEMIGOD, lf->race->id, NA, gf->text);
wingame();
} else {
say(lf, "Not here, mortal! Come to the Realm of the Gods.", SV_SHOUT);
}
} else { } else {
// not giving money to a begger // not giving money to a begger
enum ATTRBRACKET iqb; enum ATTRBRACKET iqb;
@ -4164,10 +4222,18 @@ void docomms(lifeform_t *lf) {
msg("%s doesn't respond.", lfname); msg("%s doesn't respond.", lfname);
break; break;
} }
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
aigoto(lf, c, MR_OTHER, NULL, DEF_AIFOLLOWTIME); aigoto(lf, c, MR_OTHER, NULL, DEF_AIFOLLOWTIME);
break; break;
case 'i': case 'i':
msg("You say \"What can you tell me about this area?\" to %s.", lfname); msg("You say \"What can you tell me about this area?\" to %s.", lfname);
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
if (askforinfo(lf, 2)) { if (askforinfo(lf, 2)) {
genareaknowledge(lf->flags, 0); genareaknowledge(lf->flags, 0);
docomms_areainfo(lfname, lf->flags, lf); docomms_areainfo(lfname, lf->flags, lf);
@ -4180,14 +4246,26 @@ void docomms(lifeform_t *lf) {
msg("%s doesn't respond.", lfname); msg("%s doesn't respond.", lfname);
break; break;
} }
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
recruit(lf); recruit(lf);
break; break;
case 'k': // trade Knowledge case 'k': // trade Knowledge
msg("You say \"Care to trade knowledge?\" to %s.", lfname); msg("You say \"Care to trade knowledge?\" to %s.", lfname);
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
tradeknowledge(lf); tradeknowledge(lf);
break; break;
case 'm': // mercy case 'm': // mercy
msg("You say \"Have mercy!\" to %s.", lfname); msg("You say \"Have mercy!\" to %s.", lfname);
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
if (islowhp(player) && if (islowhp(player) &&
cantalk(lf) && cantalk(lf) &&
canhear(lf, player->cell, SV_SHOUT) && canhear(lf, player->cell, SV_SHOUT) &&
@ -4259,6 +4337,10 @@ void docomms(lifeform_t *lf) {
msg("%s doesn't respond.", lfname); msg("%s doesn't respond.", lfname);
break; break;
} }
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
f = isresting(lf); f = isresting(lf);
if (f) { if (f) {
stopresting(lf); stopresting(lf);
@ -4276,6 +4358,10 @@ void docomms(lifeform_t *lf) {
} }
return; return;
case 't': case 't':
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
// ask whtehr to give/take // ask whtehr to give/take
initprompt(&prompt, "How will you trade?"); initprompt(&prompt, "How will you trade?");
snprintf(buf, BUFLEN, "Give items to %s",lfname); snprintf(buf, BUFLEN, "Give items to %s",lfname);
@ -4305,6 +4391,10 @@ void docomms(lifeform_t *lf) {
break; break;
case 'x': case 'x':
msg("You say \"Any dangers nearby that I should look out for?\" to %s.", lfname); msg("You say \"Any dangers nearby that I should look out for?\" to %s.", lfname);
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
if (askforinfo(lf, 4)) { if (askforinfo(lf, 4)) {
genareaknowledge(lf->flags, 0); genareaknowledge(lf->flags, 0);
docomms_areadangers(lfname, lf->flags, lf); docomms_areadangers(lfname, lf->flags, lf);
@ -4320,6 +4410,10 @@ void docomms(lifeform_t *lf) {
msg("%s doesn't respond.", lfname); msg("%s doesn't respond.", lfname);
break; break;
} }
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
setfollowdistance(lf, 1, 3); setfollowdistance(lf, 1, 3);
break; break;
case '>': case '>':
@ -4328,6 +4422,10 @@ void docomms(lifeform_t *lf) {
msg("%s doesn't respond.", lfname); msg("%s doesn't respond.", lfname);
break; break;
} }
if (lfhasflag(lf, F_PHANTASM)) {
msg("%s doesn't respond.", lfname);
break;
}
setfollowdistance(lf, 3, 5); setfollowdistance(lf, 3, 5);
break; break;
} }
@ -7477,12 +7575,12 @@ void doexplain(char *question) {
void dofinaloblist(obpile_t *op) { void dofinaloblist(obpile_t *op) {
object_t *o; object_t *o;
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, '\0', NULL, AO_NONE, F_NONE); o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE, '\0', NULL, MT_NOTHING, AO_NONE, F_NONE);
while (o) { while (o) {
// describe it // describe it
describeob(o); describeob(o);
// ask for another one // ask for another one
o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE,'\0', NULL, AO_NONE, F_NONE); o = doaskobject(op, "Your final possessions were", NULL, B_TRUE, B_FALSE, B_TRUE,'\0', NULL, MT_NOTHING, AO_NONE, F_NONE);
} }
real_clearmsg(B_TRUE); real_clearmsg(B_TRUE);
} }
@ -7617,7 +7715,7 @@ void doinventory(obpile_t *op) {
maxweight = getmaxcarryweight(player); maxweight = getmaxcarryweight(player);
pct = (packweight / maxweight) * 100; pct = (packweight / maxweight) * 100;
snprintf(buf, BUFLEN, "Inventory (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct); snprintf(buf, BUFLEN, "Inventory (%0.0f/%0.0f kg, %0.0f%%)", packweight, maxweight, pct);
o = doaskobject(op, buf, NULL, B_TRUE, B_TRUE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); o = doaskobject(op, buf, NULL, B_TRUE, B_TRUE, B_FALSE, '\0', NULL, MT_NOTHING, AO_NONE, F_NONE);
while (o) { while (o) {
// describe it // describe it
describeob(o); describeob(o);
@ -12256,7 +12354,13 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
f = lfhasknownflag(lf, F_HEAVENARM); f = lfhasknownflag(lf, F_HEAVENARM);
if (f && (f->known)) { if (f && (f->known)) {
mvwprintw(mainwin, y, 0, "%s %s surrounded by a shell of divine armour. ", you(lf), is(lf)); char hpbuf[BUFLEN];
if (isplayer(lf)) {
sprintf(hpbuf, " (%d hp left)", f->val[0]);
} else {
strcpy(hpbuf, "");
}
mvwprintw(mainwin, y, 0, "%s %s surrounded by a shell of divine armour.%s", you(lf), is(lf), hpbuf);
y++; y++;
} }
f = lfhasknownflag(lf, F_INVULNERABLE); f = lfhasknownflag(lf, F_INVULNERABLE);
@ -12405,6 +12509,8 @@ void showlfstats(lifeform_t *lf, int showall) {
int blocked = B_FALSE; int blocked = B_FALSE;
god = godlf[i]; god = godlf[i];
if (!god) continue;
blocked = godblocked(god->race->id); blocked = godblocked(god->race->id);
real_getlfname(god, godname, B_FALSE, B_FALSE); real_getlfname(god, godname, B_FALSE, B_FALSE);
@ -12585,6 +12691,9 @@ void tombstone(lifeform_t *lf) {
int rank,minrank,maxrank; int rank,minrank,maxrank;
char *p; char *p;
long playerscore; long playerscore;
flag_t *winflag;
winflag = lfhasflag(player, F_WINNER);
playerscore = calcscore(lf); playerscore = calcscore(lf);
@ -12594,12 +12703,21 @@ void tombstone(lifeform_t *lf) {
cls(); cls();
y = 1; y = 1;
centre(mainwin, C_GREY, y, "R.I.P."); y++; if (wintype) {
centre(mainwin, C_GREY, y, "CONGRATULATIONS!"); y+= 2;
} else {
centre(mainwin, C_GREY, y, "R.I.P."); y++;
}
//printf("%s\n",lf->name); //printf("%s\n",lf->name);
centre(mainwin, C_GREY, y, "%s (%ld points)",pname, playerscore); y++; centre(mainwin, C_GREY, y, "%s (%ld points)",pname, playerscore); y++;
getregionname(buf, player->cell->map, NULL, RF_LONG);
centre(mainwin, C_GREY, y, "Died %s.", buf); y++; // ie. "Died on level 1 of the dungeon" if (wintype) {
y++;
} else {
getregionname(buf, player->cell->map, NULL, RF_LONG);
centre(mainwin, C_GREY, y, "Died %s.", buf); y++; // ie. "Died on level 1 of the dungeon"
}
makekillertext(killer, lf->killverb, lf->lastdam, lf->cell->map, B_TRUE, B_FALSE); makekillertext(killer, lf->killverb, lf->lastdam, lf->cell->map, B_TRUE, B_FALSE);
@ -12694,6 +12812,259 @@ int real_warnabout(char *what, int lifetime, int doquestion) {
return B_FALSE; return B_FALSE;
} }
void wingame(void) {
flag_t *winflag;
winflag = lfhasflag(player, F_WINNER);
if (winflag->val[0] == WT_DEMIGOD) {
lifeform_t *god;
// find the god who ascended us.
god = findgod(winflag->val[1]);
// god says something
switch (god->race->id) {
case R_GODPURITY:
msg("Amberon flings the Godstone out into the cosmos!\""); more();
msg("\"Without the chaotic blight of this stone, the universe will be purified!\""); more();
msg("\"Deformities will be cured, chance eliminated, entropy denied.\""); more();
msg("\"From now on, all will be orderly and just.\""); more();
msg("\"I name you the Arbiter of Divine Justice!\""); more();
break;
case R_GODTHIEVES:
msg("Felix slips the Godstone into a pocket."); more();
msg("\"By bringing this stone to me, you have brought closure to thousands.\""); more();
msg("\"Every act of anger, every stolen penny, every wronged lover...\""); more();
msg("\"No more shall they be told to simply 'forgive and forget'!\""); more();
msg("\"All shall obtain their revenge!\""); more();
msg("\"I name you the Hand of Veangence!\""); more();
break;
case R_GODDEATH:
msg("A sinister smile spreads across Hecta's skull."); more();
msg("\"With this artifact, I will annihilate all living beings!\""); more();
msg("\"All souls throughout the universe shall become my servants!\""); more();
msg("\"And you, fleshling...\""); more();
msg("\"For your service, I name you my High Prince of the Dead!\""); more();
msg("\"HAHAHahahahahahaha...\""); more();
break;
case R_GODFIRE:
msg("Klikirak's flames explode outwards in a surge of triumphant fury!"); more();
msg("\"NO CREATION! NO PLANTS! NO MORE GROWING!\""); more();
msg("\"JUST FIRE! BURN! DESTROY! ANNIHILATE!\""); more();
msg("\"OBLITERATE!!!!!\""); more();
break;
case R_GODLIFE:
msg("Glorana's pulsating form melds into a female face, her eyes wide in shock."); more();
msg("\"The Godstone of Death! You have brought it to me!\""); more();
msg("\"Your efforts have earned eternal life for all humanity!\""); more();
msg("\"Such an action deserves the highest possibble reward.\""); more();
msg("\"Join me, as the Bringer of Life!\""); more();
break;
case R_GODMERCY:
msg("Yumi beams radiantly at you."); more();
msg("\"You do not know just how special this stone is.\""); more();
msg("\"Without petty acts of revenge and jealousy, there will be peace.\""); more();
msg("\"From the kindest soul, to the lowest criminal, all will know forgiveness.\""); more();
msg("\"Rise up, and spread mercy as Mankind's Redemption.\""); more();
break;
case R_GODNATURE:
msg("Ekrub gazes at the Godstone in awe."); more();
msg("\"An end to burning... an end to destruction...\""); more();
msg("\"All of nature's creations can finally grow in peace!\""); more();
msg("\"As my children shall thrive, so shall you.\""); more();
msg("\"I name you Nature's Soulmate!\""); more();
break;
case R_GODBATTLE:
msg("Bjorn cleaves the Godstone with a might stroke of his battleaxe!\""); more();
msg("\"You have won a great victory today, soldier.\""); more();
msg("\"With this power, I will rally all existence for the final battle.\""); more();
msg("\"No magic will interfere - might and battle tactics will win the day.\""); more();
msg("\"For your valour, I promote you to General of the Gods!\""); more();
break;
case R_GODMAGIC:
msg("Lumara's aging features begin to change, the years falling away in seconds.\""); more();
msg("Soon, an energised young woman stands before you.\""); more();
msg("\"You have done it!\""); more();
msg("\"The cosmic forces are already being renewed with infinite potential!\""); more();
msg("\"Henceforce all shall weild magic as easily as breathing.\""); more();
msg("\"All restraints will be lifted, actions limited only by imagination!\""); more();
msg("\"I name you the Font of Wizardry, the Arcane Grandmaster...\""); more();
msg("\"The Connoisseur of the Cosmos!\""); more();
break;
default: break;
}
msg("^%cYou ascend to a higher plane of existence as a demi-god!^n", getlfcol(player, CC_VGOOD)); more();
msg("^%cCONGRATULATIONS!!!^n", getlfcol(player, CC_VGOOD)); more();
} else { // ie. WT_GOD, killed a god
int i;
char *buf;
enum RACE opposeid;
lifeform_t *god[MAXGODS],*g;
int ngods = 0;
flag_t *tempflag[2];
opposeid = getopposinggod(winflag->val[1]);
msg("As you vanquish your foe, a sudden stillness descends."); more();
msg("For a brief moment, all is quiet."); more();
msg("Then, there is an almighty clap of thunder and a brilliant flash of light!"); more();
// make sure the player sees the gods appearing
tempflag[0] = addflag(player->flags, F_AWARENESS, B_TRUE, NA, NA, NULL);
tempflag[1] = addflag(player->flags, F_CANSEETHROUGHLF, B_TRUE, NA, NA, NULL);
setlosdirty(player);
for (i = 0; i < ngodlfs; i++) {
g = godlf[i];
if (!g) continue;
godappears(g->race->id, NULL);
god[ngods++] = g;
}
needredraw = B_TRUE;
drawscreen();
g = god[rnd(0,ngods-1)];
say(g, "You have just done the unthinkable.", SV_TALK); more();
g = god[rnd(0,ngods-1)];
say(g, "You have killed a god!", SV_TALK); more();
g = findgod(R_GODTHIEVES);
if (g) {
say(g, "This act cannot go unpunished!", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "Felix would have insisted on punishment.", SV_TALK); more();
}
g = findgod(R_GODMERCY);
if (g) {
say(g, "Although this seems unforgivable, we should always strive for mercy.", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "Yumi would have wanted mercy to be given.", SV_TALK); more();
}
g = findgod(R_GODMAGIC);
if (!g) g = god[rnd(0,ngods-1)];
say(g, "The cosmos works in mysterious ways.", SV_TALK); more();
g = findgod(R_GODBATTLE);
if (g) {
say(g, "The kill was through honourable battle!", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "We all knew this was a possibility.", SV_TALK); more();
}
// nature
g = findgod(R_GODNATURE);
if (g) {
say(g, "This is the cycle of life, nothing more. What lives must die.", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "Ekrub has withered, as all nature must do eventually.", SV_TALK); more();
}
// fire
g = findgod(R_GODFIRE);
if (g) {
say(g, "MIGHTY GOD DESTROYED!", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "The fires of destruction have been quenched.", SV_TALK); more();
}
// life
g = findgod(R_GODLIFE);
if (g) {
say(g, "To take any life is abhorrent... but that of a god?", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "The Goddess of Life destroyed? How can this be?", SV_TALK); more();
}
g = findgod(R_GODDEATH);
if (g) {
say(g, "The fleshling has given me a monumental gift.", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "Had it been one of us, Hecta would exultant now.", SV_TALK); more();
}
g = findgod(R_GODPURITY);
if (g) {
say(g, "Nevertheless, there is now an impurity within our ranks.", SV_TALK); more();
} else {
g = god[rnd(0,ngods-1)];
say(g, "It would seem there is a new vacancy within our ranks.", SV_TALK); more();
}
// don't want the opposing god of the killed one responding
g = god[rnd(0,ngods-1)];
while (g->race->id == opposeid) g = god[rnd(0,ngods-1)];
say(g, "The one before us is obviously ambitious.", SV_TALK); more();
g = god[rnd(0,ngods-1)];
while (g->race->id == opposeid) g = god[rnd(0,ngods-1)];
say(g, "He has clearly proven his power.", SV_TALK); more();
g = god[rnd(0,ngods-1)];
while (g->race->id == opposeid) g = god[rnd(0,ngods-1)];
say(g, "Are we agreed, then?", SV_TALK); more();
// the opposing god will always disagree and storm off
// in a huff.
g = findgod(opposeid);
switch (g->id) {
case R_GODPURITY:
say(g, "You fools would bring back Chaos?!", SV_SHOUT); more();
msg("\"I will not be part of this!\""); more();
break;
case R_GODTHIEVES:
say(g, "NO! Do not spoil my revenge by replacing her!", SV_SHOUT); more();
break;
case R_GODDEATH:
say(g, "Fools. Replace her if you wish, it will change nothing.", SV_SHOUT); more();
break;
case R_GODFIRE:
say(g, "NOOOO! WHY NATURE NEVER STOP REGROWING?!", SV_SHOUT); more();
break;
case R_GODLIFE:
say(g, "It would seem that somehow death will result in life...", SV_TALK); more();
msg("\"I must consider this.\""); more();
break;
case R_GODMERCY:
say(g, "\"How dare you!\"", SV_SHOUT); more();
msg("\"I show you mercy and you repay it by becoming my greatest rival?!\""); more();
break;
case R_GODNATURE:
say(g, "\"TRAITOR!\"", SV_SHOUT); more();
msg("\"I vowed to support you, but you know this is not what I meant!\""); more();
break;
case R_GODBATTLE:
say(g, "\"Not again! Magic was meant to be destroyed!\"", SV_SHOUT); more();
msg("\"Is there no end to the foul trickeries of magic?\""); more();
break;
case R_GODMAGIC:
say(g, "\"One has decided. Time will determine the wisdom of One's choice.\"", SV_TALK); more();
break;
}
// calling "unsommon" will technically kill
// the god, but since the game is about to end it doesn't
// really matter.
unsummon(g, B_TRUE);
msg("The remaining gods nod in unison."); more();
g = god[rnd(0,ngods-1)];
say(g, "Arise then, and join us!", SV_TALK); more();
msg("The combined voices the gods ring out:"); more();
buf = strdup(winflag->text);
strrep(buf, "&", "and", NULL);
makeuppercase(buf);
msg("^%c\"ALL HAIL THE NEW GOD OF %s!!\"", getlfcol(player, CC_VGOOD), buf);
more();
free(buf);
killflag(tempflag[0]);
killflag(tempflag[1]);
}
}
// @ = tab // @ = tab
char wrapprint(WINDOW *win, int *y, int *x, int newlineindent, char *format, ... ) { char wrapprint(WINDOW *win, int *y, int *x, int newlineindent, char *format, ... ) {
char word[HUGEBUFLEN],buf[HUGEBUFLEN]; char word[HUGEBUFLEN],buf[HUGEBUFLEN];
@ -12783,9 +13154,9 @@ char wrapprint(WINDOW *win, int *y, int *x, int newlineindent, char *format, ...
} else if ((*x != newlineindent) && strlen(word)) { } else if ((*x != newlineindent) && strlen(word)) {
textwithcol_real(win, " ", B_FALSE); textwithcol_real(win, " ", B_FALSE);
} }
if (strlen(repword) < 2) { /* if (strlen(repword) < 2) {
dblog("xxx"); dblog("xxx");
} } */
textwithcol_real(win, repword, B_FALSE); textwithcol_real(win, repword, B_FALSE);
//(*x) += strlen(buf); //(*x) += strlen(buf);
getyx(win, *y, *x); getyx(win, *y, *x);

3
io.h
View File

@ -21,7 +21,7 @@ int confirm_injury_action(enum BODYPART bp, enum DAMTYPE dt, char *actionname);
lifeform_t *askgod(char *prompt, int onlyprayed); lifeform_t *askgod(char *prompt, int onlyprayed);
object_t *askobject(obpile_t *op, char *title, int *count, char action, long opts); object_t *askobject(obpile_t *op, char *title, int *count, char action, long opts);
object_t *askobjectwithflag(obpile_t *op, char *title, int *count, char action, long opts, enum FLAG withflag); object_t *askobjectwithflag(obpile_t *op, char *title, int *count, char action, long opts, enum FLAG withflag);
object_t *doaskobject(obpile_t *op, char *title, int *count, int showlong, int forpickup, int showpoints, char action, object_t *sellshop, long opts, ...); object_t *doaskobject(obpile_t *op, char *title, int *count, int showlong, int forpickup, int showpoints, char action, object_t *sellshop, int wantmaterial, long opts, ...);
int askobjectmulti(obpile_t *op, char *prompt, long opts); int askobjectmulti(obpile_t *op, char *prompt, long opts);
char askchar(char *prompt, char *validchars, char *def, int showchars, int maycancel); char askchar(char *prompt, char *validchars, char *def, int showchars, int maycancel);
cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail); cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *srclf, int maxrange, enum LOFTYPE loftype, int wanttrail);
@ -137,4 +137,5 @@ void updatestatus(void);
int updateviewfor(cell_t *cell); int updateviewfor(cell_t *cell);
int warnabout(char *what); int warnabout(char *what);
int real_warnabout(char *what, int lifetime, int doquestion); int real_warnabout(char *what, int lifetime, int doquestion);
void wingame(void);
char wrapprint(WINDOW *win, int *y, int *x, int newlineindent, char *format, ... ); char wrapprint(WINDOW *win, int *y, int *x, int newlineindent, char *format, ... );

329
lf.c
View File

@ -280,6 +280,7 @@ void breakaitargets(lifeform_t *lf, int onlylowerlev) {
} }
long calcscore(lifeform_t *lf) { long calcscore(lifeform_t *lf) {
flag_t *f;
long points = 0; long points = 0;
object_t *o; object_t *o;
if (lfhasflag(lf, F_NOSCORE)) { if (lfhasflag(lf, F_NOSCORE)) {
@ -292,6 +293,15 @@ long calcscore(lifeform_t *lf) {
// points for xp // points for xp
points += (lf->xp / 10); points += (lf->xp / 10);
f = hasflag(player->flags, F_WINNER);
if (f) {
if (f->val[0] == WT_DEMIGOD) {
points *= 13;
} else if (f->val[0] == WT_GOD) {
points *= 23;
}
}
return points; return points;
} }
@ -1489,6 +1499,11 @@ int cantakeoff(lifeform_t *lf, object_t *o) {
} }
int cantalk(lifeform_t *lf) { int cantalk(lifeform_t *lf) {
// phantasms dont talk
if (lfhasflag(lf, F_PHANTASM)) {
return B_FALSE;
}
// if the lf can't explicitly talk, check its race
if (!lfhasflag(lf, F_CANTALK)) { if (!lfhasflag(lf, F_CANTALK)) {
switch (lf->race->raceclass->id) { switch (lf->race->raceclass->id) {
case RC_DEMON: case RC_DEMON:
@ -1911,15 +1926,17 @@ int celltransparentfor(lifeform_t *lf, cell_t *c, int *xray, int *rangemod) {
// check for lfs which block view // check for lfs which block view
if (c->lf && (c->lf != lf) && cansee_real(lf, c->lf, B_FALSE)) { if (c->lf && (c->lf != lf) && cansee_real(lf, c->lf, B_FALSE)) {
int sizediff; if (!lfhasflag(lf, F_CANSEETHROUGHLF)) {
// high sizediff means that the lf in the cell is bigger than the viewer int sizediff;
sizediff = getlfsize(c->lf) - getlfsize(lf); // high sizediff means that the lf in the cell is bigger than the viewer
// lf greater than 2 sizes bigger than us? sizediff = getlfsize(c->lf) - getlfsize(lf);
if (sizediff >= 2) { // lf greater than 2 sizes bigger than us?
if (xray && *xray) { if (sizediff >= 2) {
(*xray) -= (sizediff-1); if (xray && *xray) {
if (*xray < 0) *xray = 0; (*xray) -= (sizediff-1);
} else return B_FALSE; if (*xray < 0) *xray = 0;
} else return B_FALSE;
}
} }
} }
@ -2091,6 +2108,16 @@ int check_rest_ok(lifeform_t *lf) {
return B_FALSE; return B_FALSE;
} }
lifeform_t *clonelf(lifeform_t *src, cell_t *where) {
lifeform_t *lf;
lf = addmonster(where, src->race->id, NULL, B_FALSE, 1, B_FALSE, NULL);
if (lf) {
killflagsofid(lf->flags, F_XPVAL);
addflag(lf->flags, F_XPVAL, 0, NA, NA, NULL);
}
return lf;
}
// how dangerous is lf2 to lf1? // how dangerous is lf2 to lf1?
// < 0 = harder // < 0 = harder
// > 0 = easier // > 0 = easier
@ -2361,9 +2388,11 @@ int demandbribe(lifeform_t *lf) {
void die(lifeform_t *lf) { void die(lifeform_t *lf) {
char buf[BUFLEN]; char buf[BUFLEN];
flag_t *f; flag_t *f;
int killedgod = B_FALSE;
cell_t *where; cell_t *where;
//int dropobs = B_TRUE; //int dropobs = B_TRUE;
int vaporised = B_FALSE, i; int vaporised = B_FALSE, i;
int dropobs = B_TRUE;
int willbecomeghost = B_FALSE; int willbecomeghost = B_FALSE;
object_t *corpse = NULL; object_t *corpse = NULL;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
@ -2413,6 +2442,21 @@ void die(lifeform_t *lf) {
return; return;
} }
// a god died?
if (getraceclass(lf) == RC_GOD) {
flag_t *f;
// update godlf pointer
for (i = 0; i < ngodlfs; i++) {
if (godlf[i] == lf) {
godlf[i] = NULL;
break;
}
}
f = hasflag(lf->flags, F_GODOF);
addflag(player->flags, F_WINNER, WT_GOD, lf->race->id, NA, f->text);
killedgod = B_TRUE;
}
if (!willbecomeghost) { if (!willbecomeghost) {
if (isplayer(lf) && hasjob(lf, J_GOD)) { if (isplayer(lf) && hasjob(lf, J_GOD)) {
char ch; char ch;
@ -2591,9 +2635,9 @@ void die(lifeform_t *lf) {
awardxpfor(lf,100); awardxpfor(lf,100);
if ((getalignment(lf) == AL_EVIL) || isundead(lf)) { if ((getalignment(lf) == AL_EVIL) || isundead(lf)) {
pleasegodmaybe(R_GODPURITY, 5); pleasegodmaybe(R_GODPURITY, 5);
pleasegodmaybe(R_GODLIFE, 5); pleasegodmaybe(R_GODLIFE, 10);
} else if (getalignment(lf) == AL_GOOD) { } else if (getalignment(lf) == AL_GOOD) {
pleasegodmaybe(R_GODDEATH, 3); pleasegodmaybe(R_GODDEATH, 5);
} else { // ie. neutral } else { // ie. neutral
pleasegodmaybe(R_GODDEATH, 1); pleasegodmaybe(R_GODDEATH, 1);
} }
@ -2638,10 +2682,14 @@ void die(lifeform_t *lf) {
} }
} }
if (lfhasflag(lf, F_PHANTASM)) {
dropobs = B_FALSE;
}
// drop/kill all objects // drop/kill all objects
if (corpsecell && (willbecomeghost || !isplayer(lf))) { if (corpsecell && (willbecomeghost || !isplayer(lf))) {
while (lf->pack->first) { while (lf->pack->first) {
if (vaporised) { if (vaporised || !dropobs) {
killob(lf->pack->first); killob(lf->pack->first);
} else { } else {
object_t *droppedob; object_t *droppedob;
@ -2737,6 +2785,11 @@ void die(lifeform_t *lf) {
copyflag(corpse->flags, lf->flags, F_KNOWSABOUT); copyflag(corpse->flags, lf->flags, F_KNOWSABOUT);
copyflag(corpse->flags, lf->flags, F_HOMEMAP); copyflag(corpse->flags, lf->flags, F_HOMEMAP);
f = hasflag(corpse->flags, F_CORPSEOF);
if (f) {
f->val[1] = lf->level;
}
// some corpses will regenerate... // some corpses will regenerate...
if (copyflag(corpse->flags, lf->flags, F_REVIVETIMER)) { if (copyflag(corpse->flags, lf->flags, F_REVIVETIMER)) {
killflagsofid(corpse->flags, F_OBHPDRAIN); killflagsofid(corpse->flags, F_OBHPDRAIN);
@ -2832,7 +2885,6 @@ void die(lifeform_t *lf) {
} }
} }
if (willbecomeghost) { if (willbecomeghost) {
flag_t *f, *nextf; flag_t *f, *nextf;
// remove all job flags // remove all job flags
@ -2865,6 +2917,10 @@ void die(lifeform_t *lf) {
if (needredraw) { if (needredraw) {
drawscreen(); drawscreen();
} }
if (killedgod) {
wingame();
}
} }
void dumplf(void) { void dumplf(void) {
@ -3673,7 +3729,7 @@ int eat(lifeform_t *lf, object_t *o) {
if (fid != F_NONE) { if (fid != F_NONE) {
// lose half your max hp! // lose half your max hp!
losehp_real(lf, (lf->maxhp/2), DT_DIRECT, NULL, "the shock of mutation", losehp_real(lf, (lf->maxhp/2), DT_DIRECT, NULL, "the shock of mutation",
B_FALSE, o, B_FALSE); B_FALSE, o, B_FALSE, NULL);
if (isplayer(lf)) { if (isplayer(lf)) {
msg("^%cYou convulse in agony as your body mutates!", msg("^%cYou convulse in agony as your body mutates!",
getlfcol(lf, CC_BAD)); getlfcol(lf, CC_BAD));
@ -4535,6 +4591,7 @@ int fallasleep(lifeform_t *lf, enum SLEEPTYPE how, int howlong) {
} }
loseconcentration(lf); loseconcentration(lf);
interrupt(lf); interrupt(lf);
breakgrabs(lf, B_TRUE, B_FALSE);
// falling asleep while flying = fall! // falling asleep while flying = fall!
fall_from_air(lf); fall_from_air(lf);
@ -7236,11 +7293,13 @@ int getattacks(lifeform_t *lf, int *min, int *max) {
} }
// if we have high unarmed skill and our second hand is free, // if we have high unarmed skill and our second hand is free,
// we get one more attack // AND we only had 1 attack before, we get one more attack
if (lfhasflag(lf, F_HUMANOID)) { if (maxattacks < 2) {
if (getskill(lf, SK_UNARMED) >= PR_SKILLED) { if (lfhasflag(lf, F_HUMANOID)) {
if (hasbp(lf, BP_SECWEAPON) && !getequippedob(lf->pack, BP_SECWEAPON)) { if (getskill(lf, SK_UNARMED) >= PR_SKILLED) {
maxattacks++; if (hasbp(lf, BP_SECWEAPON) && !getequippedob(lf->pack, BP_SECWEAPON)) {
maxattacks++;
}
} }
} }
} }
@ -7333,7 +7392,10 @@ int getmaxmp(lifeform_t *lf) {
float getmaxpushweight(lifeform_t *lf) { float getmaxpushweight(lifeform_t *lf) {
float max; float max;
max = getlfweight(lf, B_NOOBS) * 2; // twice your body weight int pct;
pct = 100 + getstatmod(lf, A_STR);
max = getlfweight(lf, B_NOOBS); // your body weight
max = pctof(pct, max);
return max; return max;
} }
@ -9076,9 +9138,10 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
// now give start obs/skills from it // now give start obs/skills from it
givestartskills(lf, lf->flags); givestartskills(lf, lf->flags);
givestartobs(lf, NULL, lf->flags); if (!lfhasflag(lf, F_PHANTASM)) {
autoskill(lf); givestartobs(lf, NULL, lf->flags);
autoskill(lf);
}
// override hp/mp from race // override hp/mp from race
/* /*
@ -9419,8 +9482,8 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
newf = addtempflag(lf->flags, F_CANWILL, OT_A_DISARM, NA, NA, NULL, FROMSKILL); newf = addtempflag(lf->flags, F_CANWILL, OT_A_DISARM, NA, NA, NULL, FROMSKILL);
} }
// learning a new spell school skill will grant you a random first level spell from // learning a new spell school skill after the game has started will grant
// that school. (player and allies only) // you a random first level spell from that school. (player and allies only)
if (isspellskill(id) && (gamemode == GM_GAMESTARTED)) { if (isspellskill(id) && (gamemode == GM_GAMESTARTED)) {
if (isplayer(lf) || areallies(player, lf)) { if (isplayer(lf) || areallies(player, lf)) {
enum OBTYPE oid; enum OBTYPE oid;
@ -9565,7 +9628,17 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
} }
} else if (id == SK_TWOWEAPON) { } else if (id == SK_TWOWEAPON) {
if (f->val[1] == PR_EXPERT) { if (f->val[1] == PR_EXPERT) {
addflag(lf->flags, F_CANWILL, OT_A_FLURRY, NA, NA, "pw:1;"); newf = hasflagval(lf->flags, F_CANWILL, OT_A_FLURRY, NA, NA, NULL);
if (!newf) {
newf = addtempflag(lf->flags, F_CANWILL, OT_A_FLURRY, NA, NA, "pw:1;", FROMSKILL);
}
}
} else if (id == SK_UNARMED) {
if (f->val[1] == PR_EXPERT) {
newf = hasflagval(lf->flags, F_CANWILL, OT_A_FLIP, NA, NA, NULL);
if (!newf) {
newf = addtempflag(lf->flags, F_CANWILL, OT_A_FLIP, NA, NA, NULL, FROMSKILL);
}
} }
} else if (id == SK_SS_ALLOMANCY) { } else if (id == SK_SS_ALLOMANCY) {
// give all allomantic spells // give all allomantic spells
@ -12122,9 +12195,18 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) {
*amt -= rnd(1,f->val[0]); *amt -= rnd(1,f->val[0]);
} }
// gods can't die unless they are in the realm of gods
if (lf->race->raceclass->id == RC_GOD) { if (lf->race->raceclass->id == RC_GOD) {
// immortal int damok = B_FALSE;
limit(amt, 0, lf->hp-1); if (lf->cell->map->habitat->id == H_HEAVEN) {
if (hasob(player->pack, getrelatedgodstone(lf->race->id)) ) {
damok = B_TRUE;
}
}
if (!damok) {
// immortal
limit(amt, 0, lf->hp-1);
}
} else { } else {
limit(amt, 0, NA); limit(amt, 0, NA);
} }
@ -12441,23 +12523,32 @@ int askforinfo(lifeform_t *lf, int diffmod) {
} else { } else {
// they will consider it - now negotiate a price // they will consider it - now negotiate a price
f = lfhasflag(lf, F_INFOPRICE); f = lfhasflag(lf, F_INFOPRICE);
if (f) { if (f) { // already got a price in mind?
askingprice = f->val[0]; askingprice = f->val[0];
} else { } else {
int result; int result;
int difficulty; int difficulty;
int greedy = B_FALSE;
// delvers are greedy, so they'll nearly always help, but
// nearly always want money too!
if ((lf->race->id == R_DWARF) && (player->race->id != R_DWARF)) {
greedy = B_TRUE;
diffmod += 15;
}
difficulty = 20 + diffmod + ((gethitdice(player) - gethitdice(lf))*2); difficulty = 20 + diffmod + ((gethitdice(player) - gethitdice(lf))*2);
if (real_skillcheck(player, SC_SPEECH, difficulty, alignmod, &result)) { if (real_skillcheck(player, SC_SPEECH, difficulty, alignmod, &result)) {
askingprice = 0; askingprice = 0;
// passed - free! // passed - free!
} else { } else {
if (difficulty - result >= 10) { if (!greedy && (difficulty - result >= 10)) {
// will not help! // will not help!
askingprice = -1; askingprice = -1;
} else { } else {
// will help for gold // will help for gold
askingprice = rnd(gethitdice(lf)*5, gethitdice(lf)*15 ); askingprice = rnd(gethitdice(lf)*5, gethitdice(lf)*15 );
limit(&askingprice, 1, NA); // just in case
} }
} }
@ -13072,13 +13163,22 @@ void loseconcentration(lifeform_t *lf) {
interrupt(lf); interrupt(lf);
} }
void loseconsciousness(lifeform_t *lf, int howlong, lifeform_t *fromlf) {
if (!isunconscious(lf)) {
fallasleep(lf, ST_KO, rnd(50,100));
if (fromlf && isplayer(fromlf)) {
pleasegodmaybe(R_GODMERCY, 5);
}
}
}
// lose hp, and adjust damage based on resistances // lose hp, and adjust damage based on resistances
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc) { int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc) {
return losehp_real(lf, amt, damtype, fromlf, damsrc, B_TRUE, NULL, B_TRUE); return losehp_real(lf, amt, damtype, fromlf, damsrc, B_TRUE, NULL, B_TRUE, NULL);
} }
// returns the amt of damage taken // returns the amt of damage taken
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate) { int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate, int *waskod) {
char buf[BUFLEN]; char buf[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
char lfname[BUFLEN]; char lfname[BUFLEN];
@ -13173,7 +13273,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// methods of knocking unconscious // methods of knocking unconscious
if (!isundead(lf)) { if (!isundead(lf)) {
// merciful weapons // merciful weapons
if (fromob) { if (!ko && fromob) {
f = hasflag(fromob->flags, F_MERCIFUL); f = hasflag(fromob->flags, F_MERCIFUL);
if (f && (amt >= lf->hp)) { if (f && (amt >= lf->hp)) {
ko = B_TRUE; ko = B_TRUE;
@ -13205,10 +13305,14 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
if (damtypeok) { if (damtypeok) {
if (playerinvolved && godprayedto(R_GODMERCY)) { if (playerinvolved && godprayedto(R_GODMERCY)) {
threshold = -10; threshold = -10;
kochance = 75; if (isplayer(lf)) {
kochance = 75;
} else {
kochance = 50;
}
} else { } else {
threshold = -5; threshold = -5;
kochance = 50; kochance = 30;
} }
} }
@ -13232,7 +13336,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
} }
} }
// just knock them out. // just knock them out, don't kill.
if (ko) { if (ko) {
amt = lf->hp - 1; // ie end up at 1hp amt = lf->hp - 1; // ie end up at 1hp
} }
@ -13265,8 +13369,19 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
} }
} }
// take damage
lf->hp -= amt; // phantasms have a fake hp counter
f = lfhasflag(lf, F_PHANTASM);
if (f) {
f->val[0] -= amt;
// they die when their FAKE hp drops below 0
if (f->val[0] <= 0) {
lf->hp = 0;
}
} else {
// take damage
lf->hp -= amt;
}
// fill in lastdam... // fill in lastdam...
lf->lastdamtype = damtype; lf->lastdamtype = damtype;
@ -13430,13 +13545,18 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
} }
if (ko) { if (ko) {
if (!isunconscious(lf)) { int kotime;
// you are knocked unconscious for a _long_ time // is waskod was passed, allow the calling function to actually
fallasleep(lf, ST_KO, rnd(50,100)); // knock us unconscious.
breakgrabs(lf, B_TRUE, B_FALSE); //
if (fromlf && isplayer(fromlf)) { // this is mainly used in attack.c, so that we can announce
pleasegodmaybe(R_GODMERCY, 5); // "you hit xxx. xxx loses consciousness." as opposed to
} // "xxx loses consciousness. you hit xxx." which makes no sense!
kotime = rnd(50,100);
if (waskod) {
*waskod = kotime;
} else {
loseconsciousness(lf, kotime, fromlf);
} }
} else { } else {
// you wake up if you were hit, unless you were unconscious! // you wake up if you were hit, unless you were unconscious!
@ -14003,8 +14123,9 @@ void modstamina(lifeform_t *lf, float howmuch) {
if (howmuch == 0) return; if (howmuch == 0) return;
// you don't lose stamina while enraged // you don't lose stamina while enraged or caffeinated
if (lfhasflag(lf, F_RAGE) && (howmuch < 0)) return; if (lfhasflag(lf, F_RAGE) && (howmuch < 0)) return;
if (lfhasflag(lf, F_CAFFEINATED) && (howmuch < 0)) return;
if (isplayer(lf)) { if (isplayer(lf)) {
if (howmuch < 0) { if (howmuch < 0) {
@ -14377,11 +14498,13 @@ void outfitlf(lifeform_t *lf) {
// make 'lf' into a pet/ally of 'owner' // make 'lf' into a pet/ally of 'owner'
void petify(lifeform_t *lf, lifeform_t *owner) { void petify(lifeform_t *lf, lifeform_t *owner) {
makefriendly(lf, PERMENANT); if (isplayer(owner)) {
makefriendly(lf, PERMENANT);
killflagsofid(lf->flags, F_NOINFO);
killflagsofid(lf->flags, F_INFOPRICE);
}
addflag(lf->flags, F_PETOF, owner->id, owner->cell->x, owner->cell->y, NULL); addflag(lf->flags, F_PETOF, owner->id, owner->cell->x, owner->cell->y, NULL);
killflagsofid(lf->flags, F_STAYINROOM); killflagsofid(lf->flags, F_STAYINROOM);
killflagsofid(lf->flags, F_NOINFO);
killflagsofid(lf->flags, F_INFOPRICE);
} }
@ -15437,6 +15560,44 @@ int say(lifeform_t *lf, char *text, int volume) {
char hearbuf[BUFLEN]; char hearbuf[BUFLEN];
char verb[BUFLEN]; char verb[BUFLEN];
char noun[BUFLEN]; char noun[BUFLEN];
char *localtext;
int rv;
localtext = strdup(text);
// adjust text and volume for gods
if (lf) {
switch (lf->race->id) {
case R_GODMAGIC:
volume = SV_TALK;
strrep(localtext, "You have", "One has", NULL);
strrep(localtext, "You", "One", NULL);
strrep(localtext, "you", "one", NULL);
break;
case R_GODTHIEVES:
case R_GODDEATH:
volume = SV_WHISPER;
break;
case R_GODFIRE:
volume = SV_TRUCK;
makeuppercase(localtext);
break;
case R_GODPURITY:
case R_GODLIFE:
case R_GODMERCY:
case R_GODNATURE:
volume = SV_TALK;
break;
case R_GODBATTLE:
if (localtext[strlen(localtext)-1] == '.') {
localtext[strlen(localtext)-1] = '!';
}
volume = SV_SHOUT;
break;
default: break;
}
}
if (volume < 2) { if (volume < 2) {
strcpy(verb, "whispers"); strcpy(verb, "whispers");
strcpy(noun, "a whisper:"); strcpy(noun, "a whisper:");
@ -15454,10 +15615,12 @@ int say(lifeform_t *lf, char *text, int volume) {
strcpy(noun, "a bellow:"); strcpy(noun, "a bellow:");
} }
snprintf(seebuf, BUFLEN, "%s \"%s\"", verb, text); snprintf(seebuf, BUFLEN, "%s \"%s\"", verb, localtext);
snprintf(hearbuf, BUFLEN, "%s \"%s\"", noun, text); snprintf(hearbuf, BUFLEN, "%s \"%s\"", noun, localtext);
return noise(lf->cell, lf, NC_SPEECH, volume, hearbuf, seebuf); rv = noise(lf->cell, lf, NC_SPEECH, volume, hearbuf, seebuf);
free(localtext);
return rv;
} }
// volume = -1 means "auto" // volume = -1 means "auto"
@ -17175,6 +17338,7 @@ void startlfturn(lifeform_t *lf) {
// god piety gets restored over time // god piety gets restored over time
if (isplayer(lf)) { if (isplayer(lf)) {
for (i = 0; i < ngodlfs; i++) { for (i = 0; i < ngodlfs; i++) {
if (!godlf[i]) continue;
if (getpietylev(godlf[i]->race->id, NULL, NULL) == PL_TOLERATED) { if (getpietylev(godlf[i]->race->id, NULL, NULL) == PL_TOLERATED) {
// slowly tick upwards // slowly tick upwards
if (onein(2)) modpiety(godlf[i]->race->id, 1); if (onein(2)) modpiety(godlf[i]->race->id, 1);
@ -17958,6 +18122,20 @@ void startlfturn(lifeform_t *lf) {
} }
} }
} // end loop through lf flags } // end loop through lf flags
// picked up your first godstone ?
if (isplayer(lf)) {
o = hasobofclass(lf->pack, OC_GODSTONE);
if (o && !lfhasflag(lf, F_FOUNDGODSTONE)) {
lifeform_t *god,*opposegod;
// get linked gods
f = hasflag(o->flags, F_LINKGOD);
god = findgod(f->val[0]);
opposegod = findgod(getopposinggod(god->race->id));
godstone_pickup_effects(god, opposegod, o);
addflag(lf->flags, F_FOUNDGODSTONE, B_TRUE, NA, NA, NULL);
}
}
} }
// returns TRUE on failure (ie. nothing to steal) // returns TRUE on failure (ie. nothing to steal)
@ -18791,7 +18969,7 @@ int touch(lifeform_t *lf, object_t *o) {
} else { } else {
// wearing gloves? they get damaged. // wearing gloves? they get damaged.
if (gloves) { if (gloves) {
if (f->id == F_ONFIRE) { if (f->id == F_ONFIRE) { // fire will damage your gloves, just being hot will not.
takedamage(gloves, 2, DT_FIRE); takedamage(gloves, 2, DT_FIRE);
if (hasflag(gloves->flags, F_DEAD)) { if (hasflag(gloves->flags, F_DEAD)) {
gloves = NULL; gloves = NULL;
@ -19615,6 +19793,50 @@ int resizelf(lifeform_t *lf, enum LFSIZE newsize) {
return B_FALSE; return B_FALSE;
} }
lifeform_t *ressurect(object_t *o) {
flag_t *f;
race_t *r;
lifeform_t *lf;
cell_t *where;
int level = 1;
char obname[BUFLEN];
if (o->type->id != OT_CORPSE) return NULL;
if (hasflag(o->flags, F_HEADLESS)) return NULL;
f = hasflag(o->flags, F_CORPSEOF);
if (f) {
level = f->val[1];
} else {
return NULL;
}
r = findrace(f->val[0]);
if (!r) return NULL;
where = getoblocation(o);
getobname(o, obname, 1);
if (!cellwalkable(NULL, where, NULL)) {
where = getrandomadjcell(where, WE_WALKABLE, B_ALLOWEXPAND);
}
if (!where) return NULL;
lf = addlf(where, r->id, level);
// remove the corpse object
removeob(o,o->amt);
// redraw & announce
if (haslos(player, where)) {
needredraw = B_TRUE;
drawscreen();
msg("%s is restored to life!", obname);
}
return lf;
}
int rest(lifeform_t *lf, int onpurpose) { int rest(lifeform_t *lf, int onpurpose) {
flag_t *f; flag_t *f;
flag_t *ff; flag_t *ff;
@ -20134,7 +20356,6 @@ int wear(lifeform_t *lf, object_t *o) {
} }
if ((gamemode == GM_GAMESTARTED) && lf->created) { if ((gamemode == GM_GAMESTARTED) && lf->created) {
if (isplayer(lf)) { if (isplayer(lf)) {
// announce // announce
if (showpos) { if (showpos) {

5
lf.h
View File

@ -69,6 +69,7 @@ int checkburdened(lifeform_t *lf, int preburdened);
int checkfordrowning(lifeform_t *lf, object_t *o); int checkfordrowning(lifeform_t *lf, object_t *o);
int check_rest_ok(lifeform_t *lf); int check_rest_ok(lifeform_t *lf);
//void checkxp(enum RACE rid); //void checkxp(enum RACE rid);
lifeform_t *clonelf(lifeform_t *src, cell_t *where);
float comparelfs(lifeform_t *lf1, lifeform_t *lf2); float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
int confuse(lifeform_t *lf, int howlong); int confuse(lifeform_t *lf, int howlong);
void copycorpseflags(flagpile_t *dst, flagpile_t *src); void copycorpseflags(flagpile_t *dst, flagpile_t *src);
@ -348,8 +349,9 @@ flag_t *levelabilityready(lifeform_t *lf);
int loadfirearm(lifeform_t *lf, object_t *gun, object_t *ammo); int loadfirearm(lifeform_t *lf, object_t *gun, object_t *ammo);
int loadfirearmfast(lifeform_t *lf, int onpurpose); int loadfirearmfast(lifeform_t *lf, int onpurpose);
void loseconcentration(lifeform_t *lf); void loseconcentration(lifeform_t *lf);
void loseconsciousness(lifeform_t *lf, int howlong, lifeform_t *fromlf);
int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc); int losehp(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc);
int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate); int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *fromlf, char *damsrc, int reducedam, object_t *fromob, int retaliate, int *waskod);
void losemp(lifeform_t *lf, int amt); void losemp(lifeform_t *lf, int amt);
void makefriendly(lifeform_t *lf, int howlong); void makefriendly(lifeform_t *lf, int howlong);
int makenauseated(lifeform_t *lf, int amt, int howlong); int makenauseated(lifeform_t *lf, int amt, int howlong);
@ -386,6 +388,7 @@ int recruit(lifeform_t *lf);
void refreshlevelabilities(lifeform_t *lf); void refreshlevelabilities(lifeform_t *lf);
void relinklf(lifeform_t *src, map_t *dst); void relinklf(lifeform_t *src, map_t *dst);
int resizelf(lifeform_t *lf, enum LFSIZE newsize); int resizelf(lifeform_t *lf, enum LFSIZE newsize);
lifeform_t *ressurect(object_t *o);
int rest(lifeform_t *lf, int onpurpose); int rest(lifeform_t *lf, int onpurpose);
void setskillused(lifeform_t *lf, enum SKILL skid); void setskillused(lifeform_t *lf, enum SKILL skid);
void spot_hiding_lf(lifeform_t *lf, lifeform_t *hider); void spot_hiding_lf(lifeform_t *lf, lifeform_t *hider);

31
move.c
View File

@ -2525,15 +2525,34 @@ void standup(lifeform_t *lf) {
// monsters don't take time to stand up if they were feigning death! // monsters don't take time to stand up if they were feigning death!
if (!isplayer(lf) && lfhasflag(lf, F_FEIGNINGDEATH)) { if (!isplayer(lf) && lfhasflag(lf, F_FEIGNINGDEATH)) {
} else { } else {
int howlong; int baseunits = 0,armourunits = 0,totunits = 0,howlong;
float quartermax; float quartermax;
int units; enum LFSIZE sz;
// time to get up depends on armour // time to get up depends on size and armour
// base time depends on size
sz = getlfsize(lf);
if (sz < SZ_HUMAN) {
baseunits = 0;
} else if (sz == SZ_HUMAN) {
baseunits = 1;
} else if (sz == SZ_LARGE) {
baseunits = 2;
} else { // ie. SZ_HUGE or larger
baseunits = 3;
}
// 1*movespeed for every 1/4 of maxcarryweight being worn. // 1*movespeed for every 1/4 of maxcarryweight being worn.
quartermax = getmaxcarryweight(lf) / 4; quartermax = getmaxcarryweight(lf) / 4;
units = (getequippedweight(lf) / quartermax)+1; if (quartermax > 0) {
howlong = getmovespeed(lf)*units; armourunits = (getequippedweight(lf) / quartermax);
taketime(lf, howlong); }
totunits = baseunits + armourunits;
howlong = getmovespeed(lf) * totunits;
if (howlong > 0) {
taketime(lf, howlong);
}
} }
} }

View File

@ -98,6 +98,7 @@ int gameover;
int obdb = B_FALSE; int obdb = B_FALSE;
enum GAMEMODE gamemode = GM_FIRST; enum GAMEMODE gamemode = GM_FIRST;
enum WINGAMETYPE wintype = WT_NONE;
long curtime = 0; // # current game clock (in seconds) long curtime = 0; // # current game clock (in seconds)
long gamedays = 0; // # game days passed since start of game long gamedays = 0; // # game days passed since start of game
@ -360,7 +361,6 @@ int main(int argc, char **argv) {
addchoice(&prompt, 'w', getskillname(SK_SS_WILD), NULL, findskill(SK_SS_WILD), NULL); addchoice(&prompt, 'w', getskillname(SK_SS_WILD), NULL, findskill(SK_SS_WILD), NULL);
getchoice(&prompt); getchoice(&prompt);
sk = (skill_t *) prompt.result; sk = (skill_t *) prompt.result;
giveskilllev(player, sk->id, PR_NOVICE);
switch (sk->id) { switch (sk->id) {
case SK_SS_AIR: case SK_SS_AIR:
addflag(player->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL); addflag(player->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL);
@ -396,7 +396,6 @@ int main(int argc, char **argv) {
addchoice(&prompt, 't', getskillname(SK_SS_TRANSLOCATION), NULL, findskill(SK_SS_TRANSLOCATION), NULL); addchoice(&prompt, 't', getskillname(SK_SS_TRANSLOCATION), NULL, findskill(SK_SS_TRANSLOCATION), NULL);
getchoice(&prompt); getchoice(&prompt);
sk = (skill_t *) prompt.result; sk = (skill_t *) prompt.result;
giveskilllev(player, sk->id, PR_NOVICE);
switch (sk->id) { switch (sk->id) {
case SK_SS_DIVINATION: case SK_SS_DIVINATION:
sb2 = addob(player->pack, "spellbook of divination magic"); sb2 = addob(player->pack, "spellbook of divination magic");
@ -685,9 +684,14 @@ void checkdeath(void) {
void checkendgame(void) { void checkendgame(void) {
flag_t *f;
if (!player->alive) { if (!player->alive) {
gamemode = GM_GAMEOVER; gamemode = GM_GAMEOVER;
gameover = B_TRUE; gameover = B_TRUE;
} else if ((f = lfhasflag(player, F_WINNER)) != NULL) {
gamemode = GM_GAMEOVER;
gameover = B_TRUE;
wintype = f->val[0];
} }
} }

View File

@ -1264,6 +1264,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
} else { } else {
if (gamemode == GM_GAMESTARTED) { if (gamemode == GM_GAMESTARTED) {
msg("DB: created abandoned temple"); more(); msg("DB: created abandoned temple"); more();
dblog("DB: created abandoned temple");
raise(SIGINT);
} }
} }
} }
@ -1496,7 +1498,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o->material = corpserace->material; o->material = corpserace->material;
// remember the race type // remember the race type
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL); addflag(o->flags, F_CORPSEOF, corpserace->id, 1, NA, NULL);
// override ot_corpse nutrition flag based on race's size // override ot_corpse nutrition flag based on race's size
rf = hasflag(corpserace->flags, F_SIZE); rf = hasflag(corpserace->flags, F_SIZE);
@ -1572,7 +1574,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o->weight = corpserace->weight * ratio; o->weight = corpserace->weight * ratio;
// remember the race type // remember the race type
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL); addflag(o->flags, F_CORPSEOF, corpserace->id, 1, NA, NULL);
// set impassable size // set impassable size
f = hasflag(o->flags, F_IMPASSABLE); f = hasflag(o->flags, F_IMPASSABLE);
@ -1607,7 +1609,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o->material = corpserace->material; o->material = corpserace->material;
// remember the race type // remember the race type
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL); addflag(o->flags, F_CORPSEOF, corpserace->id, 1, NA, NULL);
// override ot_corpse nutrition flag based on race's size // override ot_corpse nutrition flag based on race's size
rf = hasflag(corpserace->flags, F_SIZE); rf = hasflag(corpserace->flags, F_SIZE);
@ -1635,7 +1637,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o->weight = corpserace->weight / 2; o->weight = corpserace->weight / 2;
// remember the race type // remember the race type
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL); addflag(o->flags, F_CORPSEOF, corpserace->id, 1, NA, NULL);
// override ot_roastmeat nutrition flag based on race's size // override ot_roastmeat nutrition flag based on race's size
rf = hasflag(corpserace->flags, F_SIZE); rf = hasflag(corpserace->flags, F_SIZE);
@ -2100,7 +2102,7 @@ recipe_t *addrecipe(enum OBTYPE result, ...) {
void adjustdamhardness(int *dam, enum DAMTYPE damtype, enum MATERIAL mat) { void adjustdamhardness(int *dam, enum DAMTYPE damtype, enum MATERIAL mat) {
// now check for hardness // now check for hardness
if (isphysicaldam(damtype)) { if (ismeleedam(damtype)) {
*dam -= gethardness(mat); *dam -= gethardness(mat);
if (*dam < 0) *dam = 0; if (*dam < 0) *dam = 0;
/* /*
@ -9107,12 +9109,42 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
c = getcellat(lf->cell->map, x, y); c = getcellat(lf->cell->map, x, y);
if (c && c->lf && (c->lf != lf) && haslof(lf->cell, c, LOF_NEED, NULL)) { if (c && c->lf && (c->lf != lf) && haslof(lf->cell, c, LOF_NEED, NULL)) {
int howlong = 50; int howlong = 50;
// create fire
addobfast(c->obpile, OT_FIRELARGE);
// enrage
addtempflag(c->lf->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong); addtempflag(c->lf->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong);
if (!isplayer(c->lf)) { if (!isplayer(c->lf)) {
addtempflag(c->lf->flags, F_HATESALL, B_TRUE, NA, NA, NULL, howlong); addtempflag(c->lf->flags, F_HATESALL, B_TRUE, NA, NA, NULL, howlong);
loseaitargets(c->lf); loseaitargets(c->lf);
} }
}
}
}
break;
case OT_GODSTONEL: // life
// everything in sight is restored
// all corpses in sight are revived
// everyone in lof gets f_rage, and hates everything
for (y = 0; y < lf->cell->map->h; y++) {
for (x = 0; x < lf->cell->map->w; x++) {
cell_t *c;
c = getcellat(lf->cell->map, x, y);
if (c && haslof(lf->cell, c, LOF_NEED, NULL)) {
if (c->lf) {
// restore
dospelleffects(NULL, OT_S_RESTORATION, 1,
c->lf, NULL, c->lf->cell, B_BLESSED, NULL, B_TRUE);
} else {
object_t *oo, *nextoo;
// revive corpses
for (oo = c->obpile->first ; oo ; oo = nextoo) {
nextoo = oo->next;
if (oo->type->id == OT_CORPSE) {
dospelleffects(NULL, OT_S_RESSURECTION, 1,
NULL, oo, c, B_BLESSED, NULL, B_TRUE);
}
}
}
} }
} }
} }
@ -10001,7 +10033,6 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
int amt; int amt;
int failed; int failed;
int seenbyplayer; int seenbyplayer;
int hpheal,mpheal;
flag_t *f; flag_t *f;
if (isplayer(lf)) { if (isplayer(lf)) {
@ -10276,43 +10307,7 @@ void potioneffects(lifeform_t *lf, enum OBTYPE oid, object_t *o, enum BLESSTYPE
} }
break; break;
case OT_POT_RESTORATION: case OT_POT_RESTORATION:
failed = B_TRUE; dospelleffects(NULL, OT_S_RESTORATION, 1, lf, NULL, lf->cell, potblessed, NULL, B_TRUE);
for (i = 0; i < MAXATTS; i++ ){
if (getattr(lf,i) < lf->baseatt[i]) {
setattr(lf, i, lf->baseatt[i]);
failed = B_FALSE;
}
}
// fix diseases (even magical ones)
killflagsofid(lf->flags, F_POISONED);
// blessed restores hp/mp to full
if (potblessed == B_BLESSED) {
hpheal = lf->maxhp;
mpheal = getmaxmp(lf);
} else if (potblessed == B_CURSED) {
hpheal = lf->maxhp / 3;
mpheal = getmaxmp(lf) / 3;
} else {
hpheal = lf->maxhp / 2;
mpheal = getmaxmp(lf) / 2;
}
if (lf->hp < hpheal) {
gainhp(lf, hpheal - lf->hp);
if (!isplayer(lf) && cansee(player, lf)) {
msg("%s%s health has been restored!", lfname, getpossessive(lfname));
}
failed = B_FALSE;
}
if (lf->mp < mpheal) {
gainmp(lf, mpheal - lf->mp);
failed = B_FALSE;
}
if (failed) {
if (isplayer(lf)) msg("You feel momentarily restored.");
} else {
if (isplayer(lf)) msg("You feel restored!");
}
break; break;
case OT_POT_SANCTUARY: case OT_POT_SANCTUARY:
// how long for? // how long for?
@ -11740,7 +11735,7 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) {
// now use the REAL name // now use the REAL name
real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_FALSE, B_FALSE, B_TRUE); real_getobname(o, obname, o->amt, B_TRUE, B_FALSE, B_FALSE, B_FALSE, B_TRUE);
losehp_real(owner, howmuch , damtype, NULL, obname, B_TRUE, o, B_FALSE); losehp_real(owner, howmuch , damtype, NULL, obname, B_TRUE, o, B_FALSE, NULL);
if (isdead(owner)) { if (isdead(owner)) {
return howmuch; return howmuch;
} }
@ -12636,7 +12631,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
if (thrower && (thrower->cell == srcloc)) { if (thrower && (thrower->cell == srcloc)) {
whogetsxp = thrower; whogetsxp = thrower;
} }
losehp_real(target, dam, DT_PROJECTILE, whogetsxp, damstring, B_TRUE, o, B_TRUE); losehp_real(target, dam, DT_PROJECTILE, whogetsxp, damstring, B_TRUE, o, B_TRUE, NULL);
} }
if (reduceamt && (speed >= 3)) { if (reduceamt && (speed >= 3)) {

View File

@ -411,7 +411,7 @@ enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *topte
default: wantflag = F_NONE; wantoc = OC_NONE; break; default: wantflag = F_NONE; wantoc = OC_NONE; break;
} }
*/ */
o = doaskobject(lf->pack, "What will you donate?", &count, B_TRUE, B_FALSE, B_FALSE, '\0', vm, AO_NONE, F_NONE); o = doaskobject(lf->pack, "What will you donate?", &count, B_TRUE, B_FALSE, B_FALSE, '\0', vm, MT_NOTHING, AO_NONE, F_NONE);
// validate it // validate it
if (o) { if (o) {
@ -800,7 +800,7 @@ enum SHOPRETURN shoppurchase(lifeform_t *lf, object_t *vm, int starty, char *top
// you got it! // you got it!
buyit = B_TRUE; buyit = B_TRUE;
usecharges(money, value); usecharges(money, value);
strcpy(buytext, "Charged to card:"); strcpy(buytext, "Charged to card");
if (npurchased) (*npurchased)++; if (npurchased) (*npurchased)++;
} else { } else {
// maxed! // maxed!
@ -1034,7 +1034,7 @@ enum SHOPRETURN shoprest(lifeform_t *lf, object_t *vm, int starty, char *toptext
y = starty; y = starty;
cost = applyshoppricemod(100, lf, vm, SA_BUY); cost = applyshoppricemod(10, lf, vm, SA_BUY);
mvwprintw(mainwin, y, 0, "We offer good quality rooms for only $%d per hour.", cost); mvwprintw(mainwin, y, 0, "We offer good quality rooms for only $%d per hour.", cost);
y += 2; y += 2;
@ -1107,7 +1107,7 @@ enum SHOPRETURN shopsell(lifeform_t *lf, object_t *vm, int starty, char *toptext
// ask what to sell // ask what to sell
sprintf(buf, "What will you sell (you have $%d)?", countmoney(lf->pack)); sprintf(buf, "What will you sell (you have $%d)?", countmoney(lf->pack));
o = doaskobject(player->pack, buf, &count, B_TRUE, B_FALSE, B_FALSE, '\0', vm, AO_NONE, F_NONE); o = doaskobject(player->pack, buf, &count, B_TRUE, B_FALSE, B_FALSE, '\0', vm, MT_NOTHING, AO_NONE, F_NONE);
if (!o) { if (!o) {
return SR_BACK; return SR_BACK;
} }

413
spell.c
View File

@ -45,9 +45,6 @@ extern object_t *retobs[MAXPILEOBS+1];
extern int retobscount[MAXPILEOBS+1]; extern int retobscount[MAXPILEOBS+1];
extern int nretobs; extern int nretobs;
extern lifeform_t *godlf[];
extern int ngodlfs;
extern enum ERROR reason; extern enum ERROR reason;
extern int needredraw, statdirty; extern int needredraw, statdirty;
@ -3674,6 +3671,60 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster)) { if (isplayer(caster)) {
msg("You create a alarm field around yourself."); msg("You create a alarm field around yourself.");
} }
} else if (spellid == OT_S_ALCHEMY) {
char obname[BUFLEN];
char obtocreate[BUFLEN];
obpile_t *op;
object_t *newob = NULL;
int obvalue,obamt;
// needs:
// object = which object to convert
if (!targob && isplayer(caster)) {
targob = doaskobject(caster->pack, "Convert which object to gold", NULL, B_FALSE, B_FALSE, B_FALSE, '\0', NULL, MT_METAL, AO_NONE, F_NONE);
}
if (!targob) {
fizzle(caster);
return B_TRUE;
}
op = targob->pile;
obamt = targob->amt;
getobname(targob, obname, targob->amt);
obvalue = getobvalue(targob);
obvalue = pctof(power*10, obvalue);
limit(&obvalue, 0, NA);
// original object vanishes.
killob(targob);
// create new object
if (obvalue > 0) {
if (op->owner) {
newob = hasob(op, OT_GOLD);
if (newob) {
newob->amt += obvalue;
} else {
sprintf(obtocreate, "%d gold coins", obvalue);
newob = addob(op, obtocreate);
}
} else {
sprintf(obtocreate, "%d gold coins", obvalue);
newob = addob(op, obtocreate);
}
}
// announce
if (isplayer(op->owner) || (op->where && haslos(player, op->where)) ) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
if (newob) {
char newobname[BUFLEN];
msg("%s change%s into %d gold coin%s!", obname, (obamt == 1) ? "s" : "", obvalue, (obvalue == 1) ? "" : "s");
if (newob->pile->owner && isplayer(newob->pile->owner)) {
getobname(newob, newobname, newob->amt);
msgnocap("%c - %s", newob->letter, newobname);
}
} else {
msg("%s vanishes!", obname);
if (isplayer(caster)) angergodmaybe(R_GODNATURE, 10, GA_ATTACKOBJECT);
}
}
} else if (spellid == OT_S_ANIMATEDEAD) { } else if (spellid == OT_S_ANIMATEDEAD) {
int i; int i;
object_t *o,*nexto; object_t *o,*nexto;
@ -4137,6 +4188,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
initprompt(&prompt, "Confiscate which object?"); initprompt(&prompt, "Confiscate which object?");
addchoice(&prompt, '-', "(Cancel)", NULL, NULL, NULL); addchoice(&prompt, '-', "(Cancel)", NULL, NULL, NULL);
for (o = target->pack->first ; o ; o = o->next) { for (o = target->pack->first ; o ; o = o->next) {
if (o->type->obclass->id == OC_GODSTONE) continue;
getobname(o, obname, o->amt); getobname(o, obname, o->amt);
addchoice(&prompt, ch, obname, NULL, o, NULL); addchoice(&prompt, ch, obname, NULL, o, NULL);
if (ch == 'z') { if (ch == 'z') {
@ -4145,7 +4197,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
ch++; ch++;
} }
} }
if (isplayer(caster)) { if (isplayer(caster) && (power > 1)) {
// select one // select one
getchoice(&prompt); getchoice(&prompt);
targob = (object_t *)prompt.result; targob = (object_t *)prompt.result;
@ -4420,7 +4472,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} // end while narccells } // end while narccells
} else if (spellid == OT_S_CLONE) { } else if (spellid == OT_S_CLONE) {
lifeform_t *lf;
// duplicate the caster // duplicate the caster
targcell = getrandomadjcell(caster->cell, WE_WALKABLE, B_NOEXPAND); targcell = getrandomadjcell(caster->cell, WE_WALKABLE, B_NOEXPAND);
if (!targcell) { if (!targcell) {
@ -4430,11 +4481,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster) || haslos(player, targcell)) { if (isplayer(caster) || haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
lf = addmonster(targcell, caster->race->id, NULL, B_FALSE, 1, B_FALSE, NULL); clonelf(caster, targcell);
if (lf) {
killflagsofid(lf->flags, F_XPVAL);
addflag(lf->flags, F_XPVAL, 0, NA, NA, NULL);
}
} else if (spellid == OT_S_CLOUDKILL) { } else if (spellid == OT_S_CLOUDKILL) {
int radius; int radius;
@ -6547,54 +6594,59 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int donesomething = B_FALSE,i; int donesomething = B_FALSE,i;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags; int nretflags;
int undead = B_FALSE;
target = targcell->lf; target = targcell->lf;
if (!target) { if (!target) {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
// cure certain bad effects undead = isundead(target);
if (killflagsofid(target->flags, F_PAIN)) {
donesomething = B_TRUE;
}
getflags(target->flags, retflag, &nretflags, F_POISONED, F_NONE);
for (i = 0; i < nretflags; i++) {
poisontype_t *pt;
pt = findpoisontype(retflag[i]->val[0]);
if (pt->severity == PS_CURSE) {
} else {
killflag(retflag[i]);
donesomething = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
if (!lfhasflagval(target, F_POISONED, P_ROT, NA, NA, NULL)) { // cure certain bad effects
// severed body parts if (!undead) {
getflags(target->flags, retflag, &nretflags, F_INJURY, F_NOBODYPART, F_NONE); if (killflagsofid(target->flags, F_PAIN)) {
donesomething = B_TRUE;
}
getflags(target->flags, retflag, &nretflags, F_POISONED, F_NONE);
for (i = 0; i < nretflags; i++) { for (i = 0; i < nretflags; i++) {
enum BODYPART bpgone = BP_NONE; poisontype_t *pt;
if ((retflag[i]->id == F_NOBODYPART) && (retflag[i]->val[1] == B_FROMINJURY)) { pt = findpoisontype(retflag[i]->val[0]);
bpgone = retflag[i]->val[0]; if (pt->severity == PS_CURSE) {
} else if ((retflag[i]->id == F_INJURY) && (retflag[i]->lifetime == PERMENANT)) { // permenant injury } else {
bpgone = retflag[i]->val[1]; killflag(retflag[i]);
donesomething = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
if (bpgone != BP_NONE) { }
if (isplayer(target)) {
msg("Your %s grows back!", getbodypartname(target, bpgone)); if (!lfhasflagval(target, F_POISONED, P_ROT, NA, NA, NULL)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; // severed body parts
} else if (cansee(player, target)) { getflags(target->flags, retflag, &nretflags, F_INJURY, F_NOBODYPART, F_NONE);
char targname[BUFLEN]; for (i = 0; i < nretflags; i++) {
getlfname(target, targname); enum BODYPART bpgone = BP_NONE;
msg("%s%s %s grows back!", targname, getpossessive(targname), if ((retflag[i]->id == F_NOBODYPART) && (retflag[i]->val[1] == B_FROMINJURY)) {
getbodypartname(target, bpgone)); bpgone = retflag[i]->val[0];
if (seenbyplayer) *seenbyplayer = B_TRUE; } else if ((retflag[i]->id == F_INJURY) && (retflag[i]->lifetime == PERMENANT)) { // permenant injury
bpgone = retflag[i]->val[1];
}
if (bpgone != BP_NONE) {
if (isplayer(target)) {
msg("Your %s grows back!", getbodypartname(target, bpgone));
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, target)) {
char targname[BUFLEN];
getlfname(target, targname);
msg("%s%s %s grows back!", targname, getpossessive(targname),
getbodypartname(target, bpgone));
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
killflag(retflag[i]);
donesomething = B_TRUE;
} else if ((retflag[i]->id == F_INJURY) && (retflag[i]->lifetime > 0)) {
killflag(retflag[i]);
donesomething = B_TRUE;
} }
killflag(retflag[i]);
donesomething = B_TRUE;
} else if ((retflag[i]->id == F_INJURY) && (retflag[i]->lifetime > 0)) {
killflag(retflag[i]);
donesomething = B_TRUE;
} }
} }
} }
@ -6617,47 +6669,55 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
break; break;
} }
amt = getspellduration(min,max,blessed) + (power*2); amt = getspellduration(min,max,blessed) + (power*2);
if (lfhasflagval(target, F_POISONED, P_ROT, NA, NA, NULL)) { if (!undead && lfhasflagval(target, F_POISONED, P_ROT, NA, NA, NULL)) {
amt /= 10; amt /= 10;
} }
if (amt > 0) { if (amt > 0) {
gainhp(target, amt); if (undead) {
if (isplayer(target)) { losehp(target, amt, DT_HOLY, caster, "the power of healing");
if (target->hp >= target->maxhp) { if (isplayer(target) || cansee(player, target)) {
switch (spellid) { getlfname(target, buf);
case OT_S_HEALINGMIN: msg("%s writhe%s in agony!", buf, isplayer(target) ? "" : "s");
msg("All of your scrapes and bruises are healed!");
break;
case OT_S_HEALING:
default:
msg("Your wounds close themselves!");
break;
case OT_S_HEALINGMAJ:
msg("Your injuries are healed!");
break;
}
} else {
switch (spellid) {
case OT_S_HEALINGMIN:
msg("Some of your scrapes and bruises are healed!");
break;
case OT_S_HEALING:
default:
msg("Some of your wounds close themselves!");
break;
case OT_S_HEALINGMAJ:
msg("Your injuries are partially healed!");
break;
}
} }
if (seenbyplayer) *seenbyplayer = B_TRUE; } else {
} else if (haslos(player, target->cell)) { gainhp(target, amt);
getlfname(target, buf); if (isplayer(target)) {
msg("%s looks healthier!", buf); if (target->hp >= target->maxhp) {
if (seenbyplayer) *seenbyplayer = B_TRUE; switch (spellid) {
} case OT_S_HEALINGMIN:
msg("All of your scrapes and bruises are healed!");
break;
case OT_S_HEALING:
default:
msg("Your wounds close themselves!");
break;
case OT_S_HEALINGMAJ:
msg("Your injuries are healed!");
break;
}
} else {
switch (spellid) {
case OT_S_HEALINGMIN:
msg("Some of your scrapes and bruises are healed!");
break;
case OT_S_HEALING:
default:
msg("Some of your wounds close themselves!");
break;
case OT_S_HEALINGMAJ:
msg("Your injuries are partially healed!");
break;
}
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, target->cell)) {
getlfname(target, buf);
msg("%s looks healthier!", buf);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} // end if undead
donesomething = B_TRUE;
} }
donesomething = B_TRUE;
} }
} }
@ -6674,7 +6734,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
angergodmaybe(R_GODDEATH, 40, GA_HERESY); angergodmaybe(R_GODDEATH, 40, GA_HERESY);
} }
// hostile monsters might calm down // hostile monsters might calm down
if (!frompot && donesomething && isplayer(caster) && !isplayer(target) && (getallegiance(target) == AL_HOSTILE)) { if (!undead && !frompot && donesomething && isplayer(caster) && !isplayer(target) && (getallegiance(target) == AL_HOSTILE)) {
enum ATTRBRACKET iqb; enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(target, A_IQ), A_IQ, NULL); iqb = getattrbracket(getattr(target, A_IQ), A_IQ, NULL);
if ((iqb >= IQ_ANIMAL) && cansee(target, caster)) { if ((iqb >= IQ_ANIMAL) && cansee(target, caster)) {
@ -6967,6 +7027,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
if (hasobofmaterial(targcell->obpile, MT_FIRE)) {
fizzle(caster);
return B_TRUE;
}
getlfname(target, targname); getlfname(target, targname);
if (rolltohit(caster, target, NULL, NULL)) { if (rolltohit(caster, target, NULL, NULL)) {
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
@ -7226,6 +7291,75 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
} else if (spellid == OT_S_MIRRORIMAGE) {
int i,ndone = 0;
int seen = B_FALSE;
for (i = 0; i < power; i++) {
lifeform_t *lf;
job_t *j;
object_t *o;
// create a mirror image
targcell = real_getrandomadjcell(caster->cell, WE_WALKABLE, B_ALLOWEXPAND, LOF_NEED, NULL, caster);
if (!targcell) break;
lf = clonelf(caster, targcell);
if (!lf) break;
if (isplayer(caster) || cansee(player, lf)) {
seen = B_TRUE;
}
killflagsofid(lf->flags, F_CORPSETYPE);
killflagsofid(lf->flags, F_EXTRACORPSE);
addflag(lf->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL);
addflag(lf->flags, F_PHANTASM, caster->hp, NA, NA, NULL);
// copy caster's job
j = getjob(caster);
if (j) {
givejob(lf, j->id);
}
addflag(lf->flags, F_NOTIME, B_TRUE, NA, NA, NULL);
lf->created = B_FALSE; // to avoid "the xxx puts on armour" messages
// copy caster's weapons & armour
for (o = caster->pack->first ; o ; o = o->next) {
flag_t *equipflag;
equipflag = isequipped(o);
if (equipflag) {
object_t *newob;
newob = addobfast(lf->pack,o->type->id);
if (newob) {
if (isweapon(newob) && canweild(lf, newob)) {
weild(lf, newob);
} else if (canwear(lf, newob, equipflag->val[0])) {
wear(lf, newob);
}
}
}
}
killflagsofid(lf->flags, F_NOTIME);
lf->created = B_TRUE;
addflag(lf->flags, F_NODEATHSPEECH, B_TRUE, NA, NA, NULL);
petify(lf, caster);
setfollowdistance(lf, 1, 2); // stay close
addflag(lf->flags, F_SUMMONEDBY, caster->id, PERMENANT, NA, NULL);
ndone++;
}
if (!ndone) {
fizzle(caster);
return B_TRUE;
} else if (seen) {
char copytext[BUFLEN];
if (ndone == 1) {
sprintf(copytext, "A duplicate");
} else {
sprintf(copytext, "%d duplicates", ndone);
}
msg("%s of %s appear%s!", copytext, castername, (ndone == 1) ? "s" : "");
}
} else if (spellid == OT_S_NULLIFY) { } else if (spellid == OT_S_NULLIFY) {
flag_t *retflag[MAXCANDIDATES],*poss[MAXCANDIDATES],*f; flag_t *retflag[MAXCANDIDATES],*poss[MAXCANDIDATES],*f;
int nretflags,i,ndone = 0,nposs; int nretflags,i,ndone = 0,nposs;
@ -7313,7 +7447,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int seen; int seen;
if (targcell->obpile->first) { if (targcell->obpile->first) {
targob = doaskobject(targcell->obpile, "Target which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', NULL, AO_NONE, F_NONE); targob = doaskobject(targcell->obpile, "Target which object", NULL, B_TRUE, B_FALSE, B_FALSE, '\0', NULL, MT_NOTHING, AO_NONE, F_NONE);
} }
if (!targob) { if (!targob) {
@ -9161,6 +9295,110 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
} }
} else if (spellid == OT_S_RESSURECTION) {
lifeform_t *newlf;
if (!targob) {
// select object from cell...
targob = askobjectwithflag(targcell->obpile, "Revive which corpse", NULL, '\0', AO_NONE, F_CORPSEOF);
if (!targob) {
fizzle(caster);
return B_TRUE;
}
}
newlf = ressurect(targob);
if (newlf) {
if (haslos(player, targcell)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
fizzle(caster);
return B_TRUE;
}
} else if (spellid == OT_S_RESTORATION) {
int seen = B_FALSE;
int i,hpheal,mpheal;
int failed = B_TRUE;
char lfname[BUFLEN];
if (!target) target = caster;
getlfname(target, lfname);
if (frompot) {
if (blessed == B_BLESSED) {
power = 3;
} else if (blessed == B_CURSED) {
power = 1;
} else {
power = 2;
}
}
if (!isplayer(target) && cansee(player, target)) {
seen = B_TRUE;
}
if (isundead(target)) {
if (seen) {
msg("%s writhe%s in agony!", lfname, isplayer(target) ? "" : "s");
}
losehp(target, power*10, DT_HOLY, caster, "the power of restoration");
return B_FALSE;
}
for (i = 0; i < MAXATTS; i++ ){
if (getattr(target,i) < target->baseatt[i]) {
setattr(target, i, target->baseatt[i]);
failed = B_FALSE;
}
}
// fix diseases (even magical ones)
if (killflagsofid(target->flags, F_POISONED)) {
failed = B_FALSE;
}
// wake up from sleep/ko
if (killflagsofid(target->flags, F_ASLEEP)) {
failed = B_FALSE;
}
// fix pain
if (killflagsofid(target->flags, F_PAIN)) {
failed = B_FALSE;
}
// fix injuries
if (killflagsofid(target->flags, F_INJURY)) {
failed = B_FALSE;
}
// blessed restores hp/mp to full
if (power == 3) { // heal ALL hp & mp
hpheal = target->maxhp;
mpheal = getmaxmp(target);
} else if (power == 2) { // heal 3/4 hp & mp
hpheal = pctof(target->maxhp, 75);
mpheal = pctof(getmaxmp(target), 75);
} else { // heal half hp & mp
hpheal = target->maxhp / 2;
mpheal = getmaxmp(target) / 2;
}
if (target->hp < hpheal) {
gainhp(target, hpheal - target->hp);
failed = B_FALSE;
if (!isplayer(target) && cansee(player, target)) {
msg("%s%s health has been restored!", lfname, getpossessive(lfname));
}
}
if (target->mp < mpheal) {
gainmp(target, mpheal - target->mp);
failed = B_FALSE;
}
if (failed) {
if (isplayer(target)) msg("You feel momentarily restored.");
fizzle(caster);
return B_TRUE;
} else {
if (isplayer(target)) msg("You feel restored!");
}
} else if (spellid == OT_S_REVEALHIDDEN) { } else if (spellid == OT_S_REVEALHIDDEN) {
int i; int i;
int seen = B_FALSE; int seen = B_FALSE;
@ -11825,6 +12063,9 @@ char *getspelldesc(enum OBTYPE spellid, int power, char *buf) {
snprintf(buf, BUFLEN, "reduces hunger and speed"); snprintf(buf, BUFLEN, "reduces hunger and speed");
} }
break; break;
case OT_S_MIRRORIMAGE:
snprintf(buf, BUFLEN, "Create %d mirror images", power);
break;
case OT_S_PSYARMOUR: case OT_S_PSYARMOUR:
snprintf(buf, BUFLEN, "+%d Armour Rating", power*4); snprintf(buf, BUFLEN, "+%d Armour Rating", power*4);
break; break;

28
text.c
View File

@ -16,9 +16,11 @@
extern long curtime; extern long curtime;
extern lifeform_t *player; extern lifeform_t *player;
extern enum GAMEMODE gamemode; extern enum GAMEMODE gamemode;
extern enum WINGAMETYPE wintype;
int needan(char *text) { int needan(char *text) {
if (isvowel(tolower(text[0]))) { if (isvowel(tolower(text[0]))) {
@ -145,9 +147,11 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
strcpy(extradambuf, ""); strcpy(extradambuf, "");
if ((dam == 0) && (damtype != DT_TOUCH)) { if ((dam == 0) && (damtype != DT_TOUCH)) {
if (!victim || getlorelevel(lf, victim->race->raceclass->id)) { if (!victim || getlorelevel(lf, victim->race->raceclass->id)) {
//strcpy(extradambuf, " but do no damage"); if (!lfhasflag(lf, F_PHANTASM)) {
strcpy(extradambuf, " ineffectually"); //strcpy(extradambuf, " but do no damage");
knownnodam = B_TRUE; strcpy(extradambuf, " ineffectually");
knownnodam = B_TRUE;
}
} }
} else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) { } else if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
snprintf(extradambuf, BUFLEN, " [%d dmg]",dam); snprintf(extradambuf, BUFLEN, " [%d dmg]",dam);
@ -203,11 +207,11 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
} }
strcpy(attackverb, getattackverb(lf, wep, damtype,dam,maxhp)); strcpy(attackverb, getattackverb(lf, wep, damtype,dam,maxhp));
if ((dam == 0) && (damtype != DT_TOUCH)) {
strcpy(nodamstr, "");
if ((dam == 0) && (damtype != DT_TOUCH) && !lfhasflag(lf, F_PHANTASM)) {
nodam = B_TRUE; nodam = B_TRUE;
strcpy(nodamstr, " ineffectually"); strcpy(nodamstr, " ineffectually");
} else {
strcpy(nodamstr, "");
} }
if (victim && isplayer(victim) && !nodam) { if (victim && isplayer(victim) && !nodam) {
@ -1327,6 +1331,18 @@ void makegunaimstring(lifeform_t *lf, int lfid, char *retbuf) {
char *makekillertext(char *retbuf, char *killverb, char *lastdam, map_t *where, int wantextra, int wantlocation) { char *makekillertext(char *retbuf, char *killverb, char *lastdam, map_t *where, int wantextra, int wantlocation) {
char *p, *dummy; char *p, *dummy;
char regionbuf[BUFLEN]; char regionbuf[BUFLEN];
if (wintype) {
flag_t *winflag;
winflag = lfhasflag(player, F_WINNER);
if (winflag->val[0] == WT_GOD) {
sprintf(retbuf, "Crowned the God of %s.", winflag->text); // ie. "Became the God of Fire & Destruction"
} else if (winflag->val[0] == WT_DEMIGOD) {
sprintf(retbuf, "Ascended to Demigod-hood.");
}
return retbuf;
}
p = strtok_r(lastdam,"^", &dummy); p = strtok_r(lastdam,"^", &dummy);
if (p) { if (p) {
if (!strcmp(p, "you")) { if (!strcmp(p, "you")) {