comparison xrogue/weapons.c @ 133:e6179860cb76

Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
author John "Elwin" Edwards
date Tue, 21 Apr 2015 08:55:20 -0400
parents
children ce0cf824c192
comparison
equal deleted inserted replaced
124:d10fc4a065ac 133:e6179860cb76
1 /*
2 weapons.c - Functions for dealing with problems brought about by weapons
3
4 XRogue: Expeditions into the Dungeons of Doom
5 Copyright (C) 1991 Robert Pietkivitch
6 All rights reserved.
7
8 Based on "Advanced Rogue"
9 Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T
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 <curses.h>
20 #include <ctype.h>
21 #include "rogue.h"
22
23 boomerang(ydelta, xdelta, item, tp)
24 int ydelta, xdelta;
25 register struct linked_list *item;
26 register struct thing *tp;
27 {
28 register struct object *obj;
29 struct thing midpoint;
30 coord oldpos;
31
32 obj = OBJPTR(item);
33 oldpos = obj->o_pos;
34
35 /*
36 * make it appear to fly at the target
37 */
38 do_motion(obj, ydelta, xdelta, tp);
39 hit_monster(unc(obj->o_pos), obj, tp);
40
41 /*
42 * Now let's make it fly back to the wielder. We need to
43 * use midpoint to fool do_motion into thinking the action
44 * starts there. Do_motion only looks at the t_pos field.
45 */
46 midpoint.t_pos = obj->o_pos; /* Simulate a new start position */
47 do_motion(obj, -ydelta, -xdelta, &midpoint);
48
49 obj->o_pos = oldpos;
50 }
51
52 /*
53 * do the actual motion on the screen done by an object traveling
54 * across the room. Note that we should not look at any field in
55 * tp other than t_pos unless we change boomerang().
56 */
57
58 do_motion(obj, ydelta, xdelta, tp)
59 register struct object *obj;
60 register int ydelta, xdelta;
61 register struct thing *tp;
62 {
63
64 /*
65 * Come fly with us ...
66 */
67 obj->o_pos = tp->t_pos;
68 for (;;) {
69 register int ch;
70 /*
71 * Erase the old one
72 */
73 if (!ce(obj->o_pos, tp->t_pos) &&
74 cansee(unc(obj->o_pos)) &&
75 mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
76 mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, show(obj->o_pos.y, obj->o_pos.x));
77 }
78 /*
79 * Get the new position
80 */
81 obj->o_pos.y += ydelta;
82 obj->o_pos.x += xdelta;
83 if (shoot_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR && !ce(obj->o_pos, hero)) {
84 /*
85 * It hasn't hit anything yet, so display it
86 * If it alright.
87 */
88 if (cansee(unc(obj->o_pos)) &&
89 mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') {
90 if (obj->o_type == MISSILE) nofont(cw);
91 mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type);
92 newfont(cw);
93 draw(cw);
94 }
95 continue;
96 }
97
98 /*
99 * Did we stop because of a monster or the hero? If we did
100 * not, we want to move our position back one because we could
101 * not actually make it this far.
102 */
103 if (!isalpha(ch) &&
104 !(obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)) {
105 obj->o_pos.y -= ydelta;
106 obj->o_pos.x -= xdelta;
107 }
108
109 break;
110 }
111 }
112
113
114 /*
115 * fall:
116 * Drop an item someplace around here.
117 */
118
119 fall(item, pr)
120 register struct linked_list *item;
121 bool pr;
122 {
123 register struct object *obj;
124 register struct room *rp;
125 register int i;
126 struct object *tobj;
127 struct linked_list *titem;
128 coord *fpos = NULL;
129
130 obj = OBJPTR(item);
131 /*
132 * try to drop the item, look up to 3 squares away for now
133 */
134 for (i=1; i<4; i++) {
135 if ((fpos = fallpos(&obj->o_pos, FALSE, i)) != NULL)
136 break;
137 }
138
139 if (fpos != NULL) {
140 if (obj->o_group) { /* try to add groups together */
141 for(titem=lvl_obj; titem!=NULL; titem=next(titem)) {
142 tobj = OBJPTR(titem);
143 if (tobj->o_group == obj->o_group &&
144 tobj->o_pos.y == fpos->y &&
145 tobj->o_pos.x == fpos->x) {
146 tobj->o_count += obj->o_count;
147 o_discard(item);
148 return;
149 }
150 }
151 }
152 mvaddch(fpos->y, fpos->x, obj->o_type);
153 obj->o_pos = *fpos;
154 if ((rp = roomin(&hero)) != NULL &&
155 lit_room(rp)) {
156 light(&hero);
157 mvwaddch(cw, hero.y, hero.x, PLAYER);
158 }
159 attach(lvl_obj, item);
160 return;
161 }
162 if (pr) {
163 msg("The %s vanishes as it hits the ground.",
164 weaps[obj->o_which].w_name);
165 }
166 o_discard(item);
167 }
168
169 /*
170 * Does the missile hit the monster
171 */
172
173 hit_monster(y, x, obj, tp)
174 register int y, x;
175 struct object *obj;
176 register struct thing *tp;
177 {
178 static coord mp;
179
180 mp.y = y;
181 mp.x = x;
182 if (tp == &player) {
183 /* Make sure there is a monster where it landed */
184 if (!isalpha(mvwinch(mw, y, x))) {
185 return(FALSE);
186 }
187
188 /* Player hits monster */
189 return(fight(&mp, obj, TRUE));
190 } else {
191 if (!ce(mp, hero)) {
192 /* Monster hits monster */
193 return(skirmish(tp, &mp, obj, TRUE));
194 }
195
196 /* Monster hits player */
197 return(attack(tp, obj, TRUE));
198 }
199 }
200
201 /*
202 * init_weapon:
203 * Set up the initial goodies for a weapon
204 */
205
206 init_weapon(weap, type)
207 register struct object *weap;
208 char type;
209 {
210 register struct init_weps *iwp;
211
212 iwp = &weaps[type];
213 strcpy(weap->o_damage,iwp->w_dam);
214 strcpy(weap->o_hurldmg,iwp->w_hrl);
215 weap->o_launch = iwp->w_launch;
216 weap->o_flags = iwp->w_flags;
217 weap->o_weight = iwp->w_wght;
218 if (weap->o_flags & ISMANY) {
219 weap->o_count = rnd(8) + 8;
220 weap->o_group = newgrp();
221 } else {
222 weap->o_count = 1;
223 }
224 }
225
226 /*
227 * missile:
228 * Fire a missile in a given direction
229 */
230
231 missile(ydelta, xdelta, item, tp)
232 int ydelta, xdelta;
233 register struct linked_list *item;
234 register struct thing *tp;
235 {
236 register struct object *obj;
237 register struct linked_list *nitem;
238 char ch;
239
240 /*
241 * Get which thing we are hurling
242 */
243 if (item == NULL) {
244 return;
245 }
246 obj = OBJPTR(item);
247 if (obj->o_type == RELIC && obj->o_which == AXE_AKLAD) {
248 boomerang(ydelta, xdelta, item, tp);
249 return;
250 }
251
252 if (!dropcheck(obj)) return; /* Can we get rid of it? */
253
254 if(!(obj->o_flags & ISMISL)) {
255 for(;;) {
256 msg(terse ? "Really throw? (y or n): "
257 : "Do you really want to throw %s? (y or n): ",
258 inv_name(obj, TRUE));
259 mpos = 0;
260 ch = wgetch(cw);
261 if (ch == 'n' || ch == ESC) {
262 after = FALSE;
263 return;
264 }
265 if (ch == 'y')
266 break;
267 }
268 }
269 /*
270 * Get rid of the thing. If it is a non-multiple item object, or
271 * if it is the last thing, just drop it. Otherwise, create a new
272 * item with a count of one.
273 */
274 if (obj->o_count < 2) {
275 detach(tp->t_pack, item);
276 if (tp->t_pack == pack) {
277 inpack--;
278 }
279 }
280 else {
281 obj->o_count--;
282 nitem = (struct linked_list *) new_item(sizeof *obj);
283 obj = OBJPTR(nitem);
284 *obj = *(OBJPTR(item));
285 obj->o_count = 1;
286 item = nitem;
287 }
288 updpack(FALSE, tp);
289 do_motion(obj, ydelta, xdelta, tp);
290 /*
291 * AHA! Here it has hit something. If it is a wall or a door,
292 * or if it misses (combat) the monster, put it on the floor
293 */
294 if (!hit_monster(unc(obj->o_pos), obj, tp)) {
295 fall(item, TRUE);
296 }
297 else
298 o_discard(item);
299
300 mvwaddch(cw, hero.y, hero.x, PLAYER);
301
302 }
303
304 /*
305 * num:
306 * Figure out the plus number for armor/weapons
307 */
308
309 char *
310 num(n1, n2)
311 register int n1, n2;
312 {
313 static char numbuf[LINELEN/2];
314
315 if (n1 == 0 && n2 == 0) {
316 return "+0";
317 }
318 if (n2 == 0) {
319 sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1);
320 } else {
321 sprintf(numbuf, "%s%d, %s%d", n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2);
322 }
323 return(numbuf);
324 }
325
326 /*
327 * wield:
328 * Pull out a certain weapon
329 */
330
331 wield()
332 {
333 register struct linked_list *item;
334 register struct object *obj, *oweapon;
335
336 /*
337 * It takes 2 movement periods to unwield a weapon and 2 movement
338 * periods to wield a weapon.
339 */
340 if (player.t_action != C_WIELD) {
341 player.t_action = C_WIELD;
342 player.t_using = NULL; /* Make sure this is NULL! */
343 if (cur_weapon != NULL) {
344 player.t_no_move = 2 * movement(&player);
345 return;
346 }
347 }
348
349 if ((oweapon = cur_weapon) != NULL) {
350 /* At this point we have waited at least 2 units */
351 if (!dropcheck(cur_weapon)) {
352 cur_weapon = oweapon;
353 player.t_action = A_NIL;
354 return;
355 }
356 if (terse)
357 addmsg("Was ");
358 else
359 addmsg("You were ");
360 msg("wielding %s", inv_name(oweapon, TRUE));
361 }
362
363 /* We we have something picked out? */
364 if (player.t_using == NULL) {
365 /* Now, what does he want to wield? */
366 if ((item = get_item(pack, "wield", WIELDABLE, FALSE, FALSE)) == NULL) {
367 player.t_action = A_NIL;
368 after = FALSE;
369 return;
370 }
371 player.t_using = item;
372 player.t_no_move = 2 * movement(&player);
373 return;
374 }
375
376 /* We have waited our time, let's wield the weapon */
377 item = player.t_using;
378 player.t_using = NULL;
379 player.t_action = A_NIL;
380
381 obj = OBJPTR(item);
382
383 if (is_current(obj)) {
384 msg("Item in use.");
385 after = FALSE;
386 return;
387 }
388 if (player.t_ctype != C_FIGHTER &&
389 player.t_ctype != C_RANGER &&
390 player.t_ctype != C_PALADIN &&
391 obj->o_type == WEAPON &&
392 obj->o_which == TWOSWORD) {
393 switch (rnd(3)) {
394 case 0:
395 msg("Only fighter types can wield the two-handed sword.");
396 when 1:
397 msg("Your hand does not fit the two-handed sword.");
398 otherwise:
399 msg("You can not wield the two-handed sword.");
400 }
401 return;
402 }
403 if (player.t_ctype != C_FIGHTER &&
404 player.t_ctype != C_ASSASSIN &&
405 player.t_ctype != C_THIEF &&
406 player.t_ctype != C_MONK &&
407 obj->o_type == WEAPON &&
408 obj->o_which == BASWORD) {
409 switch (rnd(3)) {
410 case 0:
411 msg("Only thief types can wield the bastard sword.");
412 when 1:
413 msg("Your hand does not fit the bastard sword.");
414 otherwise:
415 msg("You can not wield the bastard sword.");
416 }
417 return;
418 }
419
420 if (terse) {
421 addmsg("W");
422 } else {
423 addmsg("You are now w");
424 }
425 msg("ielding %s", inv_name(obj, TRUE));
426 cur_weapon = obj;
427 }
428