The latter is a work in progress and may have strange results. It is intended as a multiturn invocation that is interrupted by large hp losses. IMHO, reciting things is an action that needs to take several turns. Each turn an attempt at influencing intelligent monsters is made. They usually fall asleep, are confused or turn berserk. The delay gets cancelled when the player is heavily wounded or when there are no impressionable monsters around anymore.
I think the power formula will have to be tweaked.
Comments welcome!
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3321 c06c8d41-db1a-0410-9941-cceddc491573
23PFLB2E4QHL5SF3Q2YV5FXRH6MFHENEU2ACVC572ZCYDXCBZVQAC
JSIA5S666IBYAV6NHUUM6Z7WJ4PY2N2RAFDXYVDJXNHC5Z3JZGWQC
PSLBTBSCSC65MRX6TEGGFNKPXLP4OE2FZYGMM6VRJTBXTTGMP5UQC
KKEPQAZMWQFWPQ4P4KT5PWG2YFPG7H4JHL5K7USVHQ3Y6L4NWURQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
NQMXQ6OQVUSC7Y7F7IL252QW4A5JED224EECNHWAM4ZZYVNY745AC
PR2XIEELO6UJWT3EXDHWCJZGIZCCF3D6KF6LC67R6RWWAVNWEHWAC
X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC
C5VA63WAQRWPENIMXRPUPZLZJMC77PL2B3A77HYFWDCZU5QDG7VQC
RSIUBEQUGNU4LO6KH4PKVROWQS33DAKSY4XFVGN7T3CEKSXABCSAC
E5DMZFW6WCFAKTKKOQPYTQXZ2CGLWMVH64LRXDUI2UIG4VYUHIVQC
XRZPPYWPWUOM4SFNI6BHKH2UKJQNLKOV6Y7XIEPEZXE5QYRT26PAC
IIK2W5J4NQWD3BVXPJDUCTONSF2ENXPSZBWMZCBC25RCTNMKSK6AC
JW2KRJHES33W7UTWZ6NDO4TLMK4EFU4HKZXBWR2UJOMPCCOTR4CQC
CGYTZT5QWIEGYKUOLOK7MFXSLJKLYRZONER5ZCDZO5XYWSLG475QC
UZ6N6HOUPGVSPC5NQROEEDWMEGJA5XUWUY2AKH5QG65AZ25PVXDAC
UB67ZWGT7FOPKZ7SO5PAO3V4PUBPWPWXKQIQIUABNB533XP4JUMQC
BUSA7O6EFBZVAG2RL5T7MD2WTWKOEKKIAAZ2VS4Y3L6ECT4HQR6QC
5XSXMOBGXFLTIQE6WDXWWFVDOTUPZSIQ2FWT3YI5QMVU6D76IUYQC
GTPAKUU3R5AS3LQNCCZIP3BWV473RM4EB2AIS4FXAJRXHEOVH2PAC
DH3YTI6VVI727SQXO4CXSDCSBG2UN3UAWLFULBGRLBVH22ACRXIAC
AOAJ6D3OKSELEYKAT55XCVU5LYJ7SMCZKC6DIEGLLB3TF2LEENWQC
4EZVKDQA5GM3QDTNTCKEKGH4F6LGAYNLBT756PXODKZ2B7C4ZVHAC
MBBPLL4SZUB3JUUYQYLZW7S5OXRCEGJX3WWADOQXGHWQ7BIKCY5QC
OI7JKBFFIMIGWID2EJSMRP2EPEJH5YY42WTEY4QSSL6PFKRU3KJQC
5BJPWUPLJFS34FUTFJVKA4A52YMIGV6EWDXLNSDCWBJWBGVSQFGQC
SGR2P5BGJIJHVSSQYQHWS4ORLVHQBZTDES3D4BFC6SVAQXSKENNQC
LKLHWERPXMDTRNYPEXVDVB6PE7CT5PZ6WMNJJDTBBE5FBHOCEK5AC
2IJDLTWK74ULETLFTIPUIY2MSG6RNONVAFNFE7MADPT6UNYSSBDAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
WXSNNK2RXP3DQFAEQGQUZJHFWXJC7ZKG2WURZGL566UDM4YXFSWQC
V4DWL5WBO2JCODVS5QQNWXDH4DAYZN3D5V3UDCHM2KKOMADOTEDQC
KW43PGXTTM57DXUGGBQXJ5G5OYYIY3WB76TXIKL2ZCIJGH7GH4LAC
SPELL_GLAMOUR, "Glamour",
SPTYP_ENCHANTMENT,
SPFLAG_NONE,
5,
200,
NULL
},
{
// intended as a high-level Elven (a)bility
static int glamour_monsters(int x, int y, int pow, int garbage)
{
UNUSED( garbage );
int mon = mgrd[x][y];
// Power in this function is already limited by a function of
// experience level (10 + level / 2) since it's only an ability,
// never an actual spell. -- bwr
if (mon == NON_MONSTER)
return (0);
if (one_chance_in(5))
return (0);
if (mons_intel(menv[mon].type) < I_NORMAL)
return (0);
if (mons_class_holiness(mon) != MH_NATURAL)
return (0);
if (!mons_is_humanoid( menv[mon].type ))
return (0);
const char show_char = mons_char( menv[mon].type );
// gargoyles are immune.
if (menv[mon].type == MONS_GARGOYLE
|| menv[mon].type == MONS_METAL_GARGOYLE
|| menv[mon].type == MONS_MOLTEN_GARGOYLE)
{
return (0);
}
// orcs resist thru hatred of elves
// elves resist cause they're elves
// boggarts are malevolent highly magical wee-folk
if (show_char == 'o' || show_char == 'e' || menv[mon].type == MONS_BOGGART)
pow = (pow / 2) + 1;
if (check_mons_resist_magic(&menv[mon], pow))
return (0);
switch (random2(6))
{
case 0:
menv[mon].add_ench(ENCH_FEAR);
break;
case 1:
case 4:
menv[mon].add_ench(mon_enchant(ENCH_CONFUSION, 0, KC_YOU));
break;
case 2:
case 5:
menv[mon].add_ench(ENCH_CHARM);
break;
case 3:
menv[mon].behaviour = BEH_SLEEP;
break;
}
// why no, there's no message as to which effect happened >:^)
if (!one_chance_in(4))
{
std::string msg = menv[mon].name(DESC_CAP_THE);
switch (random2(4))
{
case 0:
msg += " looks dazed.";
break;
case 1:
msg += " blinks several times.";
break;
case 2:
msg += " rubs its eye";
if (menv[mon].type != MONS_CYCLOPS &&
menv[mon].type != MONS_POLYPHEMUS)
msg += "s";
msg += ".";
break;
case 3:
msg += " tilts its head.";
break;
}
mpr(msg.c_str());
}
return (1);
} // end glamour_monsters()
void cast_glamour(int pow)
{
apply_area_visible(glamour_monsters, pow);
} // end cast_glamour()
// monster cannot be affected in these states
static bool recite_mons_useless(const monsters *mon)
{
return (mons_is_fleeing(mon)
|| mons_is_sleeping(mon)
|| mons_friendly(mon)
|| mons_neutral(mon)
|| mon->has_ench(ENCH_BERSERK));
}
static int recite_to_monsters(int x, int y, int pow, int turn)
{
const int mon = mgrd[x][y];
if (mon == NON_MONSTER)
return (0);
monsters *mons = &menv[mon];
// monster must be intelligent
if (mons_intel(mons->type) < I_NORMAL)
return (0);
if (recite_mons_useless(mons))
return (0);
int attempt = 3 - turn;
bool bad_effect =
(mons_class_holiness(mon) == MH_DEMONIC? !one_chance_in(8)
: pow < random2(attempt*5));
// 50% chance nothing happens
if (bad_effect && coinflip())
return (0);
bool resist = check_mons_resist_magic(mons, pow);
if (bad_effect) // can still have positive effects
{
if (!resist)
{
if (one_chance_in(3) && mons->add_ench(mon_enchant(ENCH_CONFUSION,
0, KC_YOU, (16 + random2avg(13, 2)) * 10)))
{
simple_monster_message(mons, " looks confused.");
return (1);
}
if (one_chance_in(4) && mons->add_ench(ENCH_FEAR))
{
simple_monster_message(mons, " turns to flee.");
return (1);
}
if (one_chance_in(4))
{
mons->put_to_sleep();
simple_monster_message(mons, " falls asleep!");
return (1);
}
}
if (one_chance_in(3) && mons->add_ench(mon_enchant(ENCH_HASTE, 0,
KC_YOU, (16 + random2avg(13, 2)) * 10)))
{
simple_monster_message(mons, " is annoyed!");
return (1);
}
if (mons->can_go_berserk()) // seriously annoyed now
{
mons->go_berserk(true);
return (1);
}
return (0); // no effect
}
if (resist)
{
simple_monster_message(mons, " resists!");
return (0);
}
switch (random2(pow))
{
default: // nothing happens
return (0);
case 6:
case 7:
if (mons->add_ench(ENCH_FEAR))
{
simple_monster_message(mons, " turns to flee.");
return (1);
}
break;
case 8:
case 9:
mons->put_to_sleep();
simple_monster_message(mons, " falls asleep!");
return (1);
case 10:
case 11:
case 12:
if (mons->add_ench(mon_enchant(ENCH_CONFUSION, 0, KC_YOU,
(16 + random2avg(13, 2)) * 10)))
{
simple_monster_message(mons, " looks confused.");
return (1);
}
break;
case 13:
case 14:
if (mons->add_ench(mon_enchant(ENCH_PARALYSIS, 0, KC_YOU,
(16 + random2avg(13, 2)) * 10)))
{
simple_monster_message(mons, " is paralyzed!");
return (1);
}
break;
case 15:
case 16:
case 17:
case 18:
if (mons->add_ench(ENCH_NEUTRAL))
{
simple_monster_message(mons, " seems impressed!");
return (1);
}
break;
case 19:
case 20:
mons->attitude = ATT_NEUTRAL; // but same message as above
simple_monster_message(mons, " seems impressed!");
return (1);
}
}
// check whether there are monsters who might be influenced by Recite
bool check_recital_audience()
{
int mid;
monsters *mons;
for (int x = you.x_pos - 8; x <= you.x_pos + 8; x++)
for (int y = you.y_pos - 8; y <= you.y_pos + 8; y++)
{
if (!in_bounds(x,y) || !see_grid(x, y))
continue;
mid = mgrd[x][y];
if (mid == NON_MONSTER)
continue;
mons = &menv[mid];
// can not be affected in these states
if (recite_mons_useless(mons))
continue;;
return (true);
}
#ifdef DEBUG_DIAGNOSTICS
mpr(MSGCH_DIAGNOSTICS, "No audience found!");
#endif
// Sorry, no audience found!
return (false);
if ( delay.type == DELAY_RECITE)
{
if (!check_recital_audience() // maybe no unaffected monsters in LOS?
|| Options.hp_warning && you.hp*Options.hp_warning <= you.hp_max
&& delay.parm2*Options.hp_warning > you.hp_max
|| you.hp*2 < delay.parm2) // or significant health drop
{
stop_delay();
return;
}
}
"drop_item", "multidrop", "ascending_stairs", "descending_stairs", "run",
"rest", "travel", "macro", "interruptible", "uninterruptible",
"drop_item", "multidrop", "ascending_stairs", "descending_stairs", "recite",
"run", "rest", "travel", "macro", "interruptible", "uninterruptible",
break;
case ABIL_GLAMOUR:
if (you.duration[DUR_GLAMOUR])
{
canned_msg(MSG_CANNOT_DO_YET);
return (false);
}
mpr("You use your Elvish wiles.");
cast_glamour( 10 + random2(you.experience_level)
+ random2(you.experience_level) );
you.duration[DUR_GLAMOUR] = 20 + random2avg(13, 3);
if ( ((you.species == SP_GREY_ELF && you.experience_level >= 5) ||
(you.species == SP_HIGH_ELF && you.experience_level >= 15)) &&
you.attribute[ATTR_TRANSFORMATION] == TRAN_NONE )
{
add_talent(talents, ABIL_GLAMOUR, check_confused);
}