Mercurial > hg > early-roguelike
comparison urogue/weapons.c @ 256:c495a4f288c6
Import UltraRogue from the Roguelike Restoration Project (r1490)
| author | John "Elwin" Edwards |
|---|---|
| date | Tue, 31 Jan 2017 19:56:04 -0500 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 253:d9badb9c0179 | 256:c495a4f288c6 |
|---|---|
| 1 /* | |
| 2 weapons.c - Functions for dealing with problems brought about by weapons | |
| 3 | |
| 4 UltraRogue: The Ultimate Adventure in the Dungeons of Doom | |
| 5 Copyright (C) 1985, 1986, 1992, 1993, 1995 Herb Chong | |
| 6 All rights reserved. | |
| 7 | |
| 8 Based on "Advanced Rogue" | |
| 9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka | |
| 10 All rights reserved. | |
| 11 | |
| 12 Based on "Rogue: Exploring the Dungeons of Doom" | |
| 13 Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman | |
| 14 All rights reserved. | |
| 15 | |
| 16 See the file LICENSE.TXT for full copyright and licensing information. | |
| 17 */ | |
| 18 | |
| 19 #include <ctype.h> | |
| 20 #include <string.h> | |
| 21 #include "rogue.h" | |
| 22 | |
| 23 /* | |
| 24 missile() | |
| 25 Fire a missile in a given direction | |
| 26 */ | |
| 27 | |
| 28 void | |
| 29 missile(int ydelta, int xdelta, struct linked_list *item, struct thing *tp) | |
| 30 { | |
| 31 struct object *obj; | |
| 32 struct linked_list *nitem; | |
| 33 | |
| 34 if (item == NULL) /* Get which thing we are hurling */ | |
| 35 return; | |
| 36 | |
| 37 obj = OBJPTR(item); | |
| 38 | |
| 39 if (!dropcheck(obj) || is_current(obj)) | |
| 40 return; | |
| 41 | |
| 42 /* | |
| 43 * Get rid of the thing. If it is a non-multiple item object, or if | |
| 44 * it is the last thing, just drop it. Otherwise, create a new item | |
| 45 * with a count of one. | |
| 46 */ | |
| 47 | |
| 48 if (obj->o_count < 2) | |
| 49 { | |
| 50 if (tp->t_pack == pack) | |
| 51 rem_pack(obj); | |
| 52 else | |
| 53 detach(tp->t_pack, item); | |
| 54 } | |
| 55 else | |
| 56 { | |
| 57 obj->o_count--; | |
| 58 nitem = (struct linked_list *) new_item(sizeof *obj); | |
| 59 obj = OBJPTR(nitem); | |
| 60 *obj = *(OBJPTR(item)); | |
| 61 obj->o_count = 1; | |
| 62 item = nitem; | |
| 63 } | |
| 64 | |
| 65 switch (obj->o_type) | |
| 66 { | |
| 67 case ARTIFACT: | |
| 68 has_artifact &= ~(1 << obj->o_which); | |
| 69 break; | |
| 70 | |
| 71 case SCROLL: | |
| 72 if (obj->o_which == S_SCARE && obj->o_flags & ISBLESSED) | |
| 73 obj->o_flags &= ~ISBLESSED; | |
| 74 else | |
| 75 obj->o_flags |= ISCURSED; | |
| 76 } | |
| 77 | |
| 78 updpack(); | |
| 79 obj->o_pos = do_motion(obj->o_type, ydelta, xdelta, tp); | |
| 80 | |
| 81 /* | |
| 82 * AHA! Here it has hit something. If it is a wall or a door, or if | |
| 83 * it misses (combat) the monster, put it on the floor | |
| 84 */ | |
| 85 | |
| 86 if (!hit_monster(obj->o_pos.y, obj->o_pos.x, obj, tp)) | |
| 87 { | |
| 88 if (obj->o_type == WEAPON && obj->o_which == GRENADE) | |
| 89 { | |
| 90 hearmsg("BOOOM!"); | |
| 91 aggravate(); | |
| 92 | |
| 93 if (ntraps + 1 < 2 * MAXTRAPS && | |
| 94 fallpos(obj->o_pos, &traps[ntraps].tr_pos)) | |
| 95 { | |
| 96 mvaddch(traps[ntraps].tr_pos.y, traps[ntraps].tr_pos.x, | |
| 97 TRAPDOOR); | |
| 98 traps[ntraps].tr_type = TRAPDOOR; | |
| 99 traps[ntraps].tr_flags = ISFOUND; | |
| 100 traps[ntraps].tr_show = TRAPDOOR; | |
| 101 ntraps++; | |
| 102 light(&hero); | |
| 103 } | |
| 104 discard(item); | |
| 105 } | |
| 106 else if (obj->o_flags & ISLOST) | |
| 107 { | |
| 108 if (obj->o_type == WEAPON) | |
| 109 addmsg("The %s", weaps[obj->o_which].w_name); | |
| 110 else | |
| 111 addmsg(inv_name(obj, LOWERCASE)); | |
| 112 | |
| 113 msg(" vanishes in a puff of greasy smoke."); | |
| 114 discard(item); | |
| 115 } | |
| 116 else | |
| 117 { | |
| 118 fall(&player, item, TRUE, TRUE); | |
| 119 | |
| 120 if (obj->o_flags & CANRETURN) | |
| 121 msg("You have %s.", inv_name(obj, LOWERCASE)); | |
| 122 } | |
| 123 } | |
| 124 else if (obj->o_flags & ISOWNED) | |
| 125 { | |
| 126 add_pack(item, NOMESSAGE); | |
| 127 msg("You have %s.", inv_name(obj, LOWERCASE)); | |
| 128 } | |
| 129 | |
| 130 mvwaddch(cw, hero.y, hero.x, PLAYER); | |
| 131 } | |
| 132 | |
| 133 /* | |
| 134 do_motion() | |
| 135 do the actual motion on the screen done by an object | |
| 136 traveling across the room | |
| 137 */ | |
| 138 | |
| 139 coord | |
| 140 do_motion(int ob, int ydelta, int xdelta, struct thing *tp) | |
| 141 { | |
| 142 coord pos; | |
| 143 /* Come fly with us ... */ | |
| 144 | |
| 145 pos = tp->t_pos; | |
| 146 | |
| 147 for (;;) | |
| 148 { | |
| 149 int ch; | |
| 150 | |
| 151 /* Erase the old one */ | |
| 152 | |
| 153 if (!ce(pos, tp->t_pos) && | |
| 154 cansee(pos.y, pos.x) && | |
| 155 mvwinch(cw, pos.y, pos.x) != ' ') | |
| 156 { | |
| 157 mvwaddch(cw, pos.y, pos.x, show(pos.y, pos.x)); | |
| 158 } | |
| 159 | |
| 160 /* Get the new position */ | |
| 161 | |
| 162 pos.y += ydelta; | |
| 163 pos.x += xdelta; | |
| 164 | |
| 165 if (shoot_ok(ch = winat(pos.y, pos.x)) && | |
| 166 ch != DOOR && !ce(pos, hero)) | |
| 167 { | |
| 168 /* It hasn't hit anything yet, so display it if it alright. */ | |
| 169 | |
| 170 if (cansee(pos.y, pos.x) && | |
| 171 mvwinch(cw, pos.y, pos.x) != ' ') | |
| 172 { | |
| 173 mvwaddch(cw, pos.y, pos.x, ob); | |
| 174 wrefresh(cw); | |
| 175 } | |
| 176 | |
| 177 continue; | |
| 178 | |
| 179 } | |
| 180 break; | |
| 181 } | |
| 182 | |
| 183 return(pos); | |
| 184 } | |
| 185 | |
| 186 /* | |
| 187 fall() | |
| 188 Drop an item someplace around here. | |
| 189 */ | |
| 190 | |
| 191 void | |
| 192 fall(struct thing *tp, struct linked_list *item, int pr, int player_owned) | |
| 193 { | |
| 194 struct object *obj; | |
| 195 struct room *rp; | |
| 196 coord fpos; | |
| 197 | |
| 198 obj = OBJPTR(item); | |
| 199 rp = roomin(tp->t_pos); | |
| 200 | |
| 201 if (player_owned && obj->o_flags & CANRETURN) | |
| 202 { | |
| 203 add_pack(item, NOMESSAGE); | |
| 204 msg("You have %s.", inv_name(obj, LOWERCASE)); | |
| 205 return; | |
| 206 } | |
| 207 else if (fallpos(obj->o_pos, &fpos)) | |
| 208 { | |
| 209 if (obj->o_flags & CANBURN && obj->o_type == WEAPON | |
| 210 && obj->o_which == MOLOTOV | |
| 211 && ntraps + 1 < 2 * MAXTRAPS) | |
| 212 { | |
| 213 mvaddch(fpos.y, fpos.x, FIRETRAP); | |
| 214 traps[ntraps].tr_type = FIRETRAP; | |
| 215 traps[ntraps].tr_flags = ISFOUND; | |
| 216 traps[ntraps].tr_show = FIRETRAP; | |
| 217 traps[ntraps].tr_pos = fpos; | |
| 218 ntraps++; | |
| 219 | |
| 220 if (rp != NULL) | |
| 221 rp->r_flags &= ~ISDARK; | |
| 222 } | |
| 223 else | |
| 224 { | |
| 225 obj->o_pos = fpos; | |
| 226 add_obj(item, fpos.y, fpos.x); | |
| 227 } | |
| 228 | |
| 229 if (rp != NULL && | |
| 230 (!(rp->r_flags & ISDARK) || | |
| 231 (rp->r_flags & HASFIRE))) | |
| 232 { | |
| 233 light(&hero); | |
| 234 mvwaddch(cw, hero.y, hero.x, PLAYER); | |
| 235 } | |
| 236 return; | |
| 237 } | |
| 238 | |
| 239 /* get here only if there isn't a place to put it */ | |
| 240 | |
| 241 if (pr) | |
| 242 { | |
| 243 if (cansee(obj->o_pos.y, obj->o_pos.x)) | |
| 244 { | |
| 245 if (obj->o_type == WEAPON) | |
| 246 addmsg("The %s", weaps[obj->o_which].w_name); | |
| 247 else | |
| 248 addmsg(inv_name(obj, LOWERCASE)); | |
| 249 | |
| 250 msg(" vanishes as it hits the ground."); | |
| 251 } | |
| 252 } | |
| 253 discard(item); | |
| 254 } | |
| 255 | |
| 256 /* | |
| 257 init_weapon() | |
| 258 Set up the initial goodies for a weapon | |
| 259 */ | |
| 260 | |
| 261 void | |
| 262 init_weapon(struct object *weap, int type) | |
| 263 { | |
| 264 struct init_weps *iwp = &weaps[type]; | |
| 265 | |
| 266 weap->o_damage = iwp->w_dam; | |
| 267 weap->o_hurldmg = iwp->w_hrl; | |
| 268 weap->o_launch = iwp->w_launch; | |
| 269 weap->o_flags = iwp->w_flags; | |
| 270 weap->o_weight = iwp->w_wght; | |
| 271 | |
| 272 if (weap->o_flags & ISMANY) | |
| 273 { | |
| 274 weap->o_count = rnd(8) + 8; | |
| 275 weap->o_group = ++group; | |
| 276 } | |
| 277 else | |
| 278 weap->o_count = 1; | |
| 279 } | |
| 280 | |
| 281 /* | |
| 282 hit_monster() | |
| 283 does the missile hit the target? | |
| 284 */ | |
| 285 | |
| 286 int | |
| 287 hit_monster(int y, int x, struct object *weapon, struct thing *thrower) | |
| 288 { | |
| 289 struct linked_list *mon; | |
| 290 coord target; | |
| 291 | |
| 292 target.y = y; | |
| 293 target.x = x; | |
| 294 | |
| 295 if (thrower == &player) | |
| 296 return(fight(&target, weapon, THROWN)); | |
| 297 | |
| 298 if (ce(target, hero)) | |
| 299 { | |
| 300 if (good_monster(*thrower)) | |
| 301 { | |
| 302 if (on(*thrower, ISFAMILIAR)) | |
| 303 msg("Please get out of the way, Master! I nearly hit you."); | |
| 304 else | |
| 305 msg("Get out of the way %s!", whoami); | |
| 306 | |
| 307 return(FALSE); | |
| 308 } | |
| 309 | |
| 310 return(attack(thrower, weapon, THROWN)); | |
| 311 } | |
| 312 | |
| 313 if ((mon = find_mons(y, x)) != NULL) | |
| 314 return(mon_mon_attack(thrower, mon, weapon, THROWN)); | |
| 315 else | |
| 316 return(FALSE); | |
| 317 } | |
| 318 | |
| 319 | |
| 320 /* | |
| 321 num() | |
| 322 Figure out the plus number for armor/weapons | |
| 323 */ | |
| 324 | |
| 325 char * | |
| 326 num(int n1, int n2, char *buf) | |
| 327 { | |
| 328 if (buf == NULL) | |
| 329 return("UltraRogue Error #104"); | |
| 330 | |
| 331 if (n1 == 0 && n2 == 0) | |
| 332 { | |
| 333 strcpy(buf,"+0"); | |
| 334 return(buf); | |
| 335 } | |
| 336 | |
| 337 if (n2 == 0) | |
| 338 sprintf(buf, "%s%d", n1 < 0 ? "" : "+", n1); | |
| 339 else | |
| 340 sprintf(buf, "%s%d, %s%d", n1 < 0 ? "" : "+", | |
| 341 n1, n2 < 0 ? "" : "+", n2); | |
| 342 | |
| 343 return(buf); | |
| 344 } | |
| 345 | |
| 346 /* | |
| 347 wield() | |
| 348 Pull out a certain weapon | |
| 349 */ | |
| 350 | |
| 351 void | |
| 352 wield(void) | |
| 353 { | |
| 354 struct linked_list *item; | |
| 355 struct object *obj, *oweapon; | |
| 356 | |
| 357 oweapon = cur_weapon; | |
| 358 | |
| 359 if (!dropcheck(cur_weapon)) | |
| 360 { | |
| 361 cur_weapon = oweapon; | |
| 362 return; | |
| 363 } | |
| 364 | |
| 365 cur_weapon = oweapon; | |
| 366 | |
| 367 if ((item = get_item("wield", WEAPON)) == NULL) | |
| 368 { | |
| 369 after = FALSE; | |
| 370 return; | |
| 371 } | |
| 372 | |
| 373 obj = OBJPTR(item); | |
| 374 | |
| 375 if (is_current(obj)) | |
| 376 { | |
| 377 after = FALSE; | |
| 378 return; | |
| 379 } | |
| 380 | |
| 381 wield_ok(&player, obj, TRUE); |
