Split arti_invoke code into smaller functions
This commit is contained in:
+347
-286
@@ -27,6 +27,17 @@ staticfn int spec_applies(const struct artifact *, struct monst *)
|
|||||||
NONNULLARG12;
|
NONNULLARG12;
|
||||||
staticfn int invoke_ok(struct obj *);
|
staticfn int invoke_ok(struct obj *);
|
||||||
staticfn void nothing_special(struct obj *) NONNULLARG1;
|
staticfn void nothing_special(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_taming(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_healing(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_energy_boost(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_untrap(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_charge_obj(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_create_portal(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_create_ammo(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_banish(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_fling_poison(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_storm_spell(struct obj *) NONNULLARG1;
|
||||||
|
staticfn int invoke_blinding_ray(struct obj *) NONNULLARG1;
|
||||||
staticfn int arti_invoke(struct obj *);
|
staticfn int arti_invoke(struct obj *);
|
||||||
staticfn boolean Mb_hit(struct monst * magr, struct monst *mdef,
|
staticfn boolean Mb_hit(struct monst * magr, struct monst *mdef,
|
||||||
struct obj *, int *, int, boolean, char *);
|
struct obj *, int *, int, boolean, char *);
|
||||||
@@ -1750,10 +1761,331 @@ nothing_special(struct obj *obj)
|
|||||||
You_feel("a surge of power, but nothing seems to happen.");
|
You_feel("a surge of power, but nothing seems to happen.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_taming(struct obj *obj UNUSED)
|
||||||
|
{
|
||||||
|
struct obj pseudo;
|
||||||
|
|
||||||
|
pseudo = cg.zeroobj; /* neither cursed nor blessed, zero oextra too */
|
||||||
|
pseudo.otyp = SCR_TAMING;
|
||||||
|
(void) seffects(&pseudo);
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_healing(struct obj *obj)
|
||||||
|
{
|
||||||
|
int healamt = (u.uhpmax + 1 - u.uhp) / 2;
|
||||||
|
long creamed = (long) u.ucreamed;
|
||||||
|
|
||||||
|
if (Upolyd)
|
||||||
|
healamt = (u.mhmax + 1 - u.mh) / 2;
|
||||||
|
if (healamt || Sick || Slimed || Blinded > creamed)
|
||||||
|
You_feel("better.");
|
||||||
|
if (healamt || Sick || Slimed || BlindedTimeout > creamed)
|
||||||
|
You_feel("%sbetter.",
|
||||||
|
(!healamt && !Sick && !Slimed
|
||||||
|
/* when healing temporary blindness (aside from
|
||||||
|
goop covering face), might still be blind
|
||||||
|
due to PermaBlind or eyeless polymorph;
|
||||||
|
vary the message in that situation */
|
||||||
|
&& (HBlinded & ~TIMEOUT) != 0L) ? "slightly " : "");
|
||||||
|
else {
|
||||||
|
nothing_special(obj);
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
if (healamt > 0) {
|
||||||
|
if (Upolyd)
|
||||||
|
u.mh += healamt;
|
||||||
|
else
|
||||||
|
u.uhp += healamt;
|
||||||
|
}
|
||||||
|
if (Sick)
|
||||||
|
make_sick(0L, (char *) 0, FALSE, SICK_ALL);
|
||||||
|
if (Slimed)
|
||||||
|
make_slimed(0L, (char *) 0);
|
||||||
|
if (BlindedTimeout > creamed)
|
||||||
|
make_blinded(creamed, FALSE);
|
||||||
|
disp.botl = TRUE;
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_energy_boost(struct obj *obj)
|
||||||
|
{
|
||||||
|
int epboost = (u.uenmax + 1 - u.uen) / 2;
|
||||||
|
|
||||||
|
if (epboost > 120)
|
||||||
|
epboost = 120; /* arbitrary */
|
||||||
|
else if (epboost < 12)
|
||||||
|
epboost = u.uenmax - u.uen;
|
||||||
|
if (epboost) {
|
||||||
|
u.uen += epboost;
|
||||||
|
disp.botl = TRUE;
|
||||||
|
You_feel("re-energized.");
|
||||||
|
} else {
|
||||||
|
nothing_special(obj);
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_untrap(struct obj *obj)
|
||||||
|
{
|
||||||
|
if (!untrap(TRUE, 0, 0, (struct obj *) 0)) {
|
||||||
|
obj->age = 0; /* don't charge for changing their mind */
|
||||||
|
return ECMD_CANCEL;
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_charge_obj(struct obj *obj)
|
||||||
|
{
|
||||||
|
const struct artifact *oart = get_artifact(obj);
|
||||||
|
struct obj *otmp = getobj("charge", charge_ok,
|
||||||
|
GETOBJ_PROMPT | GETOBJ_ALLOWCNT);
|
||||||
|
boolean b_effect;
|
||||||
|
|
||||||
|
if (!otmp) {
|
||||||
|
obj->age = 0;
|
||||||
|
return ECMD_CANCEL;
|
||||||
|
}
|
||||||
|
b_effect = (obj->blessed && (oart->role == Role_switch
|
||||||
|
|| oart->role == NON_PM));
|
||||||
|
recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
|
||||||
|
update_inventory();
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_create_portal(struct obj *obj)
|
||||||
|
{
|
||||||
|
int i, num_ok_dungeons, last_ok_dungeon = 0;
|
||||||
|
d_level newlev;
|
||||||
|
winid tmpwin = create_nhwindow(NHW_MENU);
|
||||||
|
anything any;
|
||||||
|
int clr = NO_COLOR;
|
||||||
|
|
||||||
|
any = cg.zeroany; /* set all bits to zero */
|
||||||
|
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
||||||
|
/* use index+1 (can't use 0) as identifier */
|
||||||
|
for (i = num_ok_dungeons = 0; i < svn.n_dgns; i++) {
|
||||||
|
if (!svd.dungeons[i].dunlev_ureached)
|
||||||
|
continue;
|
||||||
|
if (i == tutorial_dnum) /* can't portal into tutorial */
|
||||||
|
continue;
|
||||||
|
any.a_int = i + 1;
|
||||||
|
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
||||||
|
ATR_NONE, clr,
|
||||||
|
svd.dungeons[i].dname, MENU_ITEMFLAGS_NONE);
|
||||||
|
num_ok_dungeons++;
|
||||||
|
last_ok_dungeon = i;
|
||||||
|
}
|
||||||
|
end_menu(tmpwin, "Open a portal to which dungeon?");
|
||||||
|
if (num_ok_dungeons > 1) {
|
||||||
|
/* more than one entry; display menu for choices */
|
||||||
|
menu_item *selected;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = select_menu(tmpwin, PICK_ONE, &selected);
|
||||||
|
if (n <= 0) {
|
||||||
|
destroy_nhwindow(tmpwin);
|
||||||
|
nothing_special(obj);
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
i = selected[0].item.a_int - 1;
|
||||||
|
free((genericptr_t) selected);
|
||||||
|
} else
|
||||||
|
i = last_ok_dungeon; /* also first & only OK dungeon */
|
||||||
|
destroy_nhwindow(tmpwin);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* i is now index into dungeon structure for the new dungeon.
|
||||||
|
* Find the closest level in the given dungeon, open
|
||||||
|
* a use-once portal to that dungeon and go there.
|
||||||
|
* The closest level is either the entry or dunlev_ureached.
|
||||||
|
*/
|
||||||
|
newlev.dnum = i;
|
||||||
|
if (svd.dungeons[i].depth_start >= depth(&u.uz))
|
||||||
|
newlev.dlevel = svd.dungeons[i].entry_lev;
|
||||||
|
else
|
||||||
|
newlev.dlevel = svd.dungeons[i].dunlev_ureached;
|
||||||
|
|
||||||
|
if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev)
|
||||||
|
|| newlev.dnum == u.uz.dnum || !next_to_u()) {
|
||||||
|
You_feel("very disoriented for a moment.");
|
||||||
|
} else {
|
||||||
|
if (!Blind)
|
||||||
|
You("are surrounded by a shimmering sphere!");
|
||||||
|
else
|
||||||
|
You_feel("weightless for a moment.");
|
||||||
|
goto_level(&newlev, FALSE, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_create_ammo(struct obj *obj)
|
||||||
|
{
|
||||||
|
struct obj *otmp = mksobj(ARROW, TRUE, FALSE);
|
||||||
|
|
||||||
|
if (!otmp) {
|
||||||
|
nothing_special(obj);
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
otmp->blessed = obj->blessed;
|
||||||
|
otmp->cursed = obj->cursed;
|
||||||
|
otmp->bknown = obj->bknown;
|
||||||
|
otmp->oeroded = otmp->oeroded2 = 0;
|
||||||
|
if (obj->blessed) {
|
||||||
|
if (otmp->spe < 0)
|
||||||
|
otmp->spe = 0;
|
||||||
|
otmp->quan += rnd(10);
|
||||||
|
} else if (obj->cursed) {
|
||||||
|
if (otmp->spe > 0)
|
||||||
|
otmp->spe = 0;
|
||||||
|
} else
|
||||||
|
otmp->quan += rnd(5);
|
||||||
|
otmp->owt = weight(otmp);
|
||||||
|
otmp = hold_another_object(otmp, "Suddenly %s out.",
|
||||||
|
aobjnam(otmp, "fall"), (char *) 0);
|
||||||
|
nhUse(otmp);
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_banish(struct obj *obj UNUSED)
|
||||||
|
{
|
||||||
|
int nvanished = 0, nstayed = 0;
|
||||||
|
struct monst *mtmp, *mtmp2;
|
||||||
|
d_level dest;
|
||||||
|
|
||||||
|
find_hell(&dest);
|
||||||
|
|
||||||
|
for (mtmp = fmon; mtmp; mtmp = mtmp2) {
|
||||||
|
int chance = 1;
|
||||||
|
|
||||||
|
mtmp2 = mtmp->nmon;
|
||||||
|
if (DEADMONSTER(mtmp) || !isok(mtmp->mx, mtmp->my))
|
||||||
|
continue;
|
||||||
|
if (!is_demon(mtmp->data) && mtmp->data->mlet != S_IMP)
|
||||||
|
continue;
|
||||||
|
if (!couldsee(mtmp->mx, mtmp->my))
|
||||||
|
continue;
|
||||||
|
if (mtmp->data->msound == MS_NEMESIS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (In_quest(&u.uz) && !svq.quest_status.killed_nemesis)
|
||||||
|
chance += 10;
|
||||||
|
if (is_dprince(mtmp->data))
|
||||||
|
chance += 2;
|
||||||
|
if (is_dlord(mtmp->data))
|
||||||
|
chance++;
|
||||||
|
|
||||||
|
mtmp->msleeping = mtmp->mtame = mtmp->mpeaceful = 0;
|
||||||
|
if (chance <= 1 || !rn2(chance)) {
|
||||||
|
if (!Inhell) {
|
||||||
|
nvanished++;
|
||||||
|
/* banish to a random level in Gehennom */
|
||||||
|
dest.dlevel = rn2(dunlevs_in_dungeon(&dest));
|
||||||
|
migrate_mon(mtmp, ledger_no(&dest), MIGR_RANDOM);
|
||||||
|
} else {
|
||||||
|
u_teleport_mon(mtmp, FALSE);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nstayed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nvanished) {
|
||||||
|
char subject[] = "demons";
|
||||||
|
|
||||||
|
if (nvanished == 1)
|
||||||
|
*(eos(subject) - 1) = '\0'; /* remove 's' */
|
||||||
|
pline("%s %s %s in a cloud of brimstone!",
|
||||||
|
nstayed ? ((nvanished > nstayed)
|
||||||
|
? "Most of the"
|
||||||
|
: "Some of the")
|
||||||
|
: "The",
|
||||||
|
subject, vtense(subject, "disappear"));
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_fling_poison(struct obj *obj)
|
||||||
|
{
|
||||||
|
if (getdir((char *) 0)) {
|
||||||
|
int venom = rn2(2) ? BLINDING_VENOM : ACID_VENOM;
|
||||||
|
struct obj *otmp = mksobj(venom, TRUE, FALSE);
|
||||||
|
|
||||||
|
otmp->spe = 1; /* the poison is yours */
|
||||||
|
throwit(otmp, 0L, FALSE, (struct obj *) 0);
|
||||||
|
} else {
|
||||||
|
/* no direction picked */
|
||||||
|
pline("%s", Never_mind);
|
||||||
|
obj->age = svm.moves;
|
||||||
|
return ECMD_CANCEL;
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_storm_spell(struct obj *obj)
|
||||||
|
{
|
||||||
|
const struct artifact *oart = get_artifact(obj);
|
||||||
|
int storm = oart->inv_prop == SNOWSTORM ? SPE_CONE_OF_COLD : SPE_FIREBALL;
|
||||||
|
int skill = spell_skilltype(storm);
|
||||||
|
int expertise = P_SKILL(skill);
|
||||||
|
|
||||||
|
P_SKILL(skill) = P_EXPERT;
|
||||||
|
(void) spelleffects(storm, FALSE, TRUE);
|
||||||
|
P_SKILL(skill) = expertise;
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
staticfn int
|
||||||
|
invoke_blinding_ray(struct obj *obj)
|
||||||
|
{
|
||||||
|
if (getdir((char *) 0)) {
|
||||||
|
if (u.dx || u.dy) {
|
||||||
|
do_blinding_ray(obj);
|
||||||
|
} else if (u.dz) {
|
||||||
|
/* up or down => light this map spot; litroom() uses
|
||||||
|
radius 0 for Sunsword, except on Rogue level where
|
||||||
|
whole room gets lit and corridor spots remain unlit */
|
||||||
|
litroom(TRUE, obj);
|
||||||
|
pline("%s", ((!Blind && levl[u.ux][u.uy].lit
|
||||||
|
&& !levl[u.ux][u.uy].waslit)
|
||||||
|
? "It is lit here now."
|
||||||
|
: nothing_seems_to_happen));
|
||||||
|
} else { /* zapyourself() */
|
||||||
|
boolean vulnerable = (u.umonnum == PM_GREMLIN);
|
||||||
|
int damg = obj->blessed ? 15 : !obj->cursed ? 10 : 5;
|
||||||
|
|
||||||
|
if (vulnerable) /* could be fatal if Unchanging */
|
||||||
|
(void) lightdamage(obj, TRUE, 2 * damg);
|
||||||
|
|
||||||
|
if (!flashburn((long) (damg + rnd(damg)), FALSE)
|
||||||
|
&& !vulnerable)
|
||||||
|
pline("%s", nothing_seems_to_happen);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* no direction picked */
|
||||||
|
pline("%s", Never_mind);
|
||||||
|
obj->age = svm.moves;
|
||||||
|
return ECMD_CANCEL;
|
||||||
|
}
|
||||||
|
return ECMD_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
staticfn int
|
staticfn int
|
||||||
arti_invoke(struct obj *obj)
|
arti_invoke(struct obj *obj)
|
||||||
{
|
{
|
||||||
const struct artifact *oart;
|
const struct artifact *oart;
|
||||||
|
int res = ECMD_OK;
|
||||||
|
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
impossible("arti_invoke without obj");
|
impossible("arti_invoke without obj");
|
||||||
@@ -1781,300 +2113,29 @@ arti_invoke(struct obj *obj)
|
|||||||
obj->age = svm.moves + rnz(100);
|
obj->age = svm.moves + rnz(100);
|
||||||
|
|
||||||
switch (oart->inv_prop) {
|
switch (oart->inv_prop) {
|
||||||
case TAMING: {
|
case TAMING: res = invoke_taming(obj); break;
|
||||||
struct obj pseudo;
|
case HEALING: res = invoke_healing(obj); break;
|
||||||
|
case ENERGY_BOOST: res = invoke_energy_boost(obj); break;
|
||||||
pseudo =
|
case UNTRAP: res = invoke_untrap(obj); break;
|
||||||
cg.zeroobj; /* neither cursed nor blessed, zero oextra too */
|
case CHARGE_OBJ: res = invoke_charge_obj(obj); break;
|
||||||
pseudo.otyp = SCR_TAMING;
|
case LEV_TELE: level_tele(); res = ECMD_TIME; break;
|
||||||
(void) seffects(&pseudo);
|
case CREATE_PORTAL: res = invoke_create_portal(obj); break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case HEALING: {
|
|
||||||
int healamt = (u.uhpmax + 1 - u.uhp) / 2;
|
|
||||||
long creamed = (long) u.ucreamed;
|
|
||||||
|
|
||||||
if (Upolyd)
|
|
||||||
healamt = (u.mhmax + 1 - u.mh) / 2;
|
|
||||||
if (healamt || Sick || Slimed || Blinded > creamed)
|
|
||||||
You_feel("better.");
|
|
||||||
if (healamt || Sick || Slimed || BlindedTimeout > creamed)
|
|
||||||
You_feel("%sbetter.",
|
|
||||||
(!healamt && !Sick && !Slimed
|
|
||||||
/* when healing temporary blindness (aside from
|
|
||||||
goop covering face), might still be blind
|
|
||||||
due to PermaBlind or eyeless polymorph;
|
|
||||||
vary the message in that situation */
|
|
||||||
&& (HBlinded & ~TIMEOUT) != 0L) ? "slightly " : "");
|
|
||||||
else {
|
|
||||||
nothing_special(obj);
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
if (healamt > 0) {
|
|
||||||
if (Upolyd)
|
|
||||||
u.mh += healamt;
|
|
||||||
else
|
|
||||||
u.uhp += healamt;
|
|
||||||
}
|
|
||||||
if (Sick)
|
|
||||||
make_sick(0L, (char *) 0, FALSE, SICK_ALL);
|
|
||||||
if (Slimed)
|
|
||||||
make_slimed(0L, (char *) 0);
|
|
||||||
if (BlindedTimeout > creamed)
|
|
||||||
make_blinded(creamed, FALSE);
|
|
||||||
disp.botl = TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ENERGY_BOOST: {
|
|
||||||
int epboost = (u.uenmax + 1 - u.uen) / 2;
|
|
||||||
|
|
||||||
if (epboost > 120)
|
|
||||||
epboost = 120; /* arbitrary */
|
|
||||||
else if (epboost < 12)
|
|
||||||
epboost = u.uenmax - u.uen;
|
|
||||||
if (epboost) {
|
|
||||||
u.uen += epboost;
|
|
||||||
disp.botl = TRUE;
|
|
||||||
You_feel("re-energized.");
|
|
||||||
} else {
|
|
||||||
nothing_special(obj);
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case UNTRAP: {
|
|
||||||
if (!untrap(TRUE, 0, 0, (struct obj *) 0)) {
|
|
||||||
obj->age = 0; /* don't charge for changing their mind */
|
|
||||||
return ECMD_OK;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CHARGE_OBJ: {
|
|
||||||
struct obj *otmp = getobj("charge", charge_ok,
|
|
||||||
GETOBJ_PROMPT | GETOBJ_ALLOWCNT);
|
|
||||||
boolean b_effect;
|
|
||||||
|
|
||||||
if (!otmp) {
|
|
||||||
obj->age = 0;
|
|
||||||
return ECMD_CANCEL;
|
|
||||||
}
|
|
||||||
b_effect = (obj->blessed && (oart->role == Role_switch
|
|
||||||
|| oart->role == NON_PM));
|
|
||||||
recharge(otmp, b_effect ? 1 : obj->cursed ? -1 : 0);
|
|
||||||
update_inventory();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case LEV_TELE:
|
|
||||||
level_tele();
|
|
||||||
break;
|
|
||||||
case CREATE_PORTAL: {
|
|
||||||
int i, num_ok_dungeons, last_ok_dungeon = 0;
|
|
||||||
d_level newlev;
|
|
||||||
winid tmpwin = create_nhwindow(NHW_MENU);
|
|
||||||
anything any;
|
|
||||||
int clr = NO_COLOR;
|
|
||||||
|
|
||||||
any = cg.zeroany; /* set all bits to zero */
|
|
||||||
start_menu(tmpwin, MENU_BEHAVE_STANDARD);
|
|
||||||
/* use index+1 (can't use 0) as identifier */
|
|
||||||
for (i = num_ok_dungeons = 0; i < svn.n_dgns; i++) {
|
|
||||||
if (!svd.dungeons[i].dunlev_ureached)
|
|
||||||
continue;
|
|
||||||
if (i == tutorial_dnum) /* can't portal into tutorial */
|
|
||||||
continue;
|
|
||||||
any.a_int = i + 1;
|
|
||||||
add_menu(tmpwin, &nul_glyphinfo, &any, 0, 0,
|
|
||||||
ATR_NONE, clr,
|
|
||||||
svd.dungeons[i].dname, MENU_ITEMFLAGS_NONE);
|
|
||||||
num_ok_dungeons++;
|
|
||||||
last_ok_dungeon = i;
|
|
||||||
}
|
|
||||||
end_menu(tmpwin, "Open a portal to which dungeon?");
|
|
||||||
if (num_ok_dungeons > 1) {
|
|
||||||
/* more than one entry; display menu for choices */
|
|
||||||
menu_item *selected;
|
|
||||||
int n;
|
|
||||||
|
|
||||||
n = select_menu(tmpwin, PICK_ONE, &selected);
|
|
||||||
if (n <= 0) {
|
|
||||||
destroy_nhwindow(tmpwin);
|
|
||||||
nothing_special(obj);
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
i = selected[0].item.a_int - 1;
|
|
||||||
free((genericptr_t) selected);
|
|
||||||
} else
|
|
||||||
i = last_ok_dungeon; /* also first & only OK dungeon */
|
|
||||||
destroy_nhwindow(tmpwin);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* i is now index into dungeon structure for the new dungeon.
|
|
||||||
* Find the closest level in the given dungeon, open
|
|
||||||
* a use-once portal to that dungeon and go there.
|
|
||||||
* The closest level is either the entry or dunlev_ureached.
|
|
||||||
*/
|
|
||||||
newlev.dnum = i;
|
|
||||||
if (svd.dungeons[i].depth_start >= depth(&u.uz))
|
|
||||||
newlev.dlevel = svd.dungeons[i].entry_lev;
|
|
||||||
else
|
|
||||||
newlev.dlevel = svd.dungeons[i].dunlev_ureached;
|
|
||||||
|
|
||||||
if (u.uhave.amulet || In_endgame(&u.uz) || In_endgame(&newlev)
|
|
||||||
|| newlev.dnum == u.uz.dnum || !next_to_u()) {
|
|
||||||
You_feel("very disoriented for a moment.");
|
|
||||||
} else {
|
|
||||||
if (!Blind)
|
|
||||||
You("are surrounded by a shimmering sphere!");
|
|
||||||
else
|
|
||||||
You_feel("weightless for a moment.");
|
|
||||||
goto_level(&newlev, FALSE, FALSE, FALSE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ENLIGHTENING:
|
case ENLIGHTENING:
|
||||||
enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
|
enlightenment(MAGICENLIGHTENMENT, ENL_GAMEINPROGRESS);
|
||||||
|
res = ECMD_TIME;
|
||||||
break;
|
break;
|
||||||
case CREATE_AMMO: {
|
case CREATE_AMMO: res = invoke_create_ammo(obj); break;
|
||||||
struct obj *otmp = mksobj(ARROW, TRUE, FALSE);
|
case BANISH: res = invoke_banish(obj); break;
|
||||||
|
case FLING_POISON: res = invoke_fling_poison(obj); break;
|
||||||
if (!otmp) {
|
|
||||||
nothing_special(obj);
|
|
||||||
return ECMD_TIME;
|
|
||||||
}
|
|
||||||
otmp->blessed = obj->blessed;
|
|
||||||
otmp->cursed = obj->cursed;
|
|
||||||
otmp->bknown = obj->bknown;
|
|
||||||
otmp->oeroded = otmp->oeroded2 = 0;
|
|
||||||
if (obj->blessed) {
|
|
||||||
if (otmp->spe < 0)
|
|
||||||
otmp->spe = 0;
|
|
||||||
otmp->quan += rnd(10);
|
|
||||||
} else if (obj->cursed) {
|
|
||||||
if (otmp->spe > 0)
|
|
||||||
otmp->spe = 0;
|
|
||||||
} else
|
|
||||||
otmp->quan += rnd(5);
|
|
||||||
otmp->owt = weight(otmp);
|
|
||||||
otmp = hold_another_object(otmp, "Suddenly %s out.",
|
|
||||||
aobjnam(otmp, "fall"), (char *) 0);
|
|
||||||
nhUse(otmp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case BANISH: {
|
|
||||||
int nvanished = 0, nstayed = 0;
|
|
||||||
struct monst *mtmp, *mtmp2;
|
|
||||||
d_level dest;
|
|
||||||
|
|
||||||
find_hell(&dest);
|
|
||||||
|
|
||||||
for (mtmp = fmon; mtmp; mtmp = mtmp2) {
|
|
||||||
int chance = 1;
|
|
||||||
|
|
||||||
mtmp2 = mtmp->nmon;
|
|
||||||
if (DEADMONSTER(mtmp) || !isok(mtmp->mx, mtmp->my))
|
|
||||||
continue;
|
|
||||||
if (!is_demon(mtmp->data) && mtmp->data->mlet != S_IMP)
|
|
||||||
continue;
|
|
||||||
if (!couldsee(mtmp->mx, mtmp->my))
|
|
||||||
continue;
|
|
||||||
if (mtmp->data->msound == MS_NEMESIS)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (In_quest(&u.uz) && !svq.quest_status.killed_nemesis)
|
|
||||||
chance += 10;
|
|
||||||
if (is_dprince(mtmp->data))
|
|
||||||
chance += 2;
|
|
||||||
if (is_dlord(mtmp->data))
|
|
||||||
chance++;
|
|
||||||
|
|
||||||
mtmp->msleeping = mtmp->mtame = mtmp->mpeaceful = 0;
|
|
||||||
if (chance <= 1 || !rn2(chance)) {
|
|
||||||
if (!Inhell) {
|
|
||||||
nvanished++;
|
|
||||||
/* banish to a random level in Gehennom */
|
|
||||||
dest.dlevel = rn2(dunlevs_in_dungeon(&dest));
|
|
||||||
migrate_mon(mtmp, ledger_no(&dest), MIGR_RANDOM);
|
|
||||||
} else {
|
|
||||||
u_teleport_mon(mtmp, FALSE);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nstayed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nvanished) {
|
|
||||||
char subject[] = "demons";
|
|
||||||
|
|
||||||
if (nvanished == 1)
|
|
||||||
*(eos(subject) - 1) = '\0'; /* remove 's' */
|
|
||||||
pline("%s %s %s in a cloud of brimstone!",
|
|
||||||
nstayed ? ((nvanished > nstayed)
|
|
||||||
? "Most of the"
|
|
||||||
: "Some of the")
|
|
||||||
: "The",
|
|
||||||
subject, vtense(subject, "disappear"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FLING_POISON:
|
|
||||||
if (getdir((char *) 0)) {
|
|
||||||
int venom = rn2(2) ? BLINDING_VENOM : ACID_VENOM;
|
|
||||||
struct obj *otmp = mksobj(venom, TRUE, FALSE);
|
|
||||||
|
|
||||||
otmp->spe = 1; /* the poison is yours */
|
|
||||||
throwit(otmp, 0L, FALSE, (struct obj *) 0);
|
|
||||||
} else {
|
|
||||||
/* no direction picked */
|
|
||||||
pline("%s", Never_mind);
|
|
||||||
obj->age = svm.moves;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SNOWSTORM:
|
case SNOWSTORM:
|
||||||
case FIRESTORM:
|
/*FALLTHRU*/
|
||||||
{
|
case FIRESTORM: res = invoke_storm_spell(obj); break;
|
||||||
int storm = oart->inv_prop == SNOWSTORM ? SPE_CONE_OF_COLD : SPE_FIREBALL;
|
case BLINDING_RAY: res = invoke_blinding_ray(obj); break;
|
||||||
int skill = spell_skilltype(storm);
|
|
||||||
int expertise = P_SKILL(skill);
|
|
||||||
|
|
||||||
P_SKILL(skill) = P_EXPERT;
|
|
||||||
(void) spelleffects(storm, FALSE, TRUE);
|
|
||||||
P_SKILL(skill) = expertise;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case BLINDING_RAY:
|
|
||||||
if (getdir((char *) 0)) {
|
|
||||||
if (u.dx || u.dy) {
|
|
||||||
do_blinding_ray(obj);
|
|
||||||
} else if (u.dz) {
|
|
||||||
/* up or down => light this map spot; litroom() uses
|
|
||||||
radius 0 for Sunsword, except on Rogue level where
|
|
||||||
whole room gets lit and corridor spots remain unlit */
|
|
||||||
litroom(TRUE, obj);
|
|
||||||
pline("%s", ((!Blind && levl[u.ux][u.uy].lit
|
|
||||||
&& !levl[u.ux][u.uy].waslit)
|
|
||||||
? "It is lit here now."
|
|
||||||
: nothing_seems_to_happen));
|
|
||||||
} else { /* zapyourself() */
|
|
||||||
boolean vulnerable = (u.umonnum == PM_GREMLIN);
|
|
||||||
int damg = obj->blessed ? 15 : !obj->cursed ? 10 : 5;
|
|
||||||
|
|
||||||
if (vulnerable) /* could be fatal if Unchanging */
|
|
||||||
(void) lightdamage(obj, TRUE, 2 * damg);
|
|
||||||
|
|
||||||
if (!flashburn((long) (damg + rnd(damg)), FALSE)
|
|
||||||
&& !vulnerable)
|
|
||||||
pline("%s", nothing_seems_to_happen);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* no direction picked */
|
|
||||||
pline("%s", Never_mind);
|
|
||||||
obj->age = svm.moves;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
impossible("Unknown invoke power %d.", oart->inv_prop);
|
impossible("Unknown invoke power %d.", oart->inv_prop);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
return res;
|
||||||
} else {
|
} else {
|
||||||
long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
|
long eprop = (u.uprops[oart->inv_prop].extrinsic ^= W_ARTI),
|
||||||
iprop = u.uprops[oart->inv_prop].intrinsic;
|
iprop = u.uprops[oart->inv_prop].intrinsic;
|
||||||
|
|||||||
Reference in New Issue
Block a user