mkcorpstat: make a corpse or statue; never returns Null. * * OEXTRA note: Passing mtmp causes mtraits to be saved * even if ptr passed as well, but ptr is always used for * the corpse type (corpsenm). That allows the corpse type * to be different from the original monster, * i.e. vampire -> human corpse * yet still allow restoration of the original monster upon * resurrection. */
| 2064 | * resurrection. |
| 2065 | */ |
| 2066 | struct obj * |
| 2067 | mkcorpstat( |
| 2068 | int objtype, /* CORPSE or STATUE */ |
| 2069 | struct monst *mtmp, /* dead monster, might be Null */ |
| 2070 | struct permonst *ptr, /* if non-Null, overrides mtmp->mndx */ |
| 2071 | coordxy x, coordxy y, /* where to place corpse; <0,0> => random */ |
| 2072 | unsigned corpstatflags) |
| 2073 | { |
| 2074 | struct obj *otmp; |
| 2075 | boolean init = ((corpstatflags & CORPSTAT_INIT) != 0); |
| 2076 | |
| 2077 | if (objtype != CORPSE && objtype != STATUE) |
| 2078 | impossible("making corpstat type %d", objtype); |
| 2079 | if (x == 0 && y == 0) { /* special case - random placement */ |
| 2080 | otmp = mksobj(objtype, init, FALSE); |
| 2081 | (void) rloco(otmp); |
| 2082 | } else { |
| 2083 | otmp = mksobj_at(objtype, x, y, init, FALSE); |
| 2084 | } |
| 2085 | /* record gender and 'historic statue' in overloaded enchantment field */ |
| 2086 | otmp->spe = (corpstatflags & CORPSTAT_SPE_VAL); |
| 2087 | otmp->norevive = gm.mkcorpstat_norevive; /* via envrmt rather than flags */ |
| 2088 | |
| 2089 | /* when 'mtmp' is non-null save the monster's details with the |
| 2090 | corpse or statue; it will also force the 'ptr' override below */ |
| 2091 | if (mtmp) { |
| 2092 | /* save_mtraits updates otmp->oextra->omonst in place */ |
| 2093 | (void) save_mtraits(otmp, mtmp); |
| 2094 | |
| 2095 | if (!ptr) |
| 2096 | ptr = mtmp->data; |
| 2097 | |
| 2098 | /* don't give a revive timer to a cancelled troll's corpse */ |
| 2099 | if (mtmp->mcan && !is_rider(ptr)) |
| 2100 | otmp->norevive = 1; |
| 2101 | } |
| 2102 | |
| 2103 | /* when 'ptr' is non-null it comes from our caller or from 'mtmp'; |
| 2104 | override mkobjs()'s initialization of a random monster type */ |
| 2105 | if (ptr) { |
| 2106 | int old_corpsenm = otmp->corpsenm; |
| 2107 | |
| 2108 | otmp->corpsenm = monsndx(ptr); |
| 2109 | otmp->owt = weight(otmp); |
| 2110 | if (otmp->otyp == CORPSE |
| 2111 | && (gz.zombify || special_corpse(old_corpsenm) |
| 2112 | || special_corpse(otmp->corpsenm))) { |
| 2113 | obj_stop_timers(otmp); |
| 2114 | start_corpse_timeout(otmp); |
| 2115 | } |
| 2116 | } |
| 2117 | return otmp; |
| 2118 | } |
| 2119 | |
| 2120 | /* |
| 2121 | * Return the type of monster that this corpse will |
no test coverage detected