over, so that any in-progress effects won't hurt them, thus turning them hostile and angering the player's god. Also try to avoid placing god gifts (friendly or hostile) in a damaging cloud, and if it's unavoidable and placing a friendly god gift there would anger the god then don't place them at all.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@8426 c06c8d41-db1a-0410-9941-cceddc491573
IYMUEJG2VI3TV7HVAZIU2L4DVQY7VNSIFVV4I3QIVP7H66EVJISAC NNMFGXB5BJXGHTLNP4IL3IZ6TRQWZGANE4CXRNSD2EGY47QW3I6QC IFBGMR2E3AYGZBCMTEGVWPOKZR7MV4R5XHAPIEAL2J2FTWTQBEDQC 5NGWEQYBNPFMXWZDEEH6XPF6CNDEPR5ZHVRWK4GGEIR4YRASWEVAC M5G5XXQQ3HR5UKGL234635NXOY5VK3CT7N5WBS6XFFAIXYVBINJAC YWOHKYO7MHOFSUIKYMJAWP5SMYNLU57WZHOHHOLJJFWBQF6U43MQC MIMW5CBZXQEGL6BFKK2LK322VRSBADFF7AXMC24F3OBCDUYKQTGQC PG5XH3WD6YPDOIZQ7SGHCQVXSDP5KQIGZLG7QNGHQVU6ULAVJWFAC XGPPA2X3G3266EVSTXGQ7ZWYOCJ32FEYPEUJV55AI5TGFYHTYTQQC 6PAG7GHXHIYXJPPTEK4KZQZT4CL2SJDAGTVIUDB4KK66PVSTWUMAC NK2TBKWOQBD2ZRGAO4Z3HMZPIN7UX3HNUS2YHEIJUUINUTRMPODQC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC L6RNMJ4AGWWA5FRQW5QRCFY5OD5NUB5QF7H36TNIKQYRTR2KPYPAC W3F2XPGTHDOSFFKZOHB3555C2ZTIG2KYSXEHSNODVUKGHOLYKGRQC X3CWUWK437W32BTAAQY7DQ3P4KI5CM3KQW5AW4E2VCHGEOP5WKCAC PWY4VZVHDLYL7UVNCCOW7BM7LYK2BOGTL23P75HXUJ33MHJPEJPQC CA6ZG6P2CE5EPAOQSB3P7NBDKTNFFHQP4CPOUFZL32ON6N32GSSQC YGDO5RDP2QWDEPUFJGY223VQUWCKPKQRNIWXIRXSMYHHXWJACSNAC MI7CWKRDXHAU7PIHLXXOSFBULRGT2OOMIMOSQLMVYOUVGABIVXGAC POP6UTTHSJGDU5NU7ENQJOZVFUHYM63HJ6HLPXDDLK7XFIP4XEIQC 2EPIGP4UVXPQVMQTEUQ2ZEZW65AXBSJWWQ6AKDIYVPTEFHWMH3RQC P2OYYNPHIBGOLT4CRLNTTIXDN34EU2QCMFQJNLAMUAHQXZTEDPXQC 2TFYJ7D72JY4DYQW3GSPEONA2WYIVHAJXTIQ2QRDIWF65XN2QFGAC CRU7JBTVJWTTVQ5JTRA2B3X2FPKPJ2RRR33IK2OG536VMOEZJYJAC GPEJOT73KMACP33IPAKFR5ROGHCOIP22VXZMQNYTGLEA2OSZUM2AC 4SWAT5KCKQV527NKELAXFQ5XA4Q5HONQXD4VBXMUZNPVPQKPCPNAC 3XL4DKV7PSWAU3ZBJSKZFJ2VUYABC47I7KKWGIRCJYXULQD453MQC OJKUO2UJ2O2MUITGVQNF3BQITGVYE3XK6QTG7XW6OYPJ4YFWCFQQC PNIUNDZ5EU2BP673QTWVFQFQJAAI2MAFIVEQAZMDBIMD4ZDWWXTQC 2DORUQ4B574MDOOMRYWGU5I72AKHMCSTZ6B3VSHQBUQOZYHRC7FAC S34LKQDIQJLIWVIPASOJBBZ6ZCXDHP5KPS7TRBZJSCDRVNCLK6UAC 6TEISZD7HYSSL24EOKIBNURU66KGSQX7B7SNAHBP4DQSAOTGH2MQC J77VWSSEGMKS4S3HUAKROJYFL3H5FQSO4MCEPXBFJDMYBU36VRLAC K27R6ZMYMKVNXIV7K3QU2NXRVOGQRLMR6TI6ZQQSVKXVKS76NLSQC EL35XZPOY2BCQPPVP2XJBMZJQOFPUSBX4EVSFANUBGRV2BR5ATIAC 3MAPXTL5GAQ6373CUUVPBARIRHBRSISAF3BO2WBEROT2KUAXWLGAC EI5XQIKW3OBVTDVT2A4Q535I5FOVEKARLFISM457IHGAK7TVOMVAC KFULGQQOHWUTXOM3BXCCYPGGVGGY4Z6265XUFRCBPNLTZAEHJZSQC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC 74LQ7JXVLAFSHLI7LCBKFX47CNTYSKGUQSXNX5FCIUIGCC2JTR3QC XC2U46CC57VN7ZWKWSVTN2MNZ43RLMMDZKZT7MQJFXX247WQ3NIAC B3HWU2BEQQ4E6WKVTW3JQQJFMWTVW3XWKY6BHFNBRHSZPRCF2OTQC OWERGKLVPNPGIIS23FZ7ZDOBWUIXCKYAFG3URXU75JAUDX3N5ENAC QS3ZRS3E6KL3YJHPKYEWCWJYRBJSXD5OOYF6Y25HZVECGPJRDB5QC LG7XJWUXOV4ZBMOTZX7R5NUC5IONVNCF5O42M4QVYLHNZ62AV25AC Y5YQ2AXS6XTWCHEQFDXRYU2IDQTBW7WXNJFES22GSKYQ2JGZ3U5AC OSGS3PH2L5CBTDVZCZS6OCFQNA4A7RMEXBYJQB7DDZBYYJW7QSSAC 542UIZKI65UDRNEMGFFDBWYD5XC7AYLTZ3JZQRR2GHYJALD3YY6QC 3HGELZU7NELOQ635HZO6IJIYLBSNCJ5VPH46IE22KA3OSLEFK7AQC PM65H4V4GNPVIJFUQW57DC3VDB7TRUUNXKVZONQKEFZSK3AXX5GQC 4C4D3H4E5MDQ3KT5CWXN5K6H4FVT567PN66GAAHHIWVROHZWG5CQC EHP6PYCIPYQ3KF4JFGBTZXEUQHN3FVAH4NUWEOWDDNKGPYVOTOJQC NVSFIV2ZKP44XHCSCXG6OZVGL67OIFINC34J2EMKTA4KULCERUEAC MHI3OM6VJY6LZUD577O22XREHPOPMWDVR3UT2JWGFDAKD7SO6Y3QC RYT42Z6CED4KV5CCJ45CHZ3DQGLFMDCVH6CSQZNXOILULDG4MXVQC IQGGFC563RBS7GDOACKCLXK752EE5RC3T6G5L6H446SXTMSA7T2AC typedef void (*delayed_callback)(const mgen_data &mg, int &midx, int placed);static void _delayed_monster(const mgen_data &mg,delayed_callback callback = NULL);static void _delayed_monster_done(std::string success, std::string failure,delayed_callback callback = NULL);static void _place_delayed_monsters();
if (create_monster(mgen_data(mon,!force_hostile ? BEH_FRIENDLY : BEH_HOSTILE,0, 0, you.pos(),!force_hostile ? you.pet_target : MHITYOU,0, GOD_YREDELEMNUL)) != -1)
for (int i = 0; i < how_many; ++i)
static void _beogh_reinf_callback(const mgen_data &mg, int &midx, int placed){ASSERT(mg.god == GOD_BEOGH);// Beogh tries a second time to place reinforcements.if (midx == -1)midx = create_monster(mg);if (midx == -1)return;monsters* mon = &menv[midx];mon->flags |= MF_ATT_CHANGE_ATTEMPT;bool high_level = (mon->type == MONS_ORC_PRIEST|| mon->type == MONS_ORC_WARRIOR|| mon->type == MONS_ORC_KNIGHT);// For high level orcs, there's a chance of being named.if (high_level && one_chance_in(5))give_monster_proper_name(mon);}
int monster =create_monster(mgen_data(follower_type, BEH_FRIENDLY, 0, 0,you.pos(), you.pet_target, 0, GOD_BEOGH));if (monster != -1){monsters *mon = &menv[monster];mon->flags |= MF_ATT_CHANGE_ATTEMPT;// For high level orcs, there's a chance of being named.if (high_level && one_chance_in(5))give_monster_proper_name(mon);success = true;}
_delayed_monster(mgen_data(follower_type, BEH_FRIENDLY, 0, 0,you.pos(), you.pet_target, 0, GOD_BEOGH),_beogh_reinf_callback);
if (how_many > 0){simple_god_message(how_many > 1 ? " grants you several undead servants!": " grants you an undead servant!");more();_inc_gift_timeout(4 + random2avg(7, 2));you.num_gifts[you.religion]++;take_note(Note(NOTE_GOD_GIFT, you.religion));}
_delayed_monster_done("grants you @an@ undead servant@s@!","", _delayed_gift_callback);
if(_first_attack_conduct[midx]
if ((mon->flags & NEW_GIFT_FLAGS) == NEW_GIFT_FLAGS){mprf(MSGCH_ERROR, "Newly created friendly god gift '%s' was hurt ""by you, shouldn't be possible; please file a bug report.",mon->name(DESC_PLAIN, true).c_str());_first_attack_was_friendly[midx] = true;}else if(_first_attack_conduct[midx]
/////////////////////////////////////////////////////////////////////////////// Stuff for placing god gift monsters after the player's turn has ended./////////////////////////////////////////////////////////////////////////////static std::vector<mgen_data> _delayed_data;static std::deque<delayed_callback> _delayed_callbacks;static std::deque<unsigned int> _delayed_done_trigger_pos;static std::deque<delayed_callback> _delayed_done_callbacks;static std::deque<std::string> _delayed_success;static std::deque<std::string> _delayed_failure;static void _delayed_monster(const mgen_data &mg, delayed_callback callback){_delayed_data.push_back(mg);_delayed_callbacks.push_back(callback);}static void _delayed_monster_done(std::string success, std::string failure,delayed_callback callback){const unsigned int size = _delayed_data.size();ASSERT(size > 0);_delayed_done_trigger_pos.push_back(size - 1);_delayed_success.push_back(success);_delayed_failure.push_back(failure);_delayed_done_callbacks.push_back(callback);}static void _place_delayed_monsters(){int placed = 0;god_type prev_god = GOD_NO_GOD;for (unsigned int i = 0; i < _delayed_data.size(); i++){mgen_data &mg = _delayed_data[i];delayed_callback cback = _delayed_callbacks[i];if (prev_god != mg.god){placed = 0;prev_god = mg.god;}int midx = create_monster(mg);if (cback)(*cback)(mg, midx, placed);if (midx != -1)placed++;if (_delayed_done_trigger_pos.size() > 0&& _delayed_done_trigger_pos[0] == i){cback = _delayed_done_callbacks[0];std::string msg;if (placed > 0)msg = _delayed_success[0];elsemsg = _delayed_failure[0];if (placed == 1){msg = replace_all(msg, "@a@", "a");msg = replace_all(msg, "@an@", "an");}else{msg = replace_all(msg, "@a@", "");msg = replace_all(msg, "@an@", "");}if (placed > 1)msg = replace_all(msg, "@s@", "s");elsemsg = replace_all(msg, "@s@", "");prev_god = GOD_NO_GOD;_delayed_done_trigger_pos.pop_front();_delayed_success.pop_front();_delayed_failure.pop_front();_delayed_done_callbacks.pop_front();if (msg == ""){if (cback)(*cback)(mg, midx, placed);continue;}// Fake it coming from simple_god_message().if (msg[0] == ' ' || msg[0] == '\'')msg = god_name(mg.god) + msg;msg = apostrophise_fixup(msg);trim_string(msg);god_speaks(mg.god, msg.c_str());if (cback)(*cback)(mg, midx, placed);}}_delayed_data.clear();_delayed_callbacks.clear();_delayed_done_trigger_pos.clear();_delayed_success.clear();_delayed_failure.clear();} // _place_delayed_monsters()
bool mons_avoids_cloud(const monsters *monster, cloud_type cl_type,bool placement = false,bool extra_careful = false);// Like the above, but prevents monsters from moving into cloud if it// would anger the player's god, and also allows a monster to move from// one damaging cloud to another.bool mons_avoids_cloud(const monsters *monster, int cloud_num,cloud_type *cl_type = NULL, bool placement = false);
// Like the above, but prevents monsters from moving into cloud if it// would anger the player's god, and also allows a monster to move from// one damaging cloud to another, even if they're of different types.bool mons_avoids_cloud(const monsters *monster, int cloud_num,cloud_type *cl_type, bool placement){if (cloud_num == EMPTY_CLOUD){if (cl_type != NULL)*cl_type = CLOUD_NONE;return (false);}const cloud_struct &cloud = env.cloud[cloud_num];if (cl_type != NULL)*cl_type = cloud.type;const bool careful_friendly= YOU_KILL(cloud.killer) && mons_friendly(monster)&& god_hates_attacking_friend(you.religion, monster);// Is the target cloud okay?if (!mons_avoids_cloud(monster, cloud.type, placement, careful_friendly))return (false);// If we're already in a cloud that we'd want to avoid then moving// from one to the other is okay.if (!in_bounds(monster->pos()) || monster->pos() == cloud.pos)return (true);const int our_cloud_num = env.cgrid(monster->pos());if (our_cloud_num == EMPTY_CLOUD)return (true);const cloud_struct &our_cloud = env.cloud[our_cloud_num];// Don't move monster from a cloud that won't anger their god to one// that will.if (!YOU_KILL(our_cloud.killer) && careful_friendly)return (true);return (!mons_avoids_cloud(monster, our_cloud.type, true,careful_friendly));}
const int cloud_num = env.cgrid(monster->pos());const cloud_type cl_type = cloud_num == EMPTY_CLOUD ? CLOUD_NONE: env.cloud[cloud_num].type;if (cloud_num != EMPTY_CLOUD)
cloud_type cl_type;const int cloud_num = env.cgrid(monster->pos());const bool avoid_cloud = mons_avoids_cloud(monster, cloud_num,&cl_type);if (cl_type != CLOUD_NONE)
const int targ_cloud_num = env.cgrid(targ);const cloud_type targ_cloud_type =(targ_cloud_num == EMPTY_CLOUD) ? CLOUD_NONE: env.cloud[targ_cloud_num].type;
cloud_type targ_cloud_type;const int targ_cloud_num = env.cgrid(targ);
const int curr_cloud_num = env.cgrid(monster->pos());const cloud_type curr_cloud_type =(curr_cloud_num == EMPTY_CLOUD) ? CLOUD_NONE: env.cloud[curr_cloud_num].type;
if (mons_avoids_cloud(monster, targ_cloud_num, &targ_cloud_type))return (false);
// Gods other than Xom will try to avoid placing their monsters// directly in harm's way.if (mg.god != GOD_NO_GOD && mg.god != GOD_XOM){monsters dummy;dummy.type = mg.cls;dummy.base_monster = mg.base_type;dummy.god = mg.god;int tries = 0;while (tries++ < 50&& mons_avoids_cloud(&dummy, env.cgrid(mg.pos), NULL, true)){mg.pos = find_newmons_square(montype, mg.pos);}const int cloud_num = env.cgrid(mg.pos);// Don't place friendly god gift in a damaging cloud created by// you if that would anger the god.if (mons_avoids_cloud(&dummy, cloud_num, NULL, true)&& mg.behaviour == BEH_FRIENDLY&& god_hates_attacking_friend(you.religion, &dummy)&& YOU_KILL(env.cloud[cloud_num].killer)){return (-1);}}