Used for objects which sometimes do special things when dropped; must be * called with the object not in any chain. Returns TRUE if the object goes * away. */
| 159 | * away. |
| 160 | */ |
| 161 | boolean |
| 162 | flooreffects( |
| 163 | struct obj *obj, /* the object landing on the floor */ |
| 164 | coordxy x, coordxy y, /* map coordinates for spot where it is landing */ |
| 165 | const char *verb) /* "fall", "drop", "land", &c */ |
| 166 | { |
| 167 | struct trap *t; |
| 168 | struct monst *mtmp; |
| 169 | struct obj *otmp; |
| 170 | coord save_bhitpos; |
| 171 | boolean tseen; |
| 172 | int ttyp = NO_TRAP, res = FALSE; |
| 173 | |
| 174 | if (obj->where != OBJ_FREE) |
| 175 | panic("flooreffects: obj not free"); |
| 176 | |
| 177 | /* make sure things like water_damage() have no pointers to follow */ |
| 178 | obj->nobj = obj->nexthere = (struct obj *) 0; |
| 179 | /* erode_obj() (called from water_damage() or lava_damage()) needs |
| 180 | bhitpos, but that was screwing up wand zapping that called us from |
| 181 | rloco(), so we now restore bhitpos before we return */ |
| 182 | save_bhitpos = gb.bhitpos; |
| 183 | gb.bhitpos.x = x, gb.bhitpos.y = y; |
| 184 | |
| 185 | if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE)) { |
| 186 | res = TRUE; |
| 187 | } else if (obj->otyp == BOULDER && (t = t_at(x, y)) != 0 |
| 188 | && (is_pit(t->ttyp) || is_hole(t->ttyp))) { |
| 189 | ttyp = t->ttyp; |
| 190 | tseen = t->tseen ? TRUE : FALSE; |
| 191 | if (((mtmp = m_at(x, y)) && mtmp->mtrapped) |
| 192 | || (u.utrap && u_at(x,y))) { |
| 193 | if (*verb && (cansee(x, y) || distu(x, y) == 0)) |
| 194 | pline("%s boulder %s into the pit%s.", |
| 195 | Blind ? "A" : "The", |
| 196 | vtense((const char *) 0, verb), |
| 197 | mtmp ? "" : " with you"); |
| 198 | if (mtmp) { |
| 199 | if (!passes_walls(mtmp->data) && !throws_rocks(mtmp->data)) { |
| 200 | /* dieroll was rnd(20); 1: maximum chance to hit |
| 201 | since trapped target is a sitting duck */ |
| 202 | int damage, dieroll = 1; |
| 203 | |
| 204 | /* As of 3.6.2: this was calling hmon() unconditionally |
| 205 | so always credited/blamed the hero but the boulder |
| 206 | might have been thrown by a giant or launched by |
| 207 | a rolling boulder trap triggered by a monster or |
| 208 | dropped by a scroll of earth read by a monster */ |
| 209 | if (svc.context.mon_moving) { |
| 210 | /* normally we'd use ohitmon() but it can call |
| 211 | drop_throw() which calls flooreffects() */ |
| 212 | damage = dmgval(obj, mtmp); |
| 213 | mtmp->mhp -= damage; |
| 214 | if (DEADMONSTER(mtmp)) { |
| 215 | if (canspotmon(mtmp)) |
| 216 | pline("%s is %s!", Monnam(mtmp), |
| 217 | (nonliving(mtmp->data) |
| 218 | || is_vampshifter(mtmp)) |
no test coverage detected