261 lines
5.4 KiB
C
261 lines
5.4 KiB
C
/*
|
|
* Functions for dealing with weapons
|
|
*
|
|
* @(#)weapons.c 9.0 (rdk) 7/17/84
|
|
*
|
|
* Super-Rogue
|
|
* Copyright (C) 1984 Robert D. Kindelberger
|
|
* 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 <string.h>
|
|
#include <ctype.h>
|
|
#include "rogue.h"
|
|
#include "rogue.ext"
|
|
|
|
/*
|
|
* missile:
|
|
* Fire a missile in a given direction
|
|
*/
|
|
void
|
|
missile(int ydelta, int xdelta)
|
|
{
|
|
reg struct object *obj, *nowwield;
|
|
reg struct linked_list *item, *nitem;
|
|
|
|
/*
|
|
* Get which thing we are hurling
|
|
*/
|
|
nowwield = cur_weapon; /* must save current weap */
|
|
if ((item = get_item("throw", WEAPON)) == NULL)
|
|
return;
|
|
obj = OBJPTR(item);
|
|
if (!dropcheck(obj) || is_current(obj))
|
|
return;
|
|
if (obj == nowwield || obj->o_type != WEAPON) {
|
|
reg int c;
|
|
|
|
msg("Do you want to throw that %s? (y or n)",obj->o_typname);
|
|
do {
|
|
c = readchar();
|
|
if (isupper(c))
|
|
c = tolower(c);
|
|
if (c == ESCAPE || c == 'n') {
|
|
msg("");
|
|
cur_weapon = nowwield;
|
|
after = FALSE; /* ooops, a mistake */
|
|
return;
|
|
}
|
|
} while (c != 'y'); /* keep looking for good ans */
|
|
}
|
|
/*
|
|
* 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(pack, item);
|
|
}
|
|
else {
|
|
obj->o_count--;
|
|
obj->o_vol = itemvol(obj);
|
|
nitem = new_item(sizeof *obj);
|
|
obj = OBJPTR(nitem);
|
|
*obj = *(OBJPTR(item));
|
|
obj->o_count = 1;
|
|
obj->o_vol = itemvol(obj);
|
|
item = nitem;
|
|
}
|
|
updpack(); /* new pack weight */
|
|
do_motion(obj, ydelta, xdelta);
|
|
if (!isalpha(mvwinch(mw, obj->o_pos.y, obj->o_pos.x))
|
|
|| !hit_monster(&obj->o_pos, obj))
|
|
fall(item, TRUE);
|
|
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
|
}
|
|
|
|
/*
|
|
* do the actual motion on the screen done by an object traveling
|
|
* across the room
|
|
*/
|
|
void
|
|
do_motion(struct object *obj, int ydelta, int xdelta)
|
|
{
|
|
reg int ch, y, x;
|
|
|
|
obj->o_pos = hero;
|
|
while (1) {
|
|
y = obj->o_pos.y;
|
|
x = obj->o_pos.x;
|
|
if (!ce(obj->o_pos, hero) && cansee(unc(obj->o_pos)) &&
|
|
mvwinch(cw, y, x) != ' ')
|
|
mvwaddch(cw, y, x, show(y, x));
|
|
/*
|
|
* Get the new position
|
|
*/
|
|
obj->o_pos.y += ydelta;
|
|
obj->o_pos.x += xdelta;
|
|
y = obj->o_pos.y;
|
|
x = obj->o_pos.x;
|
|
ch = winat(y, x);
|
|
if (step_ok(ch) && ch != DOOR) {
|
|
if (cansee(unc(obj->o_pos)) && mvwinch(cw, y, x) != ' ') {
|
|
mvwaddch(cw, y, x, obj->o_type);
|
|
draw(cw);
|
|
}
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* fall:
|
|
* Drop an item someplace around here.
|
|
*/
|
|
|
|
void
|
|
fall(struct linked_list *item, bool pr)
|
|
{
|
|
reg struct object *obj;
|
|
reg struct room *rp;
|
|
static struct coord fpos;
|
|
|
|
obj = OBJPTR(item);
|
|
if (fallpos(&obj->o_pos, &fpos, TRUE)) {
|
|
mvaddch(fpos.y, fpos.x, obj->o_type);
|
|
obj->o_pos = fpos;
|
|
rp = player.t_room;
|
|
if (rp != NULL && !rf_on(rp,ISDARK)) {
|
|
light(&hero);
|
|
mvwaddch(cw, hero.y, hero.x, PLAYER);
|
|
}
|
|
attach(lvl_obj, item);
|
|
return;
|
|
}
|
|
|
|
if (pr)
|
|
if (obj->o_type == WEAPON) /* BUGFIX: Identification trick */
|
|
msg("Your %s vanishes as it hits the ground.", w_magic[obj->o_which].mi_name);
|
|
else
|
|
msg("%s vanishes as it hits the ground.", inv_name(obj,TRUE));
|
|
|
|
discard(item);
|
|
}
|
|
|
|
/*
|
|
* init_weapon:
|
|
* Set up the initial goodies for a weapon
|
|
*/
|
|
|
|
void
|
|
init_weapon(struct object *weap, int type)
|
|
{
|
|
reg struct init_weps *iwp;
|
|
|
|
weap->o_type = WEAPON;
|
|
weap->o_which = type;
|
|
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;
|
|
weap->o_typname = things[TYP_WEAPON].mi_name;
|
|
if (o_on(weap,ISMANY))
|
|
weap->o_count = rnd(8) + 8;
|
|
else
|
|
weap->o_count = 1;
|
|
weap->o_group = newgrp();
|
|
weap->o_vol = itemvol(weap);
|
|
}
|
|
|
|
/*
|
|
* hit_monster:
|
|
* Does the missile hit the monster
|
|
*/
|
|
bool
|
|
hit_monster(struct coord *mp, struct object *obj)
|
|
{
|
|
return fight(mp, obj, TRUE);
|
|
}
|
|
|
|
/*
|
|
* num:
|
|
* Figure out the plus number for armor/weapons
|
|
*/
|
|
char *
|
|
num(int n1, int n2)
|
|
{
|
|
static char numbuf[LINLEN];
|
|
|
|
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
|
|
*/
|
|
void
|
|
wield(void)
|
|
{
|
|
reg struct linked_list *item;
|
|
reg struct object *obj, *oweapon;
|
|
|
|
oweapon = cur_weapon;
|
|
if (!dropcheck(cur_weapon)) {
|
|
cur_weapon = oweapon;
|
|
return;
|
|
}
|
|
cur_weapon = oweapon;
|
|
if ((item = get_item("wield", WEAPON)) == NULL)
|
|
return;
|
|
obj = OBJPTR(item);
|
|
if (is_current(obj)) {
|
|
after = FALSE;
|
|
return;
|
|
}
|
|
msg("Wielding %s", inv_name(obj, TRUE));
|
|
cur_weapon = obj;
|
|
}
|
|
|
|
/*
|
|
* fallpos:
|
|
* Pick a random position around the give (y, x) coordinates
|
|
*/
|
|
bool
|
|
fallpos(struct coord *pos, struct coord *newpos, bool passages)
|
|
{
|
|
reg int y, x, ch;
|
|
|
|
for (y = pos->y - 1; y <= pos->y + 1; y++) {
|
|
for (x = pos->x - 1; x <= pos->x + 1; x++) {
|
|
/*
|
|
* check to make certain the spot is empty, if it is,
|
|
* put the object there, set it in the level list
|
|
* and re-draw the room if he can see it
|
|
*/
|
|
if (y == hero.y && x == hero.x)
|
|
continue;
|
|
ch = winat(y, x);
|
|
if (ch == FLOOR || (passages && ch == PASSAGE)) {
|
|
newpos->y = y;
|
|
newpos->x = x;
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|