Skip to content

Commit

Permalink
Port splice spellbooks and wands.
Browse files Browse the repository at this point in the history
  • Loading branch information
NullCGT committed Aug 22, 2021
1 parent 8f06fe2 commit ccb30e5
Show file tree
Hide file tree
Showing 20 changed files with 1,196 additions and 48 deletions.
3 changes: 2 additions & 1 deletion include/extern.h
Expand Up @@ -451,7 +451,7 @@ extern char *rnddragonname(char *);
extern struct monst *christen_dragon(struct monst *);
extern char *rndorcname(char *);
extern struct monst *christen_orc(struct monst *, const char *, const char *);
extern const char *noveltitle(int *);
extern const char *noveltitle(int *, boolean);
extern const char *lookup_novel(const char *, int *);
#ifndef PMNAME_MACROS
extern int Mgender(struct monst *);
Expand Down Expand Up @@ -2666,6 +2666,7 @@ extern boolean lava_damage(struct obj *, xchar, xchar);
extern void acid_damage(struct obj *);
extern int water_damage(struct obj *, const char *, boolean);
extern void water_damage_chain(struct obj *, boolean);
extern int uwatereffects(void);
extern boolean drown(void);
extern void drain_en(int);
extern int dountrap(void);
Expand Down
23 changes: 20 additions & 3 deletions src/apply.c
Expand Up @@ -3502,21 +3502,36 @@ do_break_wand(struct obj *obj)
goto discard_broken_wand;
case WAN_DEATH:
case WAN_LIGHTNING:
case WAN_SONICS:
dmg *= 4;
goto wanexpl;
case WAN_FIRE:
expltype = EXPL_FIERY;
/*FALLTHRU*/
case WAN_ACID:
case WAN_POISON_GAS:
if (expltype == EXPL_MAGICAL)
expltype = EXPL_NOXIOUS;
/*FALLTHRU*/
case WAN_COLD:
if (expltype == EXPL_MAGICAL)
expltype = EXPL_FROSTY;
dmg *= 2;
/*FALLTHRU*/
case WAN_MAGIC_MISSILE:
case WAN_PSIONICS:
wanexpl:
explode(u.ux, u.uy, -(obj->otyp), dmg, WAND_CLASS, expltype);
makeknown(obj->otyp); /* explode describes the effect */
goto discard_broken_wand;
case WAN_WINDSTORM:
pline("A tornado surrounds you!");
affects_objects = TRUE;
break;
case WAN_WATER:
pline("KER-SPLOOSH!");
affects_objects = TRUE;
break;
case WAN_STRIKING:
/* we want this before the explosion instead of at the very end */
pline("A wall of force smashes down around you!");
Expand All @@ -3537,8 +3552,9 @@ do_break_wand(struct obj *obj)
/* [TODO? This really ought to prevent the explosion from being
fatal so that we never leave a bones file where none of the
surrounding targets (or underlying objects) got affected yet.] */
explode(obj->ox, obj->oy, -(obj->otyp), rnd(dmg), WAND_CLASS,
EXPL_MAGICAL);
if (obj->otyp != WAN_WINDSTORM && obj->otyp != WAN_WATER)
explode(obj->ox, obj->oy, -(obj->otyp), rnd(dmg), WAND_CLASS,
EXPL_MAGICAL);

/* prepare for potential feedback from polymorph... */
zapsetup();
Expand Down Expand Up @@ -3582,7 +3598,8 @@ do_break_wand(struct obj *obj)
: HOLE);
}
continue;
} else if (obj->otyp == WAN_CREATE_MONSTER) {
} else if (obj->otyp == WAN_CREATE_MONSTER ||
obj->otyp == WAN_CREATE_HORDE) {
/* u.ux,u.uy creates it near you--x,y might create it in rock */
(void) makemon((struct permonst *) 0, u.ux, u.uy, NO_MM_FLAGS);
continue;
Expand Down
22 changes: 19 additions & 3 deletions src/do_name.c
Expand Up @@ -2423,6 +2423,21 @@ christen_orc(struct monst *mtmp, const char *gang, const char *other)
return mtmp;
}

static const char *const encyclopedias[] = {
/* Alliteration */
"Index of Items Moste Interesting", "De Dungeons of Doom for Dummies",
"The Adventurer\'s Almanac", "The Implausibility of Identification",
"The Big Book of Bats", "Mystickism and Magick",
"Monsters Most Malevolent", "The Voluminous Volume Vol. V",
"Catacomps and Creeps", "The Encyclopedia of Enchantments",
"Mummies, Mimics, and More", "On the Magic of Markers",
/* Misc */
"A Treatise on Yendor", "Collected Essays of Og",
/* Sir Terry, Night Watch */
"Anecdotes of the Great Accountants, Vol. III",
"Some Observations on the Art of Invisibility"
};

/* make sure "The Colour of Magic" remains the first entry in here */
static const char *const sir_Terry_novels[] = {
"The Colour of Magic", "The Light Fantastic", "Equal Rites", "Mort",
Expand All @@ -2439,9 +2454,10 @@ static const char *const sir_Terry_novels[] = {
};

const char *
noveltitle(int *novidx)
noveltitle(int *novidx, boolean encyclopedia)
{
int j, k = SIZE(sir_Terry_novels);
int j = 0;
int k = encyclopedia ? SIZE(encyclopedias) : SIZE(sir_Terry_novels);

j = rn2(k);
if (novidx) {
Expand All @@ -2450,7 +2466,7 @@ noveltitle(int *novidx)
else if (*novidx >= 0 && *novidx < k)
j = *novidx;
}
return sir_Terry_novels[j];
return encyclopedia ? encyclopedias[j] : sir_Terry_novels[j];
}

/* figure out canonical novel title from player-specified one */
Expand Down
79 changes: 79 additions & 0 deletions src/engrave.c
Expand Up @@ -485,6 +485,7 @@ doengrave(void)
boolean ptext = TRUE; /* TRUE if we must prompt for engrave text */
boolean teleengr = FALSE; /* TRUE if we move the old engraving */
boolean zapwand = FALSE; /* TRUE if we remove a wand charge */
boolean wonder = FALSE; /* TRUE if the wand is a wand of wonder */
xchar type = DUST; /* Type of engraving made */
xchar oetype = 0; /* will be set to type of current engraving */
char buf[BUFSZ]; /* Buffer for final/poly engraving text */
Expand Down Expand Up @@ -654,6 +655,12 @@ doengrave(void)
if (!can_reach_floor(TRUE))
ptext = FALSE;

if (otmp->otyp == WAN_WONDER) {
otmp->otyp = WAN_LIGHT + rn2(WAN_LIGHTNING - WAN_LIGHT);
pline("You get a funny feeling about this wand.");
wonder = TRUE;
}

switch (otmp->otyp) {
/* DUST wands */
default:
Expand All @@ -662,8 +669,11 @@ doengrave(void)
case WAN_LIGHT:
case WAN_SECRET_DOOR_DETECTION:
case WAN_CREATE_MONSTER:
case WAN_CREATE_HORDE:
case WAN_WISHING:
case WAN_ENLIGHTENMENT:
if (wonder)
otmp->otyp = WAN_WONDER;
zapnodir(otmp);
break;
/* IMMEDIATE wands */
Expand All @@ -686,6 +696,14 @@ doengrave(void)
surface(u.ux, u.uy));
}
break;
case WAN_SONICS:
if (!Deaf) {
Strcpy(post_engr_text,
"The wand issues a series of loud bangs!");
doknown = TRUE;
}
wake_nearto(u.ux, u.uy, 5 * 5);
break;
case WAN_POLYMORPH:
if (oep) {
if (!Blind) {
Expand All @@ -709,7 +727,20 @@ doengrave(void)
case WAN_LOCKING:
case WAN_PROBING:
break;
case WAN_HEALING:
if (!Blind) {
Sprintf(post_engr_text, "The bugs on the %s look better!",
surface(u.ux, u.uy));
doknown = TRUE;
}
break;
/* RAY wands */
case WAN_PSIONICS:
if (!Blind)
Sprintf(post_engr_text, "The bugs on the %s run around in circles!",
surface(u.ux, u.uy));
doknown = TRUE;
break;
case WAN_MAGIC_MISSILE:
ptext = TRUE;
if (!Blind) {
Expand All @@ -718,6 +749,15 @@ doengrave(void)
surface(u.ux, u.uy));
}
break;
case WAN_WINDSTORM:
if (!Blind) {
Sprintf(post_engr_text, "The bugs on the %s are blown away!",
surface(u.ux, u.uy));
doknown = TRUE;
}
scatter(u.ux, u.uy, 4, MAY_DESTROY | MAY_HIT | VIS_EFFECTS,
(struct obj *) 0);
break;
/* can't tell sleep from death - Eric Backus */
case WAN_SLEEP:
case WAN_DEATH:
Expand All @@ -726,6 +766,27 @@ doengrave(void)
surface(u.ux, u.uy));
}
break;
case WAN_POISON_GAS:
if (!Blind) {
if (Hallucination) {
Sprintf(post_engr_text,
"The bugs on the %s cough!", surface(u.ux, u.uy));
doknown = TRUE;
} else {
Sprintf(post_engr_text,
"The bugs on the %s stop moving!", surface(u.ux, u.uy));
}
}
create_gas_cloud(u.ux, u.uy, 1, 4);
doknown = TRUE;
break;
case WAN_WATER:
if (!Blind)
Sprintf(post_engr_text,
"The bugs on the %s get washed away!", surface(u.ux, u.uy));
doknown = TRUE;
if (!oep || (oep->engr_type != BURN))
break;
case WAN_COLD:
if (!Blind)
Strcpy(post_engr_text,
Expand Down Expand Up @@ -785,6 +846,19 @@ doengrave(void)
Strcpy(post_engr_text, Blind ? "You feel the wand heat up."
: "Flames fly from the wand.");
break;
case WAN_ACID:
ptext = TRUE;
type = BURN;
if (!objects[otmp->otyp].oc_name_known && !Blind) {
if (flags.verbose)
pline("This %s is a wand of acid!", xname(otmp));
doknown = TRUE;
}
if (!Blind) {
Strcpy(post_engr_text,
"Acid sprays from the wand.");
}
break;
case WAN_LIGHTNING:
ptext = TRUE;
type = BURN;
Expand Down Expand Up @@ -896,6 +970,11 @@ doengrave(void)
* End of implement setup
*/

/* Cleanup wand of wonder */
if (wonder) {
otmp->otyp = WAN_WONDER;
doknown = TRUE;
}
/* Identify stylus */
if (doknown) {
learnwand(otmp);
Expand Down
2 changes: 1 addition & 1 deletion src/explode.c
Expand Up @@ -59,7 +59,7 @@ explode(
/* most attack wands produce specific explosions;
other types produce a generic magical explosion */
if (objects[type].oc_dir == RAY
&& type != WAN_DIGGING && type != WAN_SLEEP) {
&& type != WAN_DIGGING && type != WAN_WATER && type != WAN_SLEEP) {
type -= WAN_MAGIC_MISSILE;
if (type < 0 || type > 9) {
impossible("explode: wand has bad zap type (%d).", type);
Expand Down
1 change: 1 addition & 0 deletions src/makemon.c
Expand Up @@ -41,6 +41,7 @@ is_home_elemental(struct permonst *ptr)
return Is_firelevel(&u.uz);
case PM_ACID_ELEMENTAL:
case PM_EARTH_ELEMENTAL:
case PM_MUD_ELEMENTAL:
return Is_earthlevel(&u.uz);
case PM_WATER_ELEMENTAL:
case PM_ICE_ELEMENTAL:
Expand Down
6 changes: 4 additions & 2 deletions src/mkobj.c
Expand Up @@ -317,7 +317,7 @@ mkbox_cnts(struct obj* box)
otmp->owt = weight(otmp);
} else
while (otmp->otyp == WAN_CANCELLATION)
otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
otmp->otyp = rnd_class(WAN_LIGHT, WAN_PSIONICS);
}
}
(void) add_to_container(box, otmp);
Expand Down Expand Up @@ -1086,9 +1086,11 @@ mksobj(int otyp, boolean init, boolean artif)
case LEASH:
otmp->leashmon = 0; /* overloads corpsenm, which was set to NON_PM */
break;
case SPE_ENCYCLOPEDIA:
case SPE_NOVEL:
otmp->novelidx = -1; /* "none of the above"; will be changed */
otmp = oname(otmp, noveltitle(&otmp->novelidx));
otmp = oname(otmp, noveltitle(&otmp->novelidx,
otmp->otyp == SPE_NOVEL ? FALSE : TRUE));
break;
}

Expand Down
1 change: 1 addition & 0 deletions src/mondata.c
Expand Up @@ -1185,6 +1185,7 @@ on_fire(struct permonst* mptr, struct attack* mattk)
case PM_FOG_CLOUD:
case PM_STEAM_VORTEX:
case PM_ACID_ELEMENTAL:
case PM_MUD_ELEMENTAL:
what = "boiling";
break;
case PM_ICE_VORTEX:
Expand Down
8 changes: 8 additions & 0 deletions src/monst.c
Expand Up @@ -1393,6 +1393,14 @@ NEARDATA struct permonst mons_init[] = {
M1_NOEYES | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS | M1_BREATHLESS
| M1_UNSOLID | M1_AMPHIBIOUS | M1_SWIM,
M2_STRONG | M2_NEUTER, 0, 10, CLR_BLUE),
MON("mud elemental", S_ELEMENTAL, LVL(8, 6, 2, 30, 0), (G_NOCORPSE | G_NOGEN),
A(ATTK(AT_CLAW, AD_PHYS, 4, 6), ATTK(AT_CLAW, AD_BLND, 1, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(2500, 0, MS_SILENT, MZ_LARGE),
MR_FIRE | MR_COLD | MR_POISON | MR_STONE, 0,
M1_NOEYES | M1_NOLIMBS | M1_NOHEAD | M1_MINDLESS | M1_BREATHLESS
| M1_WALLWALK | M1_UNSOLID | M1_THICK_HIDE | M1_AMPHIBIOUS | M1_SWIM,
M2_STRONG | M2_NEUTER, 0, 11, CLR_BROWN),
MON("acid elemental", S_ELEMENTAL, LVL(8, 6, 2, 30, 0), (G_NOCORPSE | G_NOGEN),
A(ATTK(AT_CLAW, AD_ACID, 3, 6), ATTK(AT_NONE, AD_ACID, 0, 4),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
Expand Down

0 comments on commit ccb30e5

Please sign in to comment.