adjusted per monster to hand out the right resists. The current MR_RES_FIRE gives one level of resistance only.
Added a real ghost structure, discarded the old ghost values array. Adjusted bones file format so bones will work out-of-the-box with Hearse. Breaks bones format, older bones will be rejected.
Fixed some maps with bad DEPTHs.
Added more safe answers in Y/N prompts, added a check to make it less likely that Crawl will spin in a tight loop reading input from a closed tty.
(Experimental) !a will override existing foe of friendlies in LOS.
Blademasters no longer pick up stuff to throw (Erik).
Zombies of swimming things are also swimming things. Currently applies only to zombies explicitly placed in .des files, since fish zombies cannot be generated otherwise (can of worms).
Morgue is now saved before showing the inventory and other boring end-of-game stuff.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@3231 c06c8d41-db1a-0410-9941-cceddc491573
RBAGQ2PB7V5YAM5KSHSZR2E3MLKDSRVM5XYGI2TIXP5QMVBOQHDQC YLURD6WHTJTFIOY3CAK7BXWYRCS4RSIGK7FGMA7WPAMLJ3CXJIXQC G2IBQUJ2V2OGM4TR6VKC4CLNVLALTDLB5STOBN7637GOUX2SH4ZAC SPFKVC5KJVGMD4ITZWLWTB6N42IV6AWXGPEEXCYPI7BGFZKY5FHAC ID373JATLMWAY526Q6Q5FXHRNFWMEOFXPHGPAUUY5OAMPFDN5SJAC BK6MGPSEAEMU4URBAPKY3VTKK6JC6IZVN5CNOSN2UPTIOWQYEWLQC 5OZIFI7NLISEF4X2GXHWBCUA7VHPPLE45DFOXO33TACCV2SMROWQC J5EZS3FSHLPKMZSCHEQHNQRRFJMOEZ4OIGHSP6QSCZJW2XYUAVSAC W74555HMPXUQ72AGKBXC5P3STMMX5DZAW6ZESUDLNVJBCAG43PLAC 6UPCB64Z2W243QR3JQD7WPQMPVNVBPYRG7GTGZK6LTKKBBSKBHZQC A5H6EHZ5L5Z3BW2MIEJSDZMGTUQIJT6HSQXJVFBN5ZR55SGNNQNQC VUWJVWO2E2ADJ6CZGDHAQCXZOGI7AMMZZW4QSHREXMVTQDTZQPUAC ZNGET7722J4PJXQM7IISUIIUFGB6D7WBD4IXR4QQENHERHXOG7KQC TVC7W7C2XKBQSD2IJFMWFVGXZAOD4EUOW43NAQTOF5KFMAUOJABQC ZWYVZW5QFM5I2F6BLMNDDTV7FROJUHOO3O2BCBG7WSCKMKXUEMTQC ZNI3CWU5DWBFSULG4UWOW7AGV2JIBLXE5U3EOF6ESZDLFO2ZDT7QC DQUTMKIMQUJDOAC3YHRK5W4PDCOKVPQFSV7OWWS75CCUMC5B2PGAC OPNCHI4UGN7WBIYPAXVV2C4N22ZSWROA435FJCY5UZVXKWRYQ42QC V53DXVC5T3N6J47H2CNG4MMPRR4PHW4AIS66QNVTKJNNYTTTQL4AC RPOZZWKG5GLPHVZZ7ZKMKS64ZMV2LDCQSARBJFJ6FZOTOKCQO7FAC K2CS6TCX2NDVL2ASEHGP4J4K4IJ6FP3ANNKTSIWVG43HPYSBX6ZQC J6APXOT4QOGQFONWB7G546VTVF6QG42HVOROMHF7YBDJPR4K26OAC 7AMQN7MITMXBNVDAK5VOXTQ4TZIAOD6ZLOFJG7GQMBTY23Y2BKSAC 7KWDC7XFNMBLSUO2HISIROBINZBX5T67LJEEXTAORXW2YZ7VWFGAC SDLKLUNFGVKDS55DDJZCBAVIB7NL3RRYPTACAY65SCUQKV6APFSAC DDU4A3JGN5IUIPP5IASOODKPR2WBHSDSV4FITZ6HNXNSXXQACWAQC 5ASC3STDYCNLZFEBN6UTMUCGDETHBR2OCBZCF5VIAZ5RRWLOTDYQC QDTVLBRGHDTRUVT7I3O72K6TMOYAUSAJBZUHGOEFU2RKJNUPWZSQC AVCMVFA3MKCXHO6H44UK5KJNIHTGQV7UA7GYXM26VI6TXXU5ZN6QC R22TTMI6WXWULC7ODKFF3QCB7MOTETQQ6IR4BUCUPOCQKQNCTT5AC 6RJVKSL7RVZIZIZIC4TWIYJQ24RUSB346ODS3NYGDHUIRTC4Z5FQC GSQ72ULBSL6WBJZUB3GJKAPQDXZIQV7B2TDBA5OP2WVGHVJMCQFQC U3KGUJJQWQORJIIFH3ADVNIEEX5HOX6KEOXO7DJSL7L3Z6GG3PAQC YRY2TC3VHOYE47M23UJGUWDGF7H7WGU7WLWI4SUNM4EDNTGUPHGAC 7PRZJ6KZLG26YVTAMXT7YOTQLWZHGWGRTKXZZ52P4XYCQD4GT5WQC L4FQMODPEE777BQHQIASG2PGH7N7TFXL2JZSPLQL35MQ6W7VH7OAC MWHMD65QP6UKXO6Q4ZVEAMXY563AJ6KH7J6UEZOB5CRPPSRB762QC TV3ZC6WOZKSQQJQN26JIVKCHK6UK7WMDBYZDUYRWEAZ4JB4YVNAAC NUYXKJP5YXHRDUQW5QW7UC3D5U3VPANIOZAOHFCPWMSRYGMA3GCAC CG4TL4AKSN4J7CMATZFJ5N7PSDCQXLS3QYX7PZ3K67KMMBT675OQC WMHFDQKUDCUGM3R245LLVZ5NNEZSCXFDSTNMVS2O5EFUHHO7HU3AC 7AREIGBWRJPQI7N7UMSXYWGOI5D6OFUKX656PX3GOZVY3ALY75BAC NNG27Y5ZQAZX6UD7F7M4F6KEZBEDFXPEEC3LFUSX4ESKT7K6UJQAC C67GX7W5HBCDPQJRSHWMLM4DUJ3ELFSHH42SVICFJVCJW25T5Z3AC NW6P7VRKBFBQ2FRDZBXN7APJZPYC4SYCIA3MOOE2KZGX43IXNK2AC PM65H4V4GNPVIJFUQW57DC3VDB7TRUUNXKVZONQKEFZSK3AXX5GQC TAJUWPR2BXNVKYH4CN4WN3OR2Z2NESJBEDUB2P2PE6YLX64FQTRAC QWLHS4KCBWCHYDYFTNRHXC2J3Y5IBVT2JQLV6A4VOCT34SYALPEQC RZZ6G7WKMBBXHJ54W4CIUKZKPN5L5GB7QNA5QOHHQ5KULFH4OVRAC KWKVXUJSWKBWPRXD6JVI6K4YHHHNRO525VHPPDQ52XCGQRUHVXQAC WBAFNYODKTL3YSG3UOJITBJSTFYGJLIWKRNK6NMGIIP5TPC2BDGQC WFED7ME7LXUZCZY3TWX7PCPW4EAA55W626CM2OOYVJTLI2BWFTVAC 3QLM46S44Z7GDLWPH3VHBMW2RSWZAOLGJMG2BDKNGUOZIM4IX6WAC ISSEUTHG7EH3QTFLS23GXFIOQXCI5HJPJMK6GWNFMC6NDRD2H34QC F7Q5PX44SLPANIZXCY67TG2W5JTRVJMHGQW54VJLGB4XRH7R6JBQC 3C2VE43SHCSBY4LTRTFYFLIPRWFUN6DXU6D34QVWDQTSNRBUFG7AC 5TWOIGLM6G4QEASFEKKTK7UBPTL4PXASVEOL5777FPT6RHSUTBBQC SVY2PTCLXR3KNPQAWXVXTTGCC5DR334HOAKHYO3VDDRWM2BWMALAC SJDOBXECX7F3ZPPVR7FPURE53D47PP2TFIF4SB6XPS456PZV3DQAC 7Y5HSDFKA5TPLS2TWTRFMQVX6UXUDHXU5MUMXQSDFAIY4THQ3BIQC MSQI3TH6T62JAXQGLL52QZCWAMC372TGB6ZNNRDGUGMJKBNNV2VAC CRCKW7MAFIP2MB6ZNPVZXUHBGSPQNTYHGDVF2TCM2K6XLRUTUW4QC 4Q5OYUKF2SGF7WHMIVYFZVXXDCFUCYY534VLOGKWYRSPYKRXMVDAC FCZSQBKDNMJZRJS2LWQQWLUFGOXSKXDJZQIHC7L5S7HXCXQPOMMAC ILOED4VB4I6VPAUTR75ZWX6MXDYXB5DO2EDK2UH67O3HNKWV23RQC S4W5EBZLFX3HA3JNR524LF5RJ7PAPMSMN3FVRZNLQZY4QNEILGLQC OP6CTAKWCAU64JXQ3USQYR5E5IFHQHNCACII5UMVRXUTZXJQOAZAC X5WLJCJVW55SXZVP7IKP7ADCJIGNKN4PKAXFECVR6TNK7XSMZR7QC QNIQ2NBBIERVCA2YTD3O3P6QPJ5M6VDVGGX7V2BWXTW5553T4PVAC 33ZMPQC6OXTESW7SRW765GRNJUEJRSYONRVZVIEUDAUEJ2PPMB4AC ER4KHDZQ4VBEZKOUJIEUM5HBPWFGBDSB5KE56HG4UE2X6WN266QQC JYCMD6WMNHXA53K4LLKVTNX6PLRLU25F6J2TYMPQXM2ENAE66NIAC IIN7AVA6JYRBXH6ZYRR7BY7TV6PW7ANAQ2A3PD55FKBKKQFEEF2AC CVOQOT7B2FYC3E6ZPOMC7TCJMLEFFIRPTHNRNW5L65NCTAHPA42AC VCG3BRIYRTNNWYC3LOXD6KFGXOX37HAFW2HNV7WXVG2V7EUHLDZQC BWAQ3FHBBM6G3K3KYP75CRTR343RDQZJRYX5ZGYUEXYBAC3APDLAC 5HBRQ2QZTFBQE2Z2CFADUI2D52LO5Z5CNHXHA7BJP3LGO7FJPUCQC OQ4KB7QCJSK7GSW3DYBARH4DCB75HFKLUSOSOZZZ4IUFKNGFRUDQC UL7XFKMUX3WIU4O2LZANK4ECJ654UZPDBFGNXUEYZYOLKBYBCG6AC UABVRWV5U33LQGPNTESOUT72XZCGUNEGIAWTXHJQYXLSJISG4UOAC V4DWL5WBO2JCODVS5QQNWXDH4DAYZN3D5V3UDCHM2KKOMADOTEDQC 7OZGLL7FSMUNXOTGDHQILMXI2EXH7EXPJZTO4KP6KJYWZANJAKXAC HIRKGUMNJPWKSVTR6TVBPD3MWNA63CEHCLCIPWEMGDFHVB3NPLDQC U3SFBWHMMMO2PY6PAX7FMSBSND4RCWGJR42HB47LNQXLOX7ZOB6QC C5VA63WAQRWPENIMXRPUPZLZJMC77PL2B3A77HYFWDCZU5QDG7VQC I2B33Z7NZGC33AMDSSK446AZZYWKPHWLAGULVHKKZU4MVB4BNJOAC ITDUEUO7XAZANPC4GRB3SEDFBOV7GLFPNPTYE5LYNC3CS6BSVZTQC PFMHSDAXQN4VDSDA6QBDIK2DPJKGYX5HYLTSZNTKMRJYXYLIKGOQC 3V52MSSK7QX7FWLLUW63DTWCBAJEK674EFZLKP45FLZ5KZKVARHAC 6L4EP4ZRWWYLT55PD5KTTJON5J2JB5VV5MWNHF5VPZQZ5BKEYZ4QC LEY3EZGTCBV6CYX4L727KQ4ZXL2LZLT5WESN3WAF65VRMX4EDP4QC W5VEC2PBIM5DMU5233HOWAZUEPTGWJRZZIA3H35YYQQW6BTP6XUAC EOMCPVNQLX3IMLC46EAO67DPBH5KEG2FQTPBLGU62HIRWA3UQ7XQC Z63Q4DA5J5TZAC5LN55UD4CLADUMU5Z73TGEVE2YUXCHIST2Y4QAC ZCRK2DJ5VKECRQXZTWT4NUDL2VT5ZHUK7NT6NQPLRJ56TDX5PJSAC 5KJCHLIUFKRPMIVWUAYT6EOF7SW4PTQF6Y5OPEFWXGLE7DUGYLZAC 2TTHWHQ3ZDD3DLB3KRULTBMS3ZREJG472IBVZXIGTP7MBZWAU52QC TJRYL3NXPW5IUGEV3YOC7JYWEXCZDBFPLT4AUG4P227WVKVB72ZAC PFEJ4LMDNEKLMGRCMWQ7EIRVU4JMYGICI4G7X4WVWOROVXQCBZ7QC M5ZDZJBTOJ7SWQPZZQPC24JYZKP26MWSRDHXBWQE2MPPL6WCXOIQC X2FMEN4E345XD26Z2X7JMJ7VGHOGCGIELMHQRE2ITLVNQACP3NOQC EGV2HM7SD7UQSWJGLR65NQJTUBAJ7WHLM67FMH4UFP7JRSFKREPAC 3FBKOX4Y5QYPMBOCSAMHNZXCY7Z75YDQDL4EJZHZIGDXL7RMZ7TAC BW3XFNOS6LDAQLHOZ6RXARCMKCY5JVLVDSXDSSAX4DSYM3FANQBAC 2H32CFFM2FNS63JJPNM2S6HMO543EX72GMPOU5GI6HTMQYPL6I3AC TPZ3PNJN3TYJY2UDMZYE2K2J5ZQJXKHSWWLPVHMOEFCADK6UAGOAC ED62QWGKBPORWVKDFOQRKJXEIWZVNGR3O4KWQBDSRNPT36AYOQYAC JM7UAK777RAVDAVLQLEOBRTGNW2B47S5G55XITJXO243IUNZHVYQC marshallString(th, ghost.name.c_str(), 20);
marshallByte(th, res.elec);marshallByte(th, res.poison);marshallByte(th, res.fire);marshallByte(th, res.steam);marshallByte(th, res.cold);marshallByte(th, res.hellfire);marshallByte(th, res.asphyx);marshallByte(th, res.acid);marshallByte(th, res.sticky_flame);marshallByte(th, res.pierce);marshallByte(th, res.slice);marshallByte(th, res.bludgeon);}
// how many ghost values?marshallByte(th, NUM_GHOST_VALUES);
static void unmarshallResists(tagHeader &th, mon_resist_def &res){res.elec = unmarshallByte(th);res.poison = unmarshallByte(th);res.fire = unmarshallByte(th);res.steam = unmarshallByte(th);res.cold = unmarshallByte(th);res.hellfire = unmarshallByte(th);res.asphyx = unmarshallByte(th);res.acid = unmarshallByte(th);res.sticky_flame = unmarshallByte(th);res.pierce = unmarshallByte(th);res.slice = unmarshallByte(th);res.bludgeon = unmarshallByte(th);}
for (int i = 0; i < NUM_GHOST_VALUES; i++)marshallShort( th, ghost.values[i] );
static void marshallSpells(tagHeader &th, const monster_spells &spells){for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)marshallShort(th, spells[j]);
// How many ghosts?marshallShort(th, ghosts.size());
for (int j = 0; j < NUM_MONSTER_SPELL_SLOTS; ++j)spells[j] = static_cast<spell_type>( unmarshallShort(th) );}static void marshallGhost(tagHeader &th, const ghost_demon &ghost){marshallString(th, ghost.name.c_str(), 20);
for (int i = 0, size = ghosts.size(); i < size; ++i)marshallGhost(th, ghosts[i]);
marshallShort(th, ghost.species);marshallShort(th, ghost.job);marshallShort(th, ghost.best_skill);marshallShort(th, ghost.best_skill_level);marshallShort(th, ghost.xl);marshallShort(th, ghost.max_hp);marshallShort(th, ghost.ev);marshallShort(th, ghost.ac);marshallShort(th, ghost.damage);marshallShort(th, ghost.speed);marshallByte(th, ghost.see_invis);marshallShort(th, ghost.brand);marshallResists(th, ghost.resists);marshallByte(th, ghost.spellcaster);marshallByte(th, ghost.cycle_colours);marshallShort(th, ghost.fly);marshallSpells(th, ghost.spells);
// how many ghost values?int count_c = unmarshallByte(th);
ghost.species = static_cast<species_type>( unmarshallShort(th) );ghost.job = static_cast<job_type>( unmarshallShort(th) );ghost.best_skill = static_cast<skill_type>( unmarshallShort(th) );ghost.best_skill_level = unmarshallShort(th);ghost.xl = unmarshallShort(th);ghost.max_hp = unmarshallShort(th);ghost.ev = unmarshallShort(th);ghost.ac = unmarshallShort(th);ghost.damage = unmarshallShort(th);ghost.speed = unmarshallShort(th);ghost.see_invis = unmarshallByte(th);ghost.brand = static_cast<brand_type>( unmarshallShort(th) );
if (count_c > NUM_GHOST_VALUES)count_c = NUM_GHOST_VALUES;for (int i = 0; i < count_c; i++)ghost.values[i] = unmarshallShort(th);
unmarshallResists(th, ghost.resists);ghost.spellcaster = unmarshallByte(th);ghost.cycle_colours = unmarshallByte(th);ghost.fly = static_cast<flight_type>( unmarshallShort(th) );
if (!dump_char( morgue_name(se.death_time), !dead, true, &se )){mpr("Char dump unsuccessful! Sorry about that.");if (!crawl_state.seen_hups)more();clrscr();}
case BRANCH_SNAKE_PIT:if (mons_species(monster->type) == MONS_NAGA|| mons_species(monster->type) == MONS_SNAKE){return true;}return false;
case BRANCH_SNAKE_PIT:return (mons_species(monster->type) == MONS_NAGA|| mons_species(monster->type) == MONS_SNAKE);
hurted += (random2avg(steam_base_damage, 2) * 10) / speed;if (mons_res_fire(monster) < 0)hurted += (random2(steam_base_damage / 2 + 1) * 10) / speed;
hurted +=resist_adjust_damage(monster,monster->res_steam(),(random2avg(steam_base_damage, 2) * 10) / speed);
return (monster_habitable_grid(m->type, actual_grid, mons_flies(m),
// Zombified monsters enjoy the same habitat as their original.const int type = mons_is_zombified(m)? mons_zombie_base(m) : m->type;return (monster_habitable_grid(type, actual_grid, mons_flies(m),
if (habitat == HT_WATER &&(grid == DNGN_DEEP_WATER || grid == DNGN_BLUE_FOUNTAIN)){return true;}
case HT_LAVA:return (grid == DNGN_LAVA);
};struct mon_resist_def{// All values are actually saved as single-bytes, so practical// range is -128 - 127, and the game only distinguishes values in// the range -1 to 3.short elec;short poison;short fire;short steam;short cold;short hellfire;short asphyx;short acid;bool sticky_flame;// Physical damage resists (currently unused)short pierce;short slice;short bludgeon;mon_resist_def();mon_resist_def(int flags, short level = 1);mon_resist_def operator | (const mon_resist_def &other) const;const mon_resist_def &operator |= (const mon_resist_def &other);
// last updated 12may2000 {dlb}/* ************************************************************************ called from: beam - fight - monstuff* *********************************************************************** */
bool mons_res_sticky_flame( const monsters *mon );
// last updated 12may2000 {dlb}/* ************************************************************************ called from: beam - monstuff - spells4* *********************************************************************** */
int mons_res_steam( const monsters *mon );
bool mons_res_sticky_flame( const monsters *mon ){return (get_mons_resists(mon).sticky_flame|| mon->has_equipped(EQ_BODY_ARMOUR, ARM_MOTTLED_DRAGON_ARMOUR));}int mons_res_steam( const monsters *mon ){int res = get_mons_resists(mon).steam;if (mon->has_equipped(EQ_BODY_ARMOUR, ARM_STEAM_DRAGON_ARMOUR))res += 3;return (res + mons_res_fire(mon) / 2);}
if (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON)return (mon->ghost->values[ GVAL_RES_FIRE ]);int u = 0, f = get_mons_resists(mon);
const mon_resist_def res = get_mons_resists(mon);int u = std::min(res.fire + res.hellfire * 3, 3);
// no Big Prize (tm) here either if you set all three flags. It's a pity uh?//// Note that natural monster resistance is two levels, this is duplicate// the fact that having this flag used to be a lot better than armour// for monsters (it used to make them immune in a lot of cases) -- bwrif (f & MR_RES_HELLFIRE)u += 3;else if (f & MR_RES_FIRE)u += 2;else if (f & MR_VUL_FIRE)u--;
if (mc == MONS_PLAYER_GHOST || mc == MONS_PANDEMONIUM_DEMON)return (mon->ghost->values[ GVAL_RES_COLD ]);int u = 0, f = get_mons_resists(mon);// Note that natural monster resistance is two levels, this is duplicate// the fact that having this flag used to be a lot better than armour// for monsters (it used to make them immune in a lot of cases) -- bwrif (f & MR_RES_COLD)u += 2;else if (f & MR_VUL_COLD)u--;
int u = get_mons_resists(mon).cold;
hit_dice = ghost->values[ GVAL_DEMONLORD_HIT_DICE ];hit_points = ghost->values[ GVAL_MAX_HP ];max_hit_points = ghost->values[ GVAL_MAX_HP ];ac = ghost->values[ GVAL_AC ];ev = ghost->values[ GVAL_EV ];speed = (one_chance_in(3) ? 10 : 6 + roll_dice(2, 9));
hit_dice = ghost->xl;hit_points = ghost->max_hp;max_hit_points = ghost->max_hp;ac = ghost->ac;ev = ghost->ev;speed = (one_chance_in(3) ? 10 : 8 + roll_dice(2, 9));
hit_dice = ghost->values[ GVAL_EXP_LEVEL ];hit_points = ghost->values[ GVAL_MAX_HP ];max_hit_points = ghost->values[ GVAL_MAX_HP ];ac = ghost->values[ GVAL_AC];ev = ghost->values[ GVAL_EV ];speed = ghost->values[ GVAL_SPEED ];
hit_dice = ghost->xl;hit_points = ghost->max_hp;max_hit_points = ghost->max_hp;ac = ghost->ac;ev = ghost->ev;speed = ghost->speed;
{for (int i = 0; i < NUM_MONSTER_SPELL_SLOTS; i++){spells[i] =static_cast<spell_type>( ghost->values[ GVAL_SPELL_1 + i ] );#if DEBUG_DIAGNOSTICSmprf( MSGCH_DIAGNOSTICS, "spell #%d: %d", i, spells[i] );#endif}}
spells = ghost->spells;
/////////////////////////////////////////////////////////////////////////// mon_resist_defmon_resist_def::mon_resist_def(): elec(0), poison(0), fire(0), steam(0), cold(0), hellfire(0),asphyx(0), acid(0), sticky_flame(false), pierce(0),slice(0), bludgeon(0){}mon_resist_def::mon_resist_def(int flags, short level): elec(0), poison(0), fire(0), steam(0), cold(0), hellfire(0),asphyx(0), acid(0), sticky_flame(false), pierce(0),slice(0), bludgeon(0){for (int i = 0; i < 32; ++i){switch (flags & (1 << i)){case MR_RES_STEAM: steam = 3; break;case MR_RES_ELEC: elec = level; break;case MR_RES_POISON: poison = level; break;case MR_RES_FIRE: fire = level; break;case MR_RES_HELLFIRE: hellfire = level; break;case MR_RES_COLD: cold = level; break;case MR_RES_ASPHYX: asphyx = level; break;case MR_RES_ACID: acid = level; break;case MR_VUL_ELEC: elec = -level; break;case MR_VUL_POISON: poison = -level; break;case MR_VUL_FIRE: fire = -level; break;case MR_VUL_COLD: cold = -level; break;case MR_RES_PIERCE: pierce = level; break;case MR_RES_SLICE: slice = level; break;case MR_RES_BLUDGEON: bludgeon = level; break;case MR_VUL_PIERCE: pierce = -level; break;case MR_VUL_SLICE: slice = -level; break;case MR_VUL_BLUDGEON: bludgeon = -level; break;case MR_RES_STICKY_FLAME: sticky_flame = true; break;default: break;}}}const mon_resist_def &mon_resist_def::operator |= (const mon_resist_def &o){elec += o.elec;poison += o.poison;fire += o.fire;cold += o.cold;hellfire += o.hellfire;asphyx += o.asphyx;acid += o.acid;pierce += o.pierce;slice += o.slice;bludgeon += o.bludgeon;sticky_flame = sticky_flame || o.sticky_flame;return (*this);}mon_resist_def mon_resist_def::operator | (const mon_resist_def &o) const{mon_resist_def c(*this);return (c |= o);}
#ifndef GHOST_H#define GHOST_H#include "externs.h"#include "enum.h"#include "itemprop.h"#include "mon-util.h"struct ghost_demon{public:std::string name;species_type species;job_type job;skill_type best_skill;short best_skill_level;short xl;short max_hp, ev, ac, damage, speed;bool see_invis;brand_type brand;mon_resist_def resists;bool spellcaster, cycle_colours;flight_type fly;monster_spells spells;public:ghost_demon();void reset();void init_random_demon();void init_player_ghost();public:static std::vector<ghost_demon> find_ghosts();private:static int n_extra_ghosts();static void find_extra_ghosts(std::vector<ghost_demon> &ghosts, int n);static void find_transiting_ghosts(std::vector<ghost_demon> &gs, int n);static void announce_ghost(const ghost_demon &g);private:void add_spells();spell_type translate_spell(spell_type playerspell) const;};extern std::vector<ghost_demon> ghosts;#endif
values.init(0);values[GVAL_SPEED] = 10;
species = SP_UNKNOWN;job = JOB_UNKNOWN;best_skill = SK_FIGHTING;best_skill_level = 0;xl = 0;max_hp = 0;ev = 0;ac = 0;damage = 0;speed = 10;see_invis = false;brand = SPWPN_NORMAL;resists = mon_resist_def();spellcaster = false;cycle_colours = false;fly = FL_NONE;
|| values[ GVAL_BRAND ] == SPWPN_PROTECTION|| values[ GVAL_BRAND ] == SPWPN_FLAME|| values[ GVAL_BRAND ] == SPWPN_FROST);
|| brand == SPWPN_PROTECTION|| brand == SPWPN_FLAME|| brand == SPWPN_FROST);
// does demon fly? (0 = no, 1 = fly, 2 = levitate)values[GVAL_DEMONLORD_FLY] = (one_chance_in(3) ? 0 :one_chance_in(5) ? 2 : 1);// vacant <ghost best skill level>:values[GVAL_DEMONLORD_UNUSED] = 0;
// does demon fly?fly = (one_chance_in(3)? FL_NONE :one_chance_in(5)? FL_LEVITATE : FL_FLY);
values[GVAL_SPELL_4] = RANDOM_ELEMENT(search_order_misc);if ( values[GVAL_SPELL_4] == SPELL_DIG )values[GVAL_SPELL_4] = SPELL_NO_SPELL;
spells[3] = RANDOM_ELEMENT(search_order_misc);if ( spells[3] == SPELL_DIG )spells[3] = SPELL_NO_SPELL;
if (values[GVAL_EV] > 40)values[GVAL_EV] = 40;values[ GVAL_SEE_INVIS ] = player_see_invis();values[ GVAL_RES_FIRE ] = player_res_fire();values[ GVAL_RES_COLD ] = player_res_cold();values[ GVAL_RES_ELEC ] = player_res_electricity();values[ GVAL_SPEED ] = player_ghost_base_movement_speed();
if (ev > 60)ev = 60;see_invis = player_see_invis();resists.fire = player_res_fire();resists.cold = player_res_cold();resists.elec = player_res_electricity();speed = player_ghost_base_movement_speed();
values[ GVAL_DAMAGE ] = d;values[ GVAL_BRAND ] = e;values[ GVAL_SPECIES ] = you.species;values[ GVAL_BEST_SKILL ] = best_skill(SK_FIGHTING, (NUM_SKILLS - 1), 99);values[ GVAL_SKILL_LEVEL ] =you.skills[best_skill(SK_FIGHTING, (NUM_SKILLS - 1), 99)];values[ GVAL_EXP_LEVEL ] = you.experience_level;values[ GVAL_CLASS ] = you.char_class;
damage = d;brand = static_cast<brand_type>( e );species = you.species;best_skill = ::best_skill(SK_FIGHTING, (NUM_SKILLS - 1), 99);best_skill_level = you.skills[best_skill];xl = you.experience_level;job = you.char_class;
values[ GVAL_SPELL_1 ] = search_first_list(SPELL_NO_SPELL);values[ GVAL_SPELL_2 ] = search_first_list(values[GVAL_SPELL_1]);values[ GVAL_SPELL_3 ] = search_second_list(SPELL_NO_SPELL);values[ GVAL_SPELL_4 ] = search_third_list(SPELL_DIG);
spells[ 0 ] = search_first_list(SPELL_NO_SPELL);spells[ 1 ] = search_first_list(spells[0]);spells[ 2 ] = search_second_list(SPELL_NO_SPELL);spells[ 3 ] = search_third_list(SPELL_DIG);
static void write_version( FILE *dataFile, int majorVersion, int minorVersion,bool extended_version ){// write versiontagHeader versionTag;versionTag.offset = 0;versionTag.tagID = TAG_VERSION;marshallByte(versionTag, majorVersion);marshallByte(versionTag, minorVersion);// extended_version just pads the version out to four 32-bit words.// This makes the bones file compatible with Hearse with no extra// munging needed.if (extended_version){// Use a single signature 16-bit word to indicate that this is// Stone Soup and to disambiguate this (unmunged) bones file// from the munged bones files offered by the old Crawl-aware// hearse.pl. Crawl-aware hearse.pl will prefix the bones file// with the first 16-bits of the Crawl version, and the following// 7 16-bit words set to 0.marshallShort(versionTag, GHOST_SIGNATURE);// Write the three remaining 32-bit words of padding.for (int i = 0; i < 3; ++i)marshallLong(versionTag, 0);}tag_write(versionTag, dataFile);}
// write versionstruct tagHeader versionTag;versionTag.offset = 0;versionTag.tagID = TAG_VERSION;marshallByte(versionTag, majorVersion);marshallByte(versionTag, minorVersion);tag_write(versionTag, dataFile);
write_version( dataFile, majorVersion, minorVersion, extended_version );
if (majorVersion == SAVE_MAJOR_VERSION)return true;
// check for the DCSS ghost signature.if (readShort(ghostFile) != GHOST_SIGNATURE)return (false);if (majorVersion == SAVE_MAJOR_VERSION&& minorVersion <= GHOST_MINOR_VERSION){// Discard three more 32-bit words of padding.for (int i = 0; i < 3; ++i)readLong(ghostFile);return !feof(ghostFile);}
beam_temp.thrower = KILL_YOU;beam_temp.flavour = BEAM_CONFUSION;
beam_temp.thrower =attacker->atype() == ACT_PLAYER? KILL_YOU : KILL_MON;beam_temp.flavour = BEAM_CONFUSION;beam_temp.beam_source =attacker->atype() == ACT_PLAYER? MHITYOU: monster_index(atk);
if (mons_res_elec(def))break;special_damage = player_staff_damage(SK_AIR_MAGIC);
special_damage =resist_adjust_damage(defender,defender->res_elec(),player_staff_damage(SK_AIR_MAGIC));
if (mons_res_cold(def) > 0)break;special_damage = player_staff_damage(SK_ICE_MAGIC);if (mons_res_cold(def) < 0)special_damage += player_staff_damage(SK_ICE_MAGIC);
special_damage =resist_adjust_damage(defender,defender->res_cold(),player_staff_damage(SK_ICE_MAGIC));
if (mons_res_fire(def) > 0)break;special_damage = player_staff_damage(SK_FIRE_MAGIC);if (mons_res_fire(def) < 0)special_damage += player_staff_damage(SK_FIRE_MAGIC);
special_damage =resist_adjust_damage(defender,defender->res_fire(),player_staff_damage(SK_FIRE_MAGIC));
struct ghost_demon{public:std::string name;FixedVector< short, NUM_GHOST_VALUES > values;public:ghost_demon();void reset();void init_random_demon();void init_player_ghost();public:static std::vector<ghost_demon> find_ghosts();private:static int n_extra_ghosts();static void find_extra_ghosts(std::vector<ghost_demon> &ghosts, int n);static void find_transiting_ghosts(std::vector<ghost_demon> &gs, int n);static void announce_ghost(const ghost_demon &g);private:void add_spells();int translate_spell(int playerspell) const;};
enum ghost_value_type{GVAL_MAX_HP, // 0GVAL_EV,GVAL_AC,GVAL_SEE_INVIS,GVAL_RES_FIRE,GVAL_RES_COLD, // 5GVAL_RES_ELEC,GVAL_DAMAGE,GVAL_BRAND,GVAL_SPECIES,GVAL_BEST_SKILL, // 10GVAL_SKILL_LEVEL,GVAL_EXP_LEVEL,GVAL_CLASS,GVAL_SPELL_1, // 14GVAL_SPELL_2,GVAL_SPELL_3,GVAL_SPELL_4,GVAL_SPELL_5,GVAL_SPELL_6, // 19GVAL_SPEED,NUM_GHOST_VALUES, // should always be last value// these values are for demonlords, which override the above:GVAL_DEMONLORD_SPELLCASTER = 9,GVAL_DEMONLORD_FLY, // 10GVAL_DEMONLORD_UNUSED, // 11GVAL_DEMONLORD_HIT_DICE, // 12GVAL_DEMONLORD_CYCLE_COLOUR // 13};
<< ((ghost.values[GVAL_EXP_LEVEL] < 4) ? " weakling" :(ghost.values[GVAL_EXP_LEVEL] < 7) ? "n average" :(ghost.values[GVAL_EXP_LEVEL] < 11) ? "n experienced" :(ghost.values[GVAL_EXP_LEVEL] < 16) ? " powerful" :(ghost.values[GVAL_EXP_LEVEL] < 22) ? " mighty" :(ghost.values[GVAL_EXP_LEVEL] < 26) ? " great" :(ghost.values[GVAL_EXP_LEVEL] < 27) ? "n awesomely powerful": " legendary")
<< ((ghost.xl < 4) ? " weakling" :(ghost.xl < 7) ? "n average" :(ghost.xl < 11) ? "n experienced" :(ghost.xl < 16) ? " powerful" :(ghost.xl < 22) ? " mighty" :(ghost.xl < 26) ? " great" :(ghost.xl < 27) ? "n awesomely powerful": " legendary")