1
0
Fork 0
mirror of https://codeberg.org/noisytoot/notnotdnethack.git synced 2025-07-31 09:52:25 +01:00

Convert cure disease spell to "full healing" spell

Heals 50 hp per skill level in healing spells (so 200 HP max).

Also cures sliming, disease, and blindness.

Hits only one target in a line (so can heal pets).

Adjust spellbook frequencies (healing+.5% extra healing +.5% restore ability +.5% stone to flesh +.5% full healing -2% to 1.2%

This change is save-compatible but will leave current games with the new spell at 3rd level and the old frequency. This is probably not a big deal.
This commit is contained in:
chris 2022-03-02 09:32:41 -05:00
parent 742e706f78
commit c626da87f4
8 changed files with 83 additions and 77 deletions

View file

@ -24,7 +24,7 @@ struct spell {
#define spellknow(spell) spl_book[spell].sp_know
#define emergency_spell(spell) (spellid(spell) == SPE_HEALING || spellid(spell) == SPE_EXTRA_HEALING || \
spellid(spell) == SPE_MASS_HEALING || \
spellid(spell) == SPE_CURE_BLINDNESS || spellid(spell) == SPE_CURE_SICKNESS || \
spellid(spell) == SPE_CURE_BLINDNESS || spellid(spell) == SPE_FULL_HEALING || \
spellid(spell) == SPE_RESTORE_ABILITY || spellid(spell) == SPE_REMOVE_CURSE)
#define FIRST_LIGHT MAXSPELL+1
#define PART_WATER MAXSPELL+2

View file

@ -1201,13 +1201,13 @@ wiz_makemap(VOID_ARGS)
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
int ndx = monsndx(mtmp->data);
if (mtmp->isgd) {
mtmp->isgd = 0;
mongone(mtmp);
mtmp->isgd = 0;
mongone(mtmp);
}
if (mtmp->data->geno & G_UNIQ)
mvitals[ndx].mvflags &= ~(G_EXTINCT);
if (mvitals[ndx].born)
mvitals[ndx].born--;
if (mtmp->data->geno & G_UNIQ)
mvitals[ndx].mvflags &= ~(G_EXTINCT);
if (mvitals[ndx].born)
mvitals[ndx].born--;
if (DEADMONSTER(mtmp))
continue;
if (mtmp->isshk)

View file

@ -6920,7 +6920,7 @@ short otyp;
case M_AP_MONSTER:
break;
case M_AP_OBJECT:
if (otyp == SPE_HEALING || otyp == SPE_EXTRA_HEALING) {
if (otyp == SPE_HEALING || otyp == SPE_EXTRA_HEALING || otyp == SPE_FULL_HEALING) {
pline("%s seems a more vivid %s than before.",
The(simple_typename(ap)),
c_obj_colors[objects[ap].oc_color]);

View file

@ -1523,7 +1523,7 @@ SPELL(("light", "cloth"), P_DIVINATION_SPELL, 45, 1, 1, NODIR,
SPELL(("fire storm", "flame-red"), P_ATTACK_SPELL, 0, 6, 1, NODIR, CLR_RED),
SPELL(("blizzard", "snow white"), P_ATTACK_SPELL, 0, 6, 1, NODIR, CLR_WHITE),
SPELL(("detect monsters", "leather"), P_DIVINATION_SPELL, 43, 2, 1, NODIR, HI_LEATHER),
SPELL(("healing", "white"), P_HEALING_SPELL, 40, 1, 1, IMMEDIATE, CLR_WHITE),
SPELL(("healing", "white"), P_HEALING_SPELL, 45, 1, 1, IMMEDIATE, CLR_WHITE),
SPELL(("lightning storm", "ocean blue"), P_ATTACK_SPELL, 0, 7, 1, NODIR, CLR_BLUE, O_NOWISH(1)), /* unwishable */
SPELL(("knock", "pink"), P_MATTER_SPELL, 30, 1, 1, IMMEDIATE, CLR_BRIGHT_MAGENTA),
SPELL(("force bolt", "red"), P_ATTACK_SPELL, 35, 1, 1, IMMEDIATE, CLR_RED),
@ -1537,15 +1537,15 @@ SPELL(("turn undead", "copper"), P_CLERIC_SPELL, 25, 2, 1, IMMEDIATE
SPELL(("detect food", "cyan"), P_DIVINATION_SPELL, 30, 2, 1, NODIR, CLR_CYAN),
SPELL(("cause fear", "light blue"), P_ENCHANTMENT_SPELL, 25, 3, 1, NODIR, CLR_BRIGHT_BLUE),
SPELL(("clairvoyance", "dark blue"), P_DIVINATION_SPELL, 15, 3, 1, NODIR, CLR_BLUE),
SPELL(("cure sickness", "indigo"), P_HEALING_SPELL, 32, 3, 1, NODIR, CLR_BLUE),
SPELL(("full healing", "indigo"), P_HEALING_SPELL, 12, 7, 1, IMMEDIATE, CLR_BLUE),
SPELL(("pacify monster", "fuchsia"), P_ENCHANTMENT_SPELL, 10, 3, 1, IMMEDIATE, CLR_MAGENTA),
SPELL(("charm monster", "magenta"), P_ENCHANTMENT_SPELL, 10, 5, 1, IMMEDIATE, CLR_MAGENTA),
SPELL(("haste self", "purple"), P_ESCAPE_SPELL, 33, 3, 1, NODIR, CLR_MAGENTA),
SPELL(("detect unseen", "violet"), P_DIVINATION_SPELL, 20, 3, 1, NODIR, CLR_MAGENTA),
SPELL(("levitation", "tan"), P_ESCAPE_SPELL, 20, 4, 1, NODIR, CLR_BROWN),
SPELL(("extra healing", "plaid"), P_HEALING_SPELL, 27, 3, 1, IMMEDIATE, CLR_GREEN),
SPELL(("extra healing", "plaid"), P_HEALING_SPELL, 32, 3, 1, IMMEDIATE, CLR_GREEN),
SPELL(("mass healing", "spiralbound"), P_HEALING_SPELL, 0, 6, 1, NODIR, CLR_GREEN),
SPELL(("restore ability", "light brown"), P_HEALING_SPELL, 25, 4, 1, NODIR, CLR_BROWN),
SPELL(("restore ability", "light brown"), P_HEALING_SPELL, 30, 4, 1, NODIR, CLR_BROWN),
SPELL(("invisibility", "dark brown"), P_ESCAPE_SPELL, 25, 4, 1, NODIR, CLR_BROWN),
SPELL(("detect treasure", "gray"), P_DIVINATION_SPELL, 20, 4, 1, NODIR, CLR_GRAY),
SPELL(("remove curse", "wrinkled"), P_CLERIC_SPELL, 25, 3, 1, NODIR, HI_PAPER),
@ -1560,7 +1560,7 @@ SPELL(("cancellation", "shining"), P_MATTER_SPELL, 15, 6, 1, IMMEDIATE,
SPELL(("protection", "dull"), P_CLERIC_SPELL, 18, 1, 1, NODIR, HI_PAPER),
SPELL(("abjuration","ebony"), P_CLERIC_SPELL, 10, 7, 1, NODIR, CLR_BLACK),
SPELL(("jumping", "thin"), P_ESCAPE_SPELL, 20, 1, 1, IMMEDIATE, HI_PAPER),
SPELL(("stone to flesh", "thick"), P_HEALING_SPELL, 15, 3, 1, IMMEDIATE, HI_PAPER),
SPELL(("stone to flesh", "thick"), P_HEALING_SPELL, 20, 3, 1, IMMEDIATE, HI_PAPER),
#if 0 /* DEFERRED */
SPELL(("flame sphere", "canvas"), P_MATTER_SPELL, 20, 1, 1, NODIR, CLR_BROWN),
SPELL(("freeze sphere", "hardcover"), P_MATTER_SPELL, 20, 1, 1, NODIR, CLR_BROWN),

View file

@ -206,7 +206,7 @@ struct Role roles[] = {
/* Init Lower Higher */
{ 11, 0, 0, 8, 1, 0 }, /* Hit points */
{ 1, 4, 1, 2, 0, 3 },20, /* Energy */
10, 3,-3, 2, 10, A_WIS, SPE_CURE_SICKNESS, -14
10, 3,-3, 2, 10, A_WIS, SPE_FULL_HEALING, -14
},
{ {"Knight", 0}, {
{"Gallant", 0},

View file

@ -4740,6 +4740,7 @@ dothrowspell:
case SPE_DETECT_UNSEEN:
case SPE_HEALING:
case SPE_EXTRA_HEALING:
case SPE_FULL_HEALING:
case SPE_DRAIN_LIFE:
case SPE_STONE_TO_FLESH:
if (!(objects[pseudo->otyp].oc_dir == NODIR)) {
@ -4754,6 +4755,7 @@ dothrowspell:
if (iflags.paranoid_self_cast &&
pseudo->otyp != SPE_HEALING &&
pseudo->otyp != SPE_EXTRA_HEALING &&
pseudo->otyp != SPE_FULL_HEALING &&
pseudo->otyp != SPE_TELEPORT_AWAY)
{
char buf[BUFSZ];
@ -4809,15 +4811,6 @@ dothrowspell:
case SPE_CURE_BLINDNESS:
healup(0, 0, FALSE, TRUE);
break;
case SPE_CURE_SICKNESS:
if (Sick) You("are no longer ill.");
if (Slimed) {
pline_The("slime disappears!");
Slimed = 0;
/* flags.botl = 1; -- healup() handles this */
}
healup(0, 0, TRUE, FALSE);
break;
case SPE_CREATE_FAMILIAR:
if(DimensionalLock)
pline("Nothing happens.");
@ -5550,6 +5543,12 @@ int spellID;
strcat(desc3, "Blinded creatures affected can see again.");
strcat(desc4, "");
break;
case SPE_FULL_HEALING:
strcat(desc1, "Creates a directed ray of healing magic.");
strcat(desc2, "The first creature hit by the ray is greatly healed.");
strcat(desc3, "Blinded creatures hit by the ray can see again.");
strcat(desc4, "Cures food poisioning, illness, and sliming.");
break;
case SPE_DRAIN_LIFE:
strcat(desc1, "Creates a directed ray of draining magic.");
strcat(desc2, "Creatures affected by the ray lose a level and max health.");
@ -5652,12 +5651,6 @@ int spellID;
strcat(desc3, "");
strcat(desc4, "");
break;
case SPE_CURE_SICKNESS:
strcat(desc1, "Cures food poisioning, illness, and sliming.");
strcat(desc2, "");
strcat(desc3, "");
strcat(desc4, "");
break;
case SPE_CREATE_FAMILIAR:
strcat(desc1, "Creates a tame creature.");
strcat(desc2, "1/3 of the time, the summoned creature is a tame domestic pet.");

View file

@ -396,7 +396,7 @@ int how;
t0->plrace[ROLESZ] = '\0';
(void) strncpy(t0->plgend, genders[flags.female].filecode, ROLESZ);
t0->plgend[ROLESZ] = '\0';
(void) strncpy(t0->plalign, aligns[1-u.ualign.type].filecode, ROLESZ);
(void) strncpy(t0->plalign, get_alignment_code(), ROLESZ);
t0->plalign[ROLESZ] = '\0';
(void) strncpy(t0->name, plname, NAMSZ);
t0->name[NAMSZ] = '\0';

107
src/zap.c
View file

@ -399,58 +399,59 @@ struct obj *otmp;
break;
case SPE_HEALING:
case SPE_EXTRA_HEALING:
case SPE_FULL_HEALING:
case SPE_MASS_HEALING:{
int delta = mtmp->mhp;
int health = otyp == SPE_MASS_HEALING ? (50*P_SKILL(P_HEALING_SPELL)) : (d(6, otyp != SPE_HEALING ? 8 : 4) + 6*(P_SKILL(P_HEALING_SPELL)-1));
reveal_invis = TRUE;
if (mtmp->mtyp != PM_PESTILENCE) {
char hurtmonbuf[BUFSZ];
Strcpy(hurtmonbuf, Monnam(mtmp));
wake = FALSE; /* wakeup() makes the target angry */
/* skill adjustment ranges from -6 to + 18 (-6 means 0 hp healed minimum)*/
mtmp->mhp += d(6, otyp != SPE_HEALING ? 8 : 4) + 6*(P_SKILL(P_HEALING_SPELL)-1);
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
if (mtmp->mblinded) {
mtmp->mblinded = 0;
mtmp->mcansee = 1;
}
delta = mtmp->mhp - delta; //Note: final minus initial
if (canseemon(mtmp)) {
if (disguised_mimic) {
if (mtmp->m_ap_type == M_AP_OBJECT &&
mtmp->mappearance == STRANGE_OBJECT) {
/* it can do better now */
set_mimic_sym(mtmp);
newsym(mtmp->mx, mtmp->my);
} else
mimic_hit_msg(mtmp, otyp);
} else {
if (!can_see_hurtnss_of_mon(mtmp)) {
pline("%s looks%s better.", Monnam(mtmp),
otyp != SPE_HEALING ? " much" : "" );
}
else {
pline("%s %s %s.",
hurtmonbuf,
delta != 0 ? "now looks only" : "looks",
injury_desc_word(mtmp));
char hurtmonbuf[BUFSZ];
Strcpy(hurtmonbuf, Monnam(mtmp));
wake = FALSE; /* wakeup() makes the target angry */
/* skill adjustment ranges from -6 to + 18 (-6 means 0 hp healed minimum)*/
mtmp->mhp += health;
if (mtmp->mhp > mtmp->mhpmax)
mtmp->mhp = mtmp->mhpmax;
if (mtmp->mblinded) {
mtmp->mblinded = 0;
mtmp->mcansee = 1;
}
delta = mtmp->mhp - delta; //Note: final minus initial
if (canseemon(mtmp)) {
if (disguised_mimic) {
if (mtmp->m_ap_type == M_AP_OBJECT &&
mtmp->mappearance == STRANGE_OBJECT) {
/* it can do better now */
set_mimic_sym(mtmp);
newsym(mtmp->mx, mtmp->my);
} else
mimic_hit_msg(mtmp, otyp);
} else {
if (!can_see_hurtnss_of_mon(mtmp)) {
pline("%s looks%s better.", Monnam(mtmp),
otyp != SPE_HEALING ? " much" : "" );
}
else {
pline("%s %s %s.",
hurtmonbuf,
(delta != 0 && mtmp->mhp < mtmp->mhpmax) ? "now looks only" : "looks",
injury_desc_word(mtmp));
}
}
}
}
if(mtmp->mtame && Role_if(PM_HEALER)){
int xp = (experience(mtmp, 0)/10) * delta / mtmp->mhpmax;
if(wizard) pline("%d out of %d XP", xp, experience(mtmp, 0));
if(xp)
more_experienced(xp, 0);
}
if (mtmp->mtame || mtmp->mpeaceful) {
adjalign(Role_if(PM_HEALER) ? 1 : sgn(u.ualign.type));
}
if(mtmp->mtame && Role_if(PM_HEALER)){
int xp = (experience(mtmp, 0)/10) * delta / mtmp->mhpmax;
if(wizard) pline("%d out of %d XP", xp, experience(mtmp, 0));
if(xp)
more_experienced(xp, 0);
}
if (mtmp->mtame || mtmp->mpeaceful) {
adjalign(Role_if(PM_HEALER) ? 1 : sgn(u.ualign.type));
}
} else { /* Pestilence */
/* Pestilence will always resist; damage is half of 3d{4,8} */
(void) resist(mtmp, otmp->oclass,
d(3, otyp != SPE_HEALING ? 8 : 4), TELL);
/* Pestilence will always resist; damage is half of 3d{4,8} */
(void) resist(mtmp, otmp->oclass, health/2, TELL);
}
}break;
case WAN_LIGHT: /* (broken wand) */
@ -2131,6 +2132,7 @@ struct obj *obj, *otmp;
case WAN_NOTHING:
case SPE_HEALING:
case SPE_EXTRA_HEALING:
case SPE_FULL_HEALING:
res = 0;
break;
case SPE_STONE_TO_FLESH:
@ -2733,6 +2735,15 @@ boolean ordinary;
} else
You("shudder in dread.");
break;
case SPE_FULL_HEALING:
if (Sick) You("are no longer ill.");
if (Slimed) {
pline_The("slime disappears!");
Slimed = 0;
/* flags.botl = 1; -- healup() handles this */
}
healup(50*P_SKILL(P_HEALING_SPELL), 0, TRUE, TRUE);
break;
case SPE_HEALING:
case SPE_EXTRA_HEALING:
case SPE_MASS_HEALING:
@ -2849,7 +2860,6 @@ struct obj *obj; /* wand or spell */
break;
/* Default processing via bhitm() for these */
case SPE_CURE_SICKNESS:
case WAN_MAKE_INVISIBLE:
case WAN_CANCELLATION:
case SPE_CANCELLATION:
@ -2863,6 +2873,7 @@ struct obj *obj; /* wand or spell */
case WAN_SPEED_MONSTER:
case SPE_HEALING:
case SPE_EXTRA_HEALING:
case SPE_FULL_HEALING:
case WAN_DRAINING:
case SPE_DRAIN_LIFE:
case WAN_OPENING:
@ -3480,6 +3491,8 @@ boolean *obj_destroyed;/* has object been deallocated? Pointer to boolean, may b
}
if (weapon != INVIS_BEAM) {
int res = (*fhitm)(mtmp, obj);
if(obj->otyp == SPE_FULL_HEALING)
return (struct monst *)0;
if (weapon == TRIGGER_BEAM && res) {
if (obj_destroyed) *obj_destroyed = TRUE; /* doesn't destroy obj, but signals effect was done*/
return mtmp;
@ -5365,8 +5378,8 @@ int damage, tell;
resisted = rn2(100 + alev - dlev) < mons_mr;
if (resisted) {
if (tell) {
shieldeff(mtmp->mx, mtmp->my);
pline("%s resists!", Monnam(mtmp));
shieldeff(mtmp->mx, mtmp->my);
pline("%s resists!", Monnam(mtmp));
}
damage = (damage + 1) / 2;
}