Flavour and help texts haven't been altered yet.
Signed-off-by: evktalo <evktalo@users.sourceforge.net>
FF6PPL5KW5DL4T7D3DHJLPCOSX7UP6IFGX5M24VYRB2SQZPYRUNQC
CQE5AHAGXM62XV3HDIY7HCT6CJCKMVLFXOXSYF2VMFNVIT3FVVUAC
7IPYQAVJ4QTC4X7P2DD5UXREZHQUFHXM2M5IYQEM5RQBXC4QCTIQC
N73PR6EHLADBQDS2XACPYB27U6A3JV3UVI7JAFFOJKCMYCH7DDEQC
MIY6J3VK53UYICLJKXUBNISHM75PBLQ43NVQH2BDHOCP4WPPSIWQC
HREZKWJTYQ5LA2LYTHOS4Z25LT5FPFPEIUTPT73HNUKEXTJM4DEAC
4SWAT5KCKQV527NKELAXFQ5XA4Q5HONQXD4VBXMUZNPVPQKPCPNAC
WZWOQZCXUB7QX7PGQMIUCH5JM5YME25GE2GMMT2NIJP5OIZUZLBQC
K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC
SCXTTP2FDNB2A7F4XXGXSSOEKZQ7ODDGN5YBCTZXGZ22CLCEH3WQC
2QEKBZU5F3XNWVLFGN3B7B3UT36VMWZXAZPUVZW6RXA62M6R4UWQC
PRQVFUGUGPKI2Q74ODEI3CYUJQB63CKC6ONQTE3BTOHKXG4JCNLQC
JW2KRJHES33W7UTWZ6NDO4TLMK4EFU4HKZXBWR2UJOMPCCOTR4CQC
DGFWFFHCEBQK2TSMHN7RYPRNRVGEAYXM7GYJ4L37Z2ZNSIIUWQ4QC
RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC
A3QXTQ5RKIGDWIKA7JHIGIHQE5EVGO6WNNWF6XY2VZNP67JESDHQC
TJ544OJG4CFFMGMAQ2B7UJT432EIBUV5HOHDAQ7GMKZZKSDBFXZQC
5UXWZHJ23JEPCI7QAF3R7JWV37LHH7I2FEWCFD4JPC5HC7YQQJ2AC
FN7DJD6MTAC4RM4CPGE5ZNEEW2I2CS7ABVWBOHOOEKWQQJQ2HPFAC
WHY6LRRJ5T2NSBE3IUCR4X3TOAH7TTK5NPUPUIFT7TPNJ6J4HBDAC
PZNRGNZPN4YLXL2UDMEUPE33AAZZ6Z2YPK6EQGYZL2PNTRWLCUNQC
264FLET5STFALEWUDOEFCR273Y5CY2WZDHL56WHZUAQ635RUN6MAC
SNKHPEWRFHRYXKHGMWFALPTWUEQJN6BIG3RS2457V3OM4HR6JPNAC
WLVGJN2ZH2PDADVF27PMRBQYFMWAZ7TB37BLUNOTPNYRFQ4Z3HKAC
GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC
Q3XHNSHW6FI4JCXSEABATRFBJPMCF7PXNG2K6ZQTRRPVMIZFHUBQC
HGBHRHXFVTEWYYV2D5HKTKL4Z6OSNR2ZOIHFQX55CVRCXQUQ7MQAC
SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC
UET576SVCGS2TXEDRTO7BUTOTLJ77MYHIVZJCDWGH2BAXYMKG6DAC
5FZYO6GQ5DWJFMRHCFSLAI4NVGK2HJ6RE7BLHBVTNQJHN75K5LUQC
SMYBWDAHD74PCW5WLNAWZA3FL6AXFEMVLOMD3OKY2Z4VWQGFNLQAC
RIGGVFYNCRFDUUCMIAN7SDEOUL4VMMZI6OYXZW72BVNI4WXJQXWQC
V3D5CG4IQU2RUM64BMLOXVYZBK3OTU7AYENTD3HTARQR2U4AZPUAC
47NSOFQMBZCDIBHEAZSENFUGDSQCX3GJHFBUZ65ARDKCYIZ435LAC
3GQ4LKESL3LNEHHTXK334UMJJV75ZKL6O763V6RMYPDUBY5GUPZAC
EADWOF6DJ7WTY3ZAFRVJ2VHFWNLDGX6W3JXESBTXJ6K4PM2AJVDQC
WXSNNK2RXP3DQFAEQGQUZJHFWXJC7ZKG2WURZGL566UDM4YXFSWQC
OYANFNGKCXG2NLQMYW4TNFU3LFK3533XQ3HFGI3LNMY4JGMDMK5QC
FLAGBNUNSIQNFDN53CDWABJRTTFWDL4PG34AI474ZKPXDEPYHOAQC
LFPHI3TJK5V4HPJJHCG5XATY23P25OVIZ4ITQVG354DJHPEPKU4AC
PFEJ4LMDNEKLMGRCMWQ7EIRVU4JMYGICI4G7X4WVWOROVXQCBZ7QC
7KBQYZSNXBMQGEEOAZI6YU34XZ5ECFGTJA32QIJDZP2NYS3SF3IQC
I67F2U3V27EIFFIEOTQN3G3NFT7PW2J7EHUMDEUC4BVNBMSJAPUQC
KLCR26P7MSX4ZWIHQHRK7BZH7M2QGCITN46FCFVHNX7U7WQWYDAQC
UW6UG6U4J27IFH2472MBAU6BT7AUKO5YW7YOTYZ5KX4JRHUNORUAC
N3NXT75G2JYKVON7ZTE3TG34BBWITCL2HHVQ6H7QREYCDTVQFSGAC
3XL4DKV7PSWAU3ZBJSKZFJ2VUYABC47I7KKWGIRCJYXULQD453MQC
bool receive_corpses(int pow, coord_def where)
{
// pow = invocations * 4, ranges from 0 to 108
mprf(MSGCH_DIAGNOSTICS, "Receive_corpses power: %d", pow);
// Kiku gives branch-appropriate corpses (like shadow creatures)
int expected_extra_corpses = (pow / 36); // 1 at 0 inv, 7 at 7 inv
int corpse_delivery_radius = 3;
// We should get the same # of corpses in a hallway as in an open room.
int spaces_for_corpses = 0;
for (radius_iterator ri(where, corpse_delivery_radius, true, true, true); ri; ++ri)
if (mons_class_can_pass(MONS_HUMAN, grd(*ri)))
spaces_for_corpses++;
int percent_chance_a_square_receives_extra_corpse = // can be > 100
(int)(
((float) expected_extra_corpses) /
((float) spaces_for_corpses)
* 100.0
);
int corpses_generated = 0;
for (radius_iterator ri(where, corpse_delivery_radius, false, true, false); ri; ++ri)
{
bool square_is_walkable = mons_class_can_pass(MONS_HUMAN, grd(*ri));
bool square_is_player_square = (*ri == where);
bool square_gets_corpse =
(random2(100) < percent_chance_a_square_receives_extra_corpse) ||
(square_is_player_square && random2(100) < 97);
if (!square_is_walkable || !square_gets_corpse)
continue;
corpses_generated++;
// Find an appropriate monster corpse
monster_type mon_type = MONS_PROGRAM_BUG;
int adjusted_power = 0;
for (int i = 0; i < 200 && !mons_class_can_be_zombified(mon_type); i++)
{
adjusted_power = std::min(pow/4,random2(random2(pow)));
mon_type = pick_local_zombifiable_monster_type(adjusted_power);
}
// Create corpse object
monsters dummy;
dummy.type = mon_type;
int index_of_corpse_created = get_item_slot();
if (mons_genus(mon_type) == MONS_HYDRA)
dummy.number = random2(20) + 1;
int valid_corpse = fill_out_corpse(&dummy, mitm[index_of_corpse_created], false);
if (!valid_corpse)
{
mitm[index_of_corpse_created].clear();
continue;
}
mitm[index_of_corpse_created].props["DoNotDropHide"] = true;
ASSERT(valid_corpse >= 0);
// Higher power means fresher corpses.
// One out of ten corpses will always be rotten.
// (Perhaps this should be different for ghouls.)
int rottedness = 200 -
((random2(10) == 5) ?
random2(175 - pow) :
random2(100 + random2(75)));
mitm[index_of_corpse_created].special = rottedness;
// Place the corpse.
move_item_to_grid( &index_of_corpse_created, *ri );
}
if (corpses_generated)
{
simple_god_message(" delivers you corpses!");
maybe_update_stashes();
return true;
} else {
simple_god_message(" can find no living being to slaughter for you!");
return false;
}
}
case GOD_KIKUBAAQUDGHA: // gives death books
if (!you.had_book[BOOK_NECROMANCY])
gift = BOOK_NECROMANCY;
else if (!you.had_book[BOOK_DEATH])
gift = BOOK_DEATH;
else if (!you.had_book[BOOK_UNLIFE])
gift = BOOK_UNLIFE;
else if (!you.had_book[BOOK_NECRONOMICON])
gift = BOOK_NECRONOMICON;
break;
mprf("%s will now %s your weapon at an altar... once.",
god_name(you.religion).c_str(),
you.religion == GOD_SHINING_ONE ? "bless" : "corrupt",
MSGCH_GOD, you.religion);
case GOD_ZIN:
simple_god_message(" will now cure all your mutations... once.");
break;
case GOD_SHINING_ONE:
simple_god_message(" will now bless your weapon at an altar... once.");
break;
case GOD_KIKUBAAQUDGHA:
simple_god_message(" will now enhance your necromancy at an altar... once.");
break;
case GOD_LUGONU:
simple_god_message(" will now corrupt your weapon at an altar... once.");
break;
default:
break;
desc += (god == GOD_SHINING_ONE ? "blessed by the Shining One" :
god == GOD_LUGONU ? "corrupted by Lugonu"
: "touched by the gods");
desc += (god == GOD_SHINING_ONE ? "blessed by the Shining One" :
god == GOD_LUGONU ? "corrupted by Lugonu" :
god == GOD_KIKUBAAQUDGHA ? "bloodied by Kikubaaqudgha"
: "touched by the gods");
// Kikubaaqudgha blesses weapons with pain, or gives you a Necronomicon
if (you.religion == GOD_KIKUBAAQUDGHA
&& !you.num_gifts[GOD_KIKUBAAQUDGHA]
&& !player_under_penance()
&& you.piety > 160)
{
simple_god_message(
" will bless your weapon with pain or grant you the Necronomicon.");
bool kiku_did_bless_weapon = false;
const int wpn = get_player_wielded_weapon();
// Does the player want a pain branding?
if (wpn != -1 && get_weapon_brand(you.inv[wpn]) != SPWPN_PAIN)
{
kiku_did_bless_weapon =
_bless_weapon(GOD_KIKUBAAQUDGHA, SPWPN_PAIN, RED);
did_bless = kiku_did_bless_weapon;
}
else mpr("You have no weapon to bloody with pain.");
// If not, ask if the player wants a Necronomicon
if (!kiku_did_bless_weapon)
{
if (!yesno("Do you wish to receive the Necronomicon?", true, 'n'))
return(false);
int thing_created = items(1, OBJ_BOOKS, BOOK_NECRONOMICON, true, 1,
MAKE_ITEM_RANDOM_RACE,
0, 0, you.religion);
if (thing_created == NON_ITEM)
return(false);
move_item_to_grid( &thing_created, you.pos() );
if (thing_created != NON_ITEM)
{
simple_god_message(" grants you a gift!");
more();
you.num_gifts[you.religion]++;
did_bless = true;
take_note(Note(NOTE_GOD_GIFT, you.religion));
mitm[thing_created].inscription = "god gift";
}
}
return(did_bless); // Return early so we don't offer our Necronomicon to Kiku
} // end kiku gifting
/* ***********************************************************************
* Returns a monster class type of a zombie that would be generated
* on the player's current level.
* *********************************************************************** */
monster_type pick_local_zombifiable_monster_type(int power);
}
monster_type pick_local_zombifiable_monster_type(int power)
{
// Generates a dummy zombie likely to be found
// Ripped wholly from _define_zombie().
power = std::min(27, power);
// How OOD this zombie can be.
int relax = 5;
// Pick an appropriate creature to make a zombie out of,
// levelwise. The old code was generating absolutely
// incredible OOD zombies.
int cls;
while (true)
{
cls = _pick_random_zombie();
bool ignore_rarity = false;
// On certain branches, zombie creation will fail if we use
// the mons_rarity() functions, because (for example) there
// are NO zombifiable "native" abyss creatures. Other branches
// where this is a problem are hell levels and the crypt.
// we have to watch for summoned zombies on other levels, too,
// such as the Temple, HoB, and Slime Pits.
if (you.level_type != LEVEL_DUNGEON
|| player_in_hell()
|| player_in_branch(BRANCH_HALL_OF_ZOT)
|| player_in_branch(BRANCH_VESTIBULE_OF_HELL)
|| player_in_branch(BRANCH_ECUMENICAL_TEMPLE)
|| player_in_branch(BRANCH_CRYPT)
|| player_in_branch(BRANCH_TOMB)
|| player_in_branch(BRANCH_HALL_OF_BLADES)
|| player_in_branch(BRANCH_SNAKE_PIT)
|| player_in_branch(BRANCH_SLIME_PITS)
|| one_chance_in(1000))
{
ignore_rarity = true;
}
// Don't make out-of-rarity zombies when we don't have to.
if (!ignore_rarity && mons_rarity(cls) == 0)
continue;
// Check for rarity.. and OOD - identical to mons_place()
int level, diff, chance;
level = mons_level(cls) - 4;
diff = level - power;
chance = (ignore_rarity) ? 100
: mons_rarity(cls) - (diff * diff) / 2;
if (power > level - relax && power < level + relax
&& random2avg(100, 2) <= chance)
{
break;
}
// Every so often, we'll relax the OOD restrictions. Avoids
// infinite loops (if we don't do this, things like creating
// a large skeleton on level 1 may hang the game!).
if (one_chance_in(5))
relax++;
}
return (monster_type)cls;
// Kiku torments if you butcher a corpse while praying
bool kiku_torments = (you.religion == GOD_KIKUBAAQUDGHA && you.piety > 120);
if (kiku_torments)
{
simple_god_message(" inflicts torment against the living!");
torment(TORMENT_GENERIC, you.pos());
you.piety -= 8 + random2(4); // 8 to 12
}
}
ABIL_KIKU_RECALL_UNDEAD_SLAVES = 130, // 130
ABIL_KIKU_ENSLAVE_UNDEAD = 132,
ABIL_KIKU_INVOKE_DEATH,
ABIL_KIKU_RECEIVE_CORPSE = 130, // 130
}
// Kiku protects you from torment to a degree.
bool kiku_shielding_player =
(you.religion == GOD_KIKUBAAQUDGHA
&& !player_res_torment()
&& !player_under_penance()
&& you.piety > 80
&& you.gift_timeout == 0); // no protection during pain branding weapon
if (kiku_shielding_player)
{
if(!player_res_torment())
{
if (random2(600) < you.piety) // 13.33% to 33.33% chance
{
hploss = 0;
simple_god_message(" shields you entirely from torment!");
} else if (random2(250) < you.piety) { // 24% to 80% chance
hploss -= random2(hploss - 1);
simple_god_message(" shields you from torment!");
}
}
{ ABIL_KIKU_RECALL_UNDEAD_SLAVES, ABIL_NON_ABILITY,
ABIL_KIKU_ENSLAVE_UNDEAD, ABIL_NON_ABILITY, ABIL_KIKU_INVOKE_DEATH },
{ ABIL_KIKU_RECEIVE_CORPSE, ABIL_NON_ABILITY,
ABIL_NON_ABILITY, ABIL_NON_ABILITY, ABIL_NON_ABILITY },
{ ABIL_KIKU_RECALL_UNDEAD_SLAVES, "Recall Undead Slaves",
2, 0, 50, 0, ABFLAG_NONE },
{ ABIL_KIKU_ENSLAVE_UNDEAD, "Enslave Undead", 4, 0, 150, 3, ABFLAG_NONE },
{ ABIL_KIKU_INVOKE_DEATH, "Invoke Death", 4, 0, 250, 3, ABFLAG_NONE },
{ ABIL_KIKU_RECEIVE_CORPSE, "Recieve Corpses", 5, 0, 1000, 2, ABFLAG_NONE },
case ABIL_KIKU_ENSLAVE_UNDEAD:
{
god_acting gdact;
beam.range = LOS_RADIUS;
if (!spell_direction(spd, beam))
return (false);
if (!zapping(ZAP_ENSLAVE_UNDEAD, you.skills[SK_INVOCATIONS] * 8, beam,
true))
{
return (false);
}
exercise(SK_INVOCATIONS, 5 + random2(5));
break;
}
case ABIL_KIKU_INVOKE_DEATH:
summon_demon_type(MONS_REAPER,
20 + you.skills[SK_INVOCATIONS] * 3,
GOD_KIKUBAAQUDGHA);
exercise(SK_INVOCATIONS, 10 + random2(14));
break;