update
This commit is contained in:
parent
17457b0537
commit
014d591109
4
Makefile
4
Makefile
|
@ -1,2 +1,2 @@
|
||||||
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h
|
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h
|
||||||
gcc -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c -lncurses
|
gcc -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c -lncurses
|
||||||
|
|
42
ai.c
42
ai.c
|
@ -11,44 +11,77 @@ extern lifeform_t *player;
|
||||||
|
|
||||||
void aimove(lifeform_t *lf) {
|
void aimove(lifeform_t *lf) {
|
||||||
int dir;
|
int dir;
|
||||||
int db = B_TRUE;
|
int wantdb = B_TRUE;
|
||||||
|
int db = B_FALSE;
|
||||||
|
object_t *curwep,*bestwep;
|
||||||
flag_t *f;
|
flag_t *f;
|
||||||
lifeform_t *target;
|
lifeform_t *target;
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
|
|
||||||
|
|
||||||
|
if (wantdb && haslos(player, lf->cell)) {
|
||||||
|
db = B_TRUE;
|
||||||
|
} else {
|
||||||
|
db = B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (db) dblog("AIMOVE: %s", lf->race->name);
|
if (db) dblog("AIMOVE: %s", lf->race->name);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// if lifeform isn't alive, skip turn
|
// if lifeform isn't alive, skip turn
|
||||||
if (isdead(lf)) {
|
if (isdead(lf)) {
|
||||||
|
if (db) dblog(".oO { i am not alive, skipping turn. }");
|
||||||
taketime(lf, SPEED_DEAD);
|
taketime(lf, SPEED_DEAD);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// do we have a better weapon we could use?
|
||||||
|
curwep = getweapon(lf);
|
||||||
|
bestwep = getbestweapon(lf);
|
||||||
|
|
||||||
|
if (curwep != bestwep) {
|
||||||
|
if (db) dblog(".oO { i have a better weapon than my current one (%s > %s) }",bestwep->type->name, curwep ? curwep->type->name : "nothing");
|
||||||
|
// weild better one
|
||||||
|
weild(lf, bestwep);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// do we already have a target we are attacking?
|
||||||
f = hasflag(lf->flags, F_TARGET);
|
f = hasflag(lf->flags, F_TARGET);
|
||||||
if (f) {
|
if (f) {
|
||||||
int targid;
|
int targid;
|
||||||
|
if (db) dblog(".oO { i have a target... }");
|
||||||
targid = f->val[0];
|
targid = f->val[0];
|
||||||
target = findlf(lf->cell->map, targid);
|
target = findlf(lf->cell->map, targid);
|
||||||
if (target) {
|
if (target) {
|
||||||
|
if (db) dblog(".oO { my target is lfid %d (%s). }", targid, target->race->name);
|
||||||
if (haslos(lf, target->cell)) {
|
if (haslos(lf, target->cell)) {
|
||||||
|
if (db) dblog(".oO { i can see my target. will move towards it. }");
|
||||||
movetowards(lf, target->cell);
|
movetowards(lf, target->cell);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
if (db) dblog(".oO { i cannot see my target }");
|
||||||
// TODO: move towards last known location
|
// TODO: move towards last known location
|
||||||
|
|
||||||
// just try to move in a random direction
|
// just try to move in a random direction
|
||||||
dorandommove(lf);
|
if (db) dblog(".oO { will move randomly }");
|
||||||
|
dorandommove(lf, B_NOBADMOVES);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// not attacking anyone in particular
|
// not attacking anyone in particular
|
||||||
|
|
||||||
|
if (db) dblog(".oO { i do not have a target. }");
|
||||||
// TODO: are we hostile? if so, look for a target
|
// TODO: are we hostile? if so, look for a target
|
||||||
f = hasflag(lf->flags, F_HOSTILE);
|
f = hasflag(lf->flags, F_HOSTILE);
|
||||||
if (f) {
|
if (f) {
|
||||||
int x,y;
|
int x,y;
|
||||||
cell_t *c;
|
cell_t *c;
|
||||||
|
if (db) dblog(".oO { i am hostile. looking for a target. }");
|
||||||
// look around for a target
|
// look around for a target
|
||||||
// TODO: use our vis rang einstead of 10!
|
// TODO: use our vis rang einstead of 10!
|
||||||
for (y = lf->cell->y - 10; y <= lf->cell->y + 10; y++) {
|
for (y = lf->cell->y - 10; y <= lf->cell->y + 10; y++) {
|
||||||
|
@ -58,6 +91,7 @@ void aimove(lifeform_t *lf) {
|
||||||
if (c && haslos(lf, c)) {
|
if (c && haslos(lf, c)) {
|
||||||
// player there?
|
// player there?
|
||||||
if (c->lf && c->lf->controller == C_PLAYER) {
|
if (c->lf && c->lf->controller == C_PLAYER) {
|
||||||
|
if (db) dblog(".oO { found a target - lfid %d (%s) ! }",c->lf->id, c->lf->race->name);
|
||||||
// target them!
|
// target them!
|
||||||
addflag(lf->flags, F_TARGET, c->lf->id, -1, -1, "");
|
addflag(lf->flags, F_TARGET, c->lf->id, -1, -1, "");
|
||||||
// tell the player
|
// tell the player
|
||||||
|
@ -67,6 +101,7 @@ void aimove(lifeform_t *lf) {
|
||||||
msg("%s sees you!", buf);
|
msg("%s sees you!", buf);
|
||||||
}
|
}
|
||||||
// then move towards them...
|
// then move towards them...
|
||||||
|
if (db) dblog(".oO { moving towards my new target }");
|
||||||
movetowards(lf, c);
|
movetowards(lf, c);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +111,8 @@ void aimove(lifeform_t *lf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// just try to move in a random direction
|
// just try to move in a random direction
|
||||||
dorandommove(lf);
|
if (db) dblog(".oO { default - moving randomly }");
|
||||||
|
dorandommove(lf, B_NOBADMOVES);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
341
attack.c
341
attack.c
|
@ -1,28 +1,136 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "attack.h"
|
#include "attack.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include "flag.h"
|
||||||
|
#include "lf.h"
|
||||||
|
#include "objects.h"
|
||||||
|
|
||||||
extern lifeform_t *player;
|
extern lifeform_t *player;
|
||||||
|
|
||||||
void doattack(lifeform_t *lf, lifeform_t *victim) {
|
int doattack(lifeform_t *lf, lifeform_t *victim) {
|
||||||
int dam;
|
int dam;
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
char attackername[BUFLEN];
|
char attackername[BUFLEN];
|
||||||
char victimname[BUFLEN];
|
char victimname[BUFLEN];
|
||||||
int fatal = B_FALSE;
|
int fatal = B_FALSE;
|
||||||
|
flag_t *f;
|
||||||
|
object_t *wep;
|
||||||
|
enum DAMTYPE damtype;
|
||||||
|
obpile_t *op;
|
||||||
|
int attacktime;
|
||||||
|
int acc;
|
||||||
|
int hit = B_FALSE;
|
||||||
|
double dampct;
|
||||||
|
int unarmed = B_FALSE;
|
||||||
|
char wepname[BUFLEN];
|
||||||
|
int ev;
|
||||||
|
|
||||||
// depends on weapon, race attackspeed modifier flag, etc
|
|
||||||
taketime(lf, getattackspeed(lf));
|
|
||||||
|
|
||||||
// TODO: figure out if you hit
|
|
||||||
// TODO: figure out if you do damage
|
|
||||||
dam = 1;
|
|
||||||
|
|
||||||
|
// get names
|
||||||
getlfname(lf, attackername);
|
getlfname(lf, attackername);
|
||||||
getlfname(victim, victimname);
|
getlfname(victim, victimname);
|
||||||
|
|
||||||
losehp(victim, dam, lf, attackername); // TODO: use player name if required
|
|
||||||
|
// get weapon
|
||||||
|
op = addobpile(lf, NULL); // for use if we are unarmed
|
||||||
|
wep = getweapon(lf);
|
||||||
|
if (!wep) {
|
||||||
|
unarmed = B_TRUE;
|
||||||
|
|
||||||
|
// ie. unarmed
|
||||||
|
getunarmedweapon(lf, op);
|
||||||
|
|
||||||
|
if (op->first) {
|
||||||
|
wep = op->first;
|
||||||
|
} else {
|
||||||
|
// cannot attack!
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You cannot attack!");
|
||||||
|
} else if (haslos(player, lf->cell)) {
|
||||||
|
sprintf(buf, "%s",attackername);
|
||||||
|
capitalise(buf);
|
||||||
|
msg("%s looks like it wants to attack!",buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lf->controller != C_PLAYER) {
|
||||||
|
// take some time to avoid infinite loops!
|
||||||
|
taketime(lf, 1);
|
||||||
|
}
|
||||||
|
free(op);
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getobname(wep, wepname, 1);
|
||||||
|
|
||||||
|
|
||||||
|
f = hasflag(wep->flags, F_DAMTYPE);
|
||||||
|
if (f) {
|
||||||
|
damtype = f->val[0];
|
||||||
|
} else {
|
||||||
|
// default - you are just bashing with whatever
|
||||||
|
// you weilded.
|
||||||
|
damtype = DT_BASH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// depends on weapon, race attackspeed modifier flag, etc
|
||||||
|
attacktime = getobattackspeed(wep) + getlfattackspeed(lf);
|
||||||
|
taketime(lf, attacktime);
|
||||||
|
|
||||||
|
// TODO: figure out if you hit
|
||||||
|
|
||||||
|
// TODO: figure out if you do damage, and how much
|
||||||
|
|
||||||
|
acc = 100; // base accuracy of 100%
|
||||||
|
|
||||||
|
// modify for weapon's (lack of) accuracy
|
||||||
|
f = hasflag(wep->flags, F_ACCURACY);
|
||||||
|
if (f) {
|
||||||
|
// ie. accuracy of 100% means no penalty
|
||||||
|
// ie. accuracy of 75% means 25% penalty
|
||||||
|
// etc
|
||||||
|
acc -= (100 - f->val[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// modify for defender's evasion
|
||||||
|
ev = getevasion(victim);
|
||||||
|
acc -= ev;
|
||||||
|
|
||||||
|
// modify for attacker's level
|
||||||
|
acc += (lf->level * 2);
|
||||||
|
|
||||||
|
if (acc < 0) acc = 0;
|
||||||
|
if (acc > 100) acc = 100;
|
||||||
|
|
||||||
|
|
||||||
|
// did you hit?
|
||||||
|
if (rnd(1,100) <= acc) {
|
||||||
|
hit = B_TRUE;
|
||||||
|
} else {
|
||||||
|
hit = B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (hit) {
|
||||||
|
int reducepct;
|
||||||
|
int ar;
|
||||||
|
int reduceamt;
|
||||||
|
// determine damage
|
||||||
|
dam = getdamroll(wep);
|
||||||
|
|
||||||
|
// modify for attacker's armour
|
||||||
|
ar = getarmour(victim);
|
||||||
|
reducepct = ar * 2;
|
||||||
|
reduceamt = (int)(((float)reducepct / 100.0) * (float)dam);
|
||||||
|
|
||||||
|
dam -= reduceamt;
|
||||||
|
if (dam < 0) dam = 0;
|
||||||
|
|
||||||
|
// TODO: armour gets damaged
|
||||||
|
|
||||||
|
losehp(victim, dam, damtype, lf, attackername);
|
||||||
|
|
||||||
if (victim->hp <= 0) {
|
if (victim->hp <= 0) {
|
||||||
fatal = B_TRUE;
|
fatal = B_TRUE;
|
||||||
|
@ -30,21 +138,230 @@ void doattack(lifeform_t *lf, lifeform_t *victim) {
|
||||||
|
|
||||||
// announce it
|
// announce it
|
||||||
if (lf->controller == C_PLAYER) {
|
if (lf->controller == C_PLAYER) {
|
||||||
msg("You %s %s%s",
|
msg("You %s %s%s%s",
|
||||||
fatal ? "kill" : "hit",
|
fatal ? getkillverb(damtype, dam) : getattackverb(damtype, dam),
|
||||||
victimname,
|
victimname,
|
||||||
|
(dam == 0) ? " but do no damage" : "",
|
||||||
fatal ? "!" : ".");
|
fatal ? "!" : ".");
|
||||||
|
|
||||||
|
if (fatal && !hasflag(victim->flags, F_NODEATHANNOUNCE)) {
|
||||||
// don't also say "the xx dies"
|
// don't also say "the xx dies"
|
||||||
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, -1, -1, "");
|
addflag(victim->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (haslos(player, lf->cell)) {
|
||||||
|
char withwep[BUFLEN];
|
||||||
|
|
||||||
|
// capitalise first letter
|
||||||
|
sprintf(buf, "%s",attackername);
|
||||||
|
capitalise(buf);
|
||||||
|
|
||||||
|
if (wep && !unarmed) {
|
||||||
|
sprintf(withwep, " with %s", wepname);
|
||||||
|
} else {
|
||||||
|
strcpy(withwep, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
msg("%s %ss %s%s%s.", buf, getattackverb(damtype,dam), victimname,withwep,
|
||||||
|
(dam == 0) ? " but does no damage" : "" );
|
||||||
|
}
|
||||||
|
// TODO: else {if (haslineofhearing() etc
|
||||||
|
}
|
||||||
|
} else { // miss!
|
||||||
|
// announce it
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You miss %s.", victimname);
|
||||||
} else {
|
} else {
|
||||||
if (haslos(player, lf->cell)) {
|
if (haslos(player, lf->cell)) {
|
||||||
// capitalise first letter
|
// capitalise first letter
|
||||||
sprintf(buf, "%s",attackername);
|
sprintf(buf, "%s",attackername);
|
||||||
capitalise(buf);
|
capitalise(buf);
|
||||||
|
|
||||||
msg("%s hits %s.", buf, victimname);
|
msg("%s misses %s.", buf, victimname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fightback(victim, lf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get rid of temp unarmed object
|
||||||
|
if (op->first) {
|
||||||
|
killob(op->first);
|
||||||
|
}
|
||||||
|
free(op);
|
||||||
|
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getattackverb(enum DAMTYPE damtype, int dam) {
|
||||||
|
if (damtype == DT_PROJECTILE) {
|
||||||
|
return "hit";
|
||||||
|
} else if (damtype == DT_HOLY) {
|
||||||
|
return "smite";
|
||||||
|
} else if (damtype == DT_PIERCE) {
|
||||||
|
if (dam == 0) {
|
||||||
|
return "poke";
|
||||||
|
} else if (dam <= 5) {
|
||||||
|
return "nick";
|
||||||
|
} else if (dam <= 10) {
|
||||||
|
return "stab";
|
||||||
|
} else if (dam <= 15) {
|
||||||
|
return "pierce";
|
||||||
|
} else if (dam <= 20) {
|
||||||
|
return "spear";
|
||||||
|
} else {
|
||||||
|
return "deeply stab";
|
||||||
|
}
|
||||||
|
} else if (damtype == DT_CLAW) {
|
||||||
|
if (dam == 0) {
|
||||||
|
return "scratch";
|
||||||
|
} else if (dam <= 5) {
|
||||||
|
return "claw";
|
||||||
|
} else if (dam <= 15) {
|
||||||
|
return "rake";
|
||||||
|
} else if (dam <= 30) {
|
||||||
|
return "gouge";
|
||||||
|
} else {
|
||||||
|
return "eviscerate";
|
||||||
|
}
|
||||||
|
} else if (damtype == DT_SLASH) {
|
||||||
|
if (dam == 0) {
|
||||||
|
return "scratch";
|
||||||
|
} else if (dam <= 10) {
|
||||||
|
return "hit";
|
||||||
|
} else if (dam <= 20) {
|
||||||
|
return "slash";
|
||||||
|
} else {
|
||||||
|
return "slice";
|
||||||
|
}
|
||||||
|
} else if (damtype == DT_CHOP) {
|
||||||
|
if (dam == 0) {
|
||||||
|
return "hit";
|
||||||
|
} else if (dam <= 10) {
|
||||||
|
return "hack";
|
||||||
|
} else {
|
||||||
|
return "chop";
|
||||||
|
}
|
||||||
|
} else if (damtype == DT_BASH) {
|
||||||
|
if (dam == 0) {
|
||||||
|
return "whack";
|
||||||
|
} else if (dam <= 5) {
|
||||||
|
return "hit";
|
||||||
|
} else if (dam <= 10) {
|
||||||
|
return "bash";
|
||||||
|
} else if (dam <= 15) {
|
||||||
|
return "pummel";
|
||||||
|
} else if (dam <= 20) {
|
||||||
|
return "pound";
|
||||||
|
} else {
|
||||||
|
return "flatten";
|
||||||
|
}
|
||||||
|
} else if (damtype == DT_BITE) {
|
||||||
|
if (dam == 0) {
|
||||||
|
return "gnaw";
|
||||||
|
} else if (dam <= 15) {
|
||||||
|
return "bite";
|
||||||
|
} else {
|
||||||
|
return "savage";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "hit";
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getkillverb(enum DAMTYPE damtype, int dam) {
|
||||||
|
if (damtype == DT_HOLY) {
|
||||||
|
return "smite";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dam >= 50) {
|
||||||
|
if (damtype == DT_PIERCE) return "fatally stab";
|
||||||
|
if (damtype == DT_BITE) return "gore";
|
||||||
|
if (damtype == DT_CLAW) return "disembowel";
|
||||||
|
if (damtype == DT_SLASH) return "behead"; // TODO: only if they have a head! otherwise "bisect"
|
||||||
|
}
|
||||||
|
|
||||||
|
return "kill";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// return TRUE if no damage
|
||||||
|
int getdamrange(object_t *o, int *min, int *max) {
|
||||||
|
int mindam,maxdam;
|
||||||
|
flag_t *f;
|
||||||
|
|
||||||
|
f = hasflag(o->flags, F_DAM);
|
||||||
|
if (f) {
|
||||||
|
int mod,ndice,sides;
|
||||||
|
ndice = f->val[0];
|
||||||
|
sides = f->val[1];
|
||||||
|
if (f->val[2] == NA) {
|
||||||
|
mod = 0;
|
||||||
|
} else {
|
||||||
|
mod = f->val[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
mindam = (ndice * 1) + mod;
|
||||||
|
maxdam = (ndice * sides) + mod;
|
||||||
|
} else {
|
||||||
|
mindam = 0;
|
||||||
|
maxdam = 0;
|
||||||
|
}
|
||||||
|
if (min) *min = mindam;
|
||||||
|
if (max) *max = maxdam;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// roll for damage
|
||||||
|
int getdamroll(object_t *o) {
|
||||||
|
int dam;
|
||||||
|
int ndice, sides, mod;
|
||||||
|
flag_t *f;
|
||||||
|
f = hasflag(o->flags, F_DAM);
|
||||||
|
|
||||||
|
if (f) {
|
||||||
|
ndice = f->val[0];
|
||||||
|
sides = f->val[1];
|
||||||
|
if (f->val[2] != NA) {
|
||||||
|
mod = f->val[2];
|
||||||
|
} else {
|
||||||
|
mod = 0;
|
||||||
|
}
|
||||||
|
dam = rolldie(ndice, sides) + mod;
|
||||||
|
} else {
|
||||||
|
// weapon does no damage
|
||||||
|
dam = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dam;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// determine attack type for lifeform.
|
||||||
|
// add an object of this kind to the pile 'op'
|
||||||
|
// return its type;
|
||||||
|
objecttype_t *getunarmedweapon(lifeform_t *lf,obpile_t *op) {
|
||||||
|
int nposs;
|
||||||
|
flag_t *f;
|
||||||
|
int sel;
|
||||||
|
char poss[MAXPILEOBS][BUFLEN];
|
||||||
|
|
||||||
|
// pick a random attack type.
|
||||||
|
nposs = 0;
|
||||||
|
for (f = lf->flags->first ; f ; f = f->next) {
|
||||||
|
if (f->id == F_UNARMEDATTACKOB) {
|
||||||
|
strcpy(poss[nposs],f->text);
|
||||||
|
nposs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nposs > 0) {
|
||||||
|
sel = rnd(0,nposs-1);
|
||||||
|
addob(op, poss[sel]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (op->first) {
|
||||||
|
return op->first->type;
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
7
attack.h
7
attack.h
|
@ -1,3 +1,8 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
void doattack(lifeform_t *lf, lifeform_t *victim);
|
int doattack(lifeform_t *lf, lifeform_t *victim);
|
||||||
|
char *getattackverb(enum DAMTYPE damtype, int dam);
|
||||||
|
char *getkillverb(enum DAMTYPE damtype, int dam);
|
||||||
|
int getdamrange(object_t *o, int *min, int *max);
|
||||||
|
int getdamroll(object_t *o);
|
||||||
|
objecttype_t *getunarmedweapon(lifeform_t *lf, obpile_t *op);
|
||||||
|
|
154
defs.h
154
defs.h
|
@ -7,6 +7,7 @@
|
||||||
// save/load
|
// save/load
|
||||||
#define MAPDIR "data/maps"
|
#define MAPDIR "data/maps"
|
||||||
#define SAVEDIR "data/save"
|
#define SAVEDIR "data/save"
|
||||||
|
#define DUMMYCELLTYPE 0xabcd
|
||||||
|
|
||||||
// SPECIAL NUMBERS/CONSTANTS
|
// SPECIAL NUMBERS/CONSTANTS
|
||||||
#define UNLIMITED (-9876)
|
#define UNLIMITED (-9876)
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
#define MAXPILEOBS 52
|
#define MAXPILEOBS 52
|
||||||
|
|
||||||
#define MAXRANDOMOBCANDIDATES 100
|
#define MAXRANDOMOBCANDIDATES 100
|
||||||
|
#define MAXRANDOMLFCANDIDATES 100
|
||||||
|
|
||||||
#define MAX_MAPW 80
|
#define MAX_MAPW 80
|
||||||
#define MAX_MAPH 50
|
#define MAX_MAPH 50
|
||||||
|
@ -58,6 +60,12 @@
|
||||||
//
|
//
|
||||||
#define ANIMDELAY (1000000 / 100) // 1/100 of a second
|
#define ANIMDELAY (1000000 / 100) // 1/100 of a second
|
||||||
|
|
||||||
|
|
||||||
|
// askobject options
|
||||||
|
#define AO_NONE 0
|
||||||
|
#define AO_INCLUDENOTHING 1
|
||||||
|
#define AO_ONLYEQUIPPED 2
|
||||||
|
|
||||||
// CONTROLLERS
|
// CONTROLLERS
|
||||||
#define C_AI 0
|
#define C_AI 0
|
||||||
#define C_PLAYER 1
|
#define C_PLAYER 1
|
||||||
|
@ -70,6 +78,8 @@
|
||||||
#define SPEED_PICKUP 5
|
#define SPEED_PICKUP 5
|
||||||
#define SPEED_THROW 10
|
#define SPEED_THROW 10
|
||||||
#define SPEED_WAIT 10
|
#define SPEED_WAIT 10
|
||||||
|
#define SPEED_READ 10
|
||||||
|
#define SPEED_DRINK 5
|
||||||
|
|
||||||
|
|
||||||
// DIRECTION TYPES
|
// DIRECTION TYPES
|
||||||
|
@ -109,6 +119,29 @@
|
||||||
#define CT_DOORCLOSED 5
|
#define CT_DOORCLOSED 5
|
||||||
#define CT_LOOPCORRIDOR 6
|
#define CT_LOOPCORRIDOR 6
|
||||||
|
|
||||||
|
// damage type
|
||||||
|
enum DAMTYPE {
|
||||||
|
DT_PIERCE,
|
||||||
|
DT_SLASH,
|
||||||
|
DT_CLAW,
|
||||||
|
DT_BASH,
|
||||||
|
DT_BITE,
|
||||||
|
DT_CHOP,
|
||||||
|
DT_PROJECTILE,
|
||||||
|
DT_HOLY,
|
||||||
|
};
|
||||||
|
|
||||||
|
// speeds
|
||||||
|
#define SP_GODLIKE 1
|
||||||
|
#define SP_ULTRAFAST 5
|
||||||
|
#define SP_VERYFAST 10
|
||||||
|
#define SP_FAST 15
|
||||||
|
#define SP_NORMAL 20
|
||||||
|
#define SP_SLOW 25
|
||||||
|
#define SP_VERYSLOW 30
|
||||||
|
#define SP_ULTRASLOW 35
|
||||||
|
#define SP_SLOWEST 40
|
||||||
|
|
||||||
// Object Classes
|
// Object Classes
|
||||||
enum OBCLASS {
|
enum OBCLASS {
|
||||||
OC_MONEY,
|
OC_MONEY,
|
||||||
|
@ -119,6 +152,7 @@ enum OBCLASS {
|
||||||
OC_FOOD,
|
OC_FOOD,
|
||||||
OC_ROCK,
|
OC_ROCK,
|
||||||
OC_MISC,
|
OC_MISC,
|
||||||
|
OC_SPELL,
|
||||||
OC_NULL = -999
|
OC_NULL = -999
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -134,6 +168,7 @@ enum HABITAT {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RARITY {
|
enum RARITY {
|
||||||
|
RR_UNIQUE = 7,
|
||||||
RR_NEVER = 6,
|
RR_NEVER = 6,
|
||||||
RR_VERYRARE = 5,
|
RR_VERYRARE = 5,
|
||||||
RR_RARE = 4,
|
RR_RARE = 4,
|
||||||
|
@ -145,6 +180,7 @@ enum RARITY {
|
||||||
|
|
||||||
enum RACE {
|
enum RACE {
|
||||||
R_BAT,
|
R_BAT,
|
||||||
|
R_RAT,
|
||||||
R_GIANTFLY,
|
R_GIANTFLY,
|
||||||
R_GIANTBLOWFLY,
|
R_GIANTBLOWFLY,
|
||||||
R_HUMAN,
|
R_HUMAN,
|
||||||
|
@ -153,13 +189,20 @@ enum RACE {
|
||||||
|
|
||||||
// Object Materials
|
// Object Materials
|
||||||
enum MATERIAL {
|
enum MATERIAL {
|
||||||
|
MT_NOTHING,
|
||||||
|
MT_BONE,
|
||||||
MT_STONE,
|
MT_STONE,
|
||||||
MT_FIRE,
|
MT_FIRE,
|
||||||
MT_PLASTIC,
|
MT_PLASTIC,
|
||||||
MT_METAL,
|
MT_METAL,
|
||||||
|
MT_GLASS,
|
||||||
MT_FLESH,
|
MT_FLESH,
|
||||||
MT_WOOD,
|
MT_WOOD,
|
||||||
MT_GOLD
|
MT_GOLD,
|
||||||
|
MT_PAPER,
|
||||||
|
MT_ICE,
|
||||||
|
MT_WATER,
|
||||||
|
MT_LEATHER
|
||||||
};
|
};
|
||||||
|
|
||||||
// Object Types
|
// Object Types
|
||||||
|
@ -172,6 +215,61 @@ enum OBTYPE {
|
||||||
OT_CORPSEGOBLIN,
|
OT_CORPSEGOBLIN,
|
||||||
OT_CORPSEBAT,
|
OT_CORPSEBAT,
|
||||||
OT_CORPSEFLY,
|
OT_CORPSEFLY,
|
||||||
|
// spells
|
||||||
|
OT_S_RNDTELEPORT,
|
||||||
|
OT_S_MAPPING,
|
||||||
|
// potions
|
||||||
|
OT_POT_HEALING,
|
||||||
|
// scrolls
|
||||||
|
OT_MAP,
|
||||||
|
OT_SCR_RNDTELEPORT,
|
||||||
|
OT_SCR_MAPPING,
|
||||||
|
// misc objects
|
||||||
|
OT_EMPTYFLASK,
|
||||||
|
OT_BROKENGLASS,
|
||||||
|
OT_PUDDLEWATER,
|
||||||
|
// armour - feet
|
||||||
|
OT_BOOTSLEATHER,
|
||||||
|
// armour - hands
|
||||||
|
OT_GLOVESLEATHER,
|
||||||
|
// animal weapons
|
||||||
|
OT_TEETHT,
|
||||||
|
OT_CLAWST,
|
||||||
|
OT_CLAWSS,
|
||||||
|
OT_FISTS,
|
||||||
|
// stabbing weapons
|
||||||
|
OT_STEAKKNIFE,
|
||||||
|
OT_DAGGER,
|
||||||
|
OT_RAPIER,
|
||||||
|
OT_TRIDENT,
|
||||||
|
OT_QUICKBLADE,
|
||||||
|
// slashing weapons
|
||||||
|
OT_SCYTHE,
|
||||||
|
OT_SHORTSWORD,
|
||||||
|
OT_SCIMITAR,
|
||||||
|
OT_LONGSWORD,
|
||||||
|
// polearms
|
||||||
|
OT_SPEAR,
|
||||||
|
OT_QUARTERSTAFF,
|
||||||
|
// bashing weapons
|
||||||
|
OT_CLUB,
|
||||||
|
OT_MACE,
|
||||||
|
OT_MORNINGSTAR,
|
||||||
|
OT_GREATCLUB,
|
||||||
|
OT_SICKLE,
|
||||||
|
// holy
|
||||||
|
OT_HANDOFGOD,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BODYPART {
|
||||||
|
BP_WEAPON,
|
||||||
|
BP_RIGHTHAND,
|
||||||
|
BP_LEFTHAND,
|
||||||
|
BP_HANDS,
|
||||||
|
BP_HEAD,
|
||||||
|
BP_BODY,
|
||||||
|
BP_SHOULDERS,
|
||||||
|
BP_FEET,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FLAG {
|
enum FLAG {
|
||||||
|
@ -180,16 +278,40 @@ enum FLAG {
|
||||||
F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money)
|
F_NO_PLURAL, // this obname doesn't need an 's' for plurals (eg. gold, money)
|
||||||
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
|
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
|
||||||
F_EDIBLE, // you can eat this. val2 = nutrition
|
F_EDIBLE, // you can eat this. val2 = nutrition
|
||||||
|
F_EQUIPPED, // val0 = where it is equipped. CLEAR WHEN OB MOVED!
|
||||||
|
F_GOESON, // val0 = where it can be equipped.
|
||||||
|
F_OBATTACKSPEED, // how long weapon takes to attack
|
||||||
|
F_DAMTYPE, // val0 = damage type
|
||||||
|
F_DAM, // val0 = ndice, val1 = nsidesondie, val2 = mod
|
||||||
|
F_ACCURACY, // 100 - val0 = penalty to tohit% (ie. higher is better)
|
||||||
|
F_TWOHANDED, // weapon uses two hands to weild
|
||||||
|
F_UNIQUE, // only one may appear
|
||||||
|
F_GLYPH, // override the glyph with the first char of text
|
||||||
|
F_SHARP, // does damage when you step on it
|
||||||
|
F_NOPICKUP, // cannot pick this up
|
||||||
|
// armour flags
|
||||||
|
F_ARMOURRATING, // val0 * 2 = pct of damage reduced
|
||||||
|
// scroll flags
|
||||||
|
F_LINKSPELL, // val0 = spell this scroll will cast when read
|
||||||
|
// ob identification flags
|
||||||
|
F_HASHIDDENNAME, // whether this object class has a hidden name
|
||||||
|
F_IDENTIFIED, // whether this object is fully identified
|
||||||
// lifeform flags
|
// lifeform flags
|
||||||
|
F_STARTOB, // val0 = %chance of starting with it, text = ob name
|
||||||
|
F_STARTOBDT, // val0 = %chance of starting with damtype val1
|
||||||
F_CORPSETYPE, // text field specifies what corpse obtype to leave
|
F_CORPSETYPE, // text field specifies what corpse obtype to leave
|
||||||
|
F_LFATTACKDELAY, // how long this race takes to attack
|
||||||
F_FLYING, // lf is flying
|
F_FLYING, // lf is flying
|
||||||
F_HOSTILE, // lf will attack anything the player if in sight
|
F_HOSTILE, // lf will attack anything the player if in sight
|
||||||
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
|
F_NODEATHANNOUNCE, // don't say 'the xx dies' if this lf dies
|
||||||
F_TARGET, // lf will attack this lf id
|
F_TARGET, // lf will attack this lf id
|
||||||
F_ATTACKSPEED, // override default attack speed
|
|
||||||
F_MOVESPEED, // override default move speed
|
F_MOVESPEED, // override default move speed
|
||||||
F_RARITY, // val[0] = habitat, val[1] = rarity
|
F_RARITY, // val[0] = habitat, val[1] = rarity
|
||||||
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
|
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
|
||||||
|
F_HITDICE, // val0: # d4 to roll for hitdice. val1: +xx
|
||||||
|
// COMBAT
|
||||||
|
F_UNARMEDATTACKOB, // objecttype id to use when attacking unarmed
|
||||||
|
F_EVASION, // % chance of evading an attack
|
||||||
//
|
//
|
||||||
F_NULL = -1
|
F_NULL = -1
|
||||||
};
|
};
|
||||||
|
@ -204,6 +326,12 @@ enum FLAG {
|
||||||
#define B_FALSE (0)
|
#define B_FALSE (0)
|
||||||
#define B_TRUE (-1)
|
#define B_TRUE (-1)
|
||||||
|
|
||||||
|
#define B_UNKNOWN (0)
|
||||||
|
#define B_KNOWN (-1)
|
||||||
|
|
||||||
|
#define B_NOBADMOVES (0)
|
||||||
|
#define B_BADMOVESOK (1)
|
||||||
|
|
||||||
#define B_NOSTACK (0)
|
#define B_NOSTACK (0)
|
||||||
#define B_STACK (-1)
|
#define B_STACK (-1)
|
||||||
#define B_STACKOK (-1)
|
#define B_STACKOK (-1)
|
||||||
|
@ -225,7 +353,13 @@ enum ERROR {
|
||||||
E_OK = 0,
|
E_OK = 0,
|
||||||
E_WALLINWAY = 1,
|
E_WALLINWAY = 1,
|
||||||
E_LFINWAY = 2,
|
E_LFINWAY = 2,
|
||||||
E_NOSPACE = 3
|
E_NOSPACE = 3,
|
||||||
|
E_SELNOTHING = 4,
|
||||||
|
E_ALREADYUSING = 5,
|
||||||
|
E_WEARINGSOMETHINGELSE = 6,
|
||||||
|
E_NOUNARMEDATTACK = 7,
|
||||||
|
E_NOTEQUIPPED = 8,
|
||||||
|
E_NOPICKUP = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct map_s {
|
typedef struct map_s {
|
||||||
|
@ -281,6 +415,7 @@ typedef struct lifeform_s {
|
||||||
int id;
|
int id;
|
||||||
int controller;
|
int controller;
|
||||||
struct race_s *race;
|
struct race_s *race;
|
||||||
|
int level;
|
||||||
int hp,maxhp;
|
int hp,maxhp;
|
||||||
int alive;
|
int alive;
|
||||||
char *lastdam;
|
char *lastdam;
|
||||||
|
@ -288,6 +423,8 @@ typedef struct lifeform_s {
|
||||||
int timespent;
|
int timespent;
|
||||||
int sorted;
|
int sorted;
|
||||||
|
|
||||||
|
float forgettimer;
|
||||||
|
|
||||||
struct obpile_s *pack;
|
struct obpile_s *pack;
|
||||||
|
|
||||||
struct flagpile_s *flags;
|
struct flagpile_s *flags;
|
||||||
|
@ -326,15 +463,24 @@ typedef struct flag_s {
|
||||||
} flag_t;
|
} flag_t;
|
||||||
|
|
||||||
typedef struct material_s {
|
typedef struct material_s {
|
||||||
int id;
|
enum MATERIAL id;
|
||||||
char *name;
|
char *name;
|
||||||
struct material_s *next,*prev;
|
struct material_s *next,*prev;
|
||||||
} material_t;
|
} material_t;
|
||||||
|
|
||||||
|
typedef struct knowledge_s {
|
||||||
|
enum OBTYPE id;
|
||||||
|
char *hiddenname;
|
||||||
|
int known;
|
||||||
|
struct knowledge_s *next, *prev;
|
||||||
|
} knowledge_t;
|
||||||
|
|
||||||
typedef struct objectclass_s {
|
typedef struct objectclass_s {
|
||||||
enum OBCLASS id;
|
enum OBCLASS id;
|
||||||
char *name;
|
char *name;
|
||||||
|
char *desc;
|
||||||
char glyph;
|
char glyph;
|
||||||
|
struct flagpile_s *flags;
|
||||||
struct objectclass_s *next, *prev;
|
struct objectclass_s *next, *prev;
|
||||||
} objectclass_t;
|
} objectclass_t;
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,7 @@ In defs.h:
|
||||||
In objects.c:
|
In objects.c:
|
||||||
define the class with addoc()
|
define the class with addoc()
|
||||||
add the class to sortorder[] at the top
|
add the class to sortorder[] at the top
|
||||||
|
findotn() must know how to un-pluralise the name
|
||||||
|
|
||||||
|
In text.c:
|
||||||
|
makeplural() must know about the name
|
||||||
|
|
10
flag.c
10
flag.c
|
@ -29,7 +29,7 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char
|
||||||
|
|
||||||
// first blank values
|
// first blank values
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
f->val[i] = 0;
|
f->val[i] = NA;
|
||||||
}
|
}
|
||||||
|
|
||||||
f->val[0] = val1;
|
f->val[0] = val1;
|
||||||
|
@ -39,7 +39,7 @@ flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char
|
||||||
f->nvals++;
|
f->nvals++;
|
||||||
}
|
}
|
||||||
if (val3 != NA) {
|
if (val3 != NA) {
|
||||||
f->val[2] = val2;
|
f->val[2] = val3;
|
||||||
f->nvals++;
|
f->nvals++;
|
||||||
}
|
}
|
||||||
if (text) {
|
if (text) {
|
||||||
|
@ -74,9 +74,9 @@ flag_t *hasflagval(flagpile_t *fp, int id, int val1, int val2, int val3, char *t
|
||||||
flag_t *f;
|
flag_t *f;
|
||||||
for (f = fp->first ; f ; f = f->next) {
|
for (f = fp->first ; f ; f = f->next) {
|
||||||
if (f->id == id) {
|
if (f->id == id) {
|
||||||
if ( ((val1 == -1) || (f->val[0] == val1)) &&
|
if ( ((val1 == NA) || (f->val[0] == val1)) &&
|
||||||
((val2 == -1) || (f->val[1] == val2)) &&
|
((val2 == NA) || (f->val[1] == val2)) &&
|
||||||
((val3 == -1) || (f->val[2] == val3)) &&
|
((val3 == NA) || (f->val[2] == val3)) &&
|
||||||
((text == NULL) || strstr(f->text, text))) {
|
((text == NULL) || strstr(f->text, text))) {
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
622
io.c
622
io.c
|
@ -2,8 +2,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ncurses.h>
|
#include <ncurses.h>
|
||||||
|
#include "attack.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include "flag.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
|
#include "lf.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "move.h"
|
#include "move.h"
|
||||||
#include "nexus.h"
|
#include "nexus.h"
|
||||||
|
@ -18,6 +21,7 @@ extern enum ERROR reason;
|
||||||
|
|
||||||
extern FILE *logfile;
|
extern FILE *logfile;
|
||||||
extern enum OBCLASS sortorder[];
|
extern enum OBCLASS sortorder[];
|
||||||
|
extern knowledge_t *knowledge;
|
||||||
|
|
||||||
extern int gamestarted;
|
extern int gamestarted;
|
||||||
|
|
||||||
|
@ -169,7 +173,15 @@ cell_t *askcoords(char *prompt) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
object_t *askobject(obpile_t *op, char *prompt, int *count, int opts) {
|
||||||
|
doaskobject(op, prompt, count, opts, OC_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_t *askobjectofclass(obpile_t *op, char *prompt, int *count, int opts, enum OBCLASS obclass) {
|
||||||
|
doaskobject(op, prompt, count, opts, obclass);
|
||||||
|
}
|
||||||
|
|
||||||
|
object_t *doaskobject(obpile_t *op, char *prompt, int *count, int opts, enum OBCLASS obclass) {
|
||||||
int c,i;
|
int c,i;
|
||||||
object_t *mylist[MAXPILEOBS+1];
|
object_t *mylist[MAXPILEOBS+1];
|
||||||
char myletters[MAXPILEOBS+1];
|
char myletters[MAXPILEOBS+1];
|
||||||
|
@ -177,10 +189,16 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
int firstob = 0;
|
int firstob = 0;
|
||||||
int nextpage = -1;
|
int nextpage = -1;
|
||||||
int lastline = SCREENH-2;
|
int lastline = SCREENH-2;
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN],buf2[BUFLEN];
|
||||||
int finished;
|
int finished;
|
||||||
char nextlet = 'a';
|
char nextlet = 'a';
|
||||||
int useobletters;
|
int useobletters;
|
||||||
|
objectclass_t *wantoc;
|
||||||
|
flag_t *f;
|
||||||
|
|
||||||
|
reason = E_OK;
|
||||||
|
|
||||||
|
wantoc = findoc(obclass); // might be null if OC_NULL was passed.
|
||||||
|
|
||||||
// if picking form a player's pack, use the object's letters.
|
// if picking form a player's pack, use the object's letters.
|
||||||
// otherwise just label them a, b, c, etc.
|
// otherwise just label them a, b, c, etc.
|
||||||
|
@ -195,16 +213,26 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
i = 0;
|
i = 0;
|
||||||
while (sortorder[c] != OC_NULL) {
|
while (sortorder[c] != OC_NULL) {
|
||||||
object_t *o;
|
object_t *o;
|
||||||
|
if (!wantoc || (sortorder[c] == wantoc->id)) {
|
||||||
// add all objects of this class
|
// add all objects of this class
|
||||||
for (o = op->first ; o ; o = o->next) {
|
for (o = op->first ; o ; o = o->next) {
|
||||||
if (o->type->obclass->id == sortorder[c]) {
|
if (o->type->obclass->id == sortorder[c]) {
|
||||||
|
int ok;
|
||||||
|
// can we include this object?
|
||||||
|
ok = B_TRUE;
|
||||||
|
if ((opts & AO_ONLYEQUIPPED) && !hasflag(o->flags, F_EQUIPPED)) {
|
||||||
|
ok = B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
mylist[i] = o;
|
mylist[i] = o;
|
||||||
myletters[i] = nextlet;
|
myletters[i] = nextlet;
|
||||||
if (++nextlet > 'z') nextlet = 'A';
|
if (++nextlet > 'z') nextlet = 'A';
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
mylist[i] = NULL;
|
mylist[i] = NULL;
|
||||||
|
@ -219,9 +247,13 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
int y;
|
int y;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
|
|
||||||
wclear(mainwin);
|
wclear(mainwin);
|
||||||
|
|
||||||
|
|
||||||
// list the objects
|
// list the objects
|
||||||
y = 2;
|
y = 2;
|
||||||
|
|
||||||
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
|
for (i = firstob ; (mylist[i] != NULL) && (y < lastline); i++) {
|
||||||
if (mylist[i]->type->obclass->id != lastclass) {
|
if (mylist[i]->type->obclass->id != lastclass) {
|
||||||
objectclass_t *oc;
|
objectclass_t *oc;
|
||||||
|
@ -232,10 +264,23 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
|
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
|
// print object name
|
||||||
getobname(mylist[i], buf,mylist[i]->amt);
|
getobname(mylist[i], buf,mylist[i]->amt);
|
||||||
mvwprintw(mainwin, y, 0, " %c - %s",
|
sprintf(buf2, " %c - %s", useobletters ? mylist[i]->letter : myletters[i],
|
||||||
useobletters ? mylist[i]->letter : myletters[i],
|
|
||||||
buf);
|
buf);
|
||||||
|
f = hasflag(mylist[i]->flags,F_EQUIPPED);
|
||||||
|
if (f) {
|
||||||
|
if (f->val[0] == BP_WEAPON) {
|
||||||
|
strcat(buf2, " (weapon)");
|
||||||
|
} else {
|
||||||
|
strcat(buf2, " (");
|
||||||
|
strcat(buf2, getbodypartequipname(f->val[0]));
|
||||||
|
strcat(buf2, " ");
|
||||||
|
strcat(buf2, getbodypartname(f->val[0]));
|
||||||
|
strcat(buf2, ")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mvwprintw(mainwin, y, 0, buf2);
|
||||||
y++;
|
y++;
|
||||||
}
|
}
|
||||||
if (mylist[i] == NULL) {
|
if (mylist[i] == NULL) {
|
||||||
|
@ -245,9 +290,12 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
}
|
}
|
||||||
// draw prompt
|
// draw prompt
|
||||||
if (strlen(numstring) > 0) {
|
if (strlen(numstring) > 0) {
|
||||||
mvwprintw(mainwin, 0, 0, "%s (ESC to quit) [%s]: ",prompt, numstring);
|
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit) [%s]: ",prompt,
|
||||||
|
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
|
||||||
|
numstring);
|
||||||
} else {
|
} else {
|
||||||
mvwprintw(mainwin, 0, 0, "%s (ESC to quit): ", prompt);
|
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit): ", prompt,
|
||||||
|
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
|
||||||
}
|
}
|
||||||
if (nextpage != -1) {
|
if (nextpage != -1) {
|
||||||
mvwprintw(mainwin, y, 0, "-- More --");
|
mvwprintw(mainwin, y, 0, "-- More --");
|
||||||
|
@ -269,7 +317,7 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
} else {
|
} else {
|
||||||
firstob = nextpage;
|
firstob = nextpage;
|
||||||
}
|
}
|
||||||
} else if (isalpha(ch)) {
|
} else if (isalpha(ch) || (ch == '$')) {
|
||||||
object_t *o;
|
object_t *o;
|
||||||
// describe that object
|
// describe that object
|
||||||
if (useobletters) {
|
if (useobletters) {
|
||||||
|
@ -292,20 +340,27 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
*count = o->amt;
|
*count = o->amt;
|
||||||
}
|
}
|
||||||
// display game windows again
|
// display game windows again
|
||||||
|
clearmsg();
|
||||||
drawscreen();
|
drawscreen();
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
} else if ((ch == '-') && (opts & AO_INCLUDENOTHING)) { // select nothing
|
||||||
|
reason = E_SELNOTHING;
|
||||||
|
// display game windows again
|
||||||
|
clearmsg();
|
||||||
|
drawscreen();
|
||||||
|
return NULL;
|
||||||
} else if (isdigit(ch)) {
|
} else if (isdigit(ch)) {
|
||||||
char temp[2];
|
char temp[2];
|
||||||
temp[0] = ch;
|
temp[0] = ch;
|
||||||
temp[1] = '\0';
|
temp[1] = '\0';
|
||||||
strcat(numstring, temp);
|
strcat(numstring, temp);
|
||||||
*count = atoi(numstring);
|
if (count) *count = atoi(numstring);
|
||||||
} else if (ch == 8) { // backspace
|
} else if (ch == 8) { // backspace
|
||||||
if (strlen(numstring) > 0) {
|
if (strlen(numstring) > 0) {
|
||||||
// remove last letter of number string
|
// remove last letter of number string
|
||||||
numstring[strlen(numstring)-1] = '\0';
|
numstring[strlen(numstring)-1] = '\0';
|
||||||
*count = atoi(numstring);
|
if (count) *count = atoi(numstring);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +370,9 @@ object_t *askobject(obpile_t *op, char *prompt, int *count) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear msg bar
|
||||||
|
clearmsg();
|
||||||
|
|
||||||
// display game windows again
|
// display game windows again
|
||||||
drawscreen();
|
drawscreen();
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -397,13 +455,18 @@ void describeob(object_t *o) {
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
int y;
|
int y;
|
||||||
material_t *m;
|
material_t *m;
|
||||||
|
flag_t *f;
|
||||||
|
|
||||||
wclear(mainwin);
|
wclear(mainwin);
|
||||||
|
|
||||||
// title
|
// title
|
||||||
getobname(o, buf,o->amt);
|
getobname(o, buf,o->amt);
|
||||||
mvwprintw(mainwin, 0, 0, buf);
|
mvwprintw(mainwin, 0, 0, buf);
|
||||||
|
if (isknown(o)) {
|
||||||
mvwprintw(mainwin, 2, 0, o->type->desc);
|
mvwprintw(mainwin, 2, 0, o->type->desc);
|
||||||
|
} else {
|
||||||
|
mvwprintw(mainwin, 2, 0, o->type->obclass->desc);
|
||||||
|
}
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
y = 4;
|
y = 4;
|
||||||
|
@ -414,6 +477,39 @@ void describeob(object_t *o) {
|
||||||
} else {
|
} else {
|
||||||
mvwprintw(mainwin, y, 0, "They weigh %0.1fkg (%0.1f each).",(o->weight * o->amt), o->weight);
|
mvwprintw(mainwin, y, 0, "They weigh %0.1fkg (%0.1f each).",(o->weight * o->amt), o->weight);
|
||||||
}
|
}
|
||||||
|
y++;
|
||||||
|
|
||||||
|
// weapons?
|
||||||
|
if (o->type->obclass->id == OC_WEAPON) {
|
||||||
|
f = hasflag(o->flags, F_DAMTYPE);
|
||||||
|
if (f) {
|
||||||
|
int damtype;
|
||||||
|
int anydam,mindam,maxdam;
|
||||||
|
damtype = f->val[0];
|
||||||
|
getdamrange(o, &mindam, &maxdam);
|
||||||
|
f = hasflag(o->flags, F_DAM);
|
||||||
|
if (f) {
|
||||||
|
if (f->val[2] == NA) {
|
||||||
|
mvwprintw(mainwin, y, 0, "It deals %d-%d %s damage (%dd%d).",mindam,maxdam,
|
||||||
|
getdamname(damtype), f->val[0], f->val[1]);
|
||||||
|
} else {
|
||||||
|
mvwprintw(mainwin, y, 0, "It deals %d-%d %s damage (%dd%d%c%d).",mindam,maxdam,
|
||||||
|
getdamname(damtype), f->val[0], f->val[1], (f->val[2] > 0) ? '+' : '-', abs(f->val[2]));
|
||||||
|
}
|
||||||
|
y++;
|
||||||
|
} else {
|
||||||
|
mvwprintw(mainwin, y, 0, "It deals %s damage.",getdamname(damtype));
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
f = hasflag(o->flags, F_OBATTACKSPEED);
|
||||||
|
if (f) {
|
||||||
|
getspeedname(f->val[0], buf);
|
||||||
|
mvwprintw(mainwin, y, 0, "Its attack rate is %s.",buf);
|
||||||
|
y++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wrefresh(mainwin);
|
wrefresh(mainwin);
|
||||||
|
|
||||||
|
@ -425,7 +521,7 @@ void dodrop(obpile_t *op) {
|
||||||
object_t *o;
|
object_t *o;
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
int count = ALL;
|
int count = ALL;
|
||||||
o = askobject(op, "Drop what", &count);
|
o = askobject(op, "Drop what", &count, AO_NONE);
|
||||||
if (o) {
|
if (o) {
|
||||||
getobname(o, buf, count);
|
getobname(o, buf, count);
|
||||||
o = moveob(o, op->owner->cell->obpile, count);
|
o = moveob(o, op->owner->cell->obpile, count);
|
||||||
|
@ -452,7 +548,93 @@ void dodrop(obpile_t *op) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dopickup(lifeform_t *lf, obpile_t *op) {
|
int dowear(obpile_t *op) {
|
||||||
|
object_t *o,*oo;
|
||||||
|
char buf[BUFLEN];
|
||||||
|
int count = ALL;
|
||||||
|
int rv;
|
||||||
|
flag_t *f;
|
||||||
|
o = askobjectofclass(op, "Wear what", NULL, AO_NONE, OC_ARMOUR);
|
||||||
|
if (o) {
|
||||||
|
wear(player, o);
|
||||||
|
} else {
|
||||||
|
rv = B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int doweild(obpile_t *op) {
|
||||||
|
object_t *o,*oo;
|
||||||
|
char buf[BUFLEN];
|
||||||
|
int count = ALL;
|
||||||
|
int rv;
|
||||||
|
flag_t *f;
|
||||||
|
o = askobject(op, "Weild what", &count, AO_INCLUDENOTHING);
|
||||||
|
if (o) {
|
||||||
|
rv = weild(player, o);
|
||||||
|
} else if (reason == E_SELNOTHING) {
|
||||||
|
// ie. unweild
|
||||||
|
rv = weild(player, NULL);
|
||||||
|
} else {
|
||||||
|
rv = B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void doknowledgelist(void) {
|
||||||
|
knowledge_t *k;
|
||||||
|
int y = 0;
|
||||||
|
int numfound = 0;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
wclear(mainwin);
|
||||||
|
mvwprintw(mainwin, y, 0, "Current Knowledge");
|
||||||
|
y++;
|
||||||
|
y++;
|
||||||
|
for (c = 0; sortorder[c] != OC_NULL ; c++) {
|
||||||
|
int first = B_TRUE;
|
||||||
|
for (k = knowledge ; k ; k = k->next) {
|
||||||
|
if (k->known) {
|
||||||
|
objecttype_t *ot;
|
||||||
|
ot = findot(k->id);
|
||||||
|
if (ot->obclass->id == c) {
|
||||||
|
if (first) {
|
||||||
|
mvwprintw(mainwin, y, 0, "%s", ot->obclass->name);
|
||||||
|
y++;
|
||||||
|
|
||||||
|
first = B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mvwprintw(mainwin, y, 0, " %-20s (%s)",ot->name, k->hiddenname);
|
||||||
|
y++;
|
||||||
|
|
||||||
|
numfound++;
|
||||||
|
|
||||||
|
if (y >= (SCREENH-1)) {
|
||||||
|
mvwprintw(mainwin, y, 0, "--More--");
|
||||||
|
wrefresh(mainwin);
|
||||||
|
getch();
|
||||||
|
wclear(mainwin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numfound == 0) {
|
||||||
|
mvwprintw(mainwin, y, 0, "You don't know much.");
|
||||||
|
}
|
||||||
|
wrefresh(mainwin);
|
||||||
|
getch();
|
||||||
|
|
||||||
|
clearmsg();
|
||||||
|
drawscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
int dopickup(obpile_t *op) {
|
||||||
int obcount;
|
int obcount;
|
||||||
object_t *o = NULL;
|
object_t *o = NULL;
|
||||||
int howmany = ALL;
|
int howmany = ALL;
|
||||||
|
@ -461,64 +643,94 @@ void dopickup(lifeform_t *lf, obpile_t *op) {
|
||||||
obcount = countobs(op);
|
obcount = countobs(op);
|
||||||
// anything here?
|
// anything here?
|
||||||
if (obcount == 0) {
|
if (obcount == 0) {
|
||||||
if (lf->controller == C_PLAYER) {
|
|
||||||
msg("There is nothing here to pick up!");
|
msg("There is nothing here to pick up!");
|
||||||
}
|
return B_TRUE;
|
||||||
return;
|
|
||||||
} else if (obcount == 1) {
|
} else if (obcount == 1) {
|
||||||
// just get it
|
// just get it
|
||||||
o = op->first;
|
o = op->first;
|
||||||
howmany = ALL;
|
howmany = ALL;
|
||||||
} else {
|
} else {
|
||||||
// prompt which one to pick up
|
// prompt which one to pick up
|
||||||
o = askobject(op, "Pick up what", &howmany);
|
o = askobject(op, "Pick up what", &howmany, AO_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!o) {
|
if (o) {
|
||||||
return;
|
pickup(player, o, howmany);
|
||||||
}
|
|
||||||
|
|
||||||
getobname(o, buf, howmany);
|
|
||||||
|
|
||||||
// try to move whatever was selected
|
|
||||||
o = moveob(o, lf->pack, howmany);
|
|
||||||
if (o) { // if pickup was successful...
|
|
||||||
if (lf->controller == C_PLAYER) {
|
|
||||||
msg("You pick up %s.",buf);
|
|
||||||
}
|
|
||||||
taketime(lf, (SPEED_PICKUP * howmany));
|
|
||||||
} else {
|
} else {
|
||||||
// tell the player why!
|
return B_TRUE;
|
||||||
if (lf->controller == C_PLAYER) {
|
|
||||||
switch (reason) {
|
|
||||||
case E_NOSPACE:
|
|
||||||
msg("Your pack is too full to fit any more objects.");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
msg("For some reason, you cannot pick up %s!");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void doinventory(obpile_t *op) {
|
void doinventory(obpile_t *op) {
|
||||||
object_t *o;
|
object_t *o;
|
||||||
o = askobject(op, "Select object to describe", NULL);
|
o = askobject(op, "Select object to describe", NULL, AO_NONE);
|
||||||
while (o) {
|
while (o) {
|
||||||
// describe it
|
// describe it
|
||||||
describeob(o);
|
describeob(o);
|
||||||
// ask for another one
|
// ask for another one
|
||||||
o = askobject(op, "Select object to describe", NULL);
|
o = askobject(op, "Select object to describe", NULL, AO_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void doquaff(obpile_t *op) {
|
||||||
|
object_t *o;
|
||||||
|
char buf[BUFLEN],buf2[BUFLEN];
|
||||||
|
|
||||||
|
// ask which object to quaff
|
||||||
|
o = askobjectofclass(op, "Quaff what", NULL, AO_NONE, OC_POTION);
|
||||||
|
if (o) {
|
||||||
|
if (isdrinkable(o)) {
|
||||||
|
quaff(player, o);
|
||||||
|
} else {
|
||||||
|
msg("You can't drink that!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doread(obpile_t *op) {
|
||||||
|
object_t *o;
|
||||||
|
char buf[BUFLEN],buf2[BUFLEN];
|
||||||
|
|
||||||
|
// ask which object to read
|
||||||
|
o = askobjectofclass(op, "Read what", NULL, AO_NONE, OC_SCROLL);
|
||||||
|
if (o) {
|
||||||
|
if (isreadable(o)) {
|
||||||
|
read(player, o);
|
||||||
|
} else {
|
||||||
|
msg("You can't read that!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dotakeoff(obpile_t *op) {
|
||||||
|
object_t *o;
|
||||||
|
char buf[BUFLEN],buf2[BUFLEN];
|
||||||
|
flag_t *f;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
// ask which object to read
|
||||||
|
o = askobjectofclass(op, "Take off what", NULL, AO_ONLYEQUIPPED, OC_ARMOUR);
|
||||||
|
if (o) {
|
||||||
|
f = hasflag(o->flags, F_EQUIPPED);
|
||||||
|
if (f) {
|
||||||
|
rv = takeoff(player, o);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
msg("You are not wearing that!");
|
||||||
|
rv = B_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
void dothrow(obpile_t *op) {
|
void dothrow(obpile_t *op) {
|
||||||
object_t *o;
|
object_t *o;
|
||||||
char buf[BUFLEN],buf2[BUFLEN];
|
char buf[BUFLEN],buf2[BUFLEN];
|
||||||
|
|
||||||
// ask which object to throw
|
// ask which object to throw
|
||||||
o = askobject(op, "Throw what", NULL);
|
o = askobject(op, "Throw what", NULL, AO_NONE);
|
||||||
if (o) {
|
if (o) {
|
||||||
cell_t *where;
|
cell_t *where;
|
||||||
getobname(o, buf, 1);
|
getobname(o, buf, 1);
|
||||||
|
@ -539,9 +751,27 @@ void dothrow(obpile_t *op) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// draw a cell which we can't see
|
||||||
|
void drawunviscell(cell_t *cell, int x, int y) {
|
||||||
|
char glyph;
|
||||||
|
if (cell->type->glyph == '.') {
|
||||||
|
glyph = ' ';
|
||||||
|
} else {
|
||||||
|
glyph = cell->type->glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
mvwprintw(gamewin, y, x, "%c", glyph);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void drawcell(cell_t *cell, int x, int y) {
|
void drawcell(cell_t *cell, int x, int y) {
|
||||||
|
// draw ground
|
||||||
|
mvwprintw(gamewin, y, x, "%c", cell->type->glyph);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawcellwithcontents(cell_t *cell, int x, int y) {
|
||||||
if (cell->lf) { // lifeform here?
|
if (cell->lf) { // lifeform here?
|
||||||
// TODO: draw the lf's race glyph
|
// draw the lf's race glyph
|
||||||
mvwprintw(gamewin, y, x, "%c", cell->lf->race->glyph);
|
mvwprintw(gamewin, y, x, "%c", cell->lf->race->glyph);
|
||||||
} else if (countobs(cell->obpile) > 0) {
|
} else if (countobs(cell->obpile) > 0) {
|
||||||
object_t *o;
|
object_t *o;
|
||||||
|
@ -556,7 +786,7 @@ void drawcell(cell_t *cell, int x, int y) {
|
||||||
for (o = cell->obpile->last ; o ; o = o->prev) {
|
for (o = cell->obpile->last ; o ; o = o->prev) {
|
||||||
if (o->type->obclass->id == sortorder[c]) {
|
if (o->type->obclass->id == sortorder[c]) {
|
||||||
// draw it
|
// draw it
|
||||||
mvwprintw(gamewin, y, x, "%c", o->type->obclass->glyph);
|
mvwprintw(gamewin, y, x, "%c", getglyph(o));
|
||||||
drawn = B_TRUE;
|
drawn = B_TRUE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -570,8 +800,7 @@ void drawcell(cell_t *cell, int x, int y) {
|
||||||
mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph);
|
mvwprintw(gamewin, y, x, "%c", cell->obpile->first->type->obclass->glyph);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// draw ground
|
drawcell(cell, x, y);
|
||||||
mvwprintw(gamewin, y, x, "%c", cell->type->glyph);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,7 +823,9 @@ void drawlevelfor(lifeform_t *lf) {
|
||||||
cell = getcellat(map, x, y);
|
cell = getcellat(map, x, y);
|
||||||
if (cell) {
|
if (cell) {
|
||||||
if (haslos(lf, cell)) {
|
if (haslos(lf, cell)) {
|
||||||
drawcell(cell, x-viewx, y-viewy);
|
drawcellwithcontents(cell, x-viewx, y-viewy);
|
||||||
|
} else if (cell->known) {
|
||||||
|
drawunviscell(cell, x-viewx, y-viewy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -672,15 +903,34 @@ void handleinput(void) {
|
||||||
msg("Another thing is about to happen now.");
|
msg("Another thing is about to happen now.");
|
||||||
msg("Too many things are happening!");
|
msg("Too many things are happening!");
|
||||||
break;
|
break;
|
||||||
|
// player commands
|
||||||
|
case 'i': // inventory
|
||||||
|
doinventory(player->pack);
|
||||||
|
break;
|
||||||
|
case '\\': // list knowledge
|
||||||
|
doknowledgelist();
|
||||||
|
break;
|
||||||
// object functions
|
// object functions
|
||||||
case 'd': // drop
|
case 'd': // drop
|
||||||
dodrop(player->pack);
|
dodrop(player->pack);
|
||||||
break;
|
break;
|
||||||
case 'i': // inventory
|
case 'W': // wear
|
||||||
doinventory(player->pack);
|
dowear(player->pack);
|
||||||
|
break;
|
||||||
|
case 'w': // weild
|
||||||
|
doweild(player->pack);
|
||||||
|
break;
|
||||||
|
case 'T': // takeoff
|
||||||
|
dotakeoff(player->pack);
|
||||||
break;
|
break;
|
||||||
case ',': // pickup
|
case ',': // pickup
|
||||||
dopickup(player, player->cell->obpile);
|
dopickup(player->cell->obpile);
|
||||||
|
break;
|
||||||
|
case 'r': // read
|
||||||
|
doread(player->pack);
|
||||||
|
break;
|
||||||
|
case 'q': // quaff
|
||||||
|
doquaff(player->pack);
|
||||||
break;
|
break;
|
||||||
case 't': // throw
|
case 't': // throw
|
||||||
dothrow(player->pack);
|
dothrow(player->pack);
|
||||||
|
@ -721,6 +971,88 @@ int keycodetokey(int keycode) {
|
||||||
return keystroke;
|
return keystroke;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int pickup(lifeform_t *lf, object_t *what, int howmany) {
|
||||||
|
char buf[BUFLEN];
|
||||||
|
char obname[BUFLEN];
|
||||||
|
object_t *o;
|
||||||
|
flag_t *f;
|
||||||
|
|
||||||
|
if (!what) {
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
getobname(what, obname, howmany);
|
||||||
|
|
||||||
|
if (howmany == ALL) howmany = o->amt;
|
||||||
|
|
||||||
|
if (!canpickup(lf, what)){
|
||||||
|
// tell the player why!
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
switch (reason) {
|
||||||
|
case E_NOSPACE:
|
||||||
|
msg("Your pack is too full to fit any more objects.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg("For some reason, you cannot pick up %s!",obname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// some checks first...
|
||||||
|
f = hasflag(what->flags, F_SHARP);
|
||||||
|
if (f) {
|
||||||
|
object_t *gloves;
|
||||||
|
gloves = getequippedob(lf->pack, BP_HANDS);
|
||||||
|
if (!gloves) {
|
||||||
|
char *newname;
|
||||||
|
getobname(what, buf, 1);
|
||||||
|
newname = strdup(buf);
|
||||||
|
strrep(newname, "a ", "the ");
|
||||||
|
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("Ow! You cut your finger on %s.", newname);
|
||||||
|
}
|
||||||
|
taketime(lf, SPEED_PICKUP);
|
||||||
|
|
||||||
|
sprintf(buf, "stepping on %s", obname);
|
||||||
|
losehp(lf, rnd(1,2), DT_SLASH, NULL, buf);
|
||||||
|
|
||||||
|
return B_TRUE;
|
||||||
|
free(newname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to move whatever was selected
|
||||||
|
o = moveob(what, lf->pack, howmany);
|
||||||
|
if (o) { // if pickup was successful...
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You pick up %c - %s.",o->letter, obname);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
taketime(lf, (SPEED_PICKUP * howmany));
|
||||||
|
*/
|
||||||
|
taketime(lf, SPEED_PICKUP);
|
||||||
|
} else {
|
||||||
|
// tell the player why!
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
switch (reason) {
|
||||||
|
case E_NOSPACE:
|
||||||
|
msg("Your pack is too full to fit any more objects.");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg("For some reason, you cannot pick up %s!",obname);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dblog(char *format, ... ) {
|
void dblog(char *format, ... ) {
|
||||||
char buf[HUGEBUFLEN];
|
char buf[HUGEBUFLEN];
|
||||||
va_list args;
|
va_list args;
|
||||||
|
@ -745,7 +1077,8 @@ void dblog(char *format, ... ) {
|
||||||
|
|
||||||
// force a '--more--' prompt
|
// force a '--more--' prompt
|
||||||
void more(void) {
|
void more(void) {
|
||||||
msg("%100s"," ");
|
msg("^");
|
||||||
|
drawmsg();
|
||||||
}
|
}
|
||||||
|
|
||||||
void msg(char *format, ... ) {
|
void msg(char *format, ... ) {
|
||||||
|
@ -768,8 +1101,9 @@ void msg(char *format, ... ) {
|
||||||
p = msgbuf;
|
p = msgbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ie. can we fit the new text + '--more--' ?
|
// ie. can the message buffer fit:
|
||||||
if (strlen(p) + strlen(buf) + strlen(MORESTRING) >= SCREENW) {
|
// what is already there + 2 spaces + the new text + '--more--' ?
|
||||||
|
if (strlen(p) + 2 + strlen(buf) + strlen(MORESTRING) >= SCREENW) {
|
||||||
strcat(msgbuf, "^");
|
strcat(msgbuf, "^");
|
||||||
} else {
|
} else {
|
||||||
if (strlen(msgbuf) > 0) {
|
if (strlen(msgbuf) > 0) {
|
||||||
|
@ -886,12 +1220,54 @@ int savegame(void) {
|
||||||
return B_TRUE;
|
return B_TRUE;
|
||||||
}
|
}
|
||||||
savelf(f, player);
|
savelf(f, player);
|
||||||
|
saveknowledge(f);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_FALSE;
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int takeoff(lifeform_t *lf, object_t *o) {
|
||||||
|
flag_t *f;
|
||||||
|
char obname[BUFLEN];
|
||||||
|
char buf[BUFLEN];
|
||||||
|
|
||||||
|
getobname(o, obname, 1);
|
||||||
|
|
||||||
|
if (!cantakeoff(lf, o)) {
|
||||||
|
switch (reason) {
|
||||||
|
case E_NOTEQUIPPED:
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You are not wearing that!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("For some reason, you cannot take that off!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the equipped flag
|
||||||
|
f = hasflag(o->flags, F_EQUIPPED);
|
||||||
|
killflag(f);
|
||||||
|
|
||||||
|
taketime(lf, getmovespeed(lf));
|
||||||
|
if (gamestarted) {
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You take off %s.", obname);
|
||||||
|
} else if (haslos(player, lf->cell)) {
|
||||||
|
getlfname(lf, buf);
|
||||||
|
capitalise(buf);
|
||||||
|
msg("%s takes off %s.", buf, obname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void tombstone(lifeform_t *lf) {
|
void tombstone(lifeform_t *lf) {
|
||||||
// clear screen
|
// clear screen
|
||||||
wclear(mainwin);
|
wclear(mainwin);
|
||||||
|
@ -919,3 +1295,141 @@ void tombstone(lifeform_t *lf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int wear(lifeform_t *lf, object_t *o) {
|
||||||
|
int rv = B_FALSE;
|
||||||
|
char buf[BUFLEN],obname[BUFLEN];
|
||||||
|
flag_t *f;
|
||||||
|
int bp;
|
||||||
|
|
||||||
|
getobname(o, obname, 1);
|
||||||
|
|
||||||
|
if (!canwear(lf, o)) {
|
||||||
|
if (gamestarted) {
|
||||||
|
switch (reason) {
|
||||||
|
case E_ALREADYUSING:
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You're already wearing that!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case E_WEARINGSOMETHINGELSE:
|
||||||
|
f = hasflag(o->flags, F_GOESON);
|
||||||
|
if (f) {
|
||||||
|
object_t *inway;
|
||||||
|
// find what else is there
|
||||||
|
inway = getequippedob(lf->pack, f->val[0]);
|
||||||
|
getobname(inway,buf, 1);
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You need to remove your %s first!",buf);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// should never happen
|
||||||
|
msg("You can't wear that!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You can't wear that!");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // end if gamestarted
|
||||||
|
return B_TRUE;
|
||||||
|
} // end if !canwear
|
||||||
|
|
||||||
|
|
||||||
|
// wear it
|
||||||
|
f = hasflag(o->flags, F_GOESON);
|
||||||
|
bp = f->val[0];
|
||||||
|
|
||||||
|
addflag(o->flags, F_EQUIPPED, bp, -1, -1, NULL);
|
||||||
|
taketime(lf, getmovespeed(lf));
|
||||||
|
if (gamestarted) {
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You are now wearing %s.", obname);
|
||||||
|
} else if (haslos(player, lf->cell)) {
|
||||||
|
getlfname(lf, buf);
|
||||||
|
capitalise(lf);
|
||||||
|
msg("%s puts on %s.", buf, obname);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
int weild(lifeform_t *lf, object_t *o) {
|
||||||
|
char buf[BUFLEN];
|
||||||
|
flag_t *f;
|
||||||
|
object_t *oo;
|
||||||
|
|
||||||
|
if (o) {
|
||||||
|
getobname(o, buf, o->amt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: any reason you might not be able to weild it at all?
|
||||||
|
// ie. too big, already have a cursed one, etc?
|
||||||
|
|
||||||
|
if (!canweild(lf, o)) {
|
||||||
|
if (gamestarted) {
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
switch (reason) {
|
||||||
|
case E_ALREADYUSING:
|
||||||
|
msg("You are already weilding that!");
|
||||||
|
break;
|
||||||
|
case E_NOUNARMEDATTACK:
|
||||||
|
msg("You cannot fight without a weapon!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
msg("For some reason, you cannot pick up %s!",buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// anything else weilded?
|
||||||
|
for (oo = lf->pack->first ; oo ; oo = oo->next) {
|
||||||
|
f = hasflagval(oo->flags, F_EQUIPPED, BP_WEAPON, -1, -1, NULL);
|
||||||
|
if (f) {
|
||||||
|
// unweild it
|
||||||
|
killflag(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if we asked to just unweild our weapon, exit now
|
||||||
|
// with no error.
|
||||||
|
if (!o) {
|
||||||
|
if (gamestarted) {
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You are now fighting unarmed.");
|
||||||
|
} else if (haslos(player, lf->cell)) {
|
||||||
|
char buf2[BUFLEN];
|
||||||
|
getlfname(lf, buf2);
|
||||||
|
msg("%s is now fighting unarmed.",buf2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now weild this
|
||||||
|
addflag(o->flags, F_EQUIPPED, BP_WEAPON, -1, -1, NULL);
|
||||||
|
taketime(lf, getmovespeed(lf));
|
||||||
|
if (gamestarted) {
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You are now weilding %c - %s.", o->letter, buf);
|
||||||
|
// warn if it won't do any damage
|
||||||
|
f = hasflag(o->flags, F_DAM);
|
||||||
|
if (!f) {
|
||||||
|
msg("You have a feeling that this weapon will not be very effective...");
|
||||||
|
}
|
||||||
|
} else if (haslos(player, lf->cell)) {
|
||||||
|
char buf2[BUFLEN];
|
||||||
|
getlfname(lf, buf2);
|
||||||
|
msg("%s weilds %s.", buf2, buf);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
19
io.h
19
io.h
|
@ -2,7 +2,9 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
void anim(cell_t *src, cell_t *dst, char ch);
|
void anim(cell_t *src, cell_t *dst, char ch);
|
||||||
object_t *askobject(obpile_t *op, char *title, int *count);
|
object_t *askobject(obpile_t *op, char *title, int *count, int opts);
|
||||||
|
object_t *askobjectofclass(obpile_t *op, char *title, int *count, int opts, enum OBCLASS obclass);
|
||||||
|
object_t *doaskobject(obpile_t *op, char *title, int *count, int opts, enum OBCLASS obclass);
|
||||||
cell_t *askcoords(char *prompt);
|
cell_t *askcoords(char *prompt);
|
||||||
void centre(WINDOW *win, int y, char *format, ... );
|
void centre(WINDOW *win, int y, char *format, ... );
|
||||||
int chartodir(char ch);
|
int chartodir(char ch);
|
||||||
|
@ -10,9 +12,16 @@ void clearmsg(void);
|
||||||
void describeob(object_t *o);
|
void describeob(object_t *o);
|
||||||
void dodrop(obpile_t *op);
|
void dodrop(obpile_t *op);
|
||||||
void doinventory(obpile_t *op);
|
void doinventory(obpile_t *op);
|
||||||
void dopickup(lifeform_t *lf, obpile_t *op);
|
void doknowledgelist(void);
|
||||||
|
int dopickup(obpile_t *op);
|
||||||
|
void doquaff(obpile_t *op);
|
||||||
|
void doread(obpile_t *op);
|
||||||
|
int dotakeoff(obpile_t *op);
|
||||||
void dothrow(obpile_t *op);
|
void dothrow(obpile_t *op);
|
||||||
void drawcell(cell_t *cell, int x, int y);
|
int dowear(obpile_t *op);
|
||||||
|
int doweild(obpile_t *op);
|
||||||
|
void drawunviscell(cell_t *cell, int x, int y);
|
||||||
|
void drawcellwithcontents(cell_t *cell, int x, int y);
|
||||||
void drawcursor(void);
|
void drawcursor(void);
|
||||||
void drawlevelfor(lifeform_t *lf);
|
void drawlevelfor(lifeform_t *lf);
|
||||||
void drawmsg(void);
|
void drawmsg(void);
|
||||||
|
@ -23,8 +32,12 @@ void handleinput(void);
|
||||||
int keycodetokey(int keycode);
|
int keycodetokey(int keycode);
|
||||||
void more(void);
|
void more(void);
|
||||||
void msg(char *format, ... );
|
void msg(char *format, ... );
|
||||||
|
int pickup(lifeform_t *lf, object_t *what, int howmany);
|
||||||
void dblog(char *format, ... );
|
void dblog(char *format, ... );
|
||||||
void redraw(void);
|
void redraw(void);
|
||||||
int savequit(void);
|
int savequit(void);
|
||||||
|
int takeoff(lifeform_t *lf, object_t *o);
|
||||||
void tombstone(lifeform_t *lf);
|
void tombstone(lifeform_t *lf);
|
||||||
void updateviewfor(cell_t *cell);
|
void updateviewfor(cell_t *cell);
|
||||||
|
int wear(lifeform_t *lf, object_t *o);
|
||||||
|
int weild(lifeform_t *lf, object_t *o);
|
||||||
|
|
593
lf.c
593
lf.c
|
@ -1,3 +1,5 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
@ -10,13 +12,23 @@
|
||||||
extern race_t *firstrace, *lastrace;
|
extern race_t *firstrace, *lastrace;
|
||||||
extern lifeform_t *player;
|
extern lifeform_t *player;
|
||||||
|
|
||||||
|
extern int gamestarted;
|
||||||
|
|
||||||
lifeform_t *addlf(cell_t *cell, enum RACE rid) {
|
extern int loading;
|
||||||
|
|
||||||
|
extern enum ERROR reason;
|
||||||
|
|
||||||
|
lifeform_t *addlf(cell_t *cell, enum RACE rid, int level) {
|
||||||
map_t *m;
|
map_t *m;
|
||||||
lifeform_t *a;
|
lifeform_t *a;
|
||||||
int i;
|
int i;
|
||||||
flag_t *f;
|
flag_t *f;
|
||||||
|
|
||||||
|
assert(cell);
|
||||||
|
if (cell->type != (celltype_t *) DUMMYCELLTYPE) {
|
||||||
|
assert(!cell->type->solid);
|
||||||
|
}
|
||||||
|
|
||||||
m = cell->map;
|
m = cell->map;
|
||||||
|
|
||||||
// add to the end of the list
|
// add to the end of the list
|
||||||
|
@ -38,13 +50,13 @@ lifeform_t *addlf(cell_t *cell, enum RACE rid) {
|
||||||
a->id = m->nextlfid; m->nextlfid++;
|
a->id = m->nextlfid; m->nextlfid++;
|
||||||
a->controller = C_AI;
|
a->controller = C_AI;
|
||||||
a->race = findrace(rid);
|
a->race = findrace(rid);
|
||||||
a->hp = 10; // TODO: fix
|
a->level = level;
|
||||||
a->maxhp = 10; // TODO: fix
|
|
||||||
a->cell = cell; // TODO: fix
|
a->cell = cell; // TODO: fix
|
||||||
a->alive = B_TRUE;
|
a->alive = B_TRUE;
|
||||||
a->lastdam = strdup("nothing");
|
a->lastdam = strdup("nothing");
|
||||||
a->timespent = 0;
|
a->timespent = 0;
|
||||||
a->sorted = B_FALSE;
|
a->sorted = B_FALSE;
|
||||||
|
a->forgettimer = 0;
|
||||||
|
|
||||||
a->pack = addobpile(a, NOLOC);
|
a->pack = addobpile(a, NOLOC);
|
||||||
|
|
||||||
|
@ -61,8 +73,32 @@ lifeform_t *addlf(cell_t *cell, enum RACE rid) {
|
||||||
addflag(a->flags, f->id, f->val[0], f->val[1], f->val[2], f->text);
|
addflag(a->flags, f->id, f->val[0], f->val[1], f->val[2], f->text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate hp/maxhp from hit dice
|
||||||
|
// TODO: take level into account
|
||||||
|
f = hasflag(a->flags, F_HITDICE);
|
||||||
|
if (f) {
|
||||||
|
int hitdice,plus,this;
|
||||||
|
a->maxhp = 0;
|
||||||
|
for (i = 0; i < a->level; i++) {
|
||||||
|
hitdice = f->val[0];
|
||||||
|
plus = f->val[1];
|
||||||
|
this = rolldie(hitdice, 4) + plus;
|
||||||
|
a->maxhp += this;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// default - 0 hit dice + 8
|
||||||
|
a->maxhp = 8 * a->level;
|
||||||
|
}
|
||||||
|
a->hp = a->maxhp;
|
||||||
|
|
||||||
// update other things
|
// update other things
|
||||||
cell->lf = a;
|
cell->lf = a;
|
||||||
|
|
||||||
|
// give start objetcs
|
||||||
|
if (!loading) {
|
||||||
|
outfitlf(a);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
race_t *addrace(enum RACE id, char *name, char glyph) {
|
race_t *addrace(enum RACE id, char *name, char glyph) {
|
||||||
|
@ -91,6 +127,110 @@ race_t *addrace(enum RACE id, char *name, char glyph) {
|
||||||
a->flags = addflagpile();
|
a->flags = addflagpile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int canpickup(lifeform_t *lf, object_t *o) {
|
||||||
|
reason = E_OK;
|
||||||
|
if (hasflag(o->flags, F_NOPICKUP)) {
|
||||||
|
reason = E_NOPICKUP;
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// space in pack?
|
||||||
|
if (countobs(lf->pack) >= MAXPILEOBS) {
|
||||||
|
reason = E_NOSPACE;
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
if (getnextletter(lf->pack, NULL) == '-') {
|
||||||
|
reason = E_NOSPACE;
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int canwear(lifeform_t *lf, object_t *o) {
|
||||||
|
object_t *oo;
|
||||||
|
flag_t *f;
|
||||||
|
enum BODYPART bp;
|
||||||
|
|
||||||
|
reason = E_OK;
|
||||||
|
|
||||||
|
// where is this worn?
|
||||||
|
f = hasflag(o->flags, F_GOESON);
|
||||||
|
if (f) {
|
||||||
|
bp = f->val[0];
|
||||||
|
} else {
|
||||||
|
// can't wear anywhere
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// anything else worn there?
|
||||||
|
for (oo = lf->pack->first ; oo ; oo = oo->next) {
|
||||||
|
f = hasflagval(oo->flags, F_EQUIPPED, bp, -1, -1, NULL);
|
||||||
|
if (f) {
|
||||||
|
if (oo == o) { // already weilding it
|
||||||
|
reason = E_ALREADYUSING;
|
||||||
|
} else {
|
||||||
|
reason = E_WEARINGSOMETHINGELSE;
|
||||||
|
}
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// trying to fight unarmed, but no unarmed attack?
|
||||||
|
if (o == NULL) {
|
||||||
|
if (!hasflag(lf->flags, F_UNARMEDATTACKOB)) {
|
||||||
|
reason = E_NOUNARMEDATTACK;
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int canweild(lifeform_t *lf, object_t *o) {
|
||||||
|
object_t *oo;
|
||||||
|
flag_t *f;
|
||||||
|
|
||||||
|
reason = E_OK;
|
||||||
|
// anything else weilded?
|
||||||
|
for (oo = lf->pack->first ; oo ; oo = oo->next) {
|
||||||
|
f = hasflagval(oo->flags, F_EQUIPPED, BP_WEAPON, -1, -1, NULL);
|
||||||
|
if (f) {
|
||||||
|
if (oo == o) { // already weilding it
|
||||||
|
reason = E_ALREADYUSING;
|
||||||
|
return B_FALSE;
|
||||||
|
} // TODO: else if cursed...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// trying to fight unarmed, but no unarmed attack?
|
||||||
|
if (o == NULL) {
|
||||||
|
if (!hasflag(lf->flags, F_UNARMEDATTACKOB)) {
|
||||||
|
reason = E_NOUNARMEDATTACK;
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cantakeoff(lifeform_t *lf, object_t *o) {
|
||||||
|
object_t *oo;
|
||||||
|
flag_t *f;
|
||||||
|
|
||||||
|
reason = E_OK;
|
||||||
|
f = hasflag(o->flags, F_EQUIPPED);
|
||||||
|
if (!f) {
|
||||||
|
reason = E_NOTEQUIPPED;
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO CURSE
|
||||||
|
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
void die(lifeform_t *lf) {
|
void die(lifeform_t *lf) {
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
object_t *o, *nexto;
|
object_t *o, *nexto;
|
||||||
|
@ -133,6 +273,27 @@ void die(lifeform_t *lf) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fightback(lifeform_t *lf, lifeform_t *attacker) {
|
||||||
|
// they will now fight back!
|
||||||
|
if (attacker && !isdead(lf)) {
|
||||||
|
if (lf->controller != C_PLAYER) {
|
||||||
|
if (!hasflagval(lf->flags, F_TARGET, attacker->id, NA, NA, NULL)) {
|
||||||
|
addflag(lf->flags, F_TARGET, attacker->id, NA, NA, NULL);
|
||||||
|
// announce
|
||||||
|
if (haslos(player, lf->cell)) {
|
||||||
|
char attackername[BUFLEN];
|
||||||
|
char lfname[BUFLEN];
|
||||||
|
getlfname(attacker, attackername);
|
||||||
|
getlfname(lf, lfname);
|
||||||
|
capitalise(lfname);
|
||||||
|
msg("%s turns to attack %s!", lfname,
|
||||||
|
haslos(player, attacker->cell) ? attackername : "something");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lifeform_t *findlf(map_t *m, int lfid) {
|
lifeform_t *findlf(map_t *m, int lfid) {
|
||||||
lifeform_t *lf;
|
lifeform_t *lf;
|
||||||
for (lf = m->lf ; lf ; lf = lf->next) {
|
for (lf = m->lf ; lf ; lf = lf->next) {
|
||||||
|
@ -152,10 +313,160 @@ race_t *findrace(enum RACE id) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int getattackspeed(lifeform_t *lf) {
|
void gainhp(lifeform_t *lf, int amt) {
|
||||||
int speed = SPEED_ATTACK;
|
char buf[BUFLEN];
|
||||||
|
lf->hp += amt;
|
||||||
|
|
||||||
|
if (lf->hp > lf->maxhp) {
|
||||||
|
lf->hp = lf->maxhp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getarmour(lifeform_t *lf) {
|
||||||
|
object_t *o;
|
||||||
flag_t *f;
|
flag_t *f;
|
||||||
f = hasflag(lf->flags, F_ATTACKSPEED);
|
int ar = 0;
|
||||||
|
|
||||||
|
for (o = lf->pack->first ; o ; o = o->next) {
|
||||||
|
if (hasflag(o->flags, F_EQUIPPED)) {
|
||||||
|
f = hasflag(o->flags, F_ARMOURRATING);
|
||||||
|
if (f) {
|
||||||
|
ar += f->val[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ar;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getevasion(lifeform_t *lf) {
|
||||||
|
object_t *o;
|
||||||
|
flag_t *f;
|
||||||
|
int ev = 0;
|
||||||
|
// natural evasion
|
||||||
|
f = hasflag(lf->flags, F_EVASION);
|
||||||
|
if (f) {
|
||||||
|
// evasion 10 means -10% penalty to hit you
|
||||||
|
ev += (f->val[0]);
|
||||||
|
if (ev < 0) ev = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// minus armour penalties
|
||||||
|
for (o = lf->pack->first ; o ; o = o->next) {
|
||||||
|
f = hasflag(o->flags, F_EVASION);
|
||||||
|
if (f) {
|
||||||
|
ev += (f->val[0]);
|
||||||
|
if (ev < 0) ev = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ev;
|
||||||
|
|
||||||
|
}
|
||||||
|
object_t *getbestweapon(lifeform_t *lf) {
|
||||||
|
obpile_t *op;
|
||||||
|
object_t *curwep,*bestwep = NULL;
|
||||||
|
int bestmaxdam = -999;
|
||||||
|
flag_t *f;
|
||||||
|
object_t *o;
|
||||||
|
|
||||||
|
op = addobpile(lf, NULL); // for use if we are unarmed
|
||||||
|
|
||||||
|
curwep = getweapon(lf);
|
||||||
|
if (!curwep) {
|
||||||
|
getunarmedweapon(lf, op);
|
||||||
|
curwep = op->first;
|
||||||
|
}
|
||||||
|
if (curwep) {
|
||||||
|
f = hasflag(curwep->flags, F_DAM);
|
||||||
|
bestmaxdam = f->val[1];
|
||||||
|
} else {
|
||||||
|
// no current weapon, and no unarmed weapon
|
||||||
|
// anything will be better!
|
||||||
|
bestmaxdam = -999;
|
||||||
|
}
|
||||||
|
|
||||||
|
bestwep = curwep;
|
||||||
|
|
||||||
|
for (o = lf->pack->first ; o ; o = o->next) {
|
||||||
|
f = hasflag(o->flags, F_DAM);
|
||||||
|
// if it does damage and we can weild it...
|
||||||
|
if (f && canweild(lf, o)) {
|
||||||
|
// if its max damage is better...
|
||||||
|
if (f->val[1] > bestmaxdam) {
|
||||||
|
bestmaxdam = f->val[1];
|
||||||
|
bestwep = o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestwep == op->first) {
|
||||||
|
bestwep = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (op->first) {
|
||||||
|
killob(op->first);
|
||||||
|
}
|
||||||
|
free(op);
|
||||||
|
|
||||||
|
return bestwep;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *getbodypartname(enum BODYPART bp) {
|
||||||
|
switch (bp) {
|
||||||
|
case BP_WEAPON:
|
||||||
|
return "weapon";
|
||||||
|
case BP_RIGHTHAND:
|
||||||
|
return "right hand";
|
||||||
|
case BP_LEFTHAND:
|
||||||
|
return "left hand";
|
||||||
|
case BP_HANDS:
|
||||||
|
return "hands";
|
||||||
|
case BP_HEAD:
|
||||||
|
return "head";
|
||||||
|
case BP_BODY:
|
||||||
|
return "body";
|
||||||
|
case BP_SHOULDERS:
|
||||||
|
return "shoulders";
|
||||||
|
case BP_FEET:
|
||||||
|
return "feet";
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getbodypartequipname(enum BODYPART bp) {
|
||||||
|
switch (bp) {
|
||||||
|
case BP_WEAPON:
|
||||||
|
return "n/a";
|
||||||
|
case BP_RIGHTHAND:
|
||||||
|
case BP_LEFTHAND:
|
||||||
|
case BP_HANDS:
|
||||||
|
case BP_HEAD:
|
||||||
|
case BP_BODY:
|
||||||
|
case BP_FEET:
|
||||||
|
return "on";
|
||||||
|
case BP_SHOULDERS:
|
||||||
|
return "over";
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
object_t *getequippedob(obpile_t *op, enum BODYPART bp) {
|
||||||
|
object_t *o;
|
||||||
|
for (o = op->first; o ; o = o->next) {
|
||||||
|
if (hasflagval(o->flags, F_EQUIPPED, bp, NA, NA, NULL)) {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getlfattackspeed(lifeform_t *lf) {
|
||||||
|
int speed = 0; // default to taking no time at all - just use weapon delay
|
||||||
|
flag_t *f;
|
||||||
|
f = hasflag(lf->flags, F_LFATTACKDELAY);
|
||||||
if (f) {
|
if (f) {
|
||||||
speed = f->val[0];
|
speed = f->val[0];
|
||||||
}
|
}
|
||||||
|
@ -182,6 +493,112 @@ char *getlfname(lifeform_t *lf, char *buf) {
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
race_t *getrandomlf(map_t *map, int *level) {
|
||||||
|
enum RARITY rarity;
|
||||||
|
race_t *r;
|
||||||
|
int roll;
|
||||||
|
race_t *poss[MAXRANDOMLFCANDIDATES];
|
||||||
|
int nposs = 0;
|
||||||
|
int selidx;
|
||||||
|
int amt;
|
||||||
|
flag_t *f;
|
||||||
|
int db = B_FALSE;
|
||||||
|
|
||||||
|
// determine rarity of lf to generate
|
||||||
|
rarity = RR_FREQUENT;
|
||||||
|
|
||||||
|
// start with 'frequent'ly appearing items
|
||||||
|
// roll a die. 30% chance of getting rarer.
|
||||||
|
// stop when we fail the die roll.
|
||||||
|
roll = rnd(1,100);
|
||||||
|
while (roll < 30) {
|
||||||
|
rarity++;
|
||||||
|
if (rarity == RR_VERYRARE) break;
|
||||||
|
roll = rnd(1,100);
|
||||||
|
}
|
||||||
|
if (db) dblog("adding random lf of rarity %d\n",rarity);
|
||||||
|
|
||||||
|
|
||||||
|
// try to find a lf of this type which will
|
||||||
|
// fit in the map's habitat
|
||||||
|
nposs = 0;
|
||||||
|
while (nposs == 0) {
|
||||||
|
for (r = firstrace ; r ; r = r->next) {
|
||||||
|
if (hasflagval(r->flags, F_RARITY, map->habitat, rarity, NA, NULL) ||
|
||||||
|
hasflagval(r->flags, F_RARITY, H_ALL, rarity, NA, NULL) ) {
|
||||||
|
poss[nposs] = r;
|
||||||
|
nposs++;
|
||||||
|
if (nposs >= MAXRANDOMLFCANDIDATES) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// nothing found?
|
||||||
|
if (nposs == 0) {
|
||||||
|
// already at lowest rarity?
|
||||||
|
if (rarity == RR_FREQUENT) {
|
||||||
|
// give up
|
||||||
|
if (db) dblog("no possible lf at all! giving up.");
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
// lower rarity and try again
|
||||||
|
rarity--;
|
||||||
|
if (db) dblog("no possible lfs like this. trying again with rarity %d\n",rarity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (db) dblog("got %d possibilities.",nposs);
|
||||||
|
// pick a random lf from our possiblities
|
||||||
|
selidx = rnd(0,nposs-1);
|
||||||
|
r = poss[selidx];
|
||||||
|
/* TODO:
|
||||||
|
// handle lf which appear in multiples (ie. rocks)
|
||||||
|
f = hasflag(ot->flags, F_NUMAPPEAR);
|
||||||
|
if (f) {
|
||||||
|
amt = rnd(f->val[0], f->val[1]);
|
||||||
|
} else {
|
||||||
|
amt = 1;
|
||||||
|
}
|
||||||
|
if (db) sprintf(buf, "%d %s", amt, ot->name);
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: should select a level based on map difficulty/depth
|
||||||
|
if (level) {
|
||||||
|
*level = rnd(1,3);
|
||||||
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *getspeedname(int speed, char *buf) {
|
||||||
|
sprintf(buf, "unknownspeed");
|
||||||
|
switch (speed) {
|
||||||
|
case SP_GODLIKE: sprintf(buf, "insanely fast"); break;
|
||||||
|
case SP_ULTRAFAST: sprintf(buf, "extremely fast"); break;
|
||||||
|
case SP_VERYFAST: sprintf(buf, "very fast"); break;
|
||||||
|
case SP_FAST: sprintf(buf, "fast"); break;
|
||||||
|
case SP_NORMAL: sprintf(buf, "normal"); break;
|
||||||
|
case SP_SLOW: sprintf(buf, "slow"); break;
|
||||||
|
case SP_VERYSLOW: sprintf(buf, "very slow"); break;
|
||||||
|
case SP_ULTRASLOW: sprintf(buf, "extremely slow"); break;
|
||||||
|
case SP_SLOWEST: sprintf(buf, "insanely slow"); break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
object_t *getweapon(lifeform_t *lf) {
|
||||||
|
object_t *o;
|
||||||
|
flag_t *f;
|
||||||
|
for (o = lf->pack->first ; o ; o = o->next) {
|
||||||
|
f = hasflagval(o->flags, F_EQUIPPED, BP_WEAPON, NA, NA, NULL);
|
||||||
|
if (f) {
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int haslof(lifeform_t *viewer, cell_t *dest) {
|
int haslof(lifeform_t *viewer, cell_t *dest) {
|
||||||
int deltax, deltay;
|
int deltax, deltay;
|
||||||
int numpixels;
|
int numpixels;
|
||||||
|
@ -484,28 +901,61 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
|
||||||
|
|
||||||
void initrace(void) {
|
void initrace(void) {
|
||||||
addrace(R_HUMAN, "human", '@');
|
addrace(R_HUMAN, "human", '@');
|
||||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "human corpse");
|
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "human corpse");
|
||||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_RARE, -1, "");
|
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_RARE, NA, "");
|
||||||
|
addflag(lastrace->flags, F_HITDICE, 1, 4, NA, "");
|
||||||
|
addflag(lastrace->flags, F_EVASION, 0, NA, NA, NULL);
|
||||||
|
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, "");
|
||||||
|
addflag(lastrace->flags, F_UNARMEDATTACKOB, NA, NA, NA, "fists");
|
||||||
|
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "10 gold coins");
|
||||||
|
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "quickblade");
|
||||||
|
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather boots");
|
||||||
|
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "leather gloves");
|
||||||
|
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "3 potions of healing");
|
||||||
|
addflag(lastrace->flags, F_STARTOBDT, 100, DT_PIERCE, NA, NULL);
|
||||||
addrace(R_GOBLIN, "goblin", 'g');
|
addrace(R_GOBLIN, "goblin", 'g');
|
||||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "goblin corpse");
|
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "goblin corpse");
|
||||||
addflag(lastrace->flags, F_HOSTILE, B_TRUE, -1, -1, "");
|
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
||||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, -1, "");
|
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, NA, NULL);
|
||||||
|
addflag(lastrace->flags, F_HITDICE, 1, 3, NA, NULL);
|
||||||
|
addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL);
|
||||||
|
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
|
||||||
|
addflag(lastrace->flags, F_UNARMEDATTACKOB, NA, NA, NA, "small claws");
|
||||||
|
addflag(lastrace->flags, F_STARTOBDT, 50, DT_PIERCE, NA, NULL);
|
||||||
addrace(R_BAT, "bat", 'B');
|
addrace(R_BAT, "bat", 'B');
|
||||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "bat corpse");
|
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "bat corpse");
|
||||||
addflag(lastrace->flags, F_ATTACKSPEED, 5, -1, -1, "");
|
addflag(lastrace->flags, F_LFATTACKDELAY, -3, NA, NA, ""); // extra fast attacks
|
||||||
addflag(lastrace->flags, F_MOVESPEED, 5, -1, -1, "");
|
addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, "");
|
||||||
addflag(lastrace->flags, F_FLYING, B_TRUE, -1, -1, "");
|
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
|
||||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, -1, "");
|
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, NA, "");
|
||||||
|
addflag(lastrace->flags, F_HITDICE, 0, 2, NA, "");
|
||||||
|
addflag(lastrace->flags, F_UNARMEDATTACKOB, NA, NA, NA, "tiny teeth");
|
||||||
|
addflag(lastrace->flags, F_EVASION, 30, NA, NA, NULL);
|
||||||
|
addrace(R_RAT, "rat", 'r');
|
||||||
|
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "rodent corpse");
|
||||||
|
addflag(lastrace->flags, F_MOVESPEED, SP_FAST, NA, NA, "");
|
||||||
|
addflag(lastrace->flags, F_MOVESPEED, 5, NA, NA, "");
|
||||||
|
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, NA, "");
|
||||||
|
addflag(lastrace->flags, F_HITDICE, 0, 1, NA, "");
|
||||||
|
addflag(lastrace->flags, F_UNARMEDATTACKOB, NA, NA, NA, "tiny teeth");
|
||||||
|
addflag(lastrace->flags, F_UNARMEDATTACKOB, NA, NA, NA, "tiny claws");
|
||||||
|
addflag(lastrace->flags, F_EVASION, 20, NA, NA, NULL);
|
||||||
addrace(R_GIANTFLY, "giant fly", 'I');
|
addrace(R_GIANTFLY, "giant fly", 'I');
|
||||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "giant fly corpse");
|
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "fly corpse");
|
||||||
addflag(lastrace->flags, F_MOVESPEED, 2, -1, -1, "");
|
addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, "");
|
||||||
addflag(lastrace->flags, F_FLYING, B_TRUE, -1, -1, "");
|
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
|
||||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, -1, "");
|
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_COMMON, NA, "");
|
||||||
|
addflag(lastrace->flags, F_HITDICE, 0, 2, NA, "");
|
||||||
|
addflag(lastrace->flags, F_EVASION, 40, NA, NA, NULL);
|
||||||
|
addflag(lastrace->flags, F_UNARMEDATTACKOB, NA, NA, NA, "tiny teeth");
|
||||||
addrace(R_GIANTBLOWFLY, "giant blowfly", 'I');
|
addrace(R_GIANTBLOWFLY, "giant blowfly", 'I');
|
||||||
addflag(lastrace->flags, F_CORPSETYPE, -1, -1, -1, "giant fly corpse");
|
addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "fly corpse");
|
||||||
addflag(lastrace->flags, F_MOVESPEED, 2, -1, -1, "");
|
addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, "");
|
||||||
addflag(lastrace->flags, F_FLYING, B_TRUE, -1, -1, "");
|
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
|
||||||
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_UNCOMMON, -1, "");
|
addflag(lastrace->flags, F_RARITY, H_DUNGEON, RR_UNCOMMON, NA, "");
|
||||||
|
addflag(lastrace->flags, F_HITDICE, 1, 2, NA, "");
|
||||||
|
addflag(lastrace->flags, F_EVASION, 30, NA, NA, NULL);
|
||||||
|
addflag(lastrace->flags, F_UNARMEDATTACKOB, NA, NA, NA, "tiny teeth");
|
||||||
}
|
}
|
||||||
|
|
||||||
int isdead(lifeform_t *lf) {
|
int isdead(lifeform_t *lf) {
|
||||||
|
@ -516,14 +966,26 @@ int isdead(lifeform_t *lf) {
|
||||||
|
|
||||||
void killlf(lifeform_t *lf) {
|
void killlf(lifeform_t *lf) {
|
||||||
int i;
|
int i;
|
||||||
lifeform_t *nextone, *lastone;
|
lifeform_t *nextone, *lastone, *l;
|
||||||
map_t *m;
|
map_t *m;
|
||||||
|
flag_t *f;
|
||||||
|
|
||||||
m = lf->cell->map;
|
m = lf->cell->map;
|
||||||
|
|
||||||
// remove references
|
// remove references
|
||||||
lf->cell->lf = NULL;
|
lf->cell->lf = NULL;
|
||||||
|
|
||||||
|
// check if anyone is targetting us.
|
||||||
|
// if so, stop targetting us now that
|
||||||
|
// we are dead.
|
||||||
|
// TODO: check on all maps?
|
||||||
|
for (l = m->lf ; l ; l = l->next) {
|
||||||
|
f = hasflag(l->flags, F_TARGET);
|
||||||
|
if (f && (f->val[0] == lf->id)) {
|
||||||
|
killflag(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// free mem
|
// free mem
|
||||||
if (lf->lastdam) free(lf->lastdam);
|
if (lf->lastdam) free(lf->lastdam);
|
||||||
|
|
||||||
|
@ -590,7 +1052,7 @@ void killrace(race_t *race) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void losehp(lifeform_t *lf, int amt, lifeform_t *fromlf, char *damsrc) {
|
void losehp(lifeform_t *lf, int amt, int damtype, lifeform_t *fromlf, char *damsrc) {
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
lf->hp -= amt;
|
lf->hp -= amt;
|
||||||
if (lf->lastdam) {
|
if (lf->lastdam) {
|
||||||
|
@ -605,35 +1067,74 @@ void losehp(lifeform_t *lf, int amt, lifeform_t *fromlf, char *damsrc) {
|
||||||
}
|
}
|
||||||
lf->lastdam = strdup(buf);
|
lf->lastdam = strdup(buf);
|
||||||
|
|
||||||
// they will now fight back!
|
// fight back if required
|
||||||
if (fromlf && !isdead(lf)) {
|
fightback(lf, fromlf);
|
||||||
if (lf->controller != C_PLAYER) {
|
|
||||||
if (!hasflagval(lf->flags, F_TARGET, fromlf->id, -1, -1, "")) {
|
|
||||||
addflag(lf->flags, F_TARGET, fromlf->id, -1, -1, "");
|
|
||||||
// announce
|
|
||||||
if (haslos(player, lf->cell)) {
|
|
||||||
char fromlfname[BUFLEN];
|
|
||||||
char lfname[BUFLEN];
|
|
||||||
getlfname(fromlf, fromlfname);
|
|
||||||
getlfname(lf, lfname);
|
|
||||||
capitalise(lfname);
|
|
||||||
msg("%s turns to attack %s!", lfname,
|
|
||||||
haslos(player, fromlf->cell) ? fromlfname : "something");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// give initial equiment to a lifeform
|
// give initial equiment to a lifeform
|
||||||
void outfitlf(lifeform_t *lf) {
|
void outfitlf(lifeform_t *lf) {
|
||||||
if (lf->controller == C_PLAYER) {
|
flag_t *f;
|
||||||
addob(lf->pack, "10 gold");
|
object_t *bestwep;
|
||||||
|
char buf[BUFLEN];
|
||||||
|
object_t *o;
|
||||||
|
|
||||||
|
// give start objects
|
||||||
|
for (f = lf->flags->first ; f ; f = f->next) {
|
||||||
|
if (f->id == F_STARTOB) {
|
||||||
|
if (rnd(1,100) <= f->val[0]) {
|
||||||
|
addob(lf->pack, f->text);
|
||||||
|
}
|
||||||
|
} else if (f->id == F_STARTOBDT) {
|
||||||
|
if (rnd(1,100) <= f->val[0]) {
|
||||||
|
getrandomobwithdt(NULL, f->val[1], buf);
|
||||||
|
addob(lf->pack, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// weild weapons if required
|
||||||
|
bestwep = getbestweapon(lf);
|
||||||
|
if (bestwep) {
|
||||||
|
weild(lf, bestwep);
|
||||||
|
// make sure it doesn't take any time
|
||||||
|
lf->timespent = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// weild armour if required
|
||||||
|
for (o = lf->pack->first ; o ; o = o->next) {
|
||||||
|
if (canwear(lf, o)) {
|
||||||
|
wear(lf, o);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void taketime(lifeform_t *lf, int howlong) {
|
void taketime(lifeform_t *lf, int howlong) {
|
||||||
|
int db = B_TRUE;
|
||||||
|
|
||||||
|
assert(howlong > 0);
|
||||||
|
|
||||||
|
if (db && gamestarted && haslos(player, lf->cell)) {
|
||||||
|
lifeform_t *l;
|
||||||
|
dblog("lfid %d (%s) spending %d time\n",lf->id,lf->race->name, howlong);
|
||||||
|
}
|
||||||
// inc timespent
|
// inc timespent
|
||||||
lf->timespent += howlong;
|
lf->timespent += howlong;
|
||||||
// TODO: decrement lifeform's (or their object's) temporary flags
|
// TODO: decrement lifeform's (or their object's) temporary flags
|
||||||
|
|
||||||
|
// if you don't have a map, start forgetting the dungeon
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
if (!hasknownob(lf->pack, OT_MAP)) {
|
||||||
|
lf->forgettimer += ((float)howlong / 15.0);
|
||||||
|
if (lf->forgettimer > 1) {
|
||||||
|
int amt;
|
||||||
|
|
||||||
|
// TODO: modify using race memory
|
||||||
|
amt = (int)floor(lf->forgettimer);
|
||||||
|
forgetcells(lf->cell->map, amt);
|
||||||
|
lf->forgettimer -= amt;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
21
lf.h
21
lf.h
|
@ -1,19 +1,34 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
|
||||||
lifeform_t *addlf(cell_t *cell, enum RACE rid);
|
lifeform_t *addlf(cell_t *cell, enum RACE rid, int level);
|
||||||
race_t *addrace(enum RACE id, char *name, char glyph);
|
race_t *addrace(enum RACE id, char *name, char glyph);
|
||||||
|
int canpickup(lifeform_t *lf, object_t *o);
|
||||||
|
int canwear(lifeform_t *lf, object_t *o);
|
||||||
|
int canweild(lifeform_t *lf, object_t *o);
|
||||||
|
int cantakeoff(lifeform_t *lf, object_t *o);
|
||||||
void die(lifeform_t *lf);
|
void die(lifeform_t *lf);
|
||||||
|
void fightback(lifeform_t *lf, lifeform_t *attacker);
|
||||||
lifeform_t *findlf(map_t *m, int lfid);
|
lifeform_t *findlf(map_t *m, int lfid);
|
||||||
race_t *findrace(enum RACE id);
|
race_t *findrace(enum RACE id);
|
||||||
int getattackspeed(lifeform_t *lf);
|
void gainhp(lifeform_t *lf, int amt);
|
||||||
|
int getarmour(lifeform_t *lf);
|
||||||
|
object_t *getbestweapon(lifeform_t *lf);
|
||||||
|
char *getbodypartname(enum BODYPART bp);
|
||||||
|
char *getbodypartequipname(enum BODYPART bp);
|
||||||
|
object_t *getequippedob(obpile_t *op, enum BODYPART bp);
|
||||||
|
int getlfattackspeed(lifeform_t *lf);
|
||||||
int getmovespeed(lifeform_t *lf);
|
int getmovespeed(lifeform_t *lf);
|
||||||
char *getlfname(lifeform_t *lf, char *buf);
|
char *getlfname(lifeform_t *lf, char *buf);
|
||||||
|
race_t *getrandomlf(map_t *map, int *level);
|
||||||
|
char *getspeedname(int speed, char *buf);
|
||||||
|
object_t *getweapon(lifeform_t *lf);
|
||||||
int haslof(lifeform_t *viewer, cell_t *dest);
|
int haslof(lifeform_t *viewer, cell_t *dest);
|
||||||
int haslos(lifeform_t *viewer, cell_t *dest);
|
int haslos(lifeform_t *viewer, cell_t *dest);
|
||||||
void initrace(void);
|
void initrace(void);
|
||||||
int isdead(lifeform_t *lf);
|
int isdead(lifeform_t *lf);
|
||||||
void killlf(lifeform_t *lf);
|
void killlf(lifeform_t *lf);
|
||||||
void killrace(race_t *race);
|
void killrace(race_t *race);
|
||||||
void losehp(lifeform_t *lf, int amt, lifeform_t *fromlf, char *damsrc);
|
void losehp(lifeform_t *lf, int amt, int damtype, lifeform_t *fromlf, char *damsrc);
|
||||||
|
void outfitlf(lifeform_t *lf);
|
||||||
void taketime(lifeform_t *lf, int howlong);
|
void taketime(lifeform_t *lf, int howlong);
|
||||||
|
|
81
map.c
81
map.c
|
@ -5,10 +5,13 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "nexus.h"
|
#include "nexus.h"
|
||||||
|
#include "lf.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "objects.h"
|
#include "objects.h"
|
||||||
|
|
||||||
extern map_t *firstmap,*lastmap;
|
extern map_t *firstmap,*lastmap;
|
||||||
|
extern int viewx,viewy,vieww,viewh;
|
||||||
|
extern lifeform_t *player;
|
||||||
|
|
||||||
cell_t *addcell(map_t *m, int x, int y) {
|
cell_t *addcell(map_t *m, int x, int y) {
|
||||||
cell_t *cell;
|
cell_t *cell;
|
||||||
|
@ -62,11 +65,24 @@ map_t *addmap(void) {
|
||||||
|
|
||||||
void addrandomthing(cell_t *c) {
|
void addrandomthing(cell_t *c) {
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
// TODO: monsters too
|
int level;
|
||||||
|
race_t *r;
|
||||||
|
|
||||||
|
// if there's already someone there,
|
||||||
|
// then add an object.
|
||||||
|
if (c->lf || (rnd(1,2) == 1)) {
|
||||||
|
// object
|
||||||
if (getrandomob(c->map, buf)) {
|
if (getrandomob(c->map, buf)) {
|
||||||
dblog("adding %s to cell %d,%d",buf,c->x,c->y);
|
dblog("adding %s to cell %d,%d",buf,c->x,c->y);
|
||||||
addob(c->obpile, buf);
|
addob(c->obpile, buf);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
r = getrandomlf(c->map, &level);
|
||||||
|
if (r) {
|
||||||
|
dblog("adding %s to cell %d,%d",buf,c->x,c->y);
|
||||||
|
addlf(c, r->id, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_t *getcellat(map_t *map, int x, int y) {
|
cell_t *getcellat(map_t *map, int x, int y) {
|
||||||
|
@ -1080,6 +1096,44 @@ map_t *findmap(int mid) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void forgetcells(map_t *map, int amt) {
|
||||||
|
int amtleft;
|
||||||
|
//int totcells;
|
||||||
|
int i;
|
||||||
|
cell_t *poss[MAX_MAPW*MAX_MAPH];
|
||||||
|
cell_t *c;
|
||||||
|
int nposs = 0;
|
||||||
|
// how many cells to forget?
|
||||||
|
//totcells = (map->w * map->h);
|
||||||
|
//amtleft = (int) (((float) pct / 100.0) * (float)totcells);
|
||||||
|
amtleft = amt;
|
||||||
|
|
||||||
|
// get a list of all known cells
|
||||||
|
for (i = 0; i < (map->w*map->h); i++){
|
||||||
|
c = map->cell[i];
|
||||||
|
if (c && c->known && !haslos(player, c)) {
|
||||||
|
poss[nposs] = c;
|
||||||
|
nposs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (amtleft > nposs) amtleft = nposs;
|
||||||
|
|
||||||
|
// forget cells...
|
||||||
|
for (i = 0; i < amtleft; i++) {
|
||||||
|
int n;
|
||||||
|
int sel;
|
||||||
|
sel = rnd(0,nposs-1);
|
||||||
|
poss[sel]->known = B_FALSE;
|
||||||
|
// shuffle down
|
||||||
|
for (n = i; n < (amtleft-1); n++) {
|
||||||
|
poss[n] = poss[n+1];
|
||||||
|
}
|
||||||
|
nposs--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cell_t *getcellindir(cell_t *cell, int dir) {
|
cell_t *getcellindir(cell_t *cell, int dir) {
|
||||||
cell_t *newcell;
|
cell_t *newcell;
|
||||||
int newx,newy;
|
int newx,newy;
|
||||||
|
@ -1259,12 +1313,11 @@ cell_t *getrandomroomcell(map_t *map, int roomid) {
|
||||||
poss = malloc((map->w*map->h) * sizeof(cell_t));
|
poss = malloc((map->w*map->h) * sizeof(cell_t));
|
||||||
|
|
||||||
npossible = 0;
|
npossible = 0;
|
||||||
// avoid room borders!
|
for (y = 0; y < map->h; y++) {
|
||||||
for (y = 1; y < (map->h-1); y++) {
|
for (x = 0; x < map->w; x++) {
|
||||||
for (x = 1; x < (map->w-1); x++) {
|
|
||||||
c = getcellat(map, x, y);
|
c = getcellat(map, x, y);
|
||||||
// is this cell in the correct room?
|
// is this cell in the correct room and not a wall?
|
||||||
if (c && c->roomid == roomid) {
|
if (c && !c->type->solid && (c->roomid == roomid)) {
|
||||||
poss[npossible] = c;
|
poss[npossible] = c;
|
||||||
npossible++;
|
npossible++;
|
||||||
}
|
}
|
||||||
|
@ -1353,3 +1406,19 @@ void setcelltype(cell_t *cell, int id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void updateknowncells(void) {
|
||||||
|
int x,y;
|
||||||
|
map_t *map;
|
||||||
|
|
||||||
|
map = player->cell->map;
|
||||||
|
|
||||||
|
for (y = viewy; y < viewy + viewh; y++) {
|
||||||
|
for (x = viewx; x < viewx + vieww; x++) {
|
||||||
|
cell_t *cell;
|
||||||
|
cell = getcellat(map, x, y);
|
||||||
|
if (cell && !cell->known && haslos(player, cell)) {
|
||||||
|
cell->known = B_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2
map.h
2
map.h
|
@ -14,6 +14,7 @@ int dirtox(int dt, int dir);
|
||||||
int dirtoy(int dt, int dir);
|
int dirtoy(int dt, int dir);
|
||||||
void dumpmap(map_t *map);
|
void dumpmap(map_t *map);
|
||||||
map_t *findmap(int mid);
|
map_t *findmap(int mid);
|
||||||
|
void forgetcells(map_t *map, int amt);
|
||||||
cell_t *getcellindir(cell_t *cell, int dir);
|
cell_t *getcellindir(cell_t *cell, int dir);
|
||||||
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
|
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
|
||||||
int getobchance(int habitat);
|
int getobchance(int habitat);
|
||||||
|
@ -27,3 +28,4 @@ int isonmap(map_t *map, int x, int y);
|
||||||
int iswallindir(cell_t *cell, int dir);
|
int iswallindir(cell_t *cell, int dir);
|
||||||
void makedoor(cell_t *cell);
|
void makedoor(cell_t *cell);
|
||||||
void setcelltype(cell_t *cell, int id);
|
void setcelltype(cell_t *cell, int id);
|
||||||
|
void updateknowncells(void);
|
||||||
|
|
99
move.c
99
move.c
|
@ -1,7 +1,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include "attack.h"
|
#include "attack.h"
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
#include "lf.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
|
#include "objects.h"
|
||||||
|
#include "text.h"
|
||||||
|
|
||||||
extern lifeform_t *player;
|
extern lifeform_t *player;
|
||||||
|
|
||||||
|
@ -10,7 +14,8 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||||
|
|
||||||
cell = getcellindir(lf->cell, dir);
|
cell = getcellindir(lf->cell, dir);
|
||||||
|
|
||||||
if (cell->type->solid) {
|
|
||||||
|
if (!cell || cell->type->solid) {
|
||||||
if (error) *error = E_WALLINWAY;
|
if (error) *error = E_WALLINWAY;
|
||||||
return B_FALSE;
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -22,25 +27,58 @@ int canmove(lifeform_t *lf, int dir, enum ERROR *error) {
|
||||||
return B_TRUE;
|
return B_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dorandommove(lifeform_t *lf) {
|
void dorandommove(lifeform_t *lf, int badmovesok) {
|
||||||
int dir;
|
int dir;
|
||||||
int tries = 0;
|
int tries = 0;
|
||||||
|
int moveok;
|
||||||
|
enum ERROR why;
|
||||||
|
|
||||||
|
// find a valid direction
|
||||||
dir = getrandomdir(DT_COMPASS);
|
dir = getrandomdir(DT_COMPASS);
|
||||||
while (trymove(lf, dir)) {
|
|
||||||
|
moveok = canmove(lf, dir, &why);
|
||||||
|
if (!moveok && badmovesok) {
|
||||||
|
switch (why) {
|
||||||
|
case E_WALLINWAY:
|
||||||
|
case E_LFINWAY:
|
||||||
|
moveok = B_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (!moveok) {
|
||||||
|
// try next direction...
|
||||||
if (++dir > DC_NW) dir = DC_N;
|
if (++dir > DC_NW) dir = DC_N;
|
||||||
if (++tries >= MAXDIR_COMPASS) {
|
if (++tries >= MAXDIR_COMPASS) {
|
||||||
dowait(lf);
|
dowait(lf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check this direction...
|
||||||
|
moveok = canmove(lf, dir, &why);
|
||||||
|
if (!moveok && badmovesok) {
|
||||||
|
switch (why) {
|
||||||
|
case E_WALLINWAY:
|
||||||
|
case E_LFINWAY:
|
||||||
|
moveok = B_TRUE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
trymove(lf, dir);
|
||||||
|
}
|
||||||
|
|
||||||
int dowait(lifeform_t *lf) {
|
int dowait(lifeform_t *lf) {
|
||||||
taketime(lf, SPEED_WAIT);
|
taketime(lf, SPEED_WAIT);
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
// clear msg bar
|
||||||
|
clearmsg();
|
||||||
|
}
|
||||||
return B_FALSE;
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void movelf(lifeform_t *lf, cell_t *newcell) {
|
void movelf(lifeform_t *lf, cell_t *newcell) {
|
||||||
|
object_t *o,*nexto;
|
||||||
|
char obname[BUFLEN],lfname[BUFLEN],buf[BUFLEN];
|
||||||
// update current cell
|
// update current cell
|
||||||
lf->cell->lf = NULL;
|
lf->cell->lf = NULL;
|
||||||
|
|
||||||
|
@ -50,6 +88,59 @@ void movelf(lifeform_t *lf, cell_t *newcell) {
|
||||||
// update new cell
|
// update new cell
|
||||||
newcell->lf = lf;
|
newcell->lf = lf;
|
||||||
|
|
||||||
|
|
||||||
|
// check ground objects
|
||||||
|
if (!hasflag(lf->flags, F_FLYING)) {
|
||||||
|
for (o = newcell->obpile->first ; o ; o = nexto ) {
|
||||||
|
nexto = o->next;
|
||||||
|
if (hasflag(o->flags, F_SHARP)) {
|
||||||
|
object_t *boots;
|
||||||
|
// has boots on?
|
||||||
|
boots = getequippedob(lf->pack, BP_FEET);
|
||||||
|
if (boots) {
|
||||||
|
// crunch the broken glass
|
||||||
|
getobname(o, obname, 1);
|
||||||
|
|
||||||
|
if (o->amt > 1) {
|
||||||
|
char *newname;
|
||||||
|
// we want 'xx steps on some pieces of broken glass'
|
||||||
|
// not 'xx steps on 5 pieces of broken glass'
|
||||||
|
newname = makeplural(obname);
|
||||||
|
strrep(newname, "a ", "some ");
|
||||||
|
strcpy(obname, newname);
|
||||||
|
free(newname);
|
||||||
|
}
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("You crush %s underfoot.",obname);
|
||||||
|
} else if (haslos(player, newcell)) {
|
||||||
|
getlfname(lf, lfname);
|
||||||
|
capitalise(lfname);
|
||||||
|
msg("%s crushes %s.",lfname, obname);
|
||||||
|
}
|
||||||
|
// kill object
|
||||||
|
removeob(o, o->amt);
|
||||||
|
} else {
|
||||||
|
// take damage
|
||||||
|
getobname(o, obname, 1);
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
msg("Ow - you step on %s!",obname);
|
||||||
|
} else if (haslos(player, newcell)) {
|
||||||
|
getlfname(lf, lfname);
|
||||||
|
capitalise(lfname);
|
||||||
|
msg("%s steps on %s!",lfname, obname);
|
||||||
|
}
|
||||||
|
sprintf(buf, "stepping on %s", obname);
|
||||||
|
losehp(lf, rnd(1,2), DT_SLASH, NULL, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // end foreach object in cell
|
||||||
|
} // end if !flying
|
||||||
|
|
||||||
|
// update where player knows
|
||||||
|
// (but without a map you will then slowly forget it)
|
||||||
|
if (lf->controller == C_PLAYER) {
|
||||||
|
updateknowncells();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// basically this is a warpper for 'movelf' which
|
// basically this is a warpper for 'movelf' which
|
||||||
|
@ -61,7 +152,7 @@ int moveto(lifeform_t *lf, cell_t *newcell) {
|
||||||
movelf(lf, newcell);
|
movelf(lf, newcell);
|
||||||
|
|
||||||
// tell player about things
|
// tell player about things
|
||||||
if (lf->controller == C_PLAYER) {
|
if (!isdead(lf) && (lf->controller == C_PLAYER)) {
|
||||||
int numobs;
|
int numobs;
|
||||||
char buf[BUFLEN];
|
char buf[BUFLEN];
|
||||||
numobs = countobs(newcell->obpile);
|
numobs = countobs(newcell->obpile);
|
||||||
|
|
2
move.h
2
move.h
|
@ -1,7 +1,7 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
int canmove(lifeform_t *lf, int dir, enum ERROR *error);
|
int canmove(lifeform_t *lf, int dir, enum ERROR *error);
|
||||||
void dorandommove(lifeform_t *lf);
|
void dorandommove(lifeform_t *lf, int badmovesok);
|
||||||
int dowait(lifeform_t *lf);
|
int dowait(lifeform_t *lf);
|
||||||
void movelf(lifeform_t *lf, cell_t *newcell);
|
void movelf(lifeform_t *lf, cell_t *newcell);
|
||||||
int moveto(lifeform_t *lf, cell_t *newcell);
|
int moveto(lifeform_t *lf, cell_t *newcell);
|
||||||
|
|
40
nexus.c
40
nexus.c
|
@ -15,6 +15,7 @@ objecttype_t *objecttype = NULL,*lastobjecttype = NULL;
|
||||||
celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
|
celltype_t *firstcelltype = NULL,*lastcelltype = NULL;
|
||||||
race_t *firstrace = NULL,*lastrace = NULL;
|
race_t *firstrace = NULL,*lastrace = NULL;
|
||||||
map_t *firstmap = NULL,*lastmap = NULL;
|
map_t *firstmap = NULL,*lastmap = NULL;
|
||||||
|
knowledge_t *knowledge = NULL, *lastknowledge = NULL;
|
||||||
|
|
||||||
FILE *logfile;
|
FILE *logfile;
|
||||||
|
|
||||||
|
@ -46,15 +47,24 @@ int main(char **argv, int argc) {
|
||||||
createmap(firstmap, H_DUNGEON);
|
createmap(firstmap, H_DUNGEON);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if no player, add them
|
if (!knowledge) {
|
||||||
|
// populate scroll names
|
||||||
|
genhiddennames();
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no player (ie. didn't load a game), add them
|
||||||
if (!player) {
|
if (!player) {
|
||||||
|
// add player
|
||||||
|
player = addlf(getrandomcelloftype(firstmap, CT_ROOM), R_HUMAN, 1);
|
||||||
|
player->controller = C_PLAYER;
|
||||||
|
drawscreen();
|
||||||
msg("Welcome to %snexus!", newworld ? "the new " : "");
|
msg("Welcome to %snexus!", newworld ? "the new " : "");
|
||||||
more();
|
more();
|
||||||
player = addlf(getrandomcelloftype(firstmap, CT_ROOM), R_HUMAN);
|
// XXX testing
|
||||||
player->controller = C_PLAYER;
|
//addlf(getcellindir(player->cell, D_N), R_GOBLIN, 1);
|
||||||
outfitlf(player);
|
|
||||||
addlf(getcellindir(player->cell, D_N), R_BAT);
|
|
||||||
} else {
|
} else {
|
||||||
|
drawscreen();
|
||||||
msg("Welcome back!");
|
msg("Welcome back!");
|
||||||
more();
|
more();
|
||||||
}
|
}
|
||||||
|
@ -219,33 +229,47 @@ int init(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int isplayerturn(void) {
|
int isplayerturn(void) {
|
||||||
|
if (!player) return B_FALSE;
|
||||||
|
|
||||||
if (player->cell->map->lf->controller == C_PLAYER) {
|
if (player->cell->map->lf->controller == C_PLAYER) {
|
||||||
return B_TRUE;
|
return B_TRUE;
|
||||||
}
|
}
|
||||||
return B_FALSE;
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get a random number
|
// get a random number between min and max
|
||||||
int rnd(int min, int max) {
|
int rnd(int min, int max) {
|
||||||
int res;
|
int res;
|
||||||
res = (rand() % (max - min + 1)) + min;
|
res = (rand() % (max - min + 1)) + min;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
// get a random number
|
||||||
|
int rolldie(int ndice, int sides) {
|
||||||
|
int i;
|
||||||
|
int res = 0;
|
||||||
|
for (i = 0; i < ndice; i++) {
|
||||||
|
res += rnd(1,sides);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// sort map's lifeform list by time spent
|
// sort map's lifeform list by time spent
|
||||||
void sortlf(map_t *map) {
|
void sortlf(map_t *map) {
|
||||||
int donesomething;
|
int donesomething;
|
||||||
lifeform_t *l;
|
lifeform_t *l;
|
||||||
int adjustby;
|
int adjustby;
|
||||||
int db = B_FALSE;
|
int db = B_TRUE;
|
||||||
|
|
||||||
// bubblesort
|
// bubblesort
|
||||||
|
/*
|
||||||
if (db) {
|
if (db) {
|
||||||
dblog("BEFORE sortlf():");
|
dblog("BEFORE sortlf():");
|
||||||
for (l = map->lf ; l ; l = l->next) {
|
for (l = map->lf ; l ; l = l->next) {
|
||||||
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
donesomething = B_TRUE;
|
donesomething = B_TRUE;
|
||||||
while (donesomething) {
|
while (donesomething) {
|
||||||
|
@ -283,9 +307,11 @@ void sortlf(map_t *map) {
|
||||||
if (db) {
|
if (db) {
|
||||||
dblog("AFTER SORT:");
|
dblog("AFTER SORT:");
|
||||||
for (l = map->lf ; l ; l = l->next) {
|
for (l = map->lf ; l ; l = l->next) {
|
||||||
|
if (haslos(player, l->cell)) {
|
||||||
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
dblog("- %s (timespent= %d) (sorted=%d)", (l == player) ? "player" : l->race->name, l->timespent,l->sorted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// now go through the list and make the first element be 0
|
// now go through the list and make the first element be 0
|
||||||
adjustby = map->lf->timespent;
|
adjustby = map->lf->timespent;
|
||||||
|
|
1
nexus.h
1
nexus.h
|
@ -10,4 +10,5 @@ char *getdirname(int dir);
|
||||||
int init(void);
|
int init(void);
|
||||||
int isplayerturn(void);
|
int isplayerturn(void);
|
||||||
int rnd(int min, int max);
|
int rnd(int min, int max);
|
||||||
|
int rolldie(int ndice, int sides);
|
||||||
void sortlf(map_t *map);
|
void sortlf(map_t *map);
|
||||||
|
|
25
objects.h
25
objects.h
|
@ -2,8 +2,9 @@
|
||||||
#define __OBJECTS_H
|
#define __OBJECTS_H
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
|
knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known);
|
||||||
material_t *addmaterial(enum MATERIAL id, char *name);
|
material_t *addmaterial(enum MATERIAL id, char *name);
|
||||||
objectclass_t *addoc(enum OBCLASS id, char *name, char glyph);
|
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph);
|
||||||
object_t *addob(obpile_t *where, char *name);
|
object_t *addob(obpile_t *where, char *name);
|
||||||
object_t *addobject(obpile_t *where, char *name, int canstack);
|
object_t *addobject(obpile_t *where, char *name, int canstack);
|
||||||
obpile_t *addobpile(lifeform_t *owner, cell_t *where);
|
obpile_t *addobpile(lifeform_t *owner, cell_t *where);
|
||||||
|
@ -11,27 +12,47 @@ objecttype_t *addot(int id, char *name, char *description, int material, float w
|
||||||
object_t *canstackob(obpile_t *op, object_t *match);
|
object_t *canstackob(obpile_t *op, object_t *match);
|
||||||
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
|
object_t *canstacknewot(obpile_t *op, objecttype_t *match);
|
||||||
void copyobprops(object_t *dst, object_t *src);
|
void copyobprops(object_t *dst, object_t *src);
|
||||||
|
int countnames(char **list);
|
||||||
int countobs(obpile_t *op);
|
int countobs(obpile_t *op);
|
||||||
material_t *findmaterial(int id);
|
material_t *findmaterial(int id);
|
||||||
objectclass_t *findoc(int id);
|
objectclass_t *findoc(int id);
|
||||||
object_t *findobl(obpile_t *op, char let); // find object by letter
|
object_t *findobl(obpile_t *op, char let); // find object by letter
|
||||||
objecttype_t *findot(int id);
|
objecttype_t *findot(enum OBTYPE id);
|
||||||
objecttype_t *findotn(char *name); // find objecttype by name
|
objecttype_t *findotn(char *name); // find objecttype by name
|
||||||
|
void genhiddennames(void);
|
||||||
|
char *getdamname(enum DAMTYPE damtype);
|
||||||
|
char getglyph(object_t *o);
|
||||||
|
char *genhiddenname(enum OBCLASS id);
|
||||||
|
char *gethiddenname(object_t *o);
|
||||||
|
int getobattackspeed(object_t *o);
|
||||||
int getletindex(char let);
|
int getletindex(char let);
|
||||||
char getnextletter(obpile_t *op, char *wantletter);
|
char getnextletter(obpile_t *op, char *wantletter);
|
||||||
char *getobname(object_t *o, char *buf, int count);
|
char *getobname(object_t *o, char *buf, int count);
|
||||||
char *getrandomob(map_t *map, char *buf);
|
char *getrandomob(map_t *map, char *buf);
|
||||||
|
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf);
|
||||||
|
object_t *hasknownob(obpile_t *op, enum OBTYPE oid);
|
||||||
object_t *hasob(obpile_t *op, enum OBTYPE oid);
|
object_t *hasob(obpile_t *op, enum OBTYPE oid);
|
||||||
|
object_t *hasobid(obpile_t *op, int id);
|
||||||
void initobjects(void);
|
void initobjects(void);
|
||||||
|
int isdrinkable(object_t *o);
|
||||||
|
int isknown(object_t *o);
|
||||||
int isplainob(object_t *o);
|
int isplainob(object_t *o);
|
||||||
|
int isreadable(object_t *o);
|
||||||
void killmaterial(material_t *m);
|
void killmaterial(material_t *m);
|
||||||
void killob(object_t *o);
|
void killob(object_t *o);
|
||||||
void killoc(objectclass_t *oc);
|
void killoc(objectclass_t *oc);
|
||||||
void killot(objecttype_t *ot);
|
void killot(objecttype_t *ot);
|
||||||
|
void makeknown(enum OBTYPE otid);
|
||||||
object_t *moveob(object_t *src, obpile_t *dst, int howmany);
|
object_t *moveob(object_t *src, obpile_t *dst, int howmany);
|
||||||
|
object_t *obexists(enum OBTYPE obid);
|
||||||
int obfits(object_t *o, obpile_t *op);
|
int obfits(object_t *o, obpile_t *op);
|
||||||
int obpropsmatch(object_t *a, object_t *b);
|
int obpropsmatch(object_t *a, object_t *b);
|
||||||
int pilehasletter(obpile_t *op, char let);
|
int pilehasletter(obpile_t *op, char let);
|
||||||
|
void quaff(lifeform_t *lf, object_t *o);
|
||||||
|
void read(lifeform_t *lf, object_t *o);
|
||||||
|
int removeob(object_t *o, int howmany);
|
||||||
object_t *relinkob(object_t *src, obpile_t *dst);
|
object_t *relinkob(object_t *src, obpile_t *dst);
|
||||||
void throwat(lifeform_t *thrower, object_t *o, cell_t *where);
|
void throwat(lifeform_t *thrower, object_t *o, cell_t *where);
|
||||||
|
int willshatter(enum MATERIAL mat);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
119
save.c
119
save.c
|
@ -1,3 +1,4 @@
|
||||||
|
#include <assert.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -12,6 +13,9 @@
|
||||||
|
|
||||||
extern lifeform_t *player;
|
extern lifeform_t *player;
|
||||||
extern map_t *firstmap;
|
extern map_t *firstmap;
|
||||||
|
extern knowledge_t *knowledge;
|
||||||
|
|
||||||
|
int loading = B_FALSE;
|
||||||
|
|
||||||
int loadall(void) {
|
int loadall(void) {
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
|
@ -19,6 +23,8 @@ int loadall(void) {
|
||||||
char *filename;
|
char *filename;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
|
||||||
|
loading = B_TRUE;
|
||||||
|
|
||||||
dir = opendir(MAPDIR);
|
dir = opendir(MAPDIR);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
dblog("Could not open map directory '%s'",MAPDIR);
|
dblog("Could not open map directory '%s'",MAPDIR);
|
||||||
|
@ -41,10 +47,32 @@ int loadall(void) {
|
||||||
|
|
||||||
loadsavegame();
|
loadsavegame();
|
||||||
|
|
||||||
|
loading = B_FALSE;
|
||||||
|
|
||||||
return B_FALSE;
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int loadknowledge(FILE *f) {
|
||||||
|
int db = B_FALSE;
|
||||||
|
char buf[BUFLEN];
|
||||||
|
int otid,known;
|
||||||
|
char hiddenname[BUFLEN];
|
||||||
|
if (db) dblog("--> Loading knowledge...\n");
|
||||||
|
fscanf(f, "startknowledge\n");
|
||||||
|
|
||||||
|
fgets(buf, BUFLEN, f);
|
||||||
|
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||||
|
|
||||||
|
while (strcmp(buf, "endknowledge")) {
|
||||||
|
sscanf(buf, "%d^%s^%d",&otid, hiddenname, &known);
|
||||||
|
addknowledge(otid, hiddenname, known);
|
||||||
|
// get next line
|
||||||
|
fgets(buf, BUFLEN, f);
|
||||||
|
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
// load and allocate one lifeform from given file
|
// load and allocate one lifeform from given file
|
||||||
lifeform_t *loadlf(FILE *f, cell_t *where) {
|
lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||||
|
@ -57,7 +85,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||||
int obcount;
|
int obcount;
|
||||||
int mapid;
|
int mapid;
|
||||||
map_t *m;
|
map_t *m;
|
||||||
int x,y;
|
int x,y,level;
|
||||||
int db = B_TRUE;
|
int db = B_TRUE;
|
||||||
|
|
||||||
if (db) dblog("--> Loading lifeform...\n");
|
if (db) dblog("--> Loading lifeform...\n");
|
||||||
|
@ -67,6 +95,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||||
fscanf(f, "race: %d\n",&lfraceid);
|
fscanf(f, "race: %d\n",&lfraceid);
|
||||||
fscanf(f, "map: %d\n",&mapid);
|
fscanf(f, "map: %d\n",&mapid);
|
||||||
fscanf(f, "pos: %d,%d\n",&x, &y);
|
fscanf(f, "pos: %d,%d\n",&x, &y);
|
||||||
|
fscanf(f, "level: %d\n",&level);
|
||||||
|
|
||||||
// find the map
|
// find the map
|
||||||
m = findmap(mapid);
|
m = findmap(mapid);
|
||||||
|
@ -82,7 +111,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
l = addlf(where, lfraceid);
|
l = addlf(where, lfraceid,level);
|
||||||
l->id = lfid;
|
l->id = lfid;
|
||||||
l->x = x;
|
l->x = x;
|
||||||
l->y = y;
|
l->y = y;
|
||||||
|
@ -99,6 +128,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||||
fscanf(f, "timespent: %d\n",&l->timespent);
|
fscanf(f, "timespent: %d\n",&l->timespent);
|
||||||
|
|
||||||
fscanf(f, "sorted: %d\n",&l->sorted);
|
fscanf(f, "sorted: %d\n",&l->sorted);
|
||||||
|
fscanf(f, "forgettimer: %f\n",&l->forgettimer);
|
||||||
|
|
||||||
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading ob list.",l->hp,l->maxhp,l->timespent,l->sorted);
|
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading ob list.",l->hp,l->maxhp,l->timespent,l->sorted);
|
||||||
|
|
||||||
|
@ -118,14 +148,17 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
|
||||||
}
|
}
|
||||||
if (db) dblog("--> Finished oblist. Found %d objects.",obcount);
|
if (db) dblog("--> Finished oblist. Found %d objects.",obcount);
|
||||||
|
|
||||||
// now load load object defs!
|
// now load load object defs for this player!
|
||||||
fscanf(f, "obdefs\n");
|
fscanf(f, "obdefs\n");
|
||||||
for (i = 0; i < obcount; i++) {
|
for (i = 0; i < obcount; i++) {
|
||||||
|
long thisid;
|
||||||
|
if (db) dblog("--> Creating ob #%d for lf.",i);
|
||||||
//if (db) dblog("-----> ob %d/%d...\n",i+1,obcount);
|
//if (db) dblog("-----> ob %d/%d...\n",i+1,obcount);
|
||||||
if (loadob(f, l->pack)) {
|
if (loadob(f, l->pack, &thisid)) {
|
||||||
dblog("Error - can't create object %d/%d!\n",i+1,obcount);
|
dblog("Error - can't create object %d/%d!\n",i+1,obcount);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (db) dblog("----> done (id=%ld)",thisid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// is this the player?
|
// is this the player?
|
||||||
|
@ -154,14 +187,12 @@ map_t *loadmap(char *basefile) {
|
||||||
sprintf(filename, "%s/%s",MAPDIR,basefile);
|
sprintf(filename, "%s/%s",MAPDIR,basefile);
|
||||||
f = fopen(filename, "rt");
|
f = fopen(filename, "rt");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// create map
|
// create map
|
||||||
m = addmap();
|
m = addmap();
|
||||||
dummycell = malloc(sizeof(cell_t));
|
dummycell = malloc(sizeof(cell_t));
|
||||||
dummycell->obpile = addobpile(NULL, dummycell);
|
dummycell->obpile = addobpile(NULL, dummycell);
|
||||||
dummycell->map = m;
|
dummycell->map = m;
|
||||||
dummycell->type = (celltype_t *)0xabcde; // for debugging
|
dummycell->type = (celltype_t *)DUMMYCELLTYPE; // for debugging
|
||||||
|
|
||||||
if (!m) {
|
if (!m) {
|
||||||
dblog("Error creating map while loading file '%s'",filename);
|
dblog("Error creating map while loading file '%s'",filename);
|
||||||
|
@ -255,14 +286,23 @@ map_t *loadmap(char *basefile) {
|
||||||
|
|
||||||
// create all objects in a dummy cell
|
// create all objects in a dummy cell
|
||||||
for (i = 0; i < obcount; i++) {
|
for (i = 0; i < obcount; i++) {
|
||||||
if (db) dblog("-----> ob %d/%d...\n",i+1,obcount);
|
int n;
|
||||||
if (loadob(f, dummycell->obpile)) {
|
long thisid;
|
||||||
|
if (db) dblog("-----> loading into dummycell: mapob %d/%d...\n",i+1,obcount);
|
||||||
|
if (loadob(f, dummycell->obpile, &thisid)) {
|
||||||
dblog("Error - can't create object %d/%d!\n",i+1,obcount);
|
dblog("Error - can't create object %d/%d!\n",i+1,obcount);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (db) dblog("----------> got obid %ld\n",thisid);
|
||||||
|
// check!
|
||||||
|
if (!hasobid(dummycell->obpile, thisid)) {
|
||||||
|
dblog("Error: after loading obid %ld, can't find it in dummycell!\n",thisid);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hand out the objects to lifeforms...
|
// hand out the objects to lifeforms...
|
||||||
|
/*
|
||||||
for (l = m->lf ; l ; l = l->next) {
|
for (l = m->lf ; l ; l = l->next) {
|
||||||
int curob = 0;
|
int curob = 0;
|
||||||
long obid;
|
long obid;
|
||||||
|
@ -279,7 +319,7 @@ map_t *loadmap(char *basefile) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
dblog("Error loading obs - lf %d should have obid %ld but can't find it.\n",l->id, obid);
|
dblog("Error loading obs - lf %d should have obid %ld but can't find it in dummycell.\n",l->id, obid);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
// next one
|
// next one
|
||||||
|
@ -293,6 +333,7 @@ map_t *loadmap(char *basefile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// hand out objects to cells
|
// hand out objects to cells
|
||||||
for (y = 0; y < m->h; y++) {
|
for (y = 0; y < m->h; y++) {
|
||||||
|
@ -303,23 +344,21 @@ map_t *loadmap(char *basefile) {
|
||||||
c = m->cell[y * m->w + x];
|
c = m->cell[y * m->w + x];
|
||||||
|
|
||||||
obid = c->obpile->oblist[curob];
|
obid = c->obpile->oblist[curob];
|
||||||
|
dblog("Handing out objects to cell %d,%d\n",x,y);
|
||||||
while (obid != -1) {
|
while (obid != -1) {
|
||||||
int found = B_FALSE;
|
dblog(" Looking for obid %ld in dummycell...",obid);
|
||||||
// find this ob id in the dummycell
|
// find this ob id in the dummycell
|
||||||
for (o = dummycell->obpile->first ; o ; o = nexto) {
|
o = hasobid(dummycell->obpile, obid);
|
||||||
nexto = o->next;
|
if (o) {
|
||||||
if (o->id == obid) {
|
dblog(" Got it.");
|
||||||
relinkob(o, c->obpile);
|
relinkob(o, c->obpile);
|
||||||
found = B_TRUE;
|
} else {
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) {
|
|
||||||
dblog(" Error loading obs - cell %d,%d should have obid %ld but can't find it.\n",x,y, obid);
|
dblog(" Error loading obs - cell %d,%d should have obid %ld but can't find it.\n",x,y, obid);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
// next one
|
// next one
|
||||||
curob++;
|
curob++;
|
||||||
|
obid = c->obpile->oblist[curob];
|
||||||
}
|
}
|
||||||
// clear the oblist
|
// clear the oblist
|
||||||
for (i = 0; i < MAXPILEOBS; i++) {
|
for (i = 0; i < MAXPILEOBS; i++) {
|
||||||
|
@ -345,11 +384,14 @@ map_t *loadmap(char *basefile) {
|
||||||
|
|
||||||
free(dummycell);
|
free(dummycell);
|
||||||
|
|
||||||
|
// successful load - kill the map now
|
||||||
|
unlink(filename);
|
||||||
|
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
int loadob(FILE *f, obpile_t *op) {
|
int loadob(FILE *f, obpile_t *op, long *id) {
|
||||||
objecttype_t *ot;
|
objecttype_t *ot;
|
||||||
object_t *o;
|
object_t *o;
|
||||||
material_t *mat;
|
material_t *mat;
|
||||||
|
@ -359,17 +401,23 @@ int loadob(FILE *f, obpile_t *op) {
|
||||||
int flagid;
|
int flagid;
|
||||||
flag_t tempflag;
|
flag_t tempflag;
|
||||||
int rv;
|
int rv;
|
||||||
|
int db = B_TRUE;
|
||||||
|
|
||||||
fscanf(f, "id:%ld\n",&obid);
|
fscanf(f, "id:%ld\n",&obid);
|
||||||
fscanf(f, "type:%d\n",&otid);
|
fscanf(f, "type:%d\n",&otid);
|
||||||
|
|
||||||
|
if (db) dblog("... loading object id %ld",obid);
|
||||||
|
if (id) {
|
||||||
|
*id = obid;
|
||||||
|
}
|
||||||
|
|
||||||
ot = findot(otid);
|
ot = findot(otid);
|
||||||
if (!ot) {
|
if (!ot) {
|
||||||
dblog("ERROR loading objects - can't find obtype id %ld\n",obid);
|
dblog("ERROR loading objects - can't find obtype id %ld\n",obid);
|
||||||
return B_TRUE;
|
return B_TRUE;
|
||||||
}
|
}
|
||||||
// create the object
|
// create the object
|
||||||
o = addob(op, ot->name);
|
o = addobject(op, ot->name, B_NOSTACK); // no stacking!
|
||||||
|
|
||||||
// overwrite ob parameters
|
// overwrite ob parameters
|
||||||
o->id = obid;
|
o->id = obid;
|
||||||
|
@ -397,15 +445,16 @@ int loadob(FILE *f, obpile_t *op) {
|
||||||
|
|
||||||
fscanf(f, "flags:\n");
|
fscanf(f, "flags:\n");
|
||||||
|
|
||||||
|
dblog("About to start loading object flags...");
|
||||||
rv = fscanf(f, "%d,%d,%d,%d,%d\n",
|
rv = fscanf(f, "%d,%d,%d,%d,%d\n",
|
||||||
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2]);
|
&tempflag.id, &tempflag.nvals, &tempflag.val[0], &tempflag.val[1], &tempflag.val[2]);
|
||||||
|
|
||||||
|
while (tempflag.id != -1) {
|
||||||
|
dblog("got flag id=%d\n",tempflag.id);
|
||||||
// get flag text
|
// get flag text
|
||||||
fgets(buf, BUFLEN, f);
|
fgets(buf, BUFLEN, f);
|
||||||
buf[strlen(buf)-1] = '\0'; // strip newline
|
buf[strlen(buf)-1] = '\0'; // strip newline
|
||||||
|
|
||||||
while (tempflag.id != -1) {
|
|
||||||
dblog("got flag id=%d\n",tempflag.id);
|
|
||||||
|
|
||||||
addflag(o->flags, tempflag.id,
|
addflag(o->flags, tempflag.id,
|
||||||
tempflag.val[0],
|
tempflag.val[0],
|
||||||
|
@ -451,6 +500,10 @@ int loadsavegame(void) {
|
||||||
printf("Error loading savegame from file '%s'",ent->d_name);
|
printf("Error loading savegame from file '%s'",ent->d_name);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (loadknowledge(f)) {
|
||||||
|
printf("Error loading knowledge from file '%s'",ent->d_name);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
// successful load - kill the savegame now
|
// successful load - kill the savegame now
|
||||||
|
@ -462,6 +515,23 @@ int loadsavegame(void) {
|
||||||
return B_FALSE;
|
return B_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int saveknowledge(FILE *f) {
|
||||||
|
int db = B_FALSE;
|
||||||
|
char buf[BUFLEN];
|
||||||
|
int otid,known;
|
||||||
|
char hiddenname[BUFLEN];
|
||||||
|
knowledge_t *k;
|
||||||
|
if (db) dblog("--> Saving knowledge...\n");
|
||||||
|
fprintf(f, "startknowledge\n");
|
||||||
|
|
||||||
|
for (k = knowledge; k ; k = k->next) {
|
||||||
|
fprintf(f, "%d^%s^%d\n",k->id, k->hiddenname, k->known);
|
||||||
|
}
|
||||||
|
fprintf(f, "endknowledge\n");
|
||||||
|
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
int savelf(FILE *f, lifeform_t *l) {
|
int savelf(FILE *f, lifeform_t *l) {
|
||||||
object_t *o;
|
object_t *o;
|
||||||
int obcount = 0;
|
int obcount = 0;
|
||||||
|
@ -471,12 +541,15 @@ int savelf(FILE *f, lifeform_t *l) {
|
||||||
fprintf(f, "race: %d\n",l->race->id);
|
fprintf(f, "race: %d\n",l->race->id);
|
||||||
fprintf(f, "map: %d\n",l->cell->map->id);
|
fprintf(f, "map: %d\n",l->cell->map->id);
|
||||||
fprintf(f, "pos: %d,%d\n",l->cell->x, l->cell->y);
|
fprintf(f, "pos: %d,%d\n",l->cell->x, l->cell->y);
|
||||||
|
fprintf(f, "level: %d\n",l->level);
|
||||||
|
// liefform will be cfeated after loading the above.
|
||||||
fprintf(f, "contr: %d\n",l->controller);
|
fprintf(f, "contr: %d\n",l->controller);
|
||||||
fprintf(f, "hp: %d/%d\n",l->hp, l->maxhp);
|
fprintf(f, "hp: %d/%d\n",l->hp, l->maxhp);
|
||||||
fprintf(f, "alive: %d\n",l->alive);
|
fprintf(f, "alive: %d\n",l->alive);
|
||||||
fprintf(f, "lastdam: %s\n",l->lastdam);
|
fprintf(f, "lastdam: %s\n",l->lastdam);
|
||||||
fprintf(f, "timespent: %d\n",l->timespent);
|
fprintf(f, "timespent: %d\n",l->timespent);
|
||||||
fprintf(f, "sorted: %d\n",l->sorted);
|
fprintf(f, "sorted: %d\n",l->sorted);
|
||||||
|
fprintf(f, "forgettimer: %f\n",l->forgettimer);
|
||||||
// lifeform objects
|
// lifeform objects
|
||||||
obcount = 0;
|
obcount = 0;
|
||||||
for (o = l->pack->first ; o ; o = o->next) {
|
for (o = l->pack->first ; o ; o = o->next) {
|
||||||
|
|
4
save.h
4
save.h
|
@ -1,10 +1,12 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
|
|
||||||
int loadall(void);
|
int loadall(void);
|
||||||
|
int loadknowledge(FILE *f);
|
||||||
lifeform_t *loadlf(FILE *f, cell_t *where);
|
lifeform_t *loadlf(FILE *f, cell_t *where);
|
||||||
map_t *loadmap(char *basefile);
|
map_t *loadmap(char *basefile);
|
||||||
int loadob(FILE *f, obpile_t *op);
|
int loadob(FILE *f, obpile_t *op, long *id);
|
||||||
int loadsavegame(void);
|
int loadsavegame(void);
|
||||||
|
int saveknowledge(FILE *f);
|
||||||
int savelf(FILE *f, lifeform_t *l);
|
int savelf(FILE *f, lifeform_t *l);
|
||||||
int savemap(map_t *m);
|
int savemap(map_t *m);
|
||||||
int saveob(FILE *f, object_t *o);
|
int saveob(FILE *f, object_t *o);
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "defs.h"
|
||||||
|
#include "flag.h"
|
||||||
|
#include "map.h"
|
||||||
|
#include "objects.h"
|
||||||
|
#include "text.h"
|
||||||
|
|
||||||
|
extern lifeform_t *player;
|
||||||
|
|
||||||
|
void dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target) {
|
||||||
|
char buf[BUFLEN];
|
||||||
|
if (spellid == OT_S_RNDTELEPORT) {
|
||||||
|
cell_t *c = NULL;
|
||||||
|
while (!c || c->type->solid) {
|
||||||
|
c = getrandomcell(target->cell->map);
|
||||||
|
}
|
||||||
|
if ((target->controller != C_PLAYER) && haslos(player, target->cell)) {
|
||||||
|
getlfname(target, buf);
|
||||||
|
capitalise(buf);
|
||||||
|
msg("%s disappears in a puff of smoke!", buf);
|
||||||
|
}
|
||||||
|
// TODO: add smoke
|
||||||
|
movelf(target, c);
|
||||||
|
// TODO: add more smoke
|
||||||
|
if (target->controller == C_PLAYER) {
|
||||||
|
msg("Suddenly, your surroundings appear different!");
|
||||||
|
} else if (haslos(player, target->cell)) {
|
||||||
|
getlfname(target, buf);
|
||||||
|
capitalise(buf);
|
||||||
|
msg("%s appears in a puff of smoke!", buf);
|
||||||
|
}
|
||||||
|
} else if (spellid == OT_S_MAPPING) {
|
||||||
|
int x,y;
|
||||||
|
map_t *m;
|
||||||
|
m = caster->cell->map;
|
||||||
|
// reveal map
|
||||||
|
for (y = 0; y < m->h; y++) {
|
||||||
|
for (x = 0; x < m->w; x++) {
|
||||||
|
cell_t *c;
|
||||||
|
c = getcellat(m, x, y);
|
||||||
|
c->known = B_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target->controller == C_PLAYER) {
|
||||||
|
msg("An image of your surroundings appears in your mind!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __SPELLS_H
|
||||||
|
#define __SPELLS_H
|
||||||
|
#include "defs.h"
|
||||||
|
|
||||||
|
void dospelleffects(lifeform_t *caster, enum OBTYPE spellid, lifeform_t *target);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
63
text.c
63
text.c
|
@ -24,9 +24,25 @@ int isvowel (char c) {
|
||||||
// allocates and returns new string
|
// allocates and returns new string
|
||||||
char *makeplural(char *text) {
|
char *makeplural(char *text) {
|
||||||
int newlen;
|
int newlen;
|
||||||
char *newtext;
|
|
||||||
char lastlet;
|
char lastlet;
|
||||||
|
char *newtext;
|
||||||
|
char *p;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
newtext = strdup(text);
|
||||||
|
|
||||||
|
// scrolls
|
||||||
|
rv = strrep(newtext, "scroll ", "scrolls ");
|
||||||
|
if (rv) return newtext;
|
||||||
|
rv = strrep(newtext, "potion ", "potions ");
|
||||||
|
if (rv) return newtext;
|
||||||
|
rv = strrep(newtext, "piece ", "pieces ");
|
||||||
|
if (rv) return newtext;
|
||||||
|
|
||||||
|
rv = strrep(newtext, "pair ", "pairs ");
|
||||||
|
// don't return
|
||||||
|
|
||||||
|
// default
|
||||||
lastlet = text[strlen(text)-1];
|
lastlet = text[strlen(text)-1];
|
||||||
switch (lastlet) {
|
switch (lastlet) {
|
||||||
case 's':
|
case 's':
|
||||||
|
@ -39,3 +55,48 @@ char *makeplural(char *text) {
|
||||||
}
|
}
|
||||||
return newtext;
|
return newtext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int strrep(char *text, char *oldtok, char *newtok) {
|
||||||
|
char *temp;
|
||||||
|
int rv;
|
||||||
|
temp = strdup(" ");
|
||||||
|
rv = dostrrep(text, &temp, oldtok, newtok);
|
||||||
|
// swap
|
||||||
|
text = realloc(text, strlen(temp));
|
||||||
|
strcpy(text, temp);
|
||||||
|
free(temp);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns TRUE if any replacements made
|
||||||
|
int dostrrep(char* in, char** out, char* oldtok, char* newtok) {
|
||||||
|
char *temp;
|
||||||
|
char *found = strstr(in, oldtok);
|
||||||
|
int idx;
|
||||||
|
if(!found) {
|
||||||
|
*out = realloc(*out, strlen(in) + 1);
|
||||||
|
strcpy(*out, in);
|
||||||
|
return B_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
idx = found - in;
|
||||||
|
|
||||||
|
*out = realloc(*out, strlen(in) - strlen(oldtok) + strlen(newtok) + 1);
|
||||||
|
strncpy(*out, in, idx);
|
||||||
|
strcpy(*out + idx, newtok);
|
||||||
|
strcpy(*out + idx + strlen(newtok), in + idx + strlen(oldtok));
|
||||||
|
|
||||||
|
temp = malloc(idx+strlen(newtok)+1);
|
||||||
|
strncpy(temp,*out,idx+strlen(newtok));
|
||||||
|
temp[idx + strlen(newtok)] = '\0';
|
||||||
|
|
||||||
|
dostrrep(found + strlen(oldtok), out, oldtok, newtok);
|
||||||
|
temp = realloc(temp, strlen(temp) + strlen(*out) + 1);
|
||||||
|
strcat(temp,*out);
|
||||||
|
free(*out);
|
||||||
|
*out = temp;
|
||||||
|
|
||||||
|
return B_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue