static int throwspell(void);
static void cast_protection(void);
static void spell_backfire(int);
+static boolean spelleffects_check(int, int *, int *);
static const char *spelltypemnemonic(int);
static boolean can_center_spell_location(coordxy, coordxy);
static boolean spell_aim_step(genericptr_t, coordxy, coordxy);
spell_no);
}
+/* #wizcast - cast any spell even without knowing it */
+int
+dowizcast(void)
+{
+ winid win;
+ menu_item *selected;
+ anything any;
+ int i, n;
+
+ win = create_nhwindow(NHW_MENU);
+ start_menu(win, MENU_BEHAVE_STANDARD);
+ any = cg.zeroany;
+
+ for (i = 0; i < MAXSPELL; i++) {
+ n = (SPE_DIG + i);
+ if (n >= SPE_BLANK_PAPER)
+ break;
+ any.a_int = n;
+ add_menu(win, &nul_glyphinfo, &any, 0, 0, ATR_NONE, 0, OBJ_NAME(objects[n]), MENU_ITEMFLAGS_NONE);
+ }
+ end_menu(win, "Cast which spell?");
+ n = select_menu(win, PICK_ONE, &selected);
+ destroy_nhwindow(win);
+ if (n > 0) {
+ i = selected[0].item.a_int;
+ free((genericptr_t) selected);
+ return spelleffects(i, FALSE, TRUE);
+ }
+ return ECMD_OK;
+}
+
+
/* the #cast command -- cast a spell */
int
docast(void)
int spell_no;
if (getspell(&spell_no))
- return spelleffects(g.spl_book[spell_no].sp_id, FALSE);
+ return spelleffects(g.spl_book[spell_no].sp_id, FALSE, FALSE);
return ECMD_OK;
}
return;
}
-/* hero casts a spell of type spell_otyp, eg. SPE_SLEEP.
- hero must know the spell. */
-int
-spelleffects(int spell_otyp, boolean atme)
+static boolean
+spelleffects_check(int spell, int *res, int *energy)
{
- int spell = spell_idx(spell_otyp);
- int energy, damage, chance, n, intell;
- int otyp, skill, role_skill, res = ECMD_OK;
+ int chance;
boolean confused = (Confusion != 0);
- boolean physical_damage = FALSE;
- struct obj *pseudo;
- coord cc;
+
+ *energy = 0;
/*
* Reject attempting to cast while stunned or with no free hands.
* place in getspell(), we don't get called.)
*/
if ((spell == UNKNOWN_SPELL) || rejectcasting()) {
- return ECMD_OK; /* no time elapses */
+ *res = ECMD_OK; /* no time elapses */
+ return TRUE;
}
/*
* Note: dotele() also calculates energy use and checks nutrition
* and strength requirements; if any of these change, update it too.
*/
- energy = SPELL_LEV_PW(spellev(spell)); /* 5 <= energy <= 35 */
+ *energy = SPELL_LEV_PW(spellev(spell)); /* 5 <= energy <= 35 */
/*
* Spell casting no longer affects knowledge of the spell. A
Your("knowledge of this spell is twisted.");
pline("It invokes nightmarish images in your mind...");
spell_backfire(spell);
- u.uen -= rnd(energy);
+ u.uen -= rnd(*energy);
if (u.uen < 0)
u.uen = 0;
g.context.botl = 1;
- return ECMD_TIME;
+ *res = ECMD_TIME;
+ return TRUE;
} else if (spellknow(spell) <= KEEN / 200) { /* 100 turns left */
You("strain to recall the spell.");
} else if (spellknow(spell) <= KEEN / 40) { /* 500 turns left */
if (u.uhunger <= 10 && spellid(spell) != SPE_DETECT_FOOD) {
You("are too hungry to cast that spell.");
- return ECMD_OK;
+ *res = ECMD_OK;
+ return TRUE;
} else if (ACURR(A_STR) < 4 && spellid(spell) != SPE_RESTORE_ABILITY) {
You("lack the strength to cast spells.");
- return ECMD_OK;
+ *res = ECMD_OK;
+ return TRUE;
} else if (check_capacity(
"Your concentration falters while carrying so much stuff.")) {
- return ECMD_TIME;
+ *res = ECMD_TIME;
+ return TRUE;
}
/* if the cast attempt is already going to fail due to insufficient
in and no turn will be consumed; however, when it does kick in,
the attempt may fail due to lack of energy after the draining, in
which case a turn will be used up in addition to the energy loss */
- if (u.uhave.amulet && u.uen >= energy) {
+ if (u.uhave.amulet && u.uen >= *energy) {
You_feel("the amulet draining your energy away.");
/* this used to be 'energy += rnd(2 * energy)' (without 'res'),
so if amulet-induced cost was more than u.uen, nothing
and player could just try again (and again and again...);
now we drain some energy immediately, which has a
side-effect of not increasing the hunger aspect of casting */
- u.uen -= rnd(2 * energy);
+ u.uen -= rnd(2 * *energy);
if (u.uen < 0)
u.uen = 0;
g.context.botl = 1;
- res = ECMD_TIME; /* time is used even if spell doesn't get cast */
+ *res = ECMD_TIME; /* time is used even if spell doesn't get cast */
}
- if (energy > u.uen) {
+ if (*energy > u.uen) {
/*
* Hero has insufficient energy/power to cast the spell.
* Augment the message when current energy is at maximum.
*/
You("don't have enough energy to cast that spell%s.",
(u.uen < u.uenmax) ? "" /* not at full energy => normal message */
- : (energy > u.uenpeak) ? " yet" /* haven't ever had enough */
+ : (*energy > u.uenpeak) ? " yet" /* haven't ever had enough */
: " anymore"); /* once had enough but have lost some since */
- return res;
+ return TRUE;
} else {
if (spellid(spell) != SPE_DETECT_FOOD) {
- int hungr = energy * 2;
+ int hungr = *energy * 2;
/* If hero is a wizard, their current intelligence
* (bonuses + temporary + current)
* b) Wizards have spent their life at magic and
* understand quite well how to cast spells.
*/
- intell = acurr(A_INT);
+ int intell = acurr(A_INT);
if (!Role_if(PM_WIZARD))
intell = 10;
switch (intell) {
chance = percent_success(spell);
if (confused || (rnd(100) > chance)) {
You("fail to cast the spell correctly.");
- u.uen -= energy / 2;
+ u.uen -= *energy / 2;
g.context.botl = 1;
- return ECMD_TIME;
+ *res = ECMD_TIME;
+ return TRUE;
}
+ return FALSE;
+}
+
+/* hero casts a spell of type spell_otyp, eg. SPE_SLEEP.
+ hero must know the spell (unless force is TRUE). */
+int
+spelleffects(int spell_otyp, boolean atme, boolean force)
+{
+ int spell = force ? spell_otyp : spell_idx(spell_otyp);
+ int energy = 0, damage, n;
+ int otyp, skill, role_skill, res = ECMD_OK;
+ boolean physical_damage = FALSE;
+ struct obj *pseudo;
+ coord cc;
+
+ if (!force && spelleffects_check(spell, &res, &energy))
+ return res;
u.uen -= energy;
g.context.botl = 1;
exercise(A_WIS, TRUE);
/* pseudo is a temporary "false" object containing the spell stats */
- pseudo = mksobj(spellid(spell), FALSE, FALSE);
+ pseudo = mksobj(force ? spell : spellid(spell), FALSE, FALSE);
pseudo->blessed = pseudo->cursed = 0;
pseudo->quan = 20L; /* do not let useup get it */
/*