- [+] allow user to DISABLE auto dodge fatal attacks ?. enable through

"reflexive dodging" ability
- [+] first rotation in a turn takes no time
- [+] exploit: if you walk diagonally next to a monster, it moves to
      your previous space!
    - [+] fix: aigetlastknownpos should  return the cell that trails
          point to, not the cell _with_ the trails.
- [+] only recognise weapon quality (masterwork etc) if you are skilled
      in that weapon or perception
- [+] cope with mosnter necromancers, etc
    - [+] parserace should look for necromancer etc.
    - [+] if so, set "wantsubjob" to SJ_NECROMANCER etc
    - [+] move specialty mage code into "givejobspecialty"
- [+] Make wizard's job name depend on primary spell school.
    - [+] "Demonologist", "Firemage", "Icemage", "Necromancer",
          "Skymage", "Wizard" (wild)
    - [+] instead of getjob() then j->name, use "getjobname(lf)"
    - [+] f_jobname
- [+] i should never "hear voices chanting" from an abandoned temple
- [+] for monsters, show "its bite inflicts poison" in io.c racial
      knowledge
- [+] casting healing on myself pleased Glorana twice!
    - [+] one from casting a life spell
    - [+] one from casting healing.
    - [+] move ones from spell.c to castspell()
    - [+] new flag: f_pleasesgod v0=godid, v1=howmuch
    - [+] add to other spell objects:
        - [+] f_pleasesgod
            - [+] GODFIRE - spelllevel * 2
            - [+] GODDEATH = spelllevel
            - [+] GODLIFE = spelllevel*2
            - [+] GODNATURE: spelllevle*2
    - [+] show this in describespell
- [+] for god healing effects, use gainhp() so that it says "Your HP is
      fully restored."
- [+] change F_RESISTMAG to be percentage rather than 1-20
- [+] make some gods' pleasure boost power of related spells
    - [+] 1 per each positive levle of getpietylev()
    - [+] glorana: life
    - [+] hecta: death
- [+] only apply auto shortcuts for players.
- [+] subjob_t
    - [+] addsubjob()
    - [+] killsubjob()
    - [+] show subjobs in job descriptions.
    - [+] data.c:  addsubjob(.... 
    - [+] in job defs:
        - [+] f_canhavesubjob sj_xxx
    - [+] use this to determine whether to ask about them
    - [+] redo getjobname 
    - [+] remove f_job->Text
- [+] speak with dead should only work on corpses of races which can
      talk.
- [+] warrior subclasses
    - [+] "Scourge"
        - [+] gains magic resistance as you level up
            - [+] == 5 + (level * 3) %
        - [+] nospells
        - [+] no mana
    - [+] paladin
        - [+] blessed gear
        - [+] can will turn undead
        - [+] healing magic
        - [+] god = glorana.
        - [+] cannot use spells if glorana is angry.
    - [+] battlemage
        - [+] starts with one spell school (fire/ice/air)
        - [+] canlearn fire/ice/air spell schools
        - [+] limited to adept in all schools
        - [+] slightly less hp
        - [+] no warrior abilities
This commit is contained in:
Rob Pearce 2012-02-24 06:45:23 +00:00
parent 67b00b1dc0
commit 4808d2c9df
19 changed files with 997 additions and 341 deletions

88
ai.c
View File

@ -266,8 +266,9 @@ int aigetchasetime(lifeform_t *lf) {
// this function assumes that you can't just SEE the target! // this function assumes that you can't just SEE the target!
cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *lasty, int *lastdir) { cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *lasty, int *lastdir) {
flag_t *f, *tflag, *bestflag = NULL; flag_t *f, *tflag, *bestflag = NULL;
cell_t *c = NULL; cell_t *c = NULL,*trailcell = NULL,*finalcell = NULL;
int besttime = -1; int besttime = -1;
int locallastdir = D_NONE;
int i; int i;
// defaults // defaults
@ -275,50 +276,67 @@ cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *l
if (lasty) *lasty = NA; if (lasty) *lasty = NA;
if (lastdir) *lastdir = D_NONE; if (lastdir) *lastdir = D_NONE;
// check scent/footprints first // do we remember the player's last known location ?
for (i = 0; i < lf->nlos; i++) {
if (hastrailof(lf->los[i]->obpile, target, NA, &tflag, lf)) {
if (tflag->lifetime > besttime) {
besttime = tflag->lifetime;
bestflag = tflag;
c = lf->los[i];
}
}
}
if (bestflag && c) {
if (lastx) *lastx = c->x;
if (lasty) *lasty = c->y;
if (lastdir) {
// can only obtain direction from footprints if your
// tracking skill is high enough.
if (bestflag->val[2] == S_SIGHT) {
if (getskill(lf, SK_PERCEPTION) >= PR_SKILLED) {
*lastdir = bestflag->val[1];
} else {
*lastdir = D_NONE;
}
} else {
*lastdir = bestflag->val[1];
}
}
return c;
}
f = ispetortarget(lf, target); f = ispetortarget(lf, target);
if (f) { if (f) {
c = getcellat(lf->cell->map, f->val[1], f->val[2]); c = getcellat(lf->cell->map, f->val[1], f->val[2]);
if (c) { if (c) {
if (lastx) *lastx = c->x; if (lastx) *lastx = c->x;
if (lasty) *lasty = c->y; if (lasty) *lasty = c->y;
if (lastdir && strlen(f->text)) { if (strlen(f->text)) {
*lastdir = atoi(f->text); locallastdir = atoi(f->text);
} }
} }
return c; trailcell = c;
} }
return NULL; // if not, check for the most recent scent/footprints first
if (!trailcell) {
c = NULL;
for (i = 0; i < lf->nlos; i++) {
if (hastrailof(lf->los[i]->obpile, target, NA, &tflag, lf)) {
if (tflag->lifetime > besttime) {
besttime = tflag->lifetime;
bestflag = tflag;
c = lf->los[i];
}
}
}
if (bestflag && c) {
if (lastx) *lastx = c->x;
if (lasty) *lasty = c->y;
// can only obtain direction from footprints if your
// tracking skill is high enough.
if (bestflag->val[2] == S_SIGHT) {
if (getskill(lf, SK_PERCEPTION) >= PR_SKILLED) {
locallastdir = bestflag->val[1];
} else {
locallastdir = D_NONE;
}
} else {
locallastdir = bestflag->val[1];
}
trailcell = c;
}
}
// if we found somewhere, follow any trails out of there
if (trailcell) {
if (locallastdir != D_NONE) {
// follow the trail
finalcell = getcellindir(trailcell, locallastdir);
locallastdir = D_NONE;
} else {
finalcell = trailcell;
}
}
// return last movement direction
if (lastdir) {
*lastdir = locallastdir;
}
return finalcell;
} }
object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK *ra, int *range) { object_t *aigetrangedattack(lifeform_t *lf, lifeform_t *target, enum RANGEATTACK *ra, int *range) {

76
data.c
View File

@ -16,6 +16,7 @@ extern race_t *firstrace, *lastrace;
extern raceclass_t *firstraceclass, *lastraceclass; extern raceclass_t *firstraceclass, *lastraceclass;
extern job_t *firstjob, *lastjob; extern job_t *firstjob, *lastjob;
extern poisontype_t *firstpoisontype,*lastpoisontype; extern poisontype_t *firstpoisontype,*lastpoisontype;
extern subjob_t *firstsubjob,*lastsubjob;
extern skill_t *firstskill, *lastskill; extern skill_t *firstskill, *lastskill;
extern objecttype_t *objecttype; extern objecttype_t *objecttype;
extern objectclass_t *objectclass,*lastobjectclass; extern objectclass_t *objectclass,*lastobjectclass;
@ -153,6 +154,17 @@ void initcommands(void) {
void initjobs(void) { void initjobs(void) {
int i; int i;
flag_t *f; flag_t *f;
// subjob definitions - keep these in alphabetical order
addsubjob(SJ_BATTLEMAGE, "Battlemage", "Unlike other warriors Battlemages are skilled in magic, but at the expense of the regular warrior abilities.", 'b');
addsubjob(SJ_FIREMAGE, "Firemage", "", 'f');
addsubjob(SJ_ICEMAGE, "Icemage", "", 'i');
addsubjob(SJ_NECROMANCER, "Necromancer", "", 'n');
addsubjob(SJ_PALADIN, "Paladin", "Paladins are holy warriors dedicated to the Goddess of Life. They have access to powerful healing magic, but this power is dependant upon their goddess' approval.", 'p');
addsubjob(SJ_SCOURGE, "Scourge", "Scourges have dedicated their life to ridding the world of magic. Strict training has granted them an innate immunity to magic, but this immunity also extends to beneficial effects.", 's');
addsubjob(SJ_AIRMAGE, "Skymage", "", 's');
addsubjob(SJ_WILDMAGE, "Wizard", "", 'w');
// job definitions // job definitions
// NOTE: try to always make the job's primary weapon be the first object defined. // NOTE: try to always make the job's primary weapon be the first object defined.
@ -807,6 +819,10 @@ void initjobs(void) {
addflag(lastjob->flags, F_LEVABIL, 8, OT_A_AIMEDSTRIKE, NA, NULL); addflag(lastjob->flags, F_LEVABIL, 8, OT_A_AIMEDSTRIKE, NA, NULL);
addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, NA, NULL); addflag(lastjob->flags, F_LEVABIL, 10, OT_A_HURRICANESTRIKE, NA, NULL);
addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL);
// sub jobs
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_BATTLEMAGE, NA, NA, NULL);
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_PALADIN, NA, NA, NULL);
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_SCOURGE, NA, NA, NULL);
addjob(J_WIZARD, "Wizard", "Specialising in Arcane lore, high level wizards use their magic to create awe-inspiring effects on the world around them, raining death upon their enemies with eldritch wizardries. Not much is known about low level wizards, as they tend to get mauled to death by newts due to their lack of combat skills."); addjob(J_WIZARD, "Wizard", "Specialising in Arcane lore, high level wizards use their magic to create awe-inspiring effects on the world around them, raining death upon their enemies with eldritch wizardries. Not much is known about low level wizards, as they tend to get mauled to death by newts due to their lack of combat skills.");
// stats // stats
@ -871,6 +887,12 @@ void initjobs(void) {
f = addflag(lastjob->flags, F_CANCAST, OT_S_HASTE, NA, NA, NULL); addcondition(f, FC_IFMONSTER, 20); f = addflag(lastjob->flags, F_CANCAST, OT_S_HASTE, NA, NA, NULL); addcondition(f, FC_IFMONSTER, 20);
f = addflag(lastjob->flags, F_CANCAST, OT_S_HEALING, NA, NA, NULL); addcondition(f, FC_IFMONSTER, 20); f = addflag(lastjob->flags, F_CANCAST, OT_S_HEALING, NA, NA, NULL); addcondition(f, FC_IFMONSTER, 20);
addflag(lastjob->flags, F_CASTCHANCE, 30, NA, NA, NULL); addflag(lastjob->flags, F_CASTCHANCE, 30, NA, NA, NULL);
// sub jobs
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_AIRMAGE, NA, NA, NULL);
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_FIREMAGE, NA, NA, NULL);
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_ICEMAGE, NA, NA, NULL);
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_NECROMANCER, NA, NA, NULL);
addflag(lastjob->flags, F_CANHAVESUBJOB, SJ_WILDMAGE, NA, NA, NULL);
// non-player jobs // non-player jobs
addjob(J_GUARD, "Guard", "Guards are paid mercenaries employed to protect a certain area. Accordingly, they are generally outfitetd with high quality armour."); addjob(J_GUARD, "Guard", "Guards are paid mercenaries employed to protect a certain area. Accordingly, they are generally outfitetd with high quality armour.");
@ -898,6 +920,7 @@ void initobjects(void) {
flag_t *f; flag_t *f;
int i,n; int i,n;
// init poison types // init poison types
addpoisontype(P_COLD, "hypothermia", "Sick", "^bYOU cough#S violently.", OT_NONE, 1, 25, PS_DISEASE); addpoisontype(P_COLD, "hypothermia", "Sick", "^bYOU cough#S violently.", OT_NONE, 1, 25, PS_DISEASE);
addpoisontype(P_FOOD, "gastroenteritis", "Poisoned", "^bYOU vomit#S violently.", OT_VOMITPOOL, 1, 25, PS_POISON); addpoisontype(P_FOOD, "gastroenteritis", "Poisoned", "^bYOU vomit#S violently.", OT_VOMITPOOL, 1, 25, PS_POISON);
@ -2686,6 +2709,7 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 1, NA, NULL);
// l2 // l2
addot(OT_S_BLINDNESS, "blindness", "Temporarily blinds the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_BLINDNESS, "blindness", "Temporarily blinds the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration.");
@ -2712,6 +2736,7 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 2, NA, NULL);
addot(OT_S_SMITEGOOD, "smite good", "Instantly deals 1-^bpower*2^n damage to good creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_SMITEGOOD, "smite good", "Instantly deals 1-^bpower*2^n damage to good creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
@ -2719,6 +2744,7 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 2, NA, NULL);
// l3 // l3
addot(OT_S_POISONBOLT, "venom bolt", "Fires a glob of venom at the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_POISONBOLT, "venom bolt", "Fires a glob of venom at the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how difficult the venom is to dodge, and how powerful the poison is."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how difficult the venom is to dodge, and how powerful the poison is.");
@ -2728,6 +2754,7 @@ 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_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 3, NA, NULL);
addot(OT_S_DRAINLIFE, "necrobeam", "Draws life force from the victim in order to heal the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_DRAINLIFE, "necrobeam", "Draws life force from the victim in order to heal the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The amount of life force drained is ^b1d6+power^n."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The amount of life force drained is ^b1d6+power^n.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -2735,6 +2762,7 @@ 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_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 3, NA, NULL);
addot(OT_S_FLAYFLESH, "flay flesh", "Causes invisible tendrils to strike your foe, causing an automatic slash critical on fleshy creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_FLAYFLESH, "flay flesh", "Causes invisible tendrils to strike your foe, causing an automatic slash critical on fleshy creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
@ -2743,6 +2771,7 @@ void initobjects(void) {
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 3, NA, NULL);
addot(OT_S_PAIN, "pain", "Causes extreme pain in the target whenever they move.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PAIN, "pain", "Causes extreme pain in the target whenever they move.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the duration of the pain effect."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the duration of the pain effect.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
@ -2751,6 +2780,7 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 3, NA, NULL);
// l4 // l4
addot(OT_S_CURSE, "curse", "Bestow a curse upon the target's equipment, applying a -1 penalty and making them impossible to remove.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CURSE, "curse", "Bestow a curse upon the target's equipment, applying a -1 penalty and making them impossible to remove.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many objects will be cursed."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many objects will be cursed.");
@ -2774,6 +2804,7 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 4, NA, NULL);
addot(OT_S_PARALYZE, "paralyze", "Disables the target's muscles, leaving them unable to move for ^bpower*2^n turns.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PARALYZE, "paralyze", "Disables the target's muscles, leaving them unable to move for ^bpower*2^n turns.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -2781,6 +2812,7 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 4, NA, NULL);
addot(OT_S_FEEBLEMIND, "brain freeze", "Temporarily lowers the target's intelligence to that of an animal.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_FEEBLEMIND, "brain freeze", "Temporarily lowers the target's intelligence to that of an animal.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines duration."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines duration.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
@ -2790,12 +2822,14 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 4, NA, NULL);
addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the chances of the zombies being friendly."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the chances of the zombies being friendly.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
// TODO: should be "castnearob ot_corpse" // TODO: should be "castnearob ot_corpse"
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 4, NA, NULL);
// l5 // l5
addot(OT_S_HECTASSERVANT, "hecta's hand", "Summons an enormous skeletal hand to drag foes to their doom. BEWARE: the hand will attack anything living, including the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_HECTASSERVANT, "hecta's hand", "Summons an enormous skeletal hand to drag foes to their doom. BEWARE: the hand will attack anything living, including the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -2808,12 +2842,14 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 6, 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_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);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 6, NA, NULL);
addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all nearby life, including the caster!", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all nearby life, including the caster!", 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_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_CASTINGTIME, 2, NA, NA, NULL); addflag(lastot->flags, F_CASTINGTIME, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODDEATH, 6, NA, NULL);
/////////////////// ///////////////////
// divination // divination
/////////////////// ///////////////////
@ -2999,6 +3035,7 @@ 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_MAXPOWER, 3, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 3, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 1, NA, NULL);
addot(OT_S_SPARK, "flambe", "Creates very hot but short lived burst of flame around the target, dealing 2d2 fire damage to creatures and objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_SPARK, "flambe", "Creates very hot but short lived burst of flame around the target, dealing 2d2 fire damage to creatures and objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
@ -3007,11 +3044,13 @@ 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_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 1, NA, NULL);
addot(OT_S_PYROMANIA, "pyromania", "Increases the potency of all fire within the caster's line of sight.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PYROMANIA, "pyromania", "Increases the potency of all fire within the caster's line of sight.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 1, NA, NULL);
// l2 // l2
addot(OT_S_BLADEBURN, "bladeburn", "Ignites the caster's weapon, causing it to temporarily deal fire damage. The spell's power determines how long it will last.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_BLADEBURN, "bladeburn", "Ignites the caster's weapon, causing it to temporarily deal fire damage. The spell's power determines how long it will last.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its duration."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines its duration.");
@ -3020,6 +3059,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, 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_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 2, NA, NULL);
addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire, dealing 1d6+^bpower^n fire damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire, dealing 1d6+^bpower^n fire damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
@ -3027,6 +3067,7 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, 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_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 2, NA, NULL);
addot(OT_S_IMMOLATE, "immolate", "If the caster can successfully touch the target, they are instantly engulfed in flames.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_IMMOLATE, "immolate", "If the caster can successfully touch the target, they are instantly engulfed in flames.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
@ -3035,18 +3076,21 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, 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_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 2, NA, NULL);
addot(OT_S_SUPERHEAT, "superheat", "Excites the liquid molecules in a single potion, causing its contents to explode upon impact (8d2 damage).", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_SUPERHEAT, "superheat", "Excites the liquid molecules in a single potion, causing its contents to explode upon impact (8d2 damage).", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 2, NA, NULL);
// l3 // l3
addot(OT_S_FLAMEBURST, "flame burst", "Creates a radial blast of fire out from the caster, inflicting 2d6 fire damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_FLAMEBURST, "flame burst", "Creates a radial blast of fire out from the caster, inflicting 2d6 fire damage to all within.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The size of the radial blast is based on the spell's power."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The size of the radial blast is based on the spell's power.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 3, NA, NULL);
addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire, dealing up to ^bpower^nd3 damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire, dealing up to ^bpower^nd3 damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The damage is lower for enemies further away from the ball's centre."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The damage is lower for enemies further away from the ball's centre.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level 5, the size of the fireball is slightly increased."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level 5, the size of the fireball is slightly increased.");
@ -3056,6 +3100,7 @@ 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); // TODO: should be "near victim" addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // TODO: should be "near victim"
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 3, NA, NULL);
// l4 // l4
addot(OT_S_FLAMEPILLAR, "flame pillar", "Creates a tall pillar of flame.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_FLAMEPILLAR, "flame pillar", "Creates a tall pillar of flame.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the spell's range, and the fire's size."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines the spell's range, and the fire's size.");
@ -3066,6 +3111,7 @@ 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_WALLSTOP, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 4, NA, NULL);
// l5 // l5
addot(OT_S_BURNINGWAVE, "burning wave", "Fire bursts from the ground in a line towards the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_BURNINGWAVE, "burning wave", "Fire bursts from the ground in a line towards the target.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's range is based on its power."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's range is based on its power.");
@ -3076,6 +3122,7 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 5, NA, NULL);
// l6 // l6
addot(OT_S_METEOR, "meteor", "Launches a white-hot meteorite towards the target location, dealing up to ^bpower^nd6+30 damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_METEOR, "meteor", "Launches a white-hot meteorite towards the target location, dealing up to ^bpower^nd6+30 damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The damage is lower for enemies further away from the ball's centre."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The damage is lower for enemies further away from the ball's centre.");
@ -3084,6 +3131,7 @@ 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); // TODO: should be "near victim" addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // TODO: should be "near victim"
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODFIRE, 6, NA, NULL);
/////////////////// ///////////////////
// elemental - cold // elemental - cold
/////////////////// ///////////////////
@ -3190,6 +3238,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODNATURE, 5, NA, NULL);
addot(OT_S_SHARDSHOT, "shard shot", "Fires a scattered burst of small, fast moving ice shards. The shot will pass through multiple creatures, but damage is reduced with range.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_SHARDSHOT, "shard shot", "Fires a scattered burst of small, fast moving ice shards. The shot will pass through multiple creatures, but damage is reduced with range.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's range is determined by its power."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's range is determined by its power.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
@ -3219,6 +3268,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
// god pleasing for this spell is in spell.c
addot(OT_S_DETECTPOISON, "detect poison", "Detects any poisoned object in sight of the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_DETECTPOISON, "detect poison", "Detects any poisoned object in sight of the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
@ -3232,6 +3282,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODNATURE, 1, NA, NULL);
addot(OT_S_STICKTOSNAKE, "sticks to snakes", "Transforms all rod-shaped objects in sight into allied snakes.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_STICKTOSNAKE, "sticks to snakes", "Transforms all rod-shaped objects in sight into allied snakes.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell does not affect the caster's weapon."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell does not affect the caster's weapon.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
@ -3259,6 +3310,8 @@ 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_ALLY, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 3, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODNATURE, 2, NA, NULL);
addot(OT_S_REPELINSECTS, "repel insects", "Surrounds the caster with an insect-repelling smell.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_REPELINSECTS, "repel insects", "Surrounds the caster with an insect-repelling smell.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
@ -3427,6 +3480,7 @@ 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_CASTINGTIME, 2, NA, NA, NULL); addflag(lastot->flags, F_CASTINGTIME, 2, 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_PLEASESGOD, R_GODNATURE, 5, NA, NULL);
/////////////////// ///////////////////
// gravity // gravity
/////////////////// ///////////////////
@ -3511,9 +3565,11 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 1, NA, NULL);
addot(OT_S_TURNUNDEAD, "turn undead", "Instills fear in undead creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_TURNUNDEAD, "turn undead", "Instills fear in undead creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 1, NA, NULL);
// l2 // l2
addot(OT_S_SPEAKDEAD, "speak with dead", "Temporarily allow a corpse to answer questions about its former life.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_SPEAKDEAD, "speak with dead", "Temporarily allow a corpse to answer questions about its former life.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
@ -3527,6 +3583,7 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 2, NA, NULL);
// l3 // l3
addot(OT_S_HEALING, "healing", "Restores 10-20 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_HEALING, "healing", "Restores 10-20 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell heals an extra 2 damage per power level."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell heals an extra 2 damage per power level.");
@ -3536,6 +3593,7 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 3, NA, NULL);
addot(OT_S_HOLYAURA, "holy aura", "Surrounds the target with a holy aura, causing their weapon to deal holy damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_HOLYAURA, "holy aura", "Surrounds the target with a holy aura, causing their weapon to deal holy damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
@ -3543,6 +3601,7 @@ 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_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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 3, NA, NULL);
// l4 // l4
addot(OT_S_PROTEVIL, "protection from evil", "Repels the next 5+(^bpower^n*2) attacks from Evil-aligned creatures. ", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PROTEVIL, "protection from evil", "Repels the next 5+(^bpower^n*2) attacks from Evil-aligned creatures. ", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
@ -3565,6 +3624,7 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 4, NA, NULL);
addot(OT_S_CUREPOISON, "cure poison", "Cures the target of all poisons.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CUREPOISON, "cure poison", "Cures the target of all poisons.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
@ -3572,6 +3632,7 @@ 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 4, NA, NULL);
// l5 // 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); 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_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
@ -3579,6 +3640,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 5, 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_TARGETTEDSPELL, TT_ALLY, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODLIFE, 5, NA, NULL);
// l6 // l6
addot(OT_S_RESSURECTION, "ressurection", "Restore one adjacent corpse to life.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); 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_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
@ -3709,6 +3771,7 @@ 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_TARGETTEDSPELL, TT_DOOR|TT_IMPASSABLE, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_DOOR|TT_IMPASSABLE, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODTHIEVES, 5, NA, NULL);
addot(OT_S_LIGHT, "light area", "Creates a temporary light source centred on the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_LIGHT, "light area", "Creates a temporary light source centred on the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power III, you can control where the light appears."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power III, you can control where the light appears.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V, the light will blind creatures with night vision."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V, the light will blind creatures with night vision.");
@ -3780,6 +3843,7 @@ 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_SPELLLEVEL, 3, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 3, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODNATURE, 25, NA, NULL);
// l4 // l4
addot(OT_S_EXCAVATE, "excavate", "Creates a large open area surrounding the caster. No effect on living creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_EXCAVATE, "excavate", "Creates a large open area surrounding the caster. No effect on living creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
@ -3853,6 +3917,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_NONE, NA, NA, NULL); addflag(lastot->flags, F_TARGETTEDSPELL, TT_NONE, 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODNATURE, 5, NA, NULL);
// l3 // l3
addot(OT_S_CREATEMONSTER, "create monster", "Summons a (probably hostile) monster to a nearby location.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CREATEMONSTER, "create monster", "Summons a (probably hostile) monster to a nearby location.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V you can control where the monster appears."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At Power V you can control where the monster appears.");
@ -4038,9 +4103,11 @@ void initobjects(void) {
addot(OT_S_WISH, "wish", "Grants the caster any item of their choice. Beware - casting this powerful spell will reduce the caster's hit points by 50%.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_WISH, "wish", "Grants the caster any item of their choice. Beware - casting this powerful spell will reduce the caster's hit points by 50%.", 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);
addflag(lastot->flags, F_PLEASESGOD, R_GODNATURE, 10, NA, NULL);
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);
addflag(lastot->flags, F_PLEASESGOD, R_GODNATURE, 5, NA, NULL);
// l6 // l6
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);
@ -4147,6 +4214,8 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_PRAY, "pray", "Ask for help from a higher being.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_PRAY, "pray", "Ask for help from a higher being.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_REFLEXDODGE, "reflexive dodging", "Automatically use all remaining stamina to dodge fatal attacks.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_RAGE, "rage", "Enter a state of berzerker rage, gaining attack and defence bonuses.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addot(OT_A_RAGE, "rage", "Enter a state of berzerker rage, gaining attack and defence bonuses.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL);
@ -7998,7 +8067,7 @@ void initrace(void) {
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing dragons"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing dragons");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "cooking"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "cooking");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "creating objects"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "creating objects");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting nature spells"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting certain nature spells");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "damaging or destroying objects"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "damaging or destroying objects");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking plants"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "attacking plants");
@ -8086,7 +8155,7 @@ void initrace(void) {
} }
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, "destroying the undead"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "destroying the undead");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting holy spells"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "casting certain holy spells");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "natural healing");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the destruction of healing potions"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the destruction of healing potions");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "the use of poison");
@ -8181,7 +8250,7 @@ void initrace(void) {
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "starting fires"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "starting fires");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "burning objects"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "burning objects");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing with fire"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "killing with fire");
addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "using fire-based magic"); addflag(lastrace->flags, F_GODLIKES, NA, NA, NA, "using destructive fire-based magic");
addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "creating objects"); addflag(lastrace->flags, F_GODDISLIKES, NA, NA, NA, "creating objects");
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");
@ -12813,6 +12882,7 @@ void initskills(void) {
addskilldesc(SK_PERCEPTION, PR_NOVICE, "^gYou can now check for trails on staircases before descending.^n", B_TRUE); addskilldesc(SK_PERCEPTION, PR_NOVICE, "^gYou can now check for trails on staircases before descending.^n", B_TRUE);
addskilldesc(SK_PERCEPTION, PR_BEGINNER, "^gYou can now determine the depth and direction of footprints.^n", B_TRUE); addskilldesc(SK_PERCEPTION, PR_BEGINNER, "^gYou can now determine the depth and direction of footprints.^n", B_TRUE);
addskilldesc(SK_PERCEPTION, PR_BEGINNER, "^gYou now have perception of your blind spots.^n", B_TRUE); addskilldesc(SK_PERCEPTION, PR_BEGINNER, "^gYou now have perception of your blind spots.^n", B_TRUE);
addskilldesc(SK_PERCEPTION, PR_BEGINNER, "^gYou can now recognise the quality of items.^n", B_TRUE);
addskilldesc(SK_PERCEPTION, PR_ADEPT, "^gYour field of vision is now wider.^n", B_TRUE); addskilldesc(SK_PERCEPTION, PR_ADEPT, "^gYour field of vision is now wider.^n", B_TRUE);
addskilldesc(SK_PERCEPTION, PR_EXPERT, "^gYou can now move without leaving footprints.^n", B_TRUE); addskilldesc(SK_PERCEPTION, PR_EXPERT, "^gYou can now move without leaving footprints.^n", B_TRUE);
addskilldesc(SK_PERCEPTION, PR_MASTER, "^gYou field of vision now extends behind you.^n", B_TRUE); addskilldesc(SK_PERCEPTION, PR_MASTER, "^gYou field of vision now extends behind you.^n", B_TRUE);

Binary file not shown.

38
defs.h
View File

@ -1122,6 +1122,21 @@ enum JOB {
}; };
#define J_RANDOM J_NONE #define J_RANDOM J_NONE
enum SUBJOB {
SJ_NONE,
// mage
SJ_AIRMAGE,
SJ_ICEMAGE,
SJ_FIREMAGE,
SJ_NECROMANCER,
SJ_WILDMAGE,
// warrior
SJ_BATTLEMAGE,
SJ_PALADIN,
SJ_SCOURGE,
};
enum MATSTATE { enum MATSTATE {
MS_SOLID, MS_SOLID,
MS_LIQUID, MS_LIQUID,
@ -1599,6 +1614,7 @@ enum OBTYPE {
OT_A_CRUSH, OT_A_CRUSH,
OT_A_JUMP, OT_A_JUMP,
OT_A_PRAY, OT_A_PRAY,
OT_A_REFLEXDODGE,
OT_A_RAGE, OT_A_RAGE,
OT_A_REPAIR, OT_A_REPAIR,
OT_A_RESIZE, OT_A_RESIZE,
@ -2539,6 +2555,7 @@ enum FLAG {
// magic // magic
F_SPELLSCHOOL, // val0 = SPELLSCHOOL enum F_SPELLSCHOOL, // val0 = SPELLSCHOOL enum
F_SPELLLEVEL, // val0 = difficulty level of spell F_SPELLLEVEL, // val0 = difficulty level of spell
F_PLEASESGOD, // god id val0 likes this spell. pietymod=v1
F_VARPOWER, // can cast this spell at variable power level F_VARPOWER, // can cast this spell at variable power level
// for spells with this flag, the MP cost goes up // for spells with this flag, the MP cost goes up
// based on the power level. // based on the power level.
@ -2713,7 +2730,7 @@ enum FLAG {
// to take stuff out or put it in. // to take stuff out or put it in.
F_HOLDING, // this container is a xxx of holding and makes objects F_HOLDING, // this container is a xxx of holding and makes objects
// inside become weightless // inside become weightless
F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid F_STARTJOB, // val0 = %chance of starting with it, v1 = jobid, v2=subjobid
F_STARTSKILL, // val0 = skill id F_STARTSKILL, // val0 = skill id
F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS) F_STARTATT, // val0 = A_xxx, val0 = start bracket (ie. IQ_GENIUS)
// if text is set, it overrides val0. // if text is set, it overrides val0.
@ -2903,7 +2920,8 @@ enum FLAG {
F_HITDICE, // text = xdy+z to roll for maxhp per level. F_HITDICE, // text = xdy+z to roll for maxhp per level.
F_MAXHPMOD, // maxhp = pctof(v0, maxhp) F_MAXHPMOD, // maxhp = pctof(v0, maxhp)
F_MPDICE, // val0: # d4 to roll for maxmp per level. val1: +xx F_MPDICE, // val0: # d4 to roll for maxmp per level. val1: +xx
F_JOB, // val0 = player's class/job F_JOB, // val0 = player's job
// val1 = player's subjob or NA
F_GODOF, // text = what this lf is the god of. use capitals. F_GODOF, // text = what this lf is the god of. use capitals.
// if v0 is b_true, means this is a goddess // if v0 is b_true, means this is a goddess
F_GODLIKES, // text = something this god likes (ie. incs piety) F_GODLIKES, // text = something this god likes (ie. incs piety)
@ -3101,7 +3119,7 @@ enum FLAG {
F_OMNIPOTENT, // knows extra info F_OMNIPOTENT, // knows extra info
F_PHOTOMEM, // you don't forget your surroundings F_PHOTOMEM, // you don't forget your surroundings
F_REGENERATES, // regenerate HP at val0 per turn F_REGENERATES, // regenerate HP at val0 per turn
F_RESISTMAG, // immunity to magic effects. v0=amt (1-20) F_RESISTMAG, // immunity to magic effects. v0= resist%
F_MPREGEN, // regenerate MP at val0 per turn F_MPREGEN, // regenerate MP at val0 per turn
F_RAGE, // you are enraged. v0/v1 will be set to player's old hp/maxhp F_RAGE, // you are enraged. v0/v1 will be set to player's old hp/maxhp
F_REFLECTION, // missiles are reflected back at thrower F_REFLECTION, // missiles are reflected back at thrower
@ -3187,6 +3205,7 @@ enum FLAG {
F_SELECTWEAPON, // this job gets to pick their starting weapon F_SELECTWEAPON, // this job gets to pick their starting weapon
F_NOPLAYER, // players can't pick this job F_NOPLAYER, // players can't pick this job
F_HASPET, // this job starts with a pet of race f->text F_HASPET, // this job starts with a pet of race f->text
F_CANHAVESUBJOB, // this job can have subjob = v0
//F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0. //F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0.
//F_ELSE, //F_ELSE,
//F_IFPLAYER, //F_IFPLAYER,
@ -3394,6 +3413,7 @@ enum ERROR {
E_GRAVBOOSTED, E_GRAVBOOSTED,
E_NOMP, E_NOMP,
E_NOSTAM, E_NOSTAM,
E_NOSPELLS,
E_AVOIDOB, E_AVOIDOB,
E_FROZEN, E_FROZEN,
E_TOOBIG, E_TOOBIG,
@ -3635,6 +3655,14 @@ typedef struct poisontype_s {
struct poisontype_s *next, *prev; struct poisontype_s *next, *prev;
} poisontype_t; } poisontype_t;
typedef struct subjob_s {
enum SUBJOB id;
char *name;
char *desc;
char letter;
struct subjob_s *next, *prev;
} subjob_t;
typedef struct room_s { typedef struct room_s {
int id; int id;
int x1,y1,x2,y2; int x1,y1,x2,y2;
@ -3893,6 +3921,10 @@ typedef struct lifeform_s {
float stamlastturn; // for stam bar. not saved. float stamlastturn; // for stam bar. not saved.
int bartimer; // not saved. int bartimer; // not saved.
// tracks whether this lf has rotated or not this turn.
// the first rotation in a turn is free, others cost time.
int rotated;
// set to TRUE after lf has being created // set to TRUE after lf has being created
int born; int born;

2
god.c
View File

@ -2027,7 +2027,7 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
if (lf->hp < lf->maxhp) { if (lf->hp < lf->maxhp) {
lf->hp = lf->maxhp; gainhp(lf, lf->maxhp);
donesomething = B_TRUE; donesomething = B_TRUE;
statdirty = B_TRUE; statdirty = B_TRUE;

200
io.c
View File

@ -670,12 +670,10 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
strcpy(extrainfo, ""); strcpy(extrainfo, "");
getlfnamea(c->lf, buf); getlfnamea(c->lf, buf);
if (lfhasflag(c->lf, F_NAME)) { if (lfhasflag(c->lf, F_NAME)) {
job_t *j;
// add on their job // add on their job
j = getjob(c->lf); if (getjob(c->lf)) {
if (j) {
strcat(buf, " the "); strcat(buf, " the ");
strcat(buf, j->name); strcat(buf, getjobname(c->lf));
} }
} else if (c->lf->race->raceclass->id == RC_GOD) { } else if (c->lf->race->raceclass->id == RC_GOD) {
f = lfhasflag(c->lf, F_GODOF); f = lfhasflag(c->lf, F_GODOF);
@ -1433,6 +1431,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
} }
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_DODGES:
if (isplayer(lf)) {
msg("You now automatically dodge fatal attacks.");
}
donesomething = B_TRUE;
break;
case F_DTIMMUNE: case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("^gYou feel immune to %s!", getdamnamenoun(f->val[0])); msg("^gYou feel immune to %s!", getdamnamenoun(f->val[0]));
@ -1481,12 +1485,6 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
case F_DODGES:
if (isplayer(lf)) { // don't know if monsters get it
msg("You can now dodge attacks.");
donesomething = B_TRUE;
}
break;
case F_HEAVENARM: case F_HEAVENARM:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("You are surrounded by a shell of divine armour!"); msg("You are surrounded by a shell of divine armour!");
@ -2107,6 +2105,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
} }
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_DODGES:
if (isplayer(lf)) {
msg("You will no longer automatically dodge fatal attacks.");
}
donesomething = B_TRUE;
break;
case F_DTIMMUNE: case F_DTIMMUNE:
if (isplayer(lf)) { // don't know if monsters lose it if (isplayer(lf)) { // don't know if monsters lose it
msg("You are no longer immune to %s.", getdamnamenoun(f->val[0])); msg("You are no longer immune to %s.", getdamnamenoun(f->val[0]));
@ -2199,12 +2203,6 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("%s %s less sick now.", lfname, isplayer(lf) ? "feel" : "looks"); msg("%s %s less sick now.", lfname, isplayer(lf) ? "feel" : "looks");
donesomething = B_TRUE; donesomething = B_TRUE;
break; break;
case F_DODGES:
if (isplayer(lf)) { // don't know if monsters lose it
msg("You can no longer dodge attacks.");
donesomething = B_TRUE;
}
break;
case F_HEAVENARM: case F_HEAVENARM:
if (isplayer(lf)) { // don't know if monsters get it if (isplayer(lf)) { // don't know if monsters get it
msg("Your shell of divine armour vanishes!"); msg("Your shell of divine armour vanishes!");
@ -5144,6 +5142,38 @@ char *makedesc_god(lifeform_t *god, char *retbuf) {
return retbuf; return retbuf;
} }
char *makedesc_job(job_t *j, char *retbuf) {
char thisline[BUFLEN];
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
// start with job description
strcpy(retbuf, j->desc);
strcat(retbuf, "\n\n");
getflags(j->flags, retflag, &nretflags, F_CANHAVESUBJOB, F_NONE);
if (nretflags > 0) {
int first = B_TRUE;
for (i = 0; i < nretflags; i++) {
subjob_t *sj;
sj = findsubjob(retflag[i]->val[0]);
if (sj) {
if (first) {
sprintf(thisline, "%ss can have the following specialisations:\n",j->name);
strncat(retbuf, thisline, HUGEBUFLEN);
first = B_FALSE;
}
sprintf(thisline, "- %s\n",sj->name);
strncat(retbuf, thisline, HUGEBUFLEN);
}
}
}
return retbuf;
}
char *makedesc_ob(object_t *o, char *retbuf) { char *makedesc_ob(object_t *o, char *retbuf) {
char buf[BIGBUFLEN]; char buf[BIGBUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
@ -6109,6 +6139,10 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf2, "%s will detect nearby metal.\n", buf); sprintf(buf2, "%s will detect nearby metal.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
break; break;
case F_DODGES:
sprintf(buf2, "%s lets you use remaining stamina to dodge fatal attacks.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_ENHANCESEARCH: case F_ENHANCESEARCH:
sprintf(buf2, "%s enhances your searching ability.\n", buf); sprintf(buf2, "%s enhances your searching ability.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
@ -6189,10 +6223,6 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf2, "%s causes your feet to constantly burn.\n", buf); sprintf(buf2, "%s causes your feet to constantly burn.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
break; break;
case F_DODGES:
sprintf(buf2, "%s allows you to dodge attacks.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN);
break;
case F_INVISIBLE: case F_INVISIBLE:
sprintf(buf2, "%s renders you invisible to normal sight.\n", buf); sprintf(buf2, "%s renders you invisible to normal sight.\n", buf);
strncat(retbuf, buf2, HUGEBUFLEN); strncat(retbuf, buf2, HUGEBUFLEN);
@ -6650,7 +6680,7 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
strcat(buf, ")"); strcat(buf, ")");
} }
break; break;
case F_DODGES: strcpy(buf, "Can dodge attacks into adjacent locations"); break; case F_DODGES: strcpy(buf, "Can dodge fatal attacks into adjacent locations"); break;
case F_DTIMMUNE: case F_DTIMMUNE:
if (!hasflag(doneflags, F_DTIMMUNE)) { if (!hasflag(doneflags, F_DTIMMUNE)) {
if (f->val[0] == DT_ALL) { if (f->val[0] == DT_ALL) {
@ -6702,6 +6732,13 @@ char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel
case F_ENHANCESMELL: sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break; case F_ENHANCESMELL: sprintf(buf, "Enhanced sense of smell (range %d)", f->val[0]); break;
case F_FLYING: sprintf(buf, "Can fly at will"); break; case F_FLYING: sprintf(buf, "Can fly at will"); break;
case F_HEAVYBLOW: sprintf(buf, "Attacks will knock enemies backwards"); break; case F_HEAVYBLOW: sprintf(buf, "Attacks will knock enemies backwards"); break;
case F_HITCONFER:
if (f->val[0] == F_POISONED) {
poisontype_t *pt;
pt = findpoisontype(f->val[1]);
sprintf(buf, "Attacks inflict %s.", pt->name);
}
break;
case F_HUMANOID: if (!forplayersel) sprintf(buf, "Can use weapons and armour."); break; case F_HUMANOID: if (!forplayersel) sprintf(buf, "Can use weapons and armour."); break;
case F_LEVITATING: sprintf(buf, "Can levitate at will"); break; case F_LEVITATING: sprintf(buf, "Can levitate at will"); break;
case F_MEDITATES: sprintf(buf, "Meditates to retain awareness while sleeping."); break; case F_MEDITATES: sprintf(buf, "Meditates to retain awareness while sleeping."); break;
@ -7000,11 +7037,26 @@ char *makedesc_spell(objecttype_t *ot, char *retbuf) {
strncat(retbuf, buf, HUGEBUFLEN); strncat(retbuf, buf, HUGEBUFLEN);
strncat(retbuf, "\n", HUGEBUFLEN); strncat(retbuf, "\n", HUGEBUFLEN);
getflags(ot->flags, retflag, &nretflags, F_PLEASESGOD, F_NONE);
for (i = 0; i < nretflags; i++) {
lifeform_t *god;
flag_t *f;
god = findgod(retflag[i]->val[0]);
f = lfhasflag(god, F_GODOF);
sprintf(buf, "Successfully casting this spell will please %s (%s of %s).\n",god->race->name,
(f->val[0] == B_FEMALE) ? "Goddess" : "God", f->text);
strncat(retbuf, buf, BUFLEN);
}
if (nretflags) {
strncat(retbuf, "\n", HUGEBUFLEN);
}
if (ot->obclass->id == OC_SPELL) { if (ot->obclass->id == OC_SPELL) {
if (power > 0) { if (power > 0) {
sprintf(buf, "^gYou can cast it at power level %d (maximum %d).\n",power, getspellmaxpower(ot->id)); sprintf(buf, "^gYou can cast it at power level %d (maximum %d).^n\n",power, getspellmaxpower(ot->id));
} else { } else {
sprintf(buf, "^BIt is too powerful for you to cast (maximum power %d).\n", getspellmaxpower(ot->id)); sprintf(buf, "^BIt is too powerful for you to cast (maximum power %d).^n\n", getspellmaxpower(ot->id));
} }
strncat(retbuf, buf, BUFLEN); strncat(retbuf, buf, BUFLEN);
@ -7013,6 +7065,8 @@ char *makedesc_spell(objecttype_t *ot, char *retbuf) {
strncat(retbuf, buf, BUFLEN); strncat(retbuf, buf, BUFLEN);
} }
} }
return retbuf; return retbuf;
} }
@ -9408,9 +9462,7 @@ void handleinput(void) {
case CH_TURN_NW: case CH_TURN_NW:
dir = chartodir(ch); dir = chartodir(ch);
if (dir != player->facing) { if (dir != player->facing) {
if (getrelativedir(player, dir) != RD_FORWARDS) { takerotationtime(player);
taketime(player, getturnspeed(player));
}
setfacing(player, dir); setfacing(player, dir);
drawscreen(); drawscreen();
} }
@ -10622,9 +10674,9 @@ void showlfstats(lifeform_t *lf, int showall) {
if (j) { if (j) {
doheadingsmall(mainwin, y, 0, ftext, "Job"); doheadingsmall(mainwin, y, 0, ftext, "Job");
if (showall) { if (showall) {
snprintf(buf, BUFLEN, "Level %d %s", lf->level, j->name); snprintf(buf, BUFLEN, "Level %d %s", lf->level, getjobname(lf));
} else { } else {
snprintf(buf, BUFLEN, "%s", j->name); snprintf(buf, BUFLEN, "%s", getjobname(lf));
} }
wprintw(mainwin, "%-20s", buf); y++; wprintw(mainwin, "%-20s", buf); y++;
} }
@ -10752,7 +10804,7 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
break; break;
case A_CON: case A_CON:
mod = getstatmod(lf, A_CON); mod = getstatmod(lf, i);
if (mod > 0) { if (mod > 0) {
mod *= 2; // note: same code as in rollhitdice mod *= 2; // note: same code as in rollhitdice
snprintf(buf2, BUFLEN, ", +%d%% hp",mod ); snprintf(buf2, BUFLEN, ", +%d%% hp",mod );
@ -11790,6 +11842,65 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
// show boosts to spell power
if (showall) {
// note: same code as in getspellpower()
enum SPELLSCHOOL school[5];
int nschools = 5;
school[0] = SS_WILD;
school[1] = SS_MENTAL;
school[2] = SS_NATURE;
school[3] = SS_LIFE;
school[4] = SS_ALLOMANCY;
for (i = 0; i < nschools; i++) {
enum ATTRIB att = A_NONE;
int n,found = B_FALSE;
// can you cast any spells from this school?
getflags(lf->flags, retflag, &nretflags, F_CANCAST, F_CANWILL, F_NONE);
for (n = 0; n < nretflags; n++) {
enum SPELLSCHOOL thisschool;
thisschool = getspellschool(retflag[n]->val[0]);
if (thisschool == school[i]) {
found = B_TRUE;
break;
}
}
if (found) {
int mod;
enum RACE godid = R_NONE;
mod = getspellpowerstatmod(lf, school[i], &att);
if (mod) {
mvwprintw(mainwin, y, 0, "%s %s %s will %s the power of %s %s by %d.",
your(lf),
(mod > 0) ? "high" : "low", getattrname(att),
(mod > 0) ? "boost" : "lower",
(school[i] == SS_WILD) ? "arcane" :
(school[i] == SS_MENTAL) ? "Psionic" :
getschoolname(school[i]),
(school[i] == SS_MENTAL) ? "disciplines" : "spells",
abs(mod) );
y++;
}
// boosted by god?
mod = getspellpowergodmod(lf, school[i], &godid);
if (mod > 0) {
lifeform_t *god;
god = findgod(godid);
if (god) {
mvwprintw(mainwin, y, 0, "%s is boosting the power of %s %s spells by %d.",
god->race->name, your(lf), mod);
y++;
}
}
} // end if found
} // end foreach school
}
// we DONT show traits based on the monster's racial characteristics // we DONT show traits based on the monster's racial characteristics
// here. leave that to makedesc_race. // here. leave that to makedesc_race.
// //
@ -11836,16 +11947,28 @@ void showlfstats(lifeform_t *lf, int showall) {
int mr; int mr;
char adjective[BUFLEN]; char adjective[BUFLEN];
mr = getmr(lf); mr = getmr(lf);
if (mr <= 5) { if (mr <= 10) {
strcpy(adjective, "slightly"); strcpy(adjective, "very slightly");
} else if (mr <= 10) {
strcpy(adjective, "quite");
} else if (mr <= 15) {
strcpy(adjective, "very");
} else if (mr <= 20) { } else if (mr <= 20) {
strcpy(adjective, "slightly");
} else if (mr <= 30) {
strcpy(adjective, "somewhat");
} else if (mr <= 40) {
strcpy(adjective, "moderately");
} else if (mr <= 50) {
strcpy(adjective, "quite");
} else if (mr <= 60) {
strcpy(adjective, "highly");
} else if (mr <= 70) {
strcpy(adjective, "very highly");
} else if (mr <= 80) {
strcpy(adjective, "extremely"); strcpy(adjective, "extremely");
} else { // ie. 21 upwards } else if (mr <= 90) {
strcpy(adjective, "incredibly"); strcpy(adjective, "incredibly");
} else if (mr < 100) {
strcpy(adjective, "almost completely");
} else { // ie. 100 upwards
strcpy(adjective, "completely");
} }
mvwprintw(mainwin, y, 0, "%s %s %s resistant to magic.", you(lf), is(lf), adjective); mvwprintw(mainwin, y, 0, "%s %s %s resistant to magic.", you(lf), is(lf), adjective);
y++; y++;
@ -12111,6 +12234,11 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s can see things which are behind %s.", you(lf), you(lf)); mvwprintw(mainwin, y, 0, "%s can see things which are behind %s.", you(lf), you(lf));
y++; y++;
} }
f = hasflag_real(lf->flags, F_DODGES, B_TRUE, NULL, FROMRACE);
if (f) {
mvwprintw(mainwin, y, 0, "%s will automatically use your remaining stamina to dodge fatal attacks.", you(lf));
y++;
}
f = lfhasknownflag(lf, F_MAGICARMOUR); f = lfhasknownflag(lf, F_MAGICARMOUR);
if (f && (f->known)) { if (f && (f->known)) {

1
io.h
View File

@ -105,6 +105,7 @@ void initprompt(prompt_t *p, char *q1);
int keycodetokey(int keycode, int escseqok); int keycodetokey(int keycode, int escseqok);
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints, object_t *sellshop); void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints, object_t *sellshop);
char *makedesc_god(lifeform_t *god, char *retbuf); char *makedesc_god(lifeform_t *god, char *retbuf);
char *makedesc_job(job_t *j, char *retbuf);
char *makedesc_ob(object_t *o, char *retbuf); char *makedesc_ob(object_t *o, char *retbuf);
char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel); char *makedesc_race(enum RACE rid, char *retbuf, int showextra, int forplayersel);
char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite); char *makedesc_skill(enum SKILL skid, char *retbuf, enum SKILLLEVEL levhilite);

435
lf.c
View File

@ -33,6 +33,7 @@ extern raceclass_t *firstraceclass, *lastraceclass;
extern job_t *firstjob, *lastjob; extern job_t *firstjob, *lastjob;
extern skill_t *firstskill, *lastskill; extern skill_t *firstskill, *lastskill;
extern poisontype_t *firstpoisontype,*lastpoisontype; extern poisontype_t *firstpoisontype,*lastpoisontype;
extern subjob_t *firstsubjob,*lastsubjob;
extern objecttype_t *objecttype; extern objecttype_t *objecttype;
extern lifeform_t *player; extern lifeform_t *player;
@ -566,6 +567,10 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
reason = E_OK; reason = E_OK;
ot = findot(oid); ot = findot(oid);
if ((ot->obclass->id == OC_SPELL) && lfhasflag(lf, F_NOSPELLS)) {
reason = E_NOSPELLS;
return B_FALSE;
}
f = lfhasflagval(lf, F_CANWILL, oid, NA, NA, NULL); f = lfhasflagval(lf, F_CANWILL, oid, NA, NA, NULL);
if (f) { if (f) {
@ -1505,16 +1510,8 @@ int cantalk(lifeform_t *lf) {
} }
// if the lf can't explicitly talk, check its race // 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) { if (!racecantalk(lf->race->raceclass->id)) {
case RC_DEMON: return B_FALSE;
case RC_DRAGON:
case RC_GOD:
case RC_HUMANOID:
// these ones can talk
break;
default:
return B_FALSE;
break;
} }
} }
@ -1567,6 +1564,9 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
case E_NOTREADY: case E_NOTREADY:
msg("This ability is not recharged yet."); msg("This ability is not recharged yet.");
break; break;
case E_NOSPELLS:
msg("You can't cast spells.");
break;
case E_PRONE: case E_PRONE:
msg("You can't cast spells while prone."); msg("You can't cast spells while prone.");
break; break;
@ -1688,7 +1688,7 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
return B_FALSE; return B_FALSE;
} }
} }
// casting a nature spell while nature god is angry at you? // casting a god-related spell while that god is angry at you?
if (isplayer(lf) && !willflag) { if (isplayer(lf) && !willflag) {
if (godprayedto(R_GODNATURE) && godisangry(R_GODNATURE)) { if (godprayedto(R_GODNATURE) && godisangry(R_GODNATURE)) {
if (hasflagval(sp->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL)) { if (hasflagval(sp->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL)) {
@ -1842,28 +1842,33 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
} }
} }
if (isplayer(lf)) { if (isplayer(lf)) {
objecttype_t *ot;
flag_t *retflag[MAXCANDIDATES];
int nretflags,i;
pleasegodmaybe(R_GODMAGIC, getspelllevel(sid)); pleasegodmaybe(R_GODMAGIC, getspelllevel(sid));
if (!fromob) { if (!fromob) {
angergodmaybe(R_GODBATTLE, 25, GA_SPELL); angergodmaybe(R_GODBATTLE, 25, GA_SPELL);
} }
ot = findot(sid);
getflags(ot->flags, retflag, &nretflags, F_PLEASESGOD, F_NONE);
for (i = 0; i < nretflags; i++) {
f = retflag[i];
if (f->id == F_PLEASESGOD) {
pleasegodmaybe(f->val[0], f->val[1]);
}
}
// anger gods?
switch (school) { switch (school) {
case SS_COLD: case SS_COLD:
angergodmaybe(R_GODFIRE, getspelllevel(sid)*5, GA_SPELL); angergodmaybe(R_GODFIRE, getspelllevel(sid)*5, GA_SPELL);
break; break;
case SS_DEATH: case SS_DEATH:
pleasegodmaybe(R_GODDEATH, getspelllevel(sid));
angergodmaybe(R_GODLIFE, getspelllevel(sid)*5, GA_SPELL); angergodmaybe(R_GODLIFE, getspelllevel(sid)*5, GA_SPELL);
break; break;
case SS_FIRE:
pleasegodmaybe(R_GODFIRE, getspelllevel(sid)*2);
break;
case SS_LIFE: case SS_LIFE:
pleasegodmaybe(R_GODLIFE, getspelllevel(sid)*2);
angergodmaybe(R_GODDEATH, getspelllevel(sid)*5, GA_SPELL); angergodmaybe(R_GODDEATH, getspelllevel(sid)*5, GA_SPELL);
break; break;
case SS_NATURE:
pleasegodmaybe(R_GODNATURE, getspelllevel(sid)*2);
break;
default: default:
break; break;
} }
@ -2999,6 +3004,18 @@ void genareaknowledge(flagpile_t *fp, int chancemod) {
// if alignment needs to be generated randomly (or selected in the case of the player), do so. // if alignment needs to be generated randomly (or selected in the case of the player), do so.
void generatealignment(lifeform_t *lf) { void generatealignment(lifeform_t *lf) {
flag_t *f; flag_t *f;
// sometimes alignment is forced.
switch (getsubjob(lf)) {
case SJ_NECROMANCER:
setalignment(lf, AL_EVIL);
return;
case SJ_PALADIN:
setalignment(lf, AL_GOOD);
return;
default: break;
}
f = hasflagval(lf->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL); f = hasflagval(lf->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL);
if (f && strlen(f->text)) { if (f && strlen(f->text)) {
char buf[BUFLEN]; char buf[BUFLEN];
@ -4870,6 +4887,14 @@ enum SKILLLEVEL findskilllevbyname(char *name) {
return PR_INEPT; return PR_INEPT;
} }
subjob_t *findsubjob(enum SUBJOB sjid) {
subjob_t *j;
for (j = firstsubjob ; j ; j = j->next) {
if (j->id == sjid) return j;
}
return NULL;
}
// try to actually do the 'run away' action for // try to actually do the 'run away' action for
// anyone we are fleeing from. // anyone we are fleeing from.
// returns TRUE if we ran away from something // returns TRUE if we ran away from something
@ -6629,6 +6654,32 @@ job_t *getjob(lifeform_t *lf) {
return NULL; return NULL;
} }
enum SUBJOB getsubjob(lifeform_t *lf) {
flag_t *f;
f = lfhasflag(lf, F_JOB);
if (f && (f->val[1] != NA)) {
return f->val[1];
}
return SJ_NONE;
}
char *getjobname(lifeform_t *lf) {
enum SUBJOB sjid;
job_t *j;
subjob_t *sj;
sjid = getsubjob(lf);
sj = findsubjob(sjid);
if (sj) {
return sj->name;
}
j = getjob(lf);
if (j) {
return j->name;
}
return "";
}
int getlastdir(lifeform_t *lf) { int getlastdir(lifeform_t *lf) {
flag_t *f; flag_t *f;
f = lfhasflag(lf, F_LASTDIR); f = lfhasflag(lf, F_LASTDIR);
@ -6933,6 +6984,18 @@ int getmorale(lifeform_t *lf) {
return 0; return 0;
} }
int getnextshortcut(lifeform_t *lf) {
flag_t *retflag[MAXCANDIDATES];
int nretflags,i,min = 0;
getflags(lf->flags, retflag, &nretflags, F_SHORTCUT, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[0] > min) {
min = retflag[i]->val[0];
}
}
return min + 1;
}
int getnightvisrange(lifeform_t *lf) { int getnightvisrange(lifeform_t *lf) {
int range = 0; // default int range = 0; // default
flag_t *f; flag_t *f;
@ -7416,6 +7479,10 @@ int getmr(lifeform_t *lf) {
sumflags(lf->flags, F_RESISTMAG, &amt, NULL, NULL); sumflags(lf->flags, F_RESISTMAG, &amt, NULL, NULL);
if (hassubjob(lf, SJ_SCOURGE)) {
amt += (gethitdice(lf) * 3);
}
return amt; return amt;
} }
@ -7656,7 +7723,6 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
char jobstring[BUFLEN]; char jobstring[BUFLEN];
char the[6]; char the[6];
char lname[BUFLEN]; char lname[BUFLEN];
job_t *j;
flag_t *f; flag_t *f;
enum LFSIZE size,racesize; enum LFSIZE size,racesize;
int dobehaviour = B_TRUE; int dobehaviour = B_TRUE;
@ -7722,9 +7788,8 @@ char *real_getlfname(lifeform_t *lf, char *buf, int usevis, int showall) {
strcpy(jobstring, ""); strcpy(jobstring, "");
if (showall || isplayer(lf) || (getlorelevel(player, lf->race->raceclass->id) >= PR_BEGINNER)) { if (showall || isplayer(lf) || (getlorelevel(player, lf->race->raceclass->id) >= PR_BEGINNER)) {
if (!lfhasflag(lf, F_NOJOBTEXT) && !lfhasflag(lf, F_NAME) && !lfhasflag(lf, F_UNIQUE)) { if (!lfhasflag(lf, F_NOJOBTEXT) && !lfhasflag(lf, F_NAME) && !lfhasflag(lf, F_UNIQUE)) {
j = getjob(lf); if (getjob(lf)) {
if (j) { snprintf(jobstring, BUFLEN, " %s", getjobname(lf));
snprintf(jobstring, BUFLEN, " %s", j->name);
jobstring[1] = tolower(jobstring[1]); jobstring[1] = tolower(jobstring[1]);
} }
} }
@ -8000,14 +8065,12 @@ char *getplayername(char *buf) {
char *getplayernamefull(char *buf) { char *getplayernamefull(char *buf) {
char pname[BUFLEN]; char pname[BUFLEN];
job_t *j;
getplayername(pname); getplayername(pname);
if (strlen(pname)) { if (strlen(pname)) {
j = getjob(player); if (getjob(player)) {
if (j) { snprintf(buf, BUFLEN, "%s the %s %s", pname, player->race->name, getjobname(player));
snprintf(buf, BUFLEN, "%s the %s %s", pname, player->race->name, j->name);
} else { } else {
snprintf(buf, BUFLEN, "%s the %s", pname, player->race->name); snprintf(buf, BUFLEN, "%s the %s", pname, player->race->name);
} }
@ -9117,6 +9180,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
switch (f->id) { switch (f->id) {
case F_MAXHPMOD: case F_MAXHPMOD:
case F_JOBATTRMOD: case F_JOBATTRMOD:
case F_CANHAVESUBJOB:
ignorethis = B_TRUE; ignorethis = B_TRUE;
break; break;
case F_CANLEARN: case F_CANLEARN:
@ -9212,9 +9276,213 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
*/ */
} }
// extra tasks for some jobs
if (j->id == J_DRUID) {
enum OBTYPE spell;
int i;
for (i = 0;i < 3; i++) {
// pick a spell which you don't already have...
spell = getrandomspellfromschool(SS_NATURE, 1);
while (cancast(lf, spell, NULL)) {
spell = getrandomspellfromschool(SS_NATURE, 1);
}
// you can now cast it.
addflag(lf->flags, F_CANCAST, spell, NA, NA, NULL);
}
if (isplayer(lf)) {
lifeform_t *god;
// druids always worship ekrub
god = findgod(R_GODNATURE);
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL);
}
}
// select subjobs
if ((gamemode == GM_CHARGEN) && isplayer(lf)) {
subjob_t *sub;
enum SUBJOB sj = SJ_NONE;
char ch;
flag_t *retflag[MAXCANDIDATES];
int nretflags;
getflags(j->flags, retflag, &nretflags, F_CANHAVESUBJOB, F_NONE);
initprompt(&prompt, "Select your job specialty:");
for (sub = firstsubjob ; sub ; sub = sub->next) {
if (hasflagval(j->flags, F_CANHAVESUBJOB, sub->id, NA, NA, NULL)) {
addchoice(&prompt, sub->letter, sub->name, NULL, sub, sub->desc);
}
}
addchoice(&prompt, '-', "(none)", NULL, NULL, NULL);
if (prompt.nchoices > 1) {
ch = getchoice(&prompt);
sub = (subjob_t *)prompt.result;
if (sub) {
sj = sub->id;
} else {
sj = SJ_NONE;
}
}
givesubjob(lf, sj);
if (j->id == J_WIZARD) {
object_t *sb2;
skill_t *sk;
// wizards now get a secondary school
initprompt(&prompt, "Select your secondary spell school:");
addchoice(&prompt, 'd', getskillname(SK_SS_DIVINATION), NULL, findskill(SK_SS_DIVINATION), NULL);
addchoice(&prompt, 'g', getskillname(SK_SS_GRAVITY), NULL, findskill(SK_SS_GRAVITY), NULL);
addchoice(&prompt, 'm', getskillname(SK_SS_MODIFICATION), NULL, findskill(SK_SS_MODIFICATION), NULL);
addchoice(&prompt, 's', getskillname(SK_SS_SUMMONING), NULL, findskill(SK_SS_SUMMONING), NULL);
addchoice(&prompt, 't', getskillname(SK_SS_TRANSLOCATION), NULL, findskill(SK_SS_TRANSLOCATION), NULL);
getchoice(&prompt);
sk = (skill_t *) prompt.result;
switch (sk->id) {
case SK_SS_DIVINATION:
sb2 = addob(lf->pack, "spellbook of divination magic");
break;
case SK_SS_GRAVITY:
sb2 = addob(lf->pack, "spellbook of gravitation magic");
break;
case SK_SS_MODIFICATION:
sb2 = addob(lf->pack, "spellbook of modification magic");
break;
case SK_SS_SUMMONING:
sb2 = addob(lf->pack, "spellbook of summoning magic");
break;
case SK_SS_TRANSLOCATION:
sb2 = addob(lf->pack, "spellbook of translocation magic");
break;
default:
sb2 = NULL;
break;
}
if (sb2) {
addflag(lf->flags, F_CANCAST, sb2->contents->first->type->id, NA, NA, NULL);
if (isplayer(lf)) {
addflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, sb2->contents->first->type->name);
addflag(sb2->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
}
}
identify(sb2);
}
}
generatealignment(lf); generatealignment(lf);
} }
void givesubjob(lifeform_t *lf, enum SUBJOB sj) {
flag_t *jobflag;
object_t *sb1,*o;
int i;
if (sj == SJ_NONE) return;
// remember the subjob
jobflag = lfhasflag(lf, F_JOB);
jobflag->val[1] = sj;
switch (sj) {
// mage types
case SJ_AIRMAGE:
addflag(lf->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL);
sb1 = addob(lf->pack, "spellbook of air magic");
break;
case SJ_ICEMAGE:
sb1 = addob(lf->pack, "spellbook of cold magic");
break;
case SJ_FIREMAGE:
sb1 = addob(lf->pack, "spellbook of fire magic");
break;
case SJ_NECROMANCER:
sb1 = addob(lf->pack, "spellbook of necromancy");
break;
case SJ_WILDMAGE:
sb1 = addob(lf->pack, "spellbook of wild magic");
break;
// warrior types
case SJ_BATTLEMAGE:
// starts off skilled in one school
switch (rnd(1,2)) {
case 1:
giveskilllev(lf, SK_SS_FIRE, PR_NOVICE);
sb1 = addob(lf->pack, "spellbook of fire magic");
break;
case 2:
giveskilllev(lf, SK_SS_COLD, PR_NOVICE);
sb1 = addob(lf->pack, "spellbook of cold magic");
break;
}
// can learn some spell schools, but only up to adept level
addtempflag(lf->flags, F_CANLEARN, SK_SS_FIRE, PR_ADEPT, NA, NULL, FROMJOB);
addtempflag(lf->flags, F_CANLEARN, SK_SS_COLD, PR_ADEPT, NA, NULL, FROMJOB);
addtempflag(lf->flags, F_CANLEARN, SK_SS_AIR, PR_ADEPT, NA, NULL, FROMJOB);
addtempflag(lf->flags, F_CANLEARN, SK_SS_GRAVITY, PR_ADEPT, NA, NULL, FROMJOB);
addtempflag(lf->flags, F_CANLEARN, SK_SS_MODIFICATION, PR_ADEPT, NA, NULL, FROMJOB);
addtempflag(lf->flags, F_CANLEARN, SK_SS_TRANSLOCATION, PR_ADEPT, NA, NULL, FROMJOB);
addtempflag(lf->flags, F_CANLEARN, SK_SS_WILD, PR_ADEPT, NA, NULL, FROMJOB);
// raise IQ to average so that we aren't too dumb to cast L1 spells
i = rollattr(AT_AVERAGE);
limit(&i, 50, NA);
lf->baseatt[A_IQ] = i;
lf->att[A_IQ] = i;
// replace mpdice
killflagsofid(lf->flags, F_MPDICE);
addtempflag(lf->flags, F_MPDICE, 1, 0, NA, NULL, FROMJOB);
// remove warrior's hitdice bonus
killflagsofid(lf->flags, F_MAXHPMOD);
// remove warrior's level abilities
killflagsofid(lf->flags, F_LEVABIL);
break;
case SJ_PALADIN:
// healing magic
giveskilllev(lf, SK_SS_LIFE, PR_NOVICE);
sb1 = addob(lf->pack, "spellbook of life magic");
// must worship glorana
if (isplayer(lf)) {
lifeform_t *god;
god = findgod(R_GODLIFE);
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL);
}
// raise WIS to gtaverage for life magic
lf->baseatt[A_WIS] = rollattr(AT_GTAVERAGE);
lf->att[A_WIS] = lf->baseatt[A_WIS];
// can permenantly turn undead for 0 power.
addtempflag(lf->flags, F_CANWILL, OT_S_TURNUNDEAD, NA, NA, NULL, FROMJOB);
if (isplayer(lf)) {
addflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, "turn undead");
}
// all gear is blessed
for (o = lf->pack->first ; o ; o = o->next) {
if (isequipped(o)) {
blessob(o);
}
}
break;
case SJ_SCOURGE:
addtempflag(lf->flags, F_RESISTMAG, 5, NA, NA, NULL, FROMJOB);
// no mp.
killflagsofid(lf->flags, F_MPDICE);
addtempflag(lf->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL, FROMJOB);
break;
//
default:
sb1 = NULL;
break;
}
if (sb1) {
addtempflag(lf->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL, FROMJOB);
if (isplayer(lf)) {
addtempflag(lf->flags, F_SHORTCUT, getnextshortcut(lf), NA, NA, sb1->contents->first->type->name, FROMJOB);
addflag(sb1->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
}
identify(sb1);
}
}
int givemoney(lifeform_t *from, lifeform_t *to, int amt) { int givemoney(lifeform_t *from, lifeform_t *to, int amt) {
object_t *gold; object_t *gold;
@ -9542,7 +9810,10 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) {
newf = addtempflag(lf->flags, F_CANWILL, OT_A_SNATCH, NA, NA, NULL, FROMSKILL); newf = addtempflag(lf->flags, F_CANWILL, OT_A_SNATCH, NA, NA, NULL, FROMSKILL);
} }
} else if (f->val[1] == PR_SKILLED) { } else if (f->val[1] == PR_SKILLED) {
newf = addtempflag(lf->flags, F_DODGES, B_TRUE, NA, NA, NULL, FROMSKILL); newf = hasflagval(lf->flags, F_CANWILL, OT_A_REFLEXDODGE, NA, NA, NULL);
if (!newf) {
newf = addtempflag(lf->flags, F_CANWILL, OT_A_REFLEXDODGE, NA, NA, NULL, FROMSKILL);
}
} }
} else if (id == SK_LORE_ARCANA) { } else if (id == SK_LORE_ARCANA) {
if (f->val[1] == PR_ADEPT) { if (f->val[1] == PR_ADEPT) {
@ -10118,6 +10389,15 @@ int hastempinjuries(lifeform_t *lf) {
return count; return count;
} }
int hassubjob(lifeform_t *lf, enum SUBJOB id) {
flag_t *f;
f = lfhasflag(lf, F_JOB);
if (f && (f->val[1] == id)) {
return B_TRUE;
}
return B_FALSE;
}
void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch) { void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch) {
int i; int i;
for (i = 0; i < abs(howmuch); i++) { for (i = 0; i < abs(howmuch); i++) {
@ -11698,6 +11978,7 @@ object_t *isstuck(lifeform_t *lf) {
return NULL; return NULL;
} }
poisontype_t *addpoisontype(enum POISONTYPE id, char *name, char *desc, char *damverb, enum OBTYPE vomitob, int dam, int dampct, enum POISONSEVERITY severity) { poisontype_t *addpoisontype(enum POISONTYPE id, char *name, char *desc, char *damverb, enum OBTYPE vomitob, int dam, int dampct, enum POISONSEVERITY severity) {
poisontype_t *a; poisontype_t *a;
@ -11831,6 +12112,7 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
} else { } else {
a->timespent = 0; a->timespent = 0;
} }
a->rotated = B_FALSE;
a->sorted = B_FALSE; a->sorted = B_FALSE;
a->forgettimer = 0; a->forgettimer = 0;
@ -12033,6 +12315,33 @@ void addskilldesc(enum SKILL id, enum SKILLLEVEL lev, char *text, int wantmsg) {
sk->nskilldesc++; sk->nskilldesc++;
} }
subjob_t *addsubjob(enum SUBJOB id, char *name, char *desc, char letter) {
subjob_t *a;
// add to the end of the list
if (firstsubjob == NULL) {
firstsubjob = malloc(sizeof(subjob_t));
a = firstsubjob;
a->prev = NULL;
} else {
// go to end of list
a = lastsubjob;
a->next = malloc(sizeof(subjob_t));
a->next->prev = a;
a = a->next;
}
lastsubjob = a;
a->next = NULL;
// props
a->id = id;
a->name = strdup(name);
a->desc = strdup(desc);
a->letter = letter;
return a;
}
object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int doscents) { object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int doscents) {
object_t *footprint, *scent,*retob = NULL; object_t *footprint, *scent,*retob = NULL;
flag_t *fpflag = NULL; flag_t *fpflag = NULL;
@ -12674,12 +12983,7 @@ void autoshortcut(lifeform_t *lf, enum OBTYPE spellid) {
ot = findot(spellid); ot = findot(spellid);
if (ot) { if (ot) {
// set to lowest possible shortcut // set to lowest possible shortcut
getflags(lf->flags, retflag, &nretflags, F_SHORTCUT, F_NONE); min = getnextshortcut(lf);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[0] > min) {
min = retflag[i]->val[0];
}
}
if (min < 10) { if (min < 10) {
addflag(lf->flags, F_SHORTCUT, min, NA, NA, ot->name); addflag(lf->flags, F_SHORTCUT, min, NA, NA, ot->name);
} }
@ -13003,6 +13307,33 @@ void killrace(race_t *r) {
} }
} }
void killsubjob(subjob_t *sj) {
subjob_t *nextone, *lastone;
// free mem
free(sj->name);
free(sj->desc);
// remove from list
nextone = sj->next;
if (nextone != NULL) {
nextone->prev = sj->prev;
} else { /* last */
lastsubjob = sj->prev;
}
if (sj->prev == NULL) {
/* first */
nextone = sj->next;
free(firstsubjob);
firstsubjob = nextone;
} else {
lastone = sj->prev;
free (lastone->next );
lastone->next = nextone;
}
}
flag_t *levelabilityready(lifeform_t *lf) { flag_t *levelabilityready(lifeform_t *lf) {
flag_t *f; flag_t *f;
int i; int i;
@ -15109,6 +15440,27 @@ int push(lifeform_t *lf, object_t *o, int dir) {
} }
int racecantalk(enum RACE rid) {
race_t *r;
switch (rid) {
case RC_DEMON:
case RC_DRAGON:
case RC_GOD:
case RC_HUMANOID:
// these ones can talk
return B_TRUE;
break;
default:
break;
}
r = findrace(rid);
if (r) {
if (hasflag(r->flags, F_CANTALK)) return B_TRUE;
}
return B_FALSE;
}
int readytotrain(lifeform_t *lf) { int readytotrain(lifeform_t *lf) {
if (lf->skillpoints || getattpoints(lf) || levelabilityready(lf)) { if (lf->skillpoints || getattpoints(lf) || levelabilityready(lf)) {
return B_TRUE; return B_TRUE;
@ -16740,7 +17092,7 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
} }
break; break;
case SC_RESISTMAG: case SC_RESISTMAG:
attrib = (getattr(lf, A_CON)/30) + (getattr(lf, A_WIS)/30) + getmr(lf); attrib = (getattr(lf, A_CON)/30) + (getattr(lf, A_WIS)/30) + (getmr(lf)/5);
break; break;
case SC_SEARCH: case SC_SEARCH:
attrib = (getskill(lf, SK_PERCEPTION)*2); attrib = (getskill(lf, SK_PERCEPTION)*2);
@ -17160,6 +17512,7 @@ void startlfturn(lifeform_t *lf) {
if (isplayer(lf) && lfhasflag(lf, F_DRUNK)) statdirty = B_TRUE; if (isplayer(lf) && lfhasflag(lf, F_DRUNK)) statdirty = B_TRUE;
// clear one-turn-only flags // clear one-turn-only flags
lf->rotated = B_FALSE;
killflagsofid(lf->flags, F_JUSTENTERED); killflagsofid(lf->flags, F_JUSTENTERED);
killflagsofid(lf->flags, F_UNSEENATTACKER); killflagsofid(lf->flags, F_UNSEENATTACKER);
killflagsofid(lf->flags, F_DONELISTEN); killflagsofid(lf->flags, F_DONELISTEN);
@ -18516,6 +18869,17 @@ int takeoff(lifeform_t *lf, object_t *o) {
} }
void takerotationtime(lifeform_t *lf) {
// first rotation in a turn is free
if (lf->rotated) {
taketime(lf, getturnspeed(lf));
} else {
lf->rotated = B_TRUE;
}
}
void taketime(lifeform_t *lf, long howlong) { void taketime(lifeform_t *lf, long howlong) {
int db = B_FALSE; int db = B_FALSE;
map_t *map; map_t *map;
@ -19540,6 +19904,7 @@ int useringofmiracles(lifeform_t *lf, int charges) {
} }
// you know know the obejct // you know know the obejct
makeknown(o->type->id); makeknown(o->type->id);
getobname(o, obname, 1); // refresh its name in case you didnt know what it was.
// use a charge // use a charge
if (o->type->id == OT_RING_MIRACLES) { if (o->type->id == OT_RING_MIRACLES) {

10
lf.h
View File

@ -9,6 +9,7 @@ race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcol
raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill); raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill);
skill_t *addskill(enum SKILL id, char *name, char *desc, int traintime); skill_t *addskill(enum SKILL id, char *name, char *desc, int traintime);
void addskilldesc(enum SKILL id, enum SKILLLEVEL lev, char *text, int wantmsg); void addskilldesc(enum SKILL id, enum SKILLLEVEL lev, char *text, int wantmsg);
subjob_t *addsubjob(enum SUBJOB id, char *name, char *desc, char letter);
object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int doscents); object_t *addtrail(lifeform_t *lf, cell_t *where, int dir, int doprints, int doscents);
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype); void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype);
void adjustspeedforwater(lifeform_t *lf, int *speed); void adjustspeedforwater(lifeform_t *lf, int *speed);
@ -112,6 +113,7 @@ raceclass_t *findraceclass(enum RACECLASS id);
skill_t *findskill(enum SKILL id); skill_t *findskill(enum SKILL id);
skill_t *findskillbyname(char *name); skill_t *findskillbyname(char *name);
enum SKILLLEVEL findskilllevbyname(char *name); enum SKILLLEVEL findskilllevbyname(char *name);
subjob_t *findsubjob(enum SUBJOB sjid);
int flee(lifeform_t *lf); int flee(lifeform_t *lf);
void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose); void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose);
int fovlist_contains(int *endx, int *endy, int nendcells, int x, int y); int fovlist_contains(int *endx, int *endy, int nendcells, int x, int y);
@ -169,6 +171,8 @@ enum HUNGER gethungerlevel(int hunger);
char *gethungername(lifeform_t *lf, enum HUNGER hunger, char *buf); char *gethungername(lifeform_t *lf, enum HUNGER hunger, char *buf);
int gethungerval(lifeform_t *lf); int gethungerval(lifeform_t *lf);
job_t *getjob(lifeform_t *lf); job_t *getjob(lifeform_t *lf);
enum SUBJOB getsubjob(lifeform_t *lf);
char *getjobname(lifeform_t *lf);
int getlastdir(lifeform_t *lf); int getlastdir(lifeform_t *lf);
int getleftrightwalls(lifeform_t *lf); int getleftrightwalls(lifeform_t *lf);
int getlfaccuracy(lifeform_t *lf, object_t *wep); int getlfaccuracy(lifeform_t *lf, object_t *wep);
@ -179,6 +183,7 @@ enum SKILLLEVEL getmaxskilllevel(lifeform_t *lf, enum SKILL skid);
int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions); int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions);
int getmiscastchance(lifeform_t *lf); int getmiscastchance(lifeform_t *lf);
int getmorale(lifeform_t *lf); int getmorale(lifeform_t *lf);
int getnextshortcut(lifeform_t *lf);
int getnightvisrange(lifeform_t *lf); int getnightvisrange(lifeform_t *lf);
int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, char *heartext,char *seetext, int *volume); int getnoisedetails(lifeform_t *lf, enum NOISETYPE nid, char *heartext,char *seetext, int *volume);
char *getlfconditionname(enum LFCONDITION cond); char *getlfconditionname(enum LFCONDITION cond);
@ -260,6 +265,7 @@ int getweapons(lifeform_t *lf, object_t **wep, flag_t **damflag, int *lastweapon
enum SKILLLEVEL getweaponskill(lifeform_t *lf, object_t *o); enum SKILLLEVEL getweaponskill(lifeform_t *lf, object_t *o);
long getxpforlev(int level); long getxpforlev(int level);
void givejob(lifeform_t *lf, enum JOB jobid); void givejob(lifeform_t *lf, enum JOB jobid);
void givesubjob(lifeform_t *lf, enum SUBJOB sj);
int givemoney(lifeform_t *from, lifeform_t *to, int amt); int givemoney(lifeform_t *from, lifeform_t *to, int amt);
void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype); void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype);
int giverandomobs(lifeform_t *lf, int amt); int giverandomobs(lifeform_t *lf, int amt);
@ -274,6 +280,7 @@ int hasfreeaction(lifeform_t *lf);
int real_hasfreeaction(lifeform_t *lf, enum FLAG exception); int real_hasfreeaction(lifeform_t *lf, enum FLAG exception);
int hashealableinjuries(lifeform_t *lf); int hashealableinjuries(lifeform_t *lf);
job_t *hasjob(lifeform_t *lf, enum JOB job); job_t *hasjob(lifeform_t *lf, enum JOB job);
int hassubjob(lifeform_t *lf, enum SUBJOB id);
void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch); void inc_quad_range(enum QUADRANT *start, enum QUADRANT *end, int howmuch);
int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype); int injure(lifeform_t *lf, enum BODYPART where, enum DAMTYPE damtype);
int lfcanbestoned(lifeform_t *lf); int lfcanbestoned(lifeform_t *lf);
@ -345,6 +352,7 @@ void killjob(job_t *job);
void killlf(lifeform_t *lf); void killlf(lifeform_t *lf);
void killpoisontype(poisontype_t *pt); void killpoisontype(poisontype_t *pt);
void killrace(race_t *race); void killrace(race_t *race);
void killsubjob(subjob_t *sj);
flag_t *levelabilityready(lifeform_t *lf); 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);
@ -383,6 +391,7 @@ void practice(lifeform_t *lf, enum SKILL skid, int amt);
void precalclos(lifeform_t *lf); void precalclos(lifeform_t *lf);
void preparecorpse(lifeform_t *lf, object_t *corpse); void preparecorpse(lifeform_t *lf, object_t *corpse);
int push(lifeform_t *lf, object_t *o, int dir); int push(lifeform_t *lf, object_t *o, int dir);
int racecantalk(enum RACE rid);
int readytotrain(lifeform_t *lf); int readytotrain(lifeform_t *lf);
int recruit(lifeform_t *lf); int recruit(lifeform_t *lf);
void refreshlevelabilities(lifeform_t *lf); void refreshlevelabilities(lifeform_t *lf);
@ -433,6 +442,7 @@ int stun(lifeform_t *lf, int nturns);
lifeform_t *summonmonster(lifeform_t *caster, cell_t *c, enum RACE rid, char *racename, int lifetime, int wantfriendly); lifeform_t *summonmonster(lifeform_t *caster, cell_t *c, enum RACE rid, char *racename, int lifetime, int wantfriendly);
//int testammo(lifeform_t *lf, object_t *o); //int testammo(lifeform_t *lf, object_t *o);
int takeoff(lifeform_t *lf, object_t *o); int takeoff(lifeform_t *lf, object_t *o);
void takerotationtime(lifeform_t *lf);
void taketime(lifeform_t *lf, long howlong); void taketime(lifeform_t *lf, long howlong);
int throwat(lifeform_t *thrower, object_t *o, cell_t *where); int throwat(lifeform_t *thrower, object_t *o, cell_t *where);
void timeeffectslf(lifeform_t *lf); void timeeffectslf(lifeform_t *lf);

47
map.c
View File

@ -193,7 +193,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
int db = B_FALSE; int db = B_FALSE;
flagpile_t *wantflags = NULL; flagpile_t *wantflags = NULL;
enum JOB wantjob = J_NONE; enum JOB wantjob = J_NONE;
enum SUBJOB wantsubjob = SJ_NONE;
if (nadded) *nadded = 0; if (nadded) *nadded = 0;
@ -220,7 +220,7 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} else { } else {
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
rid = parserace(racename, wantflags, &wantjob); rid = parserace(racename, wantflags, &wantjob, &wantsubjob);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
if (rid == R_RANDOM) { if (rid == R_RANDOM) {
@ -288,6 +288,9 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
wantjob = f->val[1]; wantjob = f->val[1];
} }
givejob(lf, wantjob); givejob(lf, wantjob);
if (f->val[2] != NA) {
givesubjob(lf, f->val[2]);
}
break; break;
} }
} }
@ -296,6 +299,9 @@ lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int
} else { } else {
givejob(lf, wantjob); givejob(lf, wantjob);
} }
if (wantsubjob != SJ_NONE) {
givesubjob(lf, wantsubjob);
}
generatealignment(lf); generatealignment(lf);
//if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging //if (gamemode == GM_GAMESTARTED) checkallflags(player->cell->map); // debugging
@ -7166,7 +7172,7 @@ int orthdir(int compassdir) {
return D_NONE; return D_NONE;
} }
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob) { enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum SUBJOB *wantsubjob) {
int donesomething; int donesomething;
char *p; char *p;
job_t *j; job_t *j;
@ -7199,6 +7205,41 @@ enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob) {
} }
} }
if (!j) {
int foundsubjob = B_FALSE;
// search for subjob names
char *ep;
ep = strends(name, "Skymage");
if (ep && !foundsubjob) {
if (wantjob) *wantjob = J_WIZARD;
if (wantsubjob) *wantsubjob = SJ_AIRMAGE;
*ep = '\0';
foundsubjob = B_TRUE;
}
ep = strends(name, "Icemage");
if (ep && !foundsubjob) {
if (wantjob) *wantjob = J_WIZARD;
if (wantsubjob) *wantsubjob = SJ_ICEMAGE;
*ep = '\0';
foundsubjob = B_TRUE;
}
ep = strends(name, "Firemage");
if (ep && !foundsubjob) {
if (wantjob) *wantjob = J_WIZARD;
if (wantsubjob) *wantsubjob = SJ_FIREMAGE;
*ep = '\0';
foundsubjob = B_TRUE;
}
ep = strends(name, "Necromancer");
if (ep && !foundsubjob) {
if (wantjob) *wantjob = J_WIZARD;
if (wantsubjob) *wantsubjob = SJ_NECROMANCER;
*ep = '\0';
foundsubjob = B_TRUE;
}
}
// now get raceid // now get raceid
if (streq(p, "random")) { if (streq(p, "random")) {
return R_RANDOM; return R_RANDOM;

2
map.h
View File

@ -164,7 +164,7 @@ void markroomwalls(map_t *m, room_t *r);
void mapentereffects(map_t *m); void mapentereffects(map_t *m);
void moveobtoclearcell(object_t *o); void moveobtoclearcell(object_t *o);
int orthdir(int compassdir); int orthdir(int compassdir);
enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob); enum RACE parserace(char *name, flagpile_t *wantflags, enum JOB *wantjob, enum SUBJOB *wantsubjob);
int remove_deadends(map_t *m, int howmuch); int remove_deadends(map_t *m, int howmuch);
void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph); void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph);
void setcellknown(cell_t *cell, int forcelev); void setcellknown(cell_t *cell, int forcelev);

8
move.c
View File

@ -1447,7 +1447,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
//precalclos(l); //precalclos(l);
} }
if (isplayer(l)) { if (isplayer(l)) { // player saw someone move
if (areenemies(lf, l) && !isplayer(lf)) { if (areenemies(lf, l) && !isplayer(lf)) {
if (!preseenbyplayer) { if (!preseenbyplayer) {
// TODO: also check for isresting(l), if we have allies standing watch // TODO: also check for isresting(l), if we have allies standing watch
@ -1465,7 +1465,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
} }
} }
} else if (isplayer(lf)) { } else if (isplayer(lf)) { // someone saw the player move.
if (areallies(lf, l)) { if (areallies(lf, l)) {
// remember player's last known loc // remember player's last known loc
f = lfhasflag(l, F_PETOF); f = lfhasflag(l, F_PETOF);
@ -2703,7 +2703,10 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
if ((reldir != RD_FORWARDS) && !lfhasflag(lf, F_AWARENESS)) { if ((reldir != RD_FORWARDS) && !lfhasflag(lf, F_AWARENESS)) {
// if the given dir is behind us, just turn. // if the given dir is behind us, just turn.
if (!strafe) { if (!strafe) {
takerotationtime(lf);
setfacing(lf, dir); setfacing(lf, dir);
drawscreen();
if (isplayer(lf)) { if (isplayer(lf)) {
addflagifneeded(lf->flags, F_TURNED, B_TRUE, NA, NA, NULL); addflagifneeded(lf->flags, F_TURNED, B_TRUE, NA, NA, NULL);
lf->turncounter++; lf->turncounter++;
@ -2712,7 +2715,6 @@ int trymove(lifeform_t *lf, int dir, int onpurpose, int strafe) {
addtempflag(lf->flags, F_CONFUSED, B_TRUE, NA, NA, NULL, 3); addtempflag(lf->flags, F_CONFUSED, B_TRUE, NA, NA, NULL, 3);
} }
} }
taketime(lf, getturnspeed(lf));
// check for fleeing... // check for fleeing...
if (isplayer(lf) && !isdead(lf)) { if (isplayer(lf) && !isdead(lf)) {
if (prebattle && !isinbattle(lf, B_FALSE) && onpurpose) { if (prebattle && !isinbattle(lf, B_FALSE) && onpurpose) {

102
nexus.c
View File

@ -34,6 +34,7 @@ raceclass_t *firstraceclass = NULL,*lastraceclass = NULL;
recipe_t *firstrecipe = NULL,*lastrecipe = NULL; recipe_t *firstrecipe = NULL,*lastrecipe = NULL;
job_t *firstjob = NULL,*lastjob = NULL; job_t *firstjob = NULL,*lastjob = NULL;
poisontype_t *firstpoisontype = NULL,*lastpoisontype = NULL; poisontype_t *firstpoisontype = NULL,*lastpoisontype = NULL;
subjob_t *firstsubjob = NULL,*lastsubjob = NULL;
skill_t *firstskill = NULL,*lastskill = NULL; skill_t *firstskill = NULL,*lastskill = NULL;
habitat_t *firsthabitat = NULL,*lasthabitat = NULL; habitat_t *firsthabitat = NULL,*lasthabitat = NULL;
map_t *firstmap = NULL,*lastmap = NULL; map_t *firstmap = NULL,*lastmap = NULL;
@ -236,12 +237,16 @@ int main(int argc, char **argv) {
if (!j) { if (!j) {
// ask for job // ask for job
initprompt(&prompt, "Select your job:"); initprompt(&prompt, "Select your base job:");
ch = 'a'; ch = 'a';
for (j = firstjob ; j ; j = j->next) { for (j = firstjob ; j ; j = j->next) {
char *longdesc;
longdesc = malloc(HUGEBUFLEN * sizeof(char));
makedesc_job(j, longdesc);
if (!hasflag(j->flags, F_NOPLAYER)) { if (!hasflag(j->flags, F_NOPLAYER)) {
addchoice(&prompt, ch++, (j->id == J_GOD) ? "Diety (for debugging)" : j->name, NULL, j, j->desc); addchoice(&prompt, ch++, (j->id == J_GOD) ? "Diety (for debugging)" : j->name, NULL, j, longdesc);
} }
free(longdesc);
} }
j = NULL; j = NULL;
while (!j) { while (!j) {
@ -333,97 +338,6 @@ int main(int argc, char **argv) {
// give the player their job // give the player their job
givejob(player, j->id); givejob(player, j->id);
// extra choices for some jobs
if (j->id == J_DRUID) {
enum OBTYPE spell;
int i;
lifeform_t *god;
for (i = 0;i < 3; i++) {
// pick a spell which you don't already have...
spell = getrandomspellfromschool(SS_NATURE, 1);
while (cancast(player, spell, NULL)) {
spell = getrandomspellfromschool(SS_NATURE, 1);
}
// you can now cast it.
addflag(player->flags, F_CANCAST, spell, NA, NA, NULL);
}
// druids always worship ekrub
god = findgod(R_GODNATURE);
addflag(god->flags, F_PRAYEDTO, B_TRUE, NA, NA, NULL);
} else if (j->id == J_WIZARD) {
skill_t *sk;
object_t *sb1,*sb2;
initprompt(&prompt, "Select your primary spell specialty:");
addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR), NULL);
addchoice(&prompt, 'c', getskillname(SK_SS_COLD), NULL, findskill(SK_SS_COLD), NULL);
addchoice(&prompt, 'f', getskillname(SK_SS_FIRE), NULL, findskill(SK_SS_FIRE), NULL);
addchoice(&prompt, 'n', getskillname(SK_SS_DEATH), NULL, findskill(SK_SS_DEATH), NULL);
addchoice(&prompt, 'w', getskillname(SK_SS_WILD), NULL, findskill(SK_SS_WILD), NULL);
getchoice(&prompt);
sk = (skill_t *) prompt.result;
switch (sk->id) {
case SK_SS_AIR:
addflag(player->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL);
sb1 = addob(player->pack, "spellbook of air magic");
break;
case SK_SS_COLD:
sb1 = addob(player->pack, "spellbook of cold magic");
break;
case SK_SS_FIRE:
sb1 = addob(player->pack, "spellbook of fire magic");
break;
case SK_SS_DEATH:
sb1 = addob(player->pack, "spellbook of necromancy");
break;
case SK_SS_WILD:
sb1 = addob(player->pack, "spellbook of wild magic");
break;
default:
sb1 = NULL;
break;
}
if (sb1) {
addflag(player->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL);
addflag(player->flags, F_SHORTCUT, 1, NA, NA, sb1->contents->first->type->name);
addflag(sb1->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
}
initprompt(&prompt, "Select your secondary spell school:");
addchoice(&prompt, 'd', getskillname(SK_SS_DIVINATION), NULL, findskill(SK_SS_DIVINATION), NULL);
addchoice(&prompt, 'g', getskillname(SK_SS_GRAVITY), NULL, findskill(SK_SS_GRAVITY), NULL);
addchoice(&prompt, 'm', getskillname(SK_SS_MODIFICATION), NULL, findskill(SK_SS_MODIFICATION), NULL);
addchoice(&prompt, 's', getskillname(SK_SS_SUMMONING), NULL, findskill(SK_SS_SUMMONING), NULL);
addchoice(&prompt, 't', getskillname(SK_SS_TRANSLOCATION), NULL, findskill(SK_SS_TRANSLOCATION), NULL);
getchoice(&prompt);
sk = (skill_t *) prompt.result;
switch (sk->id) {
case SK_SS_DIVINATION:
sb2 = addob(player->pack, "spellbook of divination magic");
break;
case SK_SS_GRAVITY:
sb2 = addob(player->pack, "spellbook of gravitation magic");
break;
case SK_SS_MODIFICATION:
sb2 = addob(player->pack, "spellbook of modification magic");
break;
case SK_SS_SUMMONING:
sb2 = addob(player->pack, "spellbook of summoning magic");
break;
case SK_SS_TRANSLOCATION:
sb2 = addob(player->pack, "spellbook of translocation magic");
break;
default:
sb2 = NULL;
break;
}
if (sb2) {
addflag(player->flags, F_CANCAST, sb2->contents->first->type->id, NA, NA, NULL);
addflag(player->flags, F_SHORTCUT, 2, NA, NA, sb2->contents->first->type->name);
addflag(sb2->flags, F_NOPOINTS, B_TRUE, NA, NA, NULL);
}
identify(sb1);
identify(sb2);
}
////////////////////// //////////////////////
// read cheat info from player file // read cheat info from player file
@ -468,7 +382,7 @@ int main(int argc, char **argv) {
} }
// more automated shortcuts // set up automated shortcuts
autoshortcut(player, OT_A_COOK); autoshortcut(player, OT_A_COOK);
getplayernamefull(pname); getplayernamefull(pname);

View File

@ -1267,6 +1267,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
dblog("DB: created abandoned temple"); dblog("DB: created abandoned temple");
raise(SIGINT); raise(SIGINT);
} }
// abandoned tamples make no sound
killflagsofid(o->flags, F_MAKESNOISE);
} }
} }
@ -2439,20 +2441,28 @@ int blessob(object_t *o) {
if (rv == B_FALSE) { if (rv == B_FALSE) {
int seen = B_FALSE; int seen = B_FALSE;
owner = o->pile->owner; if (gamemode == GM_GAMESTARTED) {
if (owner) { owner = o->pile->owner;
if (isplayer(owner)) { if (owner) {
msg("Your %s is bathed in a divine glow!", noprefix(obname)); if (isplayer(owner)) {
seen = B_TRUE; msg("Your %s is bathed in a divine glow!", noprefix(obname));
} else if (cansee(player, owner)) { seen = B_TRUE;
char ownername[BUFLEN]; } else if (cansee(player, owner)) {
msg("%s%s %s is bathed in a divine glow!", ownername, getpossessive(ownername), char ownername[BUFLEN];
noprefix(obname)); msg("%s%s %s is bathed in a divine glow!", ownername, getpossessive(ownername),
noprefix(obname));
seen = B_TRUE;
}
} else if (haslos(player, o->pile->where)) {
msg("%s is bathed in a divine glow!", obname);
seen = B_TRUE;
}
} else {
// game not started yet.
owner = o->pile->owner;
if (owner && isplayer(owner)) {
seen = B_TRUE; seen = B_TRUE;
} }
} else if (haslos(player, o->pile->where)) {
msg("%s is bathed in a divine glow!", obname);
seen = B_TRUE;
} }
if (seen) { if (seen) {

4
save.c
View File

@ -212,6 +212,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
fscanf(f, "eyeadj: %d\n",&l->eyeadjustment); fscanf(f, "eyeadj: %d\n",&l->eyeadjustment);
fscanf(f, "facing: %d\n",&l->facing); fscanf(f, "facing: %d\n",&l->facing);
fscanf(f, "turncounter: %d\n",&l->turncounter); fscanf(f, "turncounter: %d\n",&l->turncounter);
fscanf(f, "rotated: %d\n",&l->rotated);
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted); if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted);
@ -830,6 +831,7 @@ int savelf(FILE *f, lifeform_t *l) {
fprintf(f, "eyeadj: %d\n",l->eyeadjustment); fprintf(f, "eyeadj: %d\n",l->eyeadjustment);
fprintf(f, "facing: %d\n",l->facing); fprintf(f, "facing: %d\n",l->facing);
fprintf(f, "turncounter: %d\n",l->turncounter); fprintf(f, "turncounter: %d\n",l->turncounter);
fprintf(f, "rotated: %d\n",l->rotated);
// lf flags // lf flags
saveflagpile(f, l->flags); saveflagpile(f, l->flags);
@ -1154,7 +1156,7 @@ int writehiscore(lifeform_t *lf, int *rank) {
j = getjob(player); j = getjob(player);
strcpy(racename, player->race->name); strcpy(racename, player->race->name);
capitalise(racename); capitalise(racename);
snprintf(jobname, BUFLEN, "Lv%d %s %s", player->level, racename, j->name); snprintf(jobname, BUFLEN, "Lv%d %s %s", player->level, racename, getjobname(player));
makekillertext(killedby, lf->killverb, lf->lastdam, lf->cell->map, B_FALSE, B_TRUE); makekillertext(killedby, lf->killverb, lf->lastdam, lf->cell->map, B_FALSE, B_TRUE);

243
spell.c
View File

@ -1400,6 +1400,13 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
practice(user, SK_ATHLETICS, 1); practice(user, SK_ATHLETICS, 1);
} else if (abilid == OT_A_PICKLOCK) { } else if (abilid == OT_A_PICKLOCK) {
lockpick(user, NULL, NULL, NULL); lockpick(user, NULL, NULL, NULL);
} else if (abilid == OT_A_REFLEXDODGE) {
// stopping?
if (killflagsofid(user->flags, F_DODGES)) {
return B_FALSE;
}
addflag(user->flags, F_DODGES, B_TRUE, NA, NA, NULL);
} else if (abilid == OT_A_RAGE) { } else if (abilid == OT_A_RAGE) {
int howlong; int howlong;
f = lfhasflag(user, F_RAGE); f = lfhasflag(user, F_RAGE);
@ -3850,7 +3857,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// no corpse after death (so you can't keep reanimating it) // no corpse after death (so you can't keep reanimating it)
addflag(lf->flags, F_NOCORPSE, NA, NA, NA, NULL); addflag(lf->flags, F_NOCORPSE, NA, NA, NA, NULL);
if (isplayer(caster)) { if (isplayer(caster)) {
pleasegodmaybe(R_GODNATURE, 25);
angergodmaybe(R_GODFIRE, 50, GA_HERESY); angergodmaybe(R_GODFIRE, 50, GA_HERESY);
} }
@ -4365,7 +4371,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
if (ncalmed && isplayer(caster)) { if (ncalmed && isplayer(caster)) {
pleasegod(R_GODMERCY, ncalmed); pleasegodmaybe(R_GODMERCY, ncalmed);
} }
if (!donesomething) { if (!donesomething) {
@ -4815,7 +4821,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
if (isplayer(caster)) { if (isplayer(caster)) {
pleasegodmaybe(R_GODNATURE, 5);
angergodmaybe(R_GODFIRE, 50, GA_HERESY); angergodmaybe(R_GODFIRE, 50, GA_HERESY);
} }
} else if (spellid == OT_S_CREATEMONSTER) { } else if (spellid == OT_S_CREATEMONSTER) {
@ -5043,9 +5048,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (donesomething && cansee(player, target)) { if (donesomething && cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
if (isplayer(caster) && !frompot) {
pleasegodmaybe(R_GODLIFE, 3);
}
} else { } else {
fizzle(caster); fizzle(caster);
} }
@ -5781,7 +5783,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
msg("Unseen forces rip into %s%s flesh!", targetname, getpossessive(targetname)); msg("Unseen forces rip into %s%s flesh!", targetname, getpossessive(targetname));
} }
criticalhit(caster, target, getrandomcorebp(target, NULL), rnd(1,6), DT_SLASH); criticalhit(caster, target, getrandomcorebp(target, NULL), rnd(1,6), DT_SLASH);
if (isplayer(caster)) pleasegodmaybe(R_GODDEATH, 3);
} else if (spellid == OT_S_GLYPHWARDING) { } else if (spellid == OT_S_GLYPHWARDING) {
char buf[BUFLEN]; char buf[BUFLEN];
sprintf(buf, "^g*WARD%d*^n", power/2); sprintf(buf, "^g*WARD%d*^n", power/2);
@ -5846,7 +5847,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
if (isplayer(caster)) { if (isplayer(caster)) {
pleasegodmaybe(R_GODNATURE, 5);
angergodmaybe(R_GODFIRE, 75, GA_HERESY); angergodmaybe(R_GODFIRE, 75, GA_HERESY);
} }
} else { } else {
@ -6727,9 +6727,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
if (donesomething && isplayer(caster)) { if (donesomething && isplayer(caster)) {
if (!frompot) {
pleasegodmaybe(R_GODLIFE, 3);
}
// god of death REALLY doesn't like healing. // god of death REALLY doesn't like healing.
angergodmaybe(R_GODDEATH, 40, GA_HERESY); angergodmaybe(R_GODDEATH, 40, GA_HERESY);
} }
@ -8171,9 +8168,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
if (donesomething) { if (!donesomething) {
if (isplayer(caster)) pleasegodmaybe(R_GODTHIEVES, 5);
} else {
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
@ -9209,8 +9204,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster); fizzle(caster);
return B_TRUE; return B_TRUE;
} }
if (ndone && isplayer(caster) && !frompot) { if (!ndone) {
pleasegodmaybe(R_GODLIFE, 3); return B_TRUE;
} }
} else if (spellid == OT_S_LETHARGY) { } else if (spellid == OT_S_LETHARGY) {
int amttolose; int amttolose;
@ -9836,7 +9831,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
nburnt++; nburnt++;
} }
} }
if (isplayer(caster)) pleasegodmaybe(R_GODFIRE, nburnt*2);
} else if (spellid == OT_S_SPEAKDEAD) { } else if (spellid == OT_S_SPEAKDEAD) {
object_t *corpse = NULL; object_t *corpse = NULL;
@ -9849,64 +9843,84 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
char buf[BUFLEN],corpsename[BUFLEN]; char buf[BUFLEN],corpsename[BUFLEN];
char ch; char ch;
int done = B_FALSE; int done = B_FALSE;
getobname(corpse, corpsename, 1); flag_t *cf;
msg("An ghostly spirit rises from %s!", corpsename); more(); race_t *corpserace = NULL;
while (!done) { cf = hasflag(corpse->flags, F_CORPSEOF);
snprintf(buf, BUFLEN, "What will you ask %s?", corpsename); if (cf) {
initprompt(&prompt, buf); corpserace = findrace(cf->val[0]);
addchoice(&prompt, 'a', "How did you die?", NULL, NULL, NULL); }
addchoice(&prompt, 'b', "Tell me about this area", NULL, NULL, NULL); if (corpserace) {
addchoice(&prompt, 'c', "Are there any hidden dangers nearby?", NULL, NULL, NULL); getobname(corpse, corpsename, 1);
addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL); msg("An ghostly spirit rises from %s!", corpsename); more();
prompt.maycancel = B_TRUE; if (racecantalk(corpserace->id)) {
// TODO: check if you speak a common language
while (!done) {
snprintf(buf, BUFLEN, "What will you ask %s?", corpsename);
initprompt(&prompt, buf);
addchoice(&prompt, 'a', "How did you die?", NULL, NULL, NULL);
addchoice(&prompt, 'b', "Tell me about this area", NULL, NULL, NULL);
addchoice(&prompt, 'c', "Are there any hidden dangers nearby?", NULL, NULL, NULL);
addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL);
prompt.maycancel = B_TRUE;
ch = getchoice(&prompt); ch = getchoice(&prompt);
if ((ch != '\0') && (ch != '-')) { if ((ch != '\0') && (ch != '-')) {
snprintf(buf, BUFLEN, "%s whispers:", corpsename); snprintf(buf, BUFLEN, "%s whispers:", corpsename);
msg(buf); msg(buf);
} }
if (ch == 'a') { if (ch == 'a') {
flag_t *f; flag_t *f;
char *p; char *p;
f = hasflag(corpse->flags, F_CORPSEOF); f = hasflag(corpse->flags, F_CORPSEOF);
if (f && strlen(f->text)) { if (f && strlen(f->text)) {
char killer[BUFLEN]; char killer[BUFLEN];
char weapon[BUFLEN]; char weapon[BUFLEN];
p = readuntil(killer, f->text, '^'); p = readuntil(killer, f->text, '^');
if (strstr(p, "weilding")) { if (strstr(p, "weilding")) {
p = readuntil(weapon, p, '^'); p = readuntil(weapon, p, '^');
} else {
strcpy(weapon, "");
}
snprintf(buf, BUFLEN, "\"I was killed by %s", killer);
if (strlen(weapon)) {
strcat(buf, ", ");
strcat(buf, weapon);
}
strcat(buf, ".\"");
msg(buf);
} else {
msg("\"I do not know what killed me.\"");
}
} else if (ch == 'b') {
genareaknowledge(corpse->flags, 50);
docomms_areainfo(corpsename, corpse->flags, NULL);
if (onein(3)) done = B_TRUE;
} else if (ch == 'c') {
genareaknowledge(corpse->flags, 50);
docomms_areadangers(corpsename, corpse->flags, NULL);
if (onein(3)) done = B_TRUE;
} else { } else {
strcpy(weapon, ""); done = B_TRUE;
} }
snprintf(buf, BUFLEN, "\"I was killed by %s", killer); } // end while !done
if (strlen(weapon)) {
strcat(buf, ", ");
strcat(buf, weapon);
}
strcat(buf, ".\"");
msg(buf);
} else {
msg("\"I do not know what killed me.\"");
}
} else if (ch == 'b') {
genareaknowledge(corpse->flags, 50);
docomms_areainfo(corpsename, corpse->flags, NULL);
done = B_TRUE;
} else if (ch == 'c') {
genareaknowledge(corpse->flags, 50);
docomms_areadangers(corpsename, corpse->flags, NULL);
done = B_TRUE;
} else { } else {
done = B_TRUE; // can't talk
} msg("Unfortunately, the spirit doesn't seem capable of speech.");
} // end while !done } // end if cantalk
// destroy the corpse. // destroy the corpse.
msg("%s crumbles to dust.", corpsename); msg("%s crumbles to dust.", corpsename);
removeob(corpse, ALL); removeob(corpse, ALL);
} } else {
fizzle(caster);
return B_TRUE;
}
} else {
fizzle(caster);
return B_TRUE;
} // end if corpse
} else if (spellid == OT_S_STENCH) { } else if (spellid == OT_S_STENCH) {
int howlong; int howlong;
@ -10536,7 +10550,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
f = addtempflag(target->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL, FROMSPELL); f = addtempflag(target->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL, FROMSPELL);
f->obfrom = spellid; f->obfrom = spellid;
} else if (spellid == OT_S_TURNUNDEAD) { } else if (spellid == OT_S_TURNUNDEAD) {
int i; int i,ndone = 0;
lifeform_t *lf; lifeform_t *lf;
if (!target) { if (!target) {
target = caster; target = caster;
@ -10555,9 +10569,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (worked) { if (worked) {
// don't use scare() since it will fail due to them being undead. // don't use scare() since it will fail due to them being undead.
addtempflag(lf->flags, F_FLEEFROM, target->id, NA, NA, NULL,howlong); addtempflag(lf->flags, F_FLEEFROM, target->id, NA, NA, NULL,howlong);
ndone++;
} }
} }
} }
if (!ndone) {
fizzle(caster);
return B_TRUE;
}
} else if (spellid == OT_S_TWIDDLE) { } else if (spellid == OT_S_TWIDDLE) {
target = targcell->lf; target = targcell->lf;
@ -10853,7 +10872,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
if (isplayer(caster)) { if (isplayer(caster)) {
pleasegodmaybe(R_GODNATURE, 5);
angergodmaybe(R_GODFIRE, 50, GA_HERESY); angergodmaybe(R_GODFIRE, 50, GA_HERESY);
} }
} else if (spellid == OT_S_WATERJET) { } else if (spellid == OT_S_WATERJET) {
@ -11256,7 +11274,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
if (o && isplayer(caster)) { if (o && isplayer(caster)) {
pleasegodmaybe(R_GODNATURE, 5);
angergodmaybe(R_GODFIRE, 75, GA_HERESY); angergodmaybe(R_GODFIRE, 75, GA_HERESY);
} }
} else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) { } else if ((spellid == OT_S_WISH) || (spellid == OT_S_GIFT)) {
@ -11323,7 +11340,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
if (ncreated) { if (ncreated) {
if (isplayer(caster)) { if (isplayer(caster)) {
pleasegodmaybe(R_GODNATURE, 10);
angergodmaybe(R_GODFIRE, 75, GA_HERESY); angergodmaybe(R_GODFIRE, 75, GA_HERESY);
} }
} }
@ -11393,6 +11409,7 @@ enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school) {
case SS_MODIFICATION: firstspell = OT_S_OBJECTGROWTH; break; case SS_MODIFICATION: firstspell = OT_S_OBJECTGROWTH; break;
case SS_TRANSLOCATION: firstspell = OT_S_APPORTATION; break; case SS_TRANSLOCATION: firstspell = OT_S_APPORTATION; break;
case SS_SUMMONING: firstspell = OT_S_GLYPHWARDING; break; case SS_SUMMONING: firstspell = OT_S_GLYPHWARDING; break;
case SS_LIFE: firstspell = OT_S_HEALINGMIN; break;
default: default:
case SS_WILD: firstspell = OT_S_MANASPIKE; break; case SS_WILD: firstspell = OT_S_MANASPIKE; break;
} }
@ -11841,27 +11858,18 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// plus your hitdice/3 // plus your hitdice/3
power += (gethitdice(lf)/3); power += (gethitdice(lf)/3);
// plus intelligence modifier // plus stat modifier
if (school == SS_MENTAL) { power += getspellpowerstatmod(lf, school, NULL);
// +/- 2 for iq
power += (getstatmod(lf, A_IQ) / 25);
} else if (school == SS_NATURE) {
// +/- 1 for wisdom
power += (getstatmod(lf, A_WIS) / 50);
} else if (school == SS_ALLOMANCY) {
// +/- 1 for strength
power += (getstatmod(lf, A_STR) / 50);
// TODO: clerical +/- 2 for wisdom
} else {
// +/- 1 for iq
power += (getstatmod(lf, A_IQ) / 50);
}
// plus any extra school levels // plus god modifier
power += getspellpowergodmod(lf, school, NULL);
// plus any extra school levels beyond what you need
power += (schoolskill - spelllev); power += (schoolskill - spelllev);
} else { } else {
// for monsters, just based on hitdice: // for monsters, just based on hitdice:
power = gethitdice(lf); power = gethitdice(lf)/2;
limit(&power, 1, NA);
} }
power += boost; power += boost;
@ -11869,6 +11877,59 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
return power; return power;
} }
int getspellpowergodmod(lifeform_t *lf, enum SPELLSCHOOL school, enum RACE *godid) {
int mod = 0;
if (godid) *godid = A_NONE;
if (!isplayer(lf)) return 0;
if ((school == SS_LIFE) && godprayedto(R_GODLIFE)) {
int plev;
if (godid) *godid = R_GODLIFE;
plev = getpietylev(R_GODLIFE, NULL, NULL);
if (plev > 0) mod = plev;
} else if ((school == SS_DEATH) && godprayedto(R_GODDEATH)) {
int plev;
if (godid) *godid = R_GODLIFE;
plev = getpietylev(R_GODLIFE, NULL, NULL);
if (plev > 0) mod = plev;
}
return mod;
}
int getspellpowerstatmod(lifeform_t *lf, enum SPELLSCHOOL school, enum ATTRIB *att) {
int mod = 0;
if (att) *att = A_NONE;
if (!isplayer(lf)) return 0;
if (school == SS_MENTAL) {
if (att) *att = A_IQ;
// +/- 2 for iq
mod += (getstatmod(lf, A_IQ) / 25);
} else if (school == SS_NATURE) {
if (att) *att = A_WIS;
// +/- 1 for wisdom
mod += (getstatmod(lf, A_WIS) / 50);
} else if (school == SS_ALLOMANCY) {
if (att) *att = A_STR;
// +/- 1 for strength
mod += (getstatmod(lf, A_STR) / 50);
} else if (school == SS_LIFE) {
// ie. clerical.
// +/- 2 for wisdom
if (att) *att = A_WIS;
mod += (getstatmod(lf, A_WIS) / 25);
} else {
if (att) *att = A_IQ;
// +/- 1 for iq
mod += (getstatmod(lf, A_IQ) / 50);
}
return mod;
}
enum SPELLSCHOOL getspellschool(enum OBTYPE spellid) { enum SPELLSCHOOL getspellschool(enum OBTYPE spellid) {
flag_t *f; flag_t *f;
objecttype_t *ot; objecttype_t *ot;

View File

@ -23,6 +23,8 @@ int getspelllevel(enum OBTYPE spellid);
int getspellmaxpower(enum OBTYPE spellid); int getspellmaxpower(enum OBTYPE spellid);
char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf, int forcepower); char *getspellname(enum OBTYPE spellid, lifeform_t *lf, char *buf, int forcepower);
int getspellpower(lifeform_t *lf, enum OBTYPE spellid); int getspellpower(lifeform_t *lf, enum OBTYPE spellid);
int getspellpowergodmod(lifeform_t *lf, enum SPELLSCHOOL school, enum RACE *godid);
int getspellpowerstatmod(lifeform_t *lf, enum SPELLSCHOOL school, enum ATTRIB *att);
enum SPELLSCHOOL getspellschool(enum OBTYPE spellid); enum SPELLSCHOOL getspellschool(enum OBTYPE spellid);
enum SPELLSCHOOL getspellschoolknown(lifeform_t *lf, enum OBTYPE spellid); enum SPELLSCHOOL getspellschoolknown(lifeform_t *lf, enum OBTYPE spellid);
enum SKILLLEVEL getspellskill(lifeform_t *lf, enum OBTYPE spellid); enum SKILLLEVEL getspellskill(lifeform_t *lf, enum OBTYPE spellid);

44
text.c
View File

@ -955,34 +955,34 @@ char *getobmodprefix(object_t *o, obmod_t *om) {
} }
} }
} else if (isweapon(o)) { } else if (isweapon(o)) {
flag_t *f = NULL;
skill_t *sk; skill_t *sk;
sk = getobskill(o->flags); sk = getobskill(o->flags);
if (sk) { if (sk) {
if (om->id == OM_MASTERWORK) { if (!player || (getskill(player, sk->id) >= PR_BEGINNER) || (getskill(player, SK_PERCEPTION) >= PR_BEGINNER)) {
switch (sk->id) { if (om->id == OM_MASTERWORK) {
case SK_CLUBS: switch (sk->id) {
case SK_STAVES: case SK_CLUBS:
return "reinforced "; case SK_STAVES:
default: break; return "reinforced ";
} default: break;
} else if (om->id == OM_SHODDY) { }
switch (sk->id) { } else if (om->id == OM_SHODDY) {
case SK_LONGBLADES: switch (sk->id) {
case SK_SHORTBLADES: case SK_LONGBLADES:
case SK_AXES: case SK_SHORTBLADES:
return "blunted "; case SK_AXES:
case SK_CLUBS: return "blunted ";
return "cracked "; case SK_CLUBS:
case SK_POLEARMS: return "cracked ";
return "notched "; case SK_POLEARMS:
case SK_STAVES: return "notched ";
return "blunted "; case SK_STAVES:
default: break; return "blunted ";
default: break;
}
} }
} }
} }
if (f) return f->text;
} else if (isshield(o)) { } else if (isshield(o)) {
if (om->id == OM_MASTERWORK) { if (om->id == OM_MASTERWORK) {
switch (o->material->id) { switch (o->material->id) {

View File

@ -1661,7 +1661,7 @@ int vaultthingok(enum VAULTTHING vt, char *what) {
if (r) { if (r) {
return B_TRUE; return B_TRUE;
} else { } else {
if (parserace(what, NULL, NULL)) { if (parserace(what, NULL, NULL, NULL)) {
return B_TRUE; return B_TRUE;
} }
} }