comparison arogue7/weapons.c @ 125:adfa37e67084

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