Import XRogue 8.0 from the Roguelike Restoration Project (r1490)
This commit is contained in:
parent
6af92da76a
commit
034d8d6484
51 changed files with 37250 additions and 0 deletions
401
xrogue/bolt.c
Normal file
401
xrogue/bolt.c
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
/*
|
||||
bolt.c - functions shooting an object across the room
|
||||
|
||||
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"
|
||||
|
||||
/*
|
||||
* shoot_bolt fires a bolt from the given starting point in the
|
||||
* given direction
|
||||
*/
|
||||
|
||||
shoot_bolt(shooter, start, dir, get_points, reason, name, damage)
|
||||
struct thing *shooter;
|
||||
coord start, dir;
|
||||
bool get_points;
|
||||
short reason;
|
||||
char *name;
|
||||
int damage;
|
||||
{
|
||||
unsigned char dirch = 0, ch;
|
||||
bool used, change, see_him;
|
||||
short y, x, bounces;
|
||||
coord pos;
|
||||
struct linked_list *target=NULL;
|
||||
struct {
|
||||
coord place;
|
||||
char oldch;
|
||||
} spotpos[BOLT_LENGTH];
|
||||
|
||||
switch (dir.y + dir.x) {
|
||||
case 0: dirch = '/';
|
||||
when 1: case -1: dirch = (dir.y == 0 ? '-' : '|');
|
||||
when 2: case -2: dirch = '\\';
|
||||
}
|
||||
pos.y = start.y + dir.y;
|
||||
pos.x = start.x + dir.x;
|
||||
used = FALSE;
|
||||
change = FALSE;
|
||||
|
||||
bounces = 0; /* No bounces yet */
|
||||
nofont(cw);
|
||||
for (y = 0; y < BOLT_LENGTH && !used; y++) {
|
||||
ch = winat(pos.y, pos.x);
|
||||
spotpos[y].place = pos;
|
||||
spotpos[y].oldch = mvwinch(cw, pos.y, pos.x);
|
||||
|
||||
/* Are we at hero? */
|
||||
if (ce(pos, hero)) goto at_hero;
|
||||
|
||||
switch (ch) {
|
||||
case SECRETDOOR:
|
||||
case VERTWALL:
|
||||
case HORZWALL:
|
||||
case ' ':
|
||||
if (dirch == '-' || dirch == '|') {
|
||||
dir.y = -dir.y;
|
||||
dir.x = -dir.x;
|
||||
}
|
||||
else {
|
||||
unsigned char chx = mvinch(pos.y-dir.y, pos.x),
|
||||
chy = mvinch(pos.y, pos.x-dir.x);
|
||||
bool anychange = FALSE; /* Did we change anthing */
|
||||
|
||||
if (chy == WALL || chy == SECRETDOOR ||
|
||||
chy == HORZWALL || chy == VERTWALL) {
|
||||
dir.y = -dir.y;
|
||||
change ^= TRUE; /* Change at least one direction */
|
||||
anychange = TRUE;
|
||||
}
|
||||
if (chx == WALL || chx == SECRETDOOR ||
|
||||
chx == HORZWALL || chx == VERTWALL) {
|
||||
dir.x = -dir.x;
|
||||
change ^= TRUE; /* Change at least one direction */
|
||||
anychange = TRUE;
|
||||
}
|
||||
|
||||
/* If we didn't make any change, make both changes */
|
||||
if (!anychange) {
|
||||
dir.x = -dir.x;
|
||||
dir.y = -dir.y;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we change how the bolt looks? */
|
||||
if (change) {
|
||||
change = FALSE;
|
||||
if (dirch == '\\') dirch = '/';
|
||||
else if (dirch == '/') dirch = '\\';
|
||||
}
|
||||
|
||||
y--; /* The bounce doesn't count as using up the bolt */
|
||||
|
||||
/* Make sure we aren't in an infinite bounce */
|
||||
if (++bounces > BOLT_LENGTH) used = TRUE;
|
||||
msg("The %s bounces", name);
|
||||
break;
|
||||
default:
|
||||
if (isalpha(ch)) {
|
||||
register struct linked_list *item;
|
||||
struct thing *tp;
|
||||
register char *mname;
|
||||
bool see_monster = cansee(pos.y, pos.x);
|
||||
|
||||
item = find_mons(unc(pos));
|
||||
assert(item != NULL);
|
||||
tp = THINGPTR(item);
|
||||
mname = monster_name(tp);
|
||||
|
||||
/*
|
||||
* If our prey shot this, let's record the fact that
|
||||
* he can shoot, regardless of whether he hits us.
|
||||
*/
|
||||
if (tp->t_dest != NULL && ce(*tp->t_dest, shooter->t_pos))
|
||||
tp->t_wasshot = TRUE;
|
||||
|
||||
if (!save(VS_BREATH, tp, -(shooter->t_stats.s_lvl/10))) {
|
||||
if (see_monster) {
|
||||
if (on(*tp, ISDISGUISE) &&
|
||||
(tp->t_type != tp->t_disguise)) {
|
||||
msg("Wait! That's a %s!", mname);
|
||||
turn_off(*tp, ISDISGUISE);
|
||||
}
|
||||
|
||||
turn_off(*tp, CANSURPRISE);
|
||||
msg("The %s hits %s", name, prname(mname, FALSE));
|
||||
}
|
||||
|
||||
/* Should we start to chase the shooter? */
|
||||
if (shooter != &player &&
|
||||
shooter != tp &&
|
||||
shooter->t_index != tp->t_index &&
|
||||
(tp->t_dest == NULL || rnd(100) < 25)) {
|
||||
/*
|
||||
* If we're intelligent enough to realize that this
|
||||
* is a friendly monster, we will attack the hero
|
||||
* instead.
|
||||
*/
|
||||
if (on(*shooter, ISFRIENDLY) &&
|
||||
roll(3,6) < tp->t_stats.s_intel)
|
||||
runto(tp, &hero);
|
||||
|
||||
/* Otherwise, let's chase the monster */
|
||||
else runto(tp, &shooter->t_pos);
|
||||
}
|
||||
else if (shooter == &player) {
|
||||
runto(tp, &hero);
|
||||
|
||||
/*
|
||||
* If the player shot a charmed monster, it may
|
||||
* not like being shot at.
|
||||
*/
|
||||
if (on(*tp, ISCHARMED) && save(VS_MAGIC, tp, 0)) {
|
||||
msg("The eyes of %s turn clear.",
|
||||
prname(mname, FALSE));
|
||||
turn_off(*tp, ISCHARMED);
|
||||
mname = monster_name(tp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Let the defender know that the attacker has
|
||||
* missiles!
|
||||
*/
|
||||
if (ce(*tp->t_dest, shooter->t_pos))
|
||||
tp->t_wasshot = TRUE;
|
||||
|
||||
used = TRUE;
|
||||
|
||||
/* Hit the monster -- does it do anything? */
|
||||
if ((EQUAL(name,"ice") && on(*tp, NOCOLD)) ||
|
||||
(EQUAL(name,"flame") && on(*tp, NOFIRE)) ||
|
||||
(EQUAL(name,"acid") && on(*tp, NOACID)) ||
|
||||
(EQUAL(name,"lightning bolt")&& on(*tp,NOBOLT)) ||
|
||||
(EQUAL(name,"nerve gas") &&on(*tp,NOPARALYZE))||
|
||||
(EQUAL(name,"sleeping gas") &&
|
||||
(on(*tp, NOSLEEP) || on(*tp, ISUNDEAD))) ||
|
||||
(EQUAL(name,"slow gas") && on(*tp,NOSLOW)) ||
|
||||
(EQUAL(name,"fear gas") && on(*tp,NOFEAR)) ||
|
||||
(EQUAL(name,"confusion gas") && on(*tp,ISCLEAR)) ||
|
||||
(EQUAL(name,"chlorine gas") && on(*tp,NOGAS))) {
|
||||
if (see_monster)
|
||||
msg("The %s has no effect on %s.",
|
||||
name, prname(mname, FALSE));
|
||||
}
|
||||
|
||||
else {
|
||||
see_him = !invisible(tp);
|
||||
|
||||
/* Did a spell get disrupted? */
|
||||
dsrpt_monster(tp, FALSE, see_him);
|
||||
|
||||
/*
|
||||
* Check for gas with special effects
|
||||
*/
|
||||
if (EQUAL(name, "nerve gas")) {
|
||||
tp->t_no_move = movement(tp) * FREEZETIME;
|
||||
tp->t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "sleeping gas")) {
|
||||
tp->t_no_move = movement(tp) * SLEEPTIME;
|
||||
tp->t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "slow gas")) {
|
||||
if (on(*tp, ISHASTE))
|
||||
turn_off(*tp, ISHASTE);
|
||||
else
|
||||
turn_on(*tp, ISSLOW);
|
||||
}
|
||||
else if (EQUAL(name, "fear gas")) {
|
||||
turn_on(*tp, ISFLEE);
|
||||
tp->t_dest = &hero;
|
||||
|
||||
/* It is okay to turn tail */
|
||||
tp->t_oldpos = tp->t_pos;
|
||||
}
|
||||
else if (EQUAL(name, "confusion gas")) {
|
||||
turn_on(*tp, ISHUH);
|
||||
tp->t_dest = &hero;
|
||||
}
|
||||
else if ((EQUAL(name, "lightning bolt")) &&
|
||||
on(*tp, BOLTDIVIDE)) {
|
||||
if (creat_mons(tp, tp->t_index, FALSE)) {
|
||||
if (see_monster)
|
||||
msg("The %s divides %s.",
|
||||
name,prname(mname, FALSE));
|
||||
light(&hero);
|
||||
}
|
||||
else if (see_monster)
|
||||
msg("The %s has no effect on %s.",
|
||||
name, prname(mname, FALSE));
|
||||
}
|
||||
else {
|
||||
if (save(VS_BREATH, tp,
|
||||
-(shooter->t_stats.s_lvl/10)))
|
||||
damage /= 2;
|
||||
|
||||
/* The poor fellow got killed! */
|
||||
if ((tp->t_stats.s_hpt -= damage) <= 0) {
|
||||
if (see_monster)
|
||||
msg("The %s kills %s",
|
||||
name, prname(mname, FALSE));
|
||||
else
|
||||
msg("You hear a faint groan in the distance");
|
||||
/*
|
||||
* Instead of calling killed() here, we
|
||||
* will record that the monster was killed
|
||||
* and call it at the end of the routine,
|
||||
* after we restore what was under the bolt.
|
||||
* We have to do this because in the case
|
||||
* of a bolt that first misses the monster
|
||||
* and then gets it on the bounce. If we
|
||||
* call killed here, the 'missed' space in
|
||||
* spotpos puts the monster back on the
|
||||
* screen
|
||||
*/
|
||||
target = item;
|
||||
}
|
||||
else { /* Not dead, so just scream */
|
||||
if (!see_monster)
|
||||
msg("You hear a scream in the distance");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isalpha(show(pos.y, pos.x))) {
|
||||
if (see_monster) {
|
||||
if (terse)
|
||||
msg("%s misses", name);
|
||||
else
|
||||
msg("The %s whizzes past %s",
|
||||
name, prname(mname, FALSE));
|
||||
}
|
||||
if (get_points) runto(tp, &hero);
|
||||
}
|
||||
}
|
||||
else if (pos.y == hero.y && pos.x == hero.x) {
|
||||
at_hero: if (!save(VS_BREATH, &player,
|
||||
-(shooter->t_stats.s_lvl/10))){
|
||||
if (terse)
|
||||
msg("The %s hits you", name);
|
||||
else
|
||||
msg("You are hit by the %s", name);
|
||||
used = TRUE;
|
||||
|
||||
/*
|
||||
* The Amulet of Yendor protects against all "breath"
|
||||
*
|
||||
* The following two if statements could be combined
|
||||
* into one, but it makes the compiler barf, so split
|
||||
* it up
|
||||
*/
|
||||
if (cur_relic[YENDOR_AMULET] ||
|
||||
(EQUAL(name,"chlorine gas")&&on(player, NOGAS)) ||
|
||||
(EQUAL(name,"acid")&&on(player, NOACID)) ||
|
||||
(EQUAL(name,"sleeping gas")&&ISWEARING(R_ALERT))){
|
||||
msg("The %s has no effect", name);
|
||||
}
|
||||
else if((EQUAL(name, "flame") && on(player, NOFIRE)) ||
|
||||
(EQUAL(name, "ice") && on(player, NOCOLD)) ||
|
||||
(EQUAL(name,"lightning bolt")&&
|
||||
on(player,NOBOLT)) ||
|
||||
(EQUAL(name,"fear gas")&&ISWEARING(R_HEROISM))){
|
||||
msg("The %s has no effect", name);
|
||||
}
|
||||
|
||||
else {
|
||||
dsrpt_player();
|
||||
|
||||
/*
|
||||
* Check for gas with special effects
|
||||
*/
|
||||
if (EQUAL(name, "nerve gas")) {
|
||||
msg("The nerve gas paralyzes you.");
|
||||
player.t_no_move +=
|
||||
movement(&player) * FREEZETIME;
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "sleeping gas")) {
|
||||
msg("The sleeping gas puts you to sleep.");
|
||||
player.t_no_move +=
|
||||
movement(&player) * SLEEPTIME;
|
||||
player.t_action = A_FREEZE;
|
||||
}
|
||||
else if (EQUAL(name, "confusion gas")) {
|
||||
if (off(player, ISCLEAR)) {
|
||||
if (on(player, ISHUH))
|
||||
lengthen(unconfuse,
|
||||
rnd(20)+HUHDURATION);
|
||||
else {
|
||||
turn_on(player, ISHUH);
|
||||
fuse(unconfuse, (VOID *)NULL,
|
||||
rnd(20)+HUHDURATION, AFTER);
|
||||
msg("The confusion gas has confused you.");
|
||||
}
|
||||
}
|
||||
else msg("You feel dizzy for a moment, but it quickly passes.");
|
||||
}
|
||||
else if (EQUAL(name, "slow gas")) {
|
||||
add_slow();
|
||||
}
|
||||
else if (EQUAL(name, "fear gas")) {
|
||||
turn_on(player, ISFLEE);
|
||||
player.t_dest = &shooter->t_pos;
|
||||
msg("The fear gas terrifies you.");
|
||||
}
|
||||
else {
|
||||
if (EQUAL(name, "acid") &&
|
||||
cur_armor != NULL &&
|
||||
!(cur_armor->o_flags & ISPROT) &&
|
||||
!save(VS_BREATH, &player, -2) &&
|
||||
cur_armor->o_ac < pstats.s_arm+1) {
|
||||
msg("Your armor corrodes from the acid");
|
||||
cur_armor->o_ac++;
|
||||
}
|
||||
if (save(VS_BREATH, &player,
|
||||
-(shooter->t_stats.s_lvl/10)) &&
|
||||
off(player, NOACID))
|
||||
damage /= 2;
|
||||
if ((pstats.s_hpt -= damage) <= 0)
|
||||
death(reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
msg("The %s whizzes by you", name);
|
||||
}
|
||||
|
||||
mvwaddch(cw, pos.y, pos.x, dirch);
|
||||
draw(cw);
|
||||
}
|
||||
|
||||
pos.y += dir.y;
|
||||
pos.x += dir.x;
|
||||
}
|
||||
|
||||
/* Restore what was under the bolt */
|
||||
newfont(cw);
|
||||
for (x = y - 1; x >= 0; x--)
|
||||
mvwaddch(cw, spotpos[x].place.y, spotpos[x].place.x, spotpos[x].oldch);
|
||||
|
||||
/* If we killed something, do so now. This will also blank the monster. */
|
||||
if (target) killed(target, FALSE, get_points, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue