Mercurial > hg > early-roguelike
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xrogue/weapons.c Tue Apr 21 08:55:20 2015 -0400 @@ -0,0 +1,428 @@ +/* + weapons.c - Functions for dealing with problems brought about by weapons + + XRogue: Expeditions into the Dungeons of Doom + Copyright (C) 1991 Robert Pietkivitch + All rights reserved. + + Based on "Advanced Rogue" + Copyright (C) 1984, 1985 Michael Morgan, Ken Dalka and AT&T + All rights reserved. + + Based on "Rogue: Exploring the Dungeons of Doom" + Copyright (C) 1980, 1981 Michael Toy, Ken Arnold and Glenn Wichman + All rights reserved. + + See the file LICENSE.TXT for full copyright and licensing information. +*/ + +#include <curses.h> +#include <ctype.h> +#include "rogue.h" + +boomerang(ydelta, xdelta, item, tp) +int ydelta, xdelta; +register struct linked_list *item; +register struct thing *tp; +{ + register struct object *obj; + struct thing midpoint; + coord oldpos; + + obj = OBJPTR(item); + oldpos = obj->o_pos; + + /* + * make it appear to fly at the target + */ + do_motion(obj, ydelta, xdelta, tp); + hit_monster(unc(obj->o_pos), obj, tp); + + /* + * Now let's make it fly back to the wielder. We need to + * use midpoint to fool do_motion into thinking the action + * starts there. Do_motion only looks at the t_pos field. + */ + midpoint.t_pos = obj->o_pos; /* Simulate a new start position */ + do_motion(obj, -ydelta, -xdelta, &midpoint); + + obj->o_pos = oldpos; +} + +/* + * do the actual motion on the screen done by an object traveling + * across the room. Note that we should not look at any field in + * tp other than t_pos unless we change boomerang(). + */ + +do_motion(obj, ydelta, xdelta, tp) +register struct object *obj; +register int ydelta, xdelta; +register struct thing *tp; +{ + + /* + * Come fly with us ... + */ + obj->o_pos = tp->t_pos; + for (;;) { + register int ch; + /* + * Erase the old one + */ + if (!ce(obj->o_pos, tp->t_pos) && + cansee(unc(obj->o_pos)) && + mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') { + mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, show(obj->o_pos.y, obj->o_pos.x)); + } + /* + * Get the new position + */ + obj->o_pos.y += ydelta; + obj->o_pos.x += xdelta; + if (shoot_ok(ch = winat(obj->o_pos.y, obj->o_pos.x)) && ch != DOOR && !ce(obj->o_pos, hero)) { + /* + * It hasn't hit anything yet, so display it + * If it alright. + */ + if (cansee(unc(obj->o_pos)) && + mvwinch(cw, obj->o_pos.y, obj->o_pos.x) != ' ') { + if (obj->o_type == MISSILE) nofont(cw); + mvwaddch(cw, obj->o_pos.y, obj->o_pos.x, obj->o_type); + newfont(cw); + draw(cw); + } + continue; + } + + /* + * Did we stop because of a monster or the hero? If we did + * not, we want to move our position back one because we could + * not actually make it this far. + */ + if (!isalpha(ch) && + !(obj->o_pos.y == hero.y && obj->o_pos.x == hero.x)) { + obj->o_pos.y -= ydelta; + obj->o_pos.x -= xdelta; + } + + break; + } +} + + +/* + * fall: + * Drop an item someplace around here. + */ + +fall(item, pr) +register struct linked_list *item; +bool pr; +{ + register struct object *obj; + register struct room *rp; + register int i; + struct object *tobj; + struct linked_list *titem; + coord *fpos = NULL; + + obj = OBJPTR(item); + /* + * try to drop the item, look up to 3 squares away for now + */ + for (i=1; i<4; i++) { + if ((fpos = fallpos(&obj->o_pos, FALSE, i)) != NULL) + break; + } + + if (fpos != NULL) { + if (obj->o_group) { /* try to add groups together */ + for(titem=lvl_obj; titem!=NULL; titem=next(titem)) { + tobj = OBJPTR(titem); + if (tobj->o_group == obj->o_group && + tobj->o_pos.y == fpos->y && + tobj->o_pos.x == fpos->x) { + tobj->o_count += obj->o_count; + o_discard(item); + return; + } + } + } + mvaddch(fpos->y, fpos->x, obj->o_type); + obj->o_pos = *fpos; + if ((rp = roomin(&hero)) != NULL && + lit_room(rp)) { + light(&hero); + mvwaddch(cw, hero.y, hero.x, PLAYER); + } + attach(lvl_obj, item); + return; + } + if (pr) { + msg("The %s vanishes as it hits the ground.", + weaps[obj->o_which].w_name); + } + o_discard(item); +} + +/* + * Does the missile hit the monster + */ + +hit_monster(y, x, obj, tp) +register int y, x; +struct object *obj; +register struct thing *tp; +{ + static coord mp; + + mp.y = y; + mp.x = x; + if (tp == &player) { + /* Make sure there is a monster where it landed */ + if (!isalpha(mvwinch(mw, y, x))) { + return(FALSE); + } + + /* Player hits monster */ + return(fight(&mp, obj, TRUE)); + } else { + if (!ce(mp, hero)) { + /* Monster hits monster */ + return(skirmish(tp, &mp, obj, TRUE)); + } + + /* Monster hits player */ + return(attack(tp, obj, TRUE)); + } +} + +/* + * init_weapon: + * Set up the initial goodies for a weapon + */ + +init_weapon(weap, type) +register struct object *weap; +char type; +{ + register struct init_weps *iwp; + + iwp = &weaps[type]; + strcpy(weap->o_damage,iwp->w_dam); + strcpy(weap->o_hurldmg,iwp->w_hrl); + weap->o_launch = iwp->w_launch; + weap->o_flags = iwp->w_flags; + weap->o_weight = iwp->w_wght; + if (weap->o_flags & ISMANY) { + weap->o_count = rnd(8) + 8; + weap->o_group = newgrp(); + } else { + weap->o_count = 1; + } +} + +/* + * missile: + * Fire a missile in a given direction + */ + +missile(ydelta, xdelta, item, tp) +int ydelta, xdelta; +register struct linked_list *item; +register struct thing *tp; +{ + register struct object *obj; + register struct linked_list *nitem; + char ch; + + /* + * Get which thing we are hurling + */ + if (item == NULL) { + return; + } + obj = OBJPTR(item); + if (obj->o_type == RELIC && obj->o_which == AXE_AKLAD) { + boomerang(ydelta, xdelta, item, tp); + return; + } + + if (!dropcheck(obj)) return; /* Can we get rid of it? */ + + if(!(obj->o_flags & ISMISL)) { + for(;;) { + msg(terse ? "Really throw? (y or n): " + : "Do you really want to throw %s? (y or n): ", + inv_name(obj, TRUE)); + mpos = 0; + ch = wgetch(cw); + if (ch == 'n' || ch == ESC) { + after = FALSE; + return; + } + if (ch == 'y') + break; + } + } + /* + * Get rid of the thing. If it is a non-multiple item object, or + * if it is the last thing, just drop it. Otherwise, create a new + * item with a count of one. + */ + if (obj->o_count < 2) { + detach(tp->t_pack, item); + if (tp->t_pack == pack) { + inpack--; + } + } + else { + obj->o_count--; + nitem = (struct linked_list *) new_item(sizeof *obj); + obj = OBJPTR(nitem); + *obj = *(OBJPTR(item)); + obj->o_count = 1; + item = nitem; + } + updpack(FALSE, tp); + do_motion(obj, ydelta, xdelta, tp); + /* + * AHA! Here it has hit something. If it is a wall or a door, + * or if it misses (combat) the monster, put it on the floor + */ + if (!hit_monster(unc(obj->o_pos), obj, tp)) { + fall(item, TRUE); + } + else + o_discard(item); + + mvwaddch(cw, hero.y, hero.x, PLAYER); + +} + +/* + * num: + * Figure out the plus number for armor/weapons + */ + +char * +num(n1, n2) +register int n1, n2; +{ + static char numbuf[LINELEN/2]; + + if (n1 == 0 && n2 == 0) { + return "+0"; + } + if (n2 == 0) { + sprintf(numbuf, "%s%d", n1 < 0 ? "" : "+", n1); + } else { + sprintf(numbuf, "%s%d, %s%d", n1 < 0 ? "" : "+", n1, n2 < 0 ? "" : "+", n2); + } + return(numbuf); +} + +/* + * wield: + * Pull out a certain weapon + */ + +wield() +{ + register struct linked_list *item; + register struct object *obj, *oweapon; + + /* + * It takes 2 movement periods to unwield a weapon and 2 movement + * periods to wield a weapon. + */ + if (player.t_action != C_WIELD) { + player.t_action = C_WIELD; + player.t_using = NULL; /* Make sure this is NULL! */ + if (cur_weapon != NULL) { + player.t_no_move = 2 * movement(&player); + return; + } + } + + if ((oweapon = cur_weapon) != NULL) { + /* At this point we have waited at least 2 units */ + if (!dropcheck(cur_weapon)) { + cur_weapon = oweapon; + player.t_action = A_NIL; + return; + } + if (terse) + addmsg("Was "); + else + addmsg("You were "); + msg("wielding %s", inv_name(oweapon, TRUE)); + } + + /* We we have something picked out? */ + if (player.t_using == NULL) { + /* Now, what does he want to wield? */ + if ((item = get_item(pack, "wield", WIELDABLE, FALSE, FALSE)) == NULL) { + player.t_action = A_NIL; + after = FALSE; + return; + } + player.t_using = item; + player.t_no_move = 2 * movement(&player); + return; + } + + /* We have waited our time, let's wield the weapon */ + item = player.t_using; + player.t_using = NULL; + player.t_action = A_NIL; + + obj = OBJPTR(item); + + if (is_current(obj)) { + msg("Item in use."); + after = FALSE; + return; + } + if (player.t_ctype != C_FIGHTER && + player.t_ctype != C_RANGER && + player.t_ctype != C_PALADIN && + obj->o_type == WEAPON && + obj->o_which == TWOSWORD) { + switch (rnd(3)) { + case 0: + msg("Only fighter types can wield the two-handed sword."); + when 1: + msg("Your hand does not fit the two-handed sword."); + otherwise: + msg("You can not wield the two-handed sword."); + } + return; + } + if (player.t_ctype != C_FIGHTER && + player.t_ctype != C_ASSASSIN && + player.t_ctype != C_THIEF && + player.t_ctype != C_MONK && + obj->o_type == WEAPON && + obj->o_which == BASWORD) { + switch (rnd(3)) { + case 0: + msg("Only thief types can wield the bastard sword."); + when 1: + msg("Your hand does not fit the bastard sword."); + otherwise: + msg("You can not wield the bastard sword."); + } + return; + } + + if (terse) { + addmsg("W"); + } else { + addmsg("You are now w"); + } + msg("ielding %s", inv_name(obj, TRUE)); + cur_weapon = obj; +} +