7125 lines
208 KiB
C
7125 lines
208 KiB
C
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "attack.h"
|
|
#include "defs.h"
|
|
#include "flag.h"
|
|
#include "io.h"
|
|
#include "lf.h"
|
|
#include "map.h"
|
|
#include "move.h"
|
|
#include "nexus.h"
|
|
#include "objects.h"
|
|
#include "spell.h"
|
|
#include "text.h"
|
|
|
|
extern knowledge_t *knowledge, *lastknowledge;
|
|
extern objecttype_t *objecttype,*lastobjecttype;
|
|
extern objectclass_t *objectclass,*lastobjectclass;
|
|
extern material_t *material,*lastmaterial;
|
|
|
|
extern object_t *retobs[MAXPILEOBS+1];
|
|
extern int retobscount[MAXPILEOBS+1];
|
|
extern int nretobs;
|
|
|
|
extern map_t *firstmap;
|
|
|
|
extern int gamestarted;
|
|
|
|
extern long curtime;
|
|
|
|
extern lifeform_t *player;
|
|
|
|
extern int reason;
|
|
|
|
extern int needredraw;
|
|
|
|
char *scrollname[] = {
|
|
"scroll titled ABRA CA DABRA",
|
|
"scroll titled BARBAR",
|
|
"scroll titled CRATOL JEM",
|
|
"scroll titled DELENTH YIN",
|
|
"scroll titled ETEE NOM",
|
|
"scroll titled FIE JOOHM",
|
|
"scroll titled GREE VII",
|
|
"scroll titled MARIGON",
|
|
"scroll titled MAXIMOR BLATHUS",
|
|
"scroll titled REZZ KINETO",
|
|
"scroll titled SHAZZARIO",
|
|
"scroll titled THERIUM LARGOS",
|
|
"scroll titled VOLTR YI MEN",
|
|
"scroll titled ZAREL NOR",
|
|
NULL
|
|
};
|
|
int numscrollnames;
|
|
|
|
char *potionname[] = {
|
|
// colours
|
|
"aqua potion",
|
|
"azure potion",
|
|
"blue potion",
|
|
"brown potion",
|
|
"clear potion",
|
|
"cyan potion",
|
|
"green potion",
|
|
"indigo potion",
|
|
"luminous potion", // should produce light
|
|
"magenta potion",
|
|
"orange potion",
|
|
"red potion",
|
|
"violet potion",
|
|
"yellow potion",
|
|
// other descriptions
|
|
"bubbling potion",
|
|
"fizzy potion",
|
|
"gluggy potion",
|
|
"steaming potion",
|
|
NULL
|
|
};
|
|
int numpotnames;
|
|
|
|
char *ringname[] = {
|
|
// gems
|
|
"ruby ring",
|
|
"diamond ring",
|
|
"emerald ring",
|
|
"silver ring",
|
|
"gold ring",
|
|
NULL
|
|
};
|
|
int numringnames;
|
|
|
|
char letorder[MAXPILEOBS] = {
|
|
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
|
|
};
|
|
|
|
objecttype_t *lastot = NULL;
|
|
|
|
enum OBCLASS sortorder[] = {
|
|
OC_EFFECT,
|
|
OC_DFEATURE,
|
|
OC_MONEY,
|
|
OC_WEAPON,
|
|
OC_ARMOUR,
|
|
OC_POTION,
|
|
OC_SCROLL,
|
|
OC_FOOD,
|
|
OC_CORPSE,
|
|
OC_RING,
|
|
OC_TECH,
|
|
OC_ROCK,
|
|
OC_MISC,
|
|
// omitting OC_SPELL and OC_JUMP because it shouldn't ever be displayed
|
|
OC_NULL
|
|
};
|
|
|
|
long nextoid = 0;
|
|
|
|
|
|
object_t *addemptyob(obpile_t *where, object_t *o) {
|
|
char buf[BUFLEN];
|
|
object_t *empty;
|
|
// determine what kind of empty container to drop
|
|
if (strstr(o->type->name, "vial")) {
|
|
strcpy(buf, "empty vial");
|
|
} else {
|
|
strcpy(buf, "empty flask");
|
|
}
|
|
|
|
empty = addob(where, buf);
|
|
if (!empty) {
|
|
// try to drop on ground
|
|
if (where->owner) {
|
|
empty = addob(where->owner->cell->obpile, buf);
|
|
if (empty) {
|
|
char emptyname[BUFLEN];
|
|
getobname(empty, emptyname, 1);
|
|
if (isplayer(where->owner)) {
|
|
msg("You drop the %s on the ground.", noprefix(emptyname));
|
|
} else if (haslos(player, where->owner->cell)) {
|
|
getlfname(where->owner, buf);
|
|
capitalise(buf);
|
|
msg("%s drops the %s on the ground.", buf, noprefix(emptyname));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return empty;
|
|
}
|
|
|
|
knowledge_t *addknowledge(enum OBCLASS id, char *hiddenname, int known) {
|
|
knowledge_t *a;
|
|
|
|
// add to the end of the list
|
|
if (knowledge == NULL) {
|
|
knowledge = malloc(sizeof(knowledge_t));
|
|
a = knowledge;
|
|
a->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
a = lastknowledge;
|
|
a->next = malloc(sizeof(knowledge_t));
|
|
a->next->prev = a;
|
|
a = a->next;
|
|
}
|
|
lastknowledge = a;
|
|
a->next = NULL;
|
|
|
|
// props
|
|
a->id = id;
|
|
a->hiddenname = strdup(hiddenname);
|
|
a->known = known;
|
|
|
|
return a;
|
|
}
|
|
|
|
|
|
|
|
material_t *addmaterial(enum MATERIAL id, char *name, float weightrating) {
|
|
material_t *a;
|
|
|
|
// add to the end of the list
|
|
if (material == NULL) {
|
|
material = malloc(sizeof(material_t));
|
|
a = material;
|
|
a->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
a = lastmaterial;
|
|
a->next = malloc(sizeof(material_t));
|
|
a->next->prev = a;
|
|
a = a->next;
|
|
}
|
|
lastmaterial = a;
|
|
a->next = NULL;
|
|
|
|
// props
|
|
a->id = id;
|
|
a->name = strdup(name);
|
|
a->weightrating = weightrating;
|
|
|
|
a->flags = addflagpile(NULL, NULL);
|
|
return a;
|
|
}
|
|
|
|
objectclass_t *addoc(enum OBCLASS id, char *name, char *desc, char glyph) {
|
|
objectclass_t *a;
|
|
|
|
// add to the end of the list
|
|
if (objectclass == NULL) {
|
|
objectclass = malloc(sizeof(objectclass_t));
|
|
a = objectclass;
|
|
a->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
a = lastobjectclass;
|
|
a->next = malloc(sizeof(objectclass_t));
|
|
a->next->prev = a;
|
|
a = a->next;
|
|
}
|
|
lastobjectclass = a;
|
|
a->next = NULL;
|
|
|
|
// props
|
|
a->id = id;
|
|
a->name = strdup(name);
|
|
a->desc = strdup(desc);
|
|
a->glyph = glyph;
|
|
a->flags = addflagpile(NULL, NULL);
|
|
|
|
return a;
|
|
}
|
|
|
|
|
|
|
|
// create a new object, stacking ok
|
|
object_t *addob(obpile_t *where, char *name) {
|
|
return addobject(where, name, B_TRUE);
|
|
}
|
|
|
|
// create a new object
|
|
// if canstack is true, we are allwoed
|
|
// to join similar objects together instead of
|
|
// creating new obejct entries.
|
|
object_t *addobject(obpile_t *where, char *name, int canstack) {
|
|
objecttype_t *ot;
|
|
object_t *o = NULL;
|
|
char *p,*nsp;
|
|
char numstringmin[BUFLEN];
|
|
char numstringmax[BUFLEN];
|
|
int howmany = 1;
|
|
int i;
|
|
int db = B_FALSE;
|
|
//flag_t *f;
|
|
char *localname;
|
|
int wantblessed = B_UNCURSED;
|
|
|
|
|
|
localname = strdup(name);
|
|
|
|
if (db) {
|
|
dblog("DB: called addobject() for %s, canstack = %d",localname, canstack);
|
|
}
|
|
|
|
if (where->owner && hasflag(where->owner->flags, F_NOPACK)) {
|
|
if (db) dblog("error giving ob '%s' - owner isn't allowed to carry objects!", name);
|
|
return NULL;
|
|
}
|
|
|
|
// we CAN place objects in solid cells - for example,
|
|
// placing a fire on top of a wooden door.
|
|
/*
|
|
if (where->where) {
|
|
if (where->where->type != (celltype_t *)DUMMYCELLTYPE) {
|
|
assert(!where->where->type->solid);
|
|
}
|
|
}
|
|
*/
|
|
|
|
// parse name string
|
|
nsp = numstringmin;
|
|
for (p = localname ; isdigit(*p) ; p++) {
|
|
*nsp = *p;
|
|
nsp++;
|
|
}
|
|
*nsp = '\0';
|
|
|
|
// we have a range...
|
|
if (*p == '-') {
|
|
nsp = numstringmax;
|
|
p++;
|
|
for ( ; isdigit(*p) ; p++) {
|
|
*nsp = *p;
|
|
nsp++;
|
|
}
|
|
*nsp = '\0';
|
|
} else {
|
|
strcpy(numstringmax,numstringmin);
|
|
}
|
|
|
|
|
|
// are we giving multiple objects?
|
|
if (strlen(numstringmin) > 0) {
|
|
int min,max;
|
|
// first increment name string pointer
|
|
// past any spaces
|
|
while (!isalpha(*p)) p++;
|
|
|
|
// now figure out how many
|
|
min = atoi(numstringmin);
|
|
max = atoi(numstringmax);
|
|
if (min == max) {
|
|
howmany = min;
|
|
} else {
|
|
howmany = rnd(min,max);
|
|
}
|
|
} else {
|
|
howmany = 1;
|
|
}
|
|
|
|
|
|
// new objects after the game starts have unknown
|
|
// blessed/cursed status, so we can never stack them
|
|
// if (gamestarted && !hasflag(player->flags, F_DETECTAURAS)) {
|
|
if (strstr(p, "blessed") || strstr(p, "holy water")) {
|
|
if (db) dblog("DB: ob is blessed (%s)",p);
|
|
wantblessed = B_BLESSED;
|
|
//canstack = B_FALSE;
|
|
} else if (strstr(p, "cursed") || strstr(p, "incompetence")) {
|
|
if (db) dblog("DB: ob is cursed (%s)",p);
|
|
wantblessed = B_CURSED;
|
|
//canstack = B_FALSE;
|
|
}
|
|
// }
|
|
|
|
// make sure we can find the requested object type
|
|
if (db) dblog("DB: Looking for object name '%s'", p );
|
|
ot = findotn(p);
|
|
if (!ot) {
|
|
//if (gamestarted) msg("DB: No match for object name '%s'", p );
|
|
if (db) dblog("DB: No match for object name '%s'", p );
|
|
return NULL;
|
|
}
|
|
if (db) dblog("DB: FOUND: ot->name = '%s'", ot->name );
|
|
|
|
// don't give nopickup objects to lifeforms
|
|
if (hasflag(ot->flags, F_NOPICKUP) && where->owner) {
|
|
return NULL;
|
|
}
|
|
|
|
if (ot->obclass->id == OC_SPELL) {
|
|
if (db) dblog("DB: Cannot give a spell object! object name '%s'", p );
|
|
return NULL;
|
|
}
|
|
|
|
// override canstack if required
|
|
if (!hasflag(ot->flags, F_STACKABLE)) {
|
|
if (db) dblog("DB: setting canstack = false, objecttype '%s' not stackable", ot->name );
|
|
canstack = B_FALSE;
|
|
}
|
|
|
|
|
|
// special checks for unique objects
|
|
if (hasflag(ot->flags, F_UNIQUE)) {
|
|
// does this unique ob already exist?
|
|
if (obexists(ot->id)) {
|
|
if (db) dblog("DB: Unique ob %s already exists!", p );
|
|
return NULL;
|
|
}
|
|
|
|
// otherwise make sure we are only getting one
|
|
howmany = 1;
|
|
}
|
|
|
|
if (db) dblog("DB: '%s' -> adding %d x %s",name, howmany, ot->name);
|
|
|
|
for (i = 0; i < howmany; i++) {
|
|
int added = B_FALSE;
|
|
if (canstack) {
|
|
object_t *existob;
|
|
if (db) dblog("DB: Looking for stacks...");
|
|
// TODO: if object is stackable
|
|
// TODO: if (hasflag(ob,stackable) && hasobject(where, ot)) {
|
|
// does the pile already contain one?
|
|
existob = canstacknewot(where, ot);
|
|
if (existob) {
|
|
if (db) dblog("DB: STACK FOUND (%d x %s). Adding %d obs to existing stack.",existob->amt, existob->type->name, howmany);
|
|
existob->amt++;
|
|
added = B_TRUE;
|
|
o = existob;
|
|
} else {
|
|
if (db) dblog("DB: No stacks found.");
|
|
}
|
|
}
|
|
|
|
if (!added) {
|
|
flag_t *f;
|
|
if (db) dblog("DB: Creating new object (%s).",ot->name);
|
|
|
|
// otherwise add to list
|
|
if (where->first == NULL) {
|
|
where->first = malloc(sizeof(object_t));
|
|
o = where->first;
|
|
o->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
o = where->last;
|
|
o->next = malloc(sizeof(object_t));
|
|
o->next->prev = o;
|
|
o = o->next;
|
|
}
|
|
where->last = o;
|
|
|
|
o->next = NULL;
|
|
|
|
// fill in props
|
|
o->id = nextoid++; // increment next ob id
|
|
o->type = ot;
|
|
o->pile = where;
|
|
|
|
o->birthtime = curtime;
|
|
|
|
// inherit props from objecttype
|
|
o->material = ot->material;
|
|
assert(o->material);
|
|
o->weight = ot->weight;
|
|
o->flags = addflagpile(NULL, o);
|
|
|
|
o->inscription = NULL; // non-inherited
|
|
|
|
// inherit flags from objecttype
|
|
copyflags(o->flags, ot->flags, NA);
|
|
|
|
// random flags...
|
|
f = hasflag(o->flags, F_RNDCHARGES);
|
|
if (f) {
|
|
int amt;
|
|
flag_t *chargeflag;
|
|
amt = rnd(f->val[0], f->val[1]);
|
|
chargeflag = hasflag(o->flags, F_CHARGES);
|
|
if (chargeflag) {
|
|
chargeflag->val[0] = amt;
|
|
chargeflag->val[1] = amt;
|
|
chargeflag->known = B_FALSE;
|
|
} else {
|
|
chargeflag = addflag_real(o->flags, F_CHARGES, amt, amt, NA, NULL, PERMENANT, B_UNKNOWN);
|
|
}
|
|
}
|
|
|
|
// non-inherited from here on:
|
|
// if adding to a player...
|
|
if (where->owner) {
|
|
if (o->type->obclass->id == OC_MONEY) {
|
|
o->letter = '$';
|
|
} else {
|
|
o->letter = getnextletter(where, NULL);
|
|
}
|
|
} else {
|
|
// new object on the ground - has no letter yet.
|
|
o->letter = '\0';
|
|
}
|
|
|
|
if (canstack) {
|
|
// add the full amount!
|
|
o->amt = howmany;
|
|
} else {
|
|
o->amt = 1;
|
|
}
|
|
|
|
|
|
if (hasflag(o->flags, F_NOBLESS)) {
|
|
setblessed(o, B_UNCURSED);
|
|
} else {
|
|
setblessed(o, wantblessed);
|
|
}
|
|
o->blessknown = B_FALSE;
|
|
if (canstack) {
|
|
// stop looping through
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (o) {
|
|
char *p2;
|
|
int bonus = 0;
|
|
// check for premods. eg. "flaming xxx"
|
|
if (strstr(name, "flaming ")) {
|
|
addflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL);
|
|
if (o->type->obclass->id == OC_WEAPON) {
|
|
if (!hasflagval(o->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL)) {
|
|
addflag(o->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check for bonuses. eg. "+1"
|
|
p2 = strchr(p, '+');
|
|
if (p2) {
|
|
char *p3;
|
|
char numbuf[BUFLENSMALL];
|
|
p3 = numbuf;
|
|
|
|
p2++;
|
|
|
|
while (isdigit(*p2)) {
|
|
*p3 = *p2;
|
|
p2++;
|
|
p3++;
|
|
}
|
|
*p3 = '\0';
|
|
|
|
bonus += atoi(numbuf);
|
|
}
|
|
// check for penalties. eg. "-1"
|
|
p2 = strchr(p, '-');
|
|
if (p2) {
|
|
char *p3;
|
|
char numbuf[BUFLENSMALL];
|
|
p3 = numbuf;
|
|
|
|
p2++;
|
|
|
|
while (isdigit(*p2)) {
|
|
*p3 = *p2;
|
|
p2++;
|
|
p3++;
|
|
}
|
|
*p3 = '\0';
|
|
|
|
bonus -= atoi(numbuf);
|
|
}
|
|
|
|
addflag_real(o->flags, F_BONUS, bonus, NA, NA, NULL, PERMENANT, B_UNKNOWN);
|
|
|
|
// check for postmods. eg. "xxx of pyromania"
|
|
if (strstr(name, " of pyromania")) {
|
|
addflag_real(o->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN);
|
|
}
|
|
}
|
|
|
|
|
|
free(localname);
|
|
|
|
if (where->owner) {
|
|
// new owner gains "hold confer" flags conferred by this object
|
|
giveobflags(where->owner, o, F_HOLDCONFER);
|
|
}
|
|
|
|
// special cases
|
|
if (o->type->id == OT_VENDINGMACHINE) {
|
|
char buf[BUFLEN];
|
|
cell_t *loc;
|
|
loc = getoblocation(o);
|
|
// populate with objects
|
|
for (i = 0; i < 10; i++) {
|
|
objecttype_t *ot2;
|
|
strcpy(buf, "");
|
|
while (!strcmp(buf, "")) {
|
|
real_getrandomob(loc->map, buf, RO_NONE, NA, loc->map->depth + rnd(10,15));
|
|
// make sure you can hold it
|
|
ot2 = findotn(buf);
|
|
if (!ot2 || hasflag(ot2->flags, F_NOPICKUP)) {
|
|
strcpy(buf, "");
|
|
}
|
|
}
|
|
|
|
// replace "1 potion" with "a potion"
|
|
if (strstr(buf, "1 ") == buf) {
|
|
char temp[BUFLEN];
|
|
strcpy(temp, buf);
|
|
sprintf(buf, "a %s",temp + 2);
|
|
}
|
|
addflag(o->flags, F_CONTAINSOB, 'a' + i, NA, NA, buf);
|
|
}
|
|
}
|
|
|
|
// return the last object given
|
|
return o;
|
|
}
|
|
|
|
obpile_t *addobpile(lifeform_t *owner, cell_t *where) {
|
|
obpile_t *op;
|
|
op = malloc(sizeof(obpile_t));
|
|
op->first = NULL;
|
|
op->last = NULL;
|
|
op->owner = owner;
|
|
op->where = where;
|
|
|
|
return op;
|
|
}
|
|
|
|
|
|
objecttype_t *addot(int id, char *name, char *description, int material, float weight, int obclassid) {
|
|
objecttype_t *a, *ot;
|
|
//flag_t *f;
|
|
|
|
// does this ob already exist?
|
|
ot = findot(id);
|
|
assert(!ot);
|
|
|
|
// add to the end of the list
|
|
if (objecttype == NULL) {
|
|
objecttype = malloc(sizeof(objecttype_t));
|
|
a = objecttype;
|
|
a->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
a = lastobjecttype;
|
|
a->next = malloc(sizeof(objecttype_t));
|
|
a->next->prev = a;
|
|
a = a->next;
|
|
}
|
|
lastobjecttype = a;
|
|
a->next = NULL;
|
|
|
|
// props
|
|
a->id = id;
|
|
a->name = strdup(name);
|
|
a->desc = strdup(description);
|
|
a->material = findmaterial(material);
|
|
a->weight = weight;
|
|
a->obclass = findoc(obclassid);
|
|
a->flags = addflagpile(NULL, NULL);
|
|
// inherit flags from object class
|
|
/*
|
|
for (f = a->obclass->flags->first ; f ; f = f->next) {
|
|
addflag(a->flags, f->id, f->val[0], f->val[1], f->val[2], f->text);
|
|
}
|
|
*/
|
|
copyflags(a->flags, a->obclass->flags, NA);
|
|
if (a->material) {
|
|
// inherit flags from material
|
|
/*
|
|
for (f = a->material->flags->first ; f ; f = f->next) {
|
|
addflag(a->flags, f->id, f->val[0], f->val[1], f->val[2], f->text);
|
|
}
|
|
*/
|
|
copyflags(a->flags, a->material->flags, FROMMAT);
|
|
}
|
|
|
|
// for easy addition of flags
|
|
lastot = a;
|
|
return a;
|
|
}
|
|
|
|
// adjust damage based on material being damaged
|
|
void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat) {
|
|
// adjust based on material
|
|
if (mat == MT_GAS) {
|
|
switch (damtype) {
|
|
case DT_HOLY:
|
|
case DT_DIRECT:
|
|
case DT_NONE:
|
|
break;
|
|
default:
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
}
|
|
|
|
// adjust based on damage type
|
|
if (damtype == DT_FIRE) {
|
|
switch (mat) {
|
|
case MT_PAPER:
|
|
*dam *= 3;
|
|
break;
|
|
case MT_WOOD:
|
|
case MT_ICE:
|
|
case MT_SLIME:
|
|
*dam *= 2;
|
|
break;
|
|
case MT_METAL:
|
|
case MT_BONE:
|
|
case MT_STONE:
|
|
case MT_BLOOD:
|
|
case MT_FIRE: // immune to itself
|
|
*dam = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (damtype == DT_CHOP) {
|
|
switch (mat) {
|
|
case MT_WOOD:
|
|
*dam *= 2;
|
|
break;
|
|
case MT_SLIME:
|
|
*dam /= 2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (damtype == DT_SLASH) {
|
|
switch (mat) {
|
|
case MT_WOOD:
|
|
case MT_SLIME:
|
|
case MT_BONE:
|
|
*dam /= 2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (damtype == DT_PIERCE) {
|
|
switch (mat) {
|
|
case MT_WOOD:
|
|
case MT_SLIME:
|
|
case MT_BONE:
|
|
*dam /= 2;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if (damtype == DT_BASH) {
|
|
switch (mat) {
|
|
case MT_PAPER:
|
|
*dam = 0;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) {
|
|
// objects can't get hurt the turn they
|
|
// were created.
|
|
if (o->birthtime == curtime) {
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
// only some objects can be hurt
|
|
if (!hasflag(o->flags, F_DAMAGABLE)) {
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
// immune?
|
|
if (hasflagval(o->flags, F_DTIMMUNE, damtype, NA, NA, NULL)) {
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
// poison gas never hurts objects
|
|
if (damtype == DT_POISONGAS) {
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
|
|
// adjust damage
|
|
if (o->blessed == B_BLESSED) {
|
|
// change of no hp loss
|
|
if (rnd(1,2) == 1) {
|
|
lifeform_t *owner;
|
|
owner = o->pile->owner;
|
|
if (owner && isplayer(owner)) {
|
|
// become known if owned by player
|
|
if (!isblessknown(o)) {
|
|
char obname[BUFLEN];
|
|
getobname(o, obname, o->amt);
|
|
msg("Your %s pulses with holy light as it is struck!",noprefix(obname));
|
|
}
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
return;
|
|
}
|
|
} else if (o->blessed == B_CURSED) {
|
|
// chance of double damage!
|
|
if (rnd(1,2) == 1) {
|
|
lifeform_t *owner;
|
|
(*dam) *= 2;
|
|
owner = o->pile->owner;
|
|
if (owner && (owner->controller == C_PLAYER)) {
|
|
// become known if a player's
|
|
if (!isblessknown(o)) {
|
|
char obname[BUFLEN];
|
|
getobname(o, obname, o->amt);
|
|
msg("Your %s emits a wave of dread as it is struck!",noprefix(obname));
|
|
}
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// adjust damage for material too
|
|
adjustdammaterial(dam, damtype, o->material->id);
|
|
}
|
|
|
|
// adjust price for magical effects etc
|
|
/*
|
|
void adjustprice(objecttype_t *ot, float *price) {
|
|
int min,max;
|
|
flag_t *f;
|
|
|
|
// bonuses/penalties
|
|
|
|
}
|
|
*/
|
|
|
|
void appendinscription(object_t *o, char *text) {
|
|
if (o->inscription) {
|
|
int len;
|
|
char *buf;
|
|
len = strlen(o->inscription) + strlen(text) + 1;
|
|
if (len > BUFLEN) len = BUFLEN;
|
|
buf = malloc(len * sizeof(char));
|
|
snprintf(buf, len, "%s%s",o->inscription, text);
|
|
setinscription(o, buf);
|
|
free(buf);
|
|
} else {
|
|
setinscription(o, text);
|
|
}
|
|
}
|
|
|
|
|
|
int blessob(object_t *o) {
|
|
char obname[BUFLEN];
|
|
int rv = B_FALSE;
|
|
lifeform_t *owner;
|
|
|
|
getobname(o, obname, o->amt);
|
|
|
|
switch (o->blessed) {
|
|
case B_BLESSED:
|
|
rv = B_TRUE;
|
|
break;
|
|
case B_CURSED:
|
|
case B_UNCURSED:
|
|
setblessed(o, B_BLESSED);
|
|
break;
|
|
}
|
|
|
|
if (rv == B_FALSE) {
|
|
int seen = B_FALSE;
|
|
owner = o->pile->owner;
|
|
if (owner) {
|
|
if (isplayer(owner)) {
|
|
msg("Your %s is bathed in a divine glow!", noprefix(obname));
|
|
seen = B_TRUE;
|
|
} else if (haslos(player, owner->cell)) {
|
|
char ownername[BUFLEN];
|
|
msg("%s%s %s is bathed in a divine glow!", ownername, getpossessive(ownername),
|
|
noprefix(obname));
|
|
seen = B_TRUE;
|
|
}
|
|
} else if (haslos(player, o->pile->where)) {
|
|
msg("%s is bathed in a divine glow!", obname);
|
|
seen = B_TRUE;
|
|
}
|
|
|
|
if (seen) {
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
void brightflash(cell_t *centre, int range, lifeform_t *immunelf) {
|
|
int x,y;
|
|
cell_t *c;
|
|
|
|
animradial(centre, range, '}');
|
|
|
|
// announce
|
|
if (haslos(player, centre) && !isblind(player)) {
|
|
msg("You see an intense flash of light!");
|
|
}
|
|
/*
|
|
if (getcelldist(player->cell, centre) <= range) {
|
|
// player is in range but can't see - announce it beacuse it
|
|
// will make you deaf!
|
|
youhear(centre, "a deafening bang!");
|
|
} else { // not in range of the flash
|
|
youhear(centre, "a loud bang!");
|
|
}
|
|
*/
|
|
// blind monsters
|
|
for (y = centre->y - range; y <= centre->y + range; y++) {
|
|
for (x = centre->x - range; x <= centre->x + range; x++) {
|
|
c = getcellat(centre->map, x, y);
|
|
if (c) {
|
|
lifeform_t *lf;
|
|
lf = haslf(c);
|
|
if (lf && (lf != immunelf)) {
|
|
if (haslos(lf, centre) && !isblind(lf)) {
|
|
if (!isplayer(lf)) { // we'll blind the player last
|
|
if (!eyesshaded(lf)) {
|
|
if (lfhasflag(lf, F_SEEINDARK)) {
|
|
// blind for 20-30 turns
|
|
addtempflag(lf->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(20,30));
|
|
} else {
|
|
// blind for 5-10 turns
|
|
addtempflag(lf->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10));
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// TODO: deafen
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// handle the player last, so that you see all the
|
|
// 'xx is blinded' messages before losing your own
|
|
// sight.
|
|
if (player != immunelf) {
|
|
if (haslos(player, centre) && (getcelldist(player->cell, centre) <= range) && !isblind(player)) {
|
|
if (!eyesshaded(player)) {
|
|
if (lfhasflag(player, F_SEEINDARK)) {
|
|
msg("You eyes feel like they are burning!");
|
|
addtempflag(player->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(20,30));
|
|
} else {
|
|
addtempflag(player->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// does the pile "op" have an object we can
|
|
// stack "o" with
|
|
object_t *canstackob(obpile_t *op, object_t *match) {
|
|
object_t *o;
|
|
if (!hasflag(match->flags, F_STACKABLE)) {
|
|
return NULL;
|
|
}
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o != match) {
|
|
if (obpropsmatch(o, match)) return o;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// does the pile "op" have an object we can
|
|
// stack a new object of type "ot" with
|
|
object_t *canstacknewot(obpile_t *op, objecttype_t *match) {
|
|
object_t *o;
|
|
if (!hasflag(match->flags, F_STACKABLE)) {
|
|
return NULL;
|
|
}
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->type == match) {
|
|
if (isplainob(o)) return o;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int changemat(object_t *o, enum MATERIAL mat) {
|
|
material_t *m;
|
|
flag_t *f, *nextf;
|
|
|
|
|
|
m = findmaterial(mat);
|
|
if (!m) {
|
|
return E_FAILED;
|
|
}
|
|
|
|
if (o->material->id == mat) return E_NOEFFECT;
|
|
|
|
// won't work on pyromania objects
|
|
f = hasflag(o->flags, F_FLAMESTRIKE);
|
|
if (f) {
|
|
if (isplayer(o->pile->owner)) {
|
|
f->known = B_TRUE;
|
|
} else if (o->pile->owner && haslos(player, o->pile->owner->cell)) {
|
|
f->known = B_TRUE;
|
|
} else if (haslos(player, o->pile->where)) {
|
|
f->known = B_TRUE;
|
|
}
|
|
return E_NOEFFECT;
|
|
}
|
|
|
|
// remove flags which came from old material
|
|
for (f = o->flags->first ; f; f = nextf) {
|
|
nextf = f->next;
|
|
if (f->lifetime == FROMMAT) {
|
|
killflag(f);
|
|
}
|
|
}
|
|
|
|
// change material
|
|
o->material = m;
|
|
|
|
// inherit flags from new material
|
|
copyflags(m->flags, o->flags, FROMMAT);
|
|
|
|
if (mat == MT_ICE) {
|
|
// if it turned to ice..
|
|
|
|
// it stops burning
|
|
extinguish(o);
|
|
|
|
// it will melt...
|
|
if (!hasflag(o->flags, F_OBHP)) {
|
|
int myhp;
|
|
// give hp
|
|
myhp = getobweight(o) * 20;
|
|
if (myhp <= 0) myhp = 2;
|
|
|
|
addtempflag(o->flags, F_OBHP, myhp, myhp, NA, NULL, FROMMAT);
|
|
}
|
|
if (!hasflag(o->flags, F_DAMAGABLE)) {
|
|
addtempflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL, FROMMAT);
|
|
}
|
|
// make it melt
|
|
addtempflag(o->flags, F_OBHPDRAIN, 1, DT_MELT, NA, NULL, FROMMAT);
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
void copyobprops(object_t *dst, object_t *src) {
|
|
dst->material = src->material;
|
|
dst->weight = src->weight;
|
|
if (src->inscription) {
|
|
dst->inscription = strdup(src->inscription);
|
|
}
|
|
setblessed(dst, src->blessed);
|
|
dst->blessknown = src->blessknown;
|
|
|
|
// copy flags
|
|
while (dst->flags->first) {
|
|
killflag(dst->flags->first);
|
|
}
|
|
copyflags(dst->flags, src->flags, NA);
|
|
|
|
}
|
|
|
|
int countnames(char **list) {
|
|
int count;
|
|
for (count = 0; list[count]; count++);
|
|
return count;
|
|
}
|
|
|
|
int countobs(obpile_t *op) {
|
|
object_t *o;
|
|
|
|
int count = 0;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
int curseob(object_t *o) {
|
|
int rv = B_FALSE;
|
|
switch (o->blessed) {
|
|
case B_BLESSED:
|
|
setblessed(o, B_UNCURSED);
|
|
break;
|
|
case B_CURSED:
|
|
rv = B_TRUE;
|
|
break;
|
|
case B_UNCURSED:
|
|
setblessed(o, B_CURSED);
|
|
break;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
void damageallobs(object_t *exception, obpile_t *op, int howmuch, int damtype) {
|
|
object_t *o, *nexto;
|
|
for (o = op->first ; o ; o = nexto) {
|
|
nexto = o->next;
|
|
if ((o != exception) && !hasflag(o->flags, F_DEAD)) {
|
|
takedamage(o, howmuch, damtype);
|
|
}
|
|
}
|
|
}
|
|
|
|
void explodeob(object_t *o, flag_t *f, int bigness) {
|
|
cell_t *c;
|
|
int dam;
|
|
char obname[BUFLEN];
|
|
|
|
dam = f->val[0];
|
|
c = getoblocation(o);
|
|
getobname(o, obname, o->amt);
|
|
|
|
// announce
|
|
if (o->pile->owner) {
|
|
if (isplayer(o->pile->owner)) {
|
|
msg("Your %s explodes!", noprefix(obname));
|
|
} else if (haslos(player, o->pile->owner->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(o->pile->owner, lfname);
|
|
msg("%s%s %s explodes!", lfname, getpossessive(lfname), noprefix(obname));
|
|
}
|
|
} else if (haslos(player, c)) {
|
|
msg("%s explodes!", obname);
|
|
}
|
|
explodecells(c, dam, bigness ? B_TRUE : B_FALSE, o, bigness ? 1 : 0, B_FALSE);
|
|
|
|
// hurt everything!
|
|
/*
|
|
if (bigness) {
|
|
int dir;
|
|
cell_t *cc;
|
|
explodecell(c, dam, (bigness) ? B_TRUE : B_FALSE, NULL);
|
|
for (dir = DC_N; dir <= DC_NW; dir++) {
|
|
cc = getcellindir(c, dir);
|
|
}
|
|
} else {
|
|
explodecell(c, dam, (bigness) ? B_TRUE : B_FALSE, NULL);
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
void extinguish(object_t *o) {
|
|
flag_t *f;
|
|
char obname[BUFLEN];
|
|
f = hasflag(o->flags, F_ONFIRE);
|
|
getobname(o, obname, o->amt);
|
|
if (f) {
|
|
if (o->pile->owner) {
|
|
if (isplayer(o->pile->owner)) {
|
|
msg("Your %s %s extinguished.", noprefix(obname),
|
|
(o->amt == 1) ? "is" : "are");
|
|
} else if (haslos(player, o->pile->owner->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(o->pile->owner, lfname);
|
|
msg("%s%s %s %s extinguished.", lfname, getpossessive(lfname), noprefix(obname),
|
|
(o->amt == 1) ? "is" : "are");
|
|
}
|
|
} else if (o->pile->where && haslos(player, o->pile->where)) {
|
|
getobname(o, obname, o->amt);
|
|
msg("%s %s extinguished.", obname,
|
|
(o->amt == 1) ? "is" : "are");
|
|
}
|
|
killflag(f);
|
|
}
|
|
}
|
|
|
|
material_t *findmaterial(int id) {
|
|
material_t *m;
|
|
for (m = material ; m ; m = m->next) {
|
|
if (m->id == id) return m;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
objectclass_t *findoc(int id) {
|
|
objectclass_t *oc;
|
|
for (oc = objectclass ; oc ; oc = oc->next) {
|
|
if (oc->id == id) return oc;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
object_t *findobl(obpile_t *op, char let) {
|
|
object_t *o;
|
|
for (o = op->first; o ; o = o->next) {
|
|
if (o->letter == let) return o;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
objecttype_t *findot(enum OBTYPE id) {
|
|
objecttype_t *ot;
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (ot->id == id) return ot;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
objecttype_t *findotn(char *name) {
|
|
objecttype_t *ot;
|
|
char *searchfor, *modname;
|
|
char *p;
|
|
modname = strdup(name);
|
|
|
|
// make some replacements
|
|
//replace scrolls with scroll etc
|
|
modname = strrep(modname, "berries ", "berry ", NULL);
|
|
modname = strrep(modname, "blocks ", "block ", NULL);
|
|
modname = strrep(modname, "cans ", "can ", NULL);
|
|
modname = strrep(modname, "chunks ", "chunk ", NULL);
|
|
modname = strrep(modname, "gems ", "gem ", NULL);
|
|
modname = strrep(modname, "loaves ", "load ", NULL);
|
|
modname = strrep(modname, "lumps ", "lump ", NULL);
|
|
modname = strrep(modname, "pieces ", "piece ", NULL);
|
|
modname = strrep(modname, "piles ", "pile ", NULL);
|
|
modname = strrep(modname, "pools ", "pool ", NULL);
|
|
modname = strrep(modname, "potions ", "potion ", NULL);
|
|
modname = strrep(modname, "puddles ", "puddle ", NULL);
|
|
modname = strrep(modname, "rings ", "ring ", NULL);
|
|
modname = strrep(modname, "scrolls ", "scroll ", NULL);
|
|
modname = strrep(modname, "vials ", "vial ", NULL);
|
|
|
|
// only at start...
|
|
if (strstr(modname, "the ") == modname) modname = strrep(modname, "the ", "", NULL);
|
|
if (strstr(modname, "an ") == modname) modname = strrep(modname, "an ", "", NULL);
|
|
if (strstr(modname, "a ") == modname) modname = strrep(modname, "a ", "", NULL);
|
|
|
|
modname = strrep(modname, "blessed ", "", NULL);
|
|
modname = strrep(modname, "uncursed ", "", NULL);
|
|
modname = strrep(modname, "cursed ", "", NULL);
|
|
//realloc(modname, strlen(temp)); strcpy(modname, temp); free(temp); // swap
|
|
|
|
// strip out extra mods
|
|
modname = strrep(modname, "flaming ", "", NULL);
|
|
modname = strrep(modname, " of pyromania", "", NULL);
|
|
|
|
// special cases
|
|
modname = strrep(modname, "holy water", "water", NULL);
|
|
modname = strrep(modname, "incompetence", "competence", NULL);
|
|
|
|
// skip past bonusses
|
|
p = strchr(modname, '+');
|
|
if (p) {
|
|
while (!isalpha(*p)) {
|
|
p++;
|
|
}
|
|
strcpy(modname, p);
|
|
}
|
|
p = strchr(modname, '-');
|
|
if (p) {
|
|
while (!isalpha(*p)) {
|
|
p++;
|
|
}
|
|
strcpy(modname, p);
|
|
}
|
|
|
|
dblog("findotn(): modname is '%s'",modname);
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
// check for exact matches first...
|
|
if (!strcmp(ot->name, modname)) {
|
|
free(modname);
|
|
// found it!
|
|
return ot;
|
|
}
|
|
}
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
// then partial matches
|
|
if (strstr(ot->name, modname)) {
|
|
free(modname);
|
|
// found it!
|
|
return ot;
|
|
}
|
|
}
|
|
|
|
searchfor = strdup(modname);
|
|
|
|
// haven't found it yet - check for plurals
|
|
// search for words ending in "es" (eg. tomatoes)
|
|
if ((searchfor[strlen(searchfor)-1] == 's') &&
|
|
(searchfor[strlen(searchfor)-2] == 'e') ) {
|
|
// remove trailing 'es'
|
|
searchfor[strlen(searchfor)-1] = '\0';
|
|
searchfor[strlen(searchfor)-2] = '\0';
|
|
dblog("findotn(): searchfor without 'es' is '%s'",searchfor);
|
|
// search again
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (strstr(ot->name, searchfor)) {
|
|
free(modname);
|
|
free(searchfor);
|
|
return ot;
|
|
}
|
|
}
|
|
}
|
|
// reset back to inital word
|
|
free(searchfor);
|
|
searchfor = strdup(modname);
|
|
|
|
// search for words ending in "s" (eg. "swords")
|
|
if (searchfor[strlen(searchfor)-1] == 's') {
|
|
// remove trailing 's'
|
|
searchfor[strlen(searchfor)-1] = '\0';
|
|
dblog("findotn(): searchfor without 's' is '%s'",searchfor);
|
|
// search again
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (strstr(ot->name, searchfor)) {
|
|
free(modname);
|
|
free(searchfor);
|
|
return ot;
|
|
}
|
|
}
|
|
}
|
|
free(modname);
|
|
free(searchfor);
|
|
return NULL;
|
|
}
|
|
|
|
// ie. "the apple is xxx"
|
|
// ie. "the apples are xxx"
|
|
char *getfillingname(int nutrition) {
|
|
if (nutrition > 100) {
|
|
return "extremely substantial";
|
|
} else if (nutrition >= 90) {
|
|
return "very filling";
|
|
} else if (nutrition >= 70) {
|
|
return "ample for a meal";
|
|
} else if (nutrition >= 50) {
|
|
return "enough for a light meal";
|
|
} else if (nutrition >= 25) {
|
|
return "snack-sized";
|
|
} else if (nutrition > 0) {
|
|
return "barely worth eating";
|
|
}
|
|
// ie. < 0
|
|
return "of zero nutritional substance";
|
|
}
|
|
|
|
int getfirearmrange(object_t *o) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_RANGE);
|
|
if (f) {
|
|
return f->val[0];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int getfirearmspeed(object_t *o) {
|
|
int firespeed;
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_FIRESPEED);
|
|
if (f) {
|
|
firespeed = f->val[0];
|
|
} else {
|
|
// default to very slow
|
|
firespeed = 1;
|
|
}
|
|
return firespeed;
|
|
}
|
|
|
|
char getglyph(object_t *o) {
|
|
flag_t *f;
|
|
int isopen;
|
|
char g = ' '; // default
|
|
if (isdoor(o, &isopen)) {
|
|
if (isopen) {
|
|
g = '-';
|
|
} else {
|
|
g = '+';
|
|
}
|
|
} else {
|
|
f = hasflag(o->flags, F_GLYPH);
|
|
if (f) {
|
|
g = f->text[0];
|
|
} else {
|
|
g = o->type->obclass->glyph;
|
|
}
|
|
}
|
|
return g;
|
|
}
|
|
|
|
void genhiddennames(void) {
|
|
objecttype_t *ot;
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (hasflag(ot->flags, F_HASHIDDENNAME)) {
|
|
char *thisname;
|
|
thisname = genhiddenname(ot->obclass->id);
|
|
addknowledge(ot->id, thisname, B_UNKNOWN);
|
|
free(thisname);
|
|
}
|
|
}
|
|
}
|
|
|
|
char *genhiddenname(enum OBCLASS id) {
|
|
char temp[BUFLEN];
|
|
char *name;
|
|
int *numnames;
|
|
int sel,i;
|
|
char **namelist;
|
|
|
|
switch (id) {
|
|
case OC_SCROLL:
|
|
namelist = scrollname;
|
|
numnames = &numscrollnames;
|
|
break;
|
|
case OC_POTION:
|
|
namelist = potionname;
|
|
numnames = &numpotnames;
|
|
break;
|
|
case OC_RING:
|
|
namelist = ringname;
|
|
numnames = &numringnames;
|
|
break;
|
|
default:
|
|
dblog("ERROR! genhiddenname for unknown class %d\n",id);
|
|
exit(1);
|
|
}
|
|
|
|
assert((*numnames != 0));
|
|
sel = rnd(0,*numnames-1);
|
|
strcpy(temp, namelist[sel]);
|
|
name = strdup(temp);
|
|
// remove this name from the candidate list
|
|
for (i = sel; i < (*numnames-1); i++) {
|
|
namelist[i] = namelist[i+1];
|
|
}
|
|
(*numnames)--;
|
|
|
|
return name;
|
|
}
|
|
|
|
// returns -1 if object doesn't have the flag
|
|
int getcharges(object_t *o) {
|
|
flag_t *f;
|
|
int amt = -1;
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
if (f) {
|
|
amt = f->val[0];
|
|
}
|
|
return amt;
|
|
}
|
|
|
|
int getobaccuracy(object_t *wep) {
|
|
int acc;
|
|
flag_t *f;
|
|
|
|
acc = 100; // default accuracy of 100%
|
|
|
|
if (wep) {
|
|
// blessed weapons have better base accuracy
|
|
if (wep->blessed == B_BLESSED) acc += 50;
|
|
|
|
// override with 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 = f->val[0];
|
|
}
|
|
|
|
// modify for attacker's level
|
|
if (wep->pile->owner) {
|
|
acc += (wep->pile->owner->level * 2);
|
|
}
|
|
}
|
|
return acc;
|
|
}
|
|
|
|
// returns value of obejcts, in gold
|
|
int getobvalue(object_t *o) {
|
|
float price;
|
|
flag_t *f;
|
|
|
|
if (o->type->id == OT_GOLD) {
|
|
return o->amt;
|
|
}
|
|
|
|
// base value: weight * material value
|
|
price = (float)getobweight(o) * (float)getmaterialvalue(o->material->id);
|
|
//adjustprice(o->type, &price);
|
|
|
|
// fixed prices
|
|
f = hasflag(o->flags, F_VALUE);
|
|
if (f) {
|
|
price += f->val[0];
|
|
}
|
|
|
|
for (f = o->flags->first ; f ; f = f->next) {
|
|
// damage
|
|
if (f->id == F_DAM) {
|
|
flag_t *ff;
|
|
float mod = 1;
|
|
int min,max;
|
|
getdamrange(o->flags, &min, &max);
|
|
ff = hasflag(o->flags, F_OBATTACKSPEED);
|
|
if (ff) {
|
|
switch (ff->val[0]) {
|
|
case SP_FAST:
|
|
case SP_VERYFAST:
|
|
mod = 1.5;
|
|
break;
|
|
case SP_ULTRAFAST:
|
|
case SP_GODLIKE:
|
|
mod = 2;
|
|
default:
|
|
mod = 1;
|
|
break;
|
|
}
|
|
}
|
|
price += (max*mod*5);
|
|
}
|
|
// armour rating
|
|
if (f->id == F_ARMOURRATING) {
|
|
float rating;
|
|
rating = (float)f->val[0];
|
|
price += (rating * 20.0);
|
|
}
|
|
// bonus/penalties
|
|
if (f->id == F_BONUS) {
|
|
price += (f->val[0] * 100);
|
|
}
|
|
// food
|
|
if (f->id == F_EDIBLE) {
|
|
price += ((float)f->val[0] / 5.0);
|
|
}
|
|
// one-off magical effects (linkspell) - use spell price
|
|
if (f->id == F_LINKSPELL) {
|
|
//flag_t *ff;
|
|
objecttype_t *sp;
|
|
sp = findot(f->val[0]);
|
|
// TODO : spelllevel^2 * 20
|
|
// ooooooooo
|
|
}
|
|
}
|
|
|
|
|
|
// TODO: conferred intrinsics - depends on which one
|
|
|
|
// TODO: conferred spells - use spell price * multiplier
|
|
|
|
// TODO: potions - hardcode?
|
|
|
|
// speical material prices like velvet, silk
|
|
if (strstr(o->type->name, "velvet")) {
|
|
price *= 1.5;
|
|
}
|
|
if (strstr(o->type->name, "silk")) {
|
|
price *= 2;
|
|
}
|
|
|
|
// TODO: extra price for tech/tools - hardcode?
|
|
|
|
// rarity
|
|
f = hasflag(o->flags, F_RARITY);
|
|
if (f) {
|
|
if (f->val[1] >= 70) {
|
|
price /= 1.5;
|
|
} else if (f->val[1] <= 40) {
|
|
price *= 1.5;
|
|
} else if (f->val[1] <= 20) {
|
|
price *= 2;
|
|
} else if (f->val[1] <= 10) {
|
|
price *= 5;
|
|
}
|
|
}
|
|
|
|
|
|
// blessed/cursed
|
|
if (isblessed(o)) price *= 1.5;
|
|
if (iscursed(o)) price /= 2;
|
|
|
|
// minimum
|
|
if (price < 1) price = 1;
|
|
return (int) price;
|
|
}
|
|
|
|
/*
|
|
int getobtypevalue(objecttype_t *ot) {
|
|
float price;
|
|
if (ot->id == OT_GOLD) {
|
|
return 1;
|
|
}
|
|
// base value: weight * material value
|
|
price = (float)ot->weight * (float)getmaterialvalue(ot->material->id);
|
|
|
|
adjustprice(ot, &price);
|
|
return (int) price;
|
|
}
|
|
*/
|
|
|
|
// ie. "it has xxx accuracy"
|
|
char *getaccuracyname(int accpct) {
|
|
if (accpct >= 200) {
|
|
return "godlike";
|
|
} else if (accpct >= 150) {
|
|
return "incredible";
|
|
} else if (accpct >= 100) {
|
|
return "very good";
|
|
} else if (accpct >= 70) {
|
|
return "good";
|
|
} else if (accpct >= 50) {
|
|
return "average";
|
|
} else if (accpct >= 30) {
|
|
return "poor";
|
|
} else if (accpct >= 20) {
|
|
return "very poor";
|
|
} else if (accpct >= 0) {
|
|
return "incredibly poor";
|
|
} else {
|
|
return "a complete lack of";
|
|
}
|
|
}
|
|
|
|
|
|
object_t *getammo(lifeform_t *lf) {
|
|
object_t *o;
|
|
o = hasobwithflag(lf->pack, F_CURAMMO);
|
|
return o;
|
|
}
|
|
|
|
object_t *getrandomammo(lifeform_t *lf) {
|
|
object_t *gun;
|
|
object_t *o;
|
|
flag_t *f;
|
|
|
|
gun = getfirearm(lf);
|
|
if (!gun) {
|
|
return NULL;
|
|
}
|
|
// TODO: at the moment we are jsut picking the first
|
|
// possible ammo. Need to allow the player to
|
|
// pick a specific ammo to use. USe a flag on wep
|
|
// to do this? Or a flag on the player?
|
|
for (f = gun->flags->first ; f ; f = f->next) {
|
|
if (f->id == F_AMMOOB) {
|
|
for (o = lf->pack->first ; o ; o = o->next) {
|
|
if (o->type->id == f->val[0]) {
|
|
return o;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
char *getdamname(enum DAMTYPE damtype) {
|
|
switch (damtype) {
|
|
case DT_ACID: return "acid";
|
|
case DT_MELT: return "melting";
|
|
case DT_PIERCE: return "piercing";
|
|
case DT_SLASH: return "slashing";
|
|
case DT_CLAW: return "claw";
|
|
case DT_ELECTRIC: return "electricity";
|
|
case DT_EXPLOSIVE: return "explosive";
|
|
case DT_FIRE: return "fire";
|
|
case DT_BITE: return "bite";
|
|
case DT_BASH: return "bludgeoning";
|
|
case DT_CHOP: return "chopping";
|
|
case DT_COLD: return "cold";
|
|
case DT_POISONGAS: return "poison gas";
|
|
case DT_PROJECTILE: return "projectile";
|
|
case DT_HOLY: return "holy";
|
|
case DT_DIRECT: return "direct";
|
|
case DT_WATER: return "water";
|
|
case DT_DECAY: return "decay";
|
|
case DT_MAGIC: return "magical";
|
|
case DT_TOUCH: return "touch";
|
|
default: return "unknown";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
char *getdamnamenoun(enum DAMTYPE damtype) {
|
|
switch (damtype) {
|
|
case DT_ACID: return "acid";
|
|
case DT_MELT: return "melting";
|
|
case DT_PIERCE: return "piercing damage";
|
|
case DT_POISONGAS: return "poison gas";
|
|
case DT_SLASH: return "slashing damage";
|
|
case DT_CLAW: return "claw damage";
|
|
case DT_ELECTRIC: return "electricity";
|
|
case DT_EXPLOSIVE: return "explosives";
|
|
case DT_FIRE: return "fire";
|
|
case DT_BITE: return "bite";
|
|
case DT_BASH: return "bludgeoning";
|
|
case DT_CHOP: return "chopping";
|
|
case DT_COLD: return "cold";
|
|
case DT_PROJECTILE: return "projectiles";
|
|
case DT_HOLY: return "holy damage";
|
|
case DT_DIRECT: return "direct damage";
|
|
case DT_DECAY: return "decay damage";
|
|
case DT_WATER: return "water";
|
|
case DT_MAGIC: return "magical damage";
|
|
case DT_TOUCH: return "touch effects";
|
|
default: return "unknown";
|
|
}
|
|
return "unkmown";
|
|
}
|
|
|
|
char *gethiddenname(object_t *o) {
|
|
knowledge_t *k;
|
|
// if id'd, return the full name
|
|
if (hasflag(o->flags, F_IDENTIFIED)) {
|
|
return o->type->name;
|
|
}
|
|
// otherwise check if it has a hidden name
|
|
for (k = knowledge; k ; k = k->next) {
|
|
if (k->id == o->type->id) {
|
|
// it DOES have a hidden name.
|
|
// does the player know about it?
|
|
if (k->known) {
|
|
// if so, return real name
|
|
return o->type->name;
|
|
} else {
|
|
// otherwise return hidden one
|
|
return k->hiddenname;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// no hidden name, return real one
|
|
return o->type->name;
|
|
}
|
|
|
|
int getobattackspeed(object_t *o) {
|
|
int speed = SPEED_ATTACK;
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_OBATTACKSPEED);
|
|
if (f) {
|
|
speed = f->val[0];
|
|
}
|
|
return speed;
|
|
}
|
|
|
|
|
|
int getletidx(char let) {
|
|
int i;
|
|
for (i = 0; i < MAXPILEOBS; i++) {
|
|
if (letorder[i] == let) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int getmaterialvalue(enum MATERIAL mat) {
|
|
switch (mat) {
|
|
case MT_NOTHING:
|
|
case MT_MAGIC:
|
|
case MT_FIRE:
|
|
case MT_GAS:
|
|
return 0;
|
|
case MT_FOOD:
|
|
case MT_ICE:
|
|
case MT_STONE:
|
|
return 1;
|
|
case MT_WATER:
|
|
return 1;
|
|
case MT_FLESH:
|
|
case MT_BONE:
|
|
case MT_BLOOD:
|
|
case MT_SLIME:
|
|
return 2;
|
|
case MT_CLOTH:
|
|
case MT_LEATHER:
|
|
return 2;
|
|
case MT_WOOD:
|
|
return 3;
|
|
case MT_PAPER:
|
|
case MT_WETPAPER:
|
|
return 4;
|
|
case MT_PLASTIC:
|
|
case MT_RUBBER:
|
|
case MT_GLASS:
|
|
return 5;
|
|
case MT_METAL:
|
|
return 6;
|
|
case MT_GOLD:
|
|
return 7;
|
|
}
|
|
// default
|
|
return 1;
|
|
}
|
|
|
|
int getmaxthrowrange(lifeform_t *lf, object_t *o) {
|
|
int maxdist;
|
|
// TODO: adjust for lifeform strength
|
|
maxdist = 10 - (getobunitweight(o) / 2);
|
|
return maxdist;
|
|
}
|
|
|
|
// select lowest possible letter
|
|
char getnextletter(obpile_t *op, char *wantletter) {
|
|
int curidx = -1;
|
|
char let;
|
|
//int db = B_FALSE;
|
|
|
|
// try 'wantletter' first
|
|
if (wantletter && (*wantletter != '\0')) {
|
|
if (!pilehasletter(op, *wantletter)) {
|
|
return *wantletter;
|
|
}
|
|
}
|
|
|
|
curidx = 0; // ie 'a'
|
|
|
|
for (curidx = 0; curidx < MAXPILEOBS; curidx++) {
|
|
// does any other object in the pile have this letter?
|
|
let = letorder[curidx];
|
|
if (!pilehasletter(op, let)) {
|
|
// if we didn't find it, this letter is okay.
|
|
return let;
|
|
}
|
|
}
|
|
|
|
return '\0';
|
|
}
|
|
|
|
|
|
int getnumshards(object_t *o) {
|
|
int numshards,maxshards;
|
|
maxshards = ceil(getobunitweight(o)) * 10;
|
|
if (maxshards < 1) maxshards = 1;
|
|
numshards = rnd(1,maxshards);
|
|
return numshards;
|
|
}
|
|
|
|
int getnutritionbase(object_t *o) {
|
|
float basenutr;
|
|
flag_t *f;
|
|
if (o->material->id == MT_ICE) {
|
|
// use the object's weight
|
|
basenutr = getobweight(o) * 10;
|
|
} else {
|
|
// use nutrition flag
|
|
f = hasflag(o->flags, F_EDIBLE);
|
|
if (f) {
|
|
basenutr = (float)f->val[1];
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return basenutr;
|
|
}
|
|
|
|
int getnutrition(object_t *o) {
|
|
float nutrpct;
|
|
int nutrition;
|
|
|
|
if (isrotting(o)) {
|
|
nutrition = -(HUNGERCONST/2);
|
|
} else {
|
|
nutrpct = getnutritionbase(o);
|
|
|
|
if (nutrpct <= 0) {
|
|
nutrition = 0;
|
|
} else {
|
|
nutrition = pctof(nutrpct, (float) HUNGERCONST);
|
|
}
|
|
}
|
|
|
|
return nutrition;
|
|
}
|
|
|
|
char *getobdesc(object_t *o, char *buf) {
|
|
if (isknown(o)) {
|
|
sprintf(buf, "%s", o->type->desc);
|
|
} else {
|
|
sprintf(buf, "%s", o->type->obclass->desc);
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
cell_t *getoblocation(object_t *o) {
|
|
if (o->pile->owner) return o->pile->owner->cell;
|
|
else return o->pile->where;
|
|
}
|
|
|
|
char *getobname(object_t *o, char *buf, int count) {
|
|
return real_getobname(o, buf, count, B_TRUE, B_TRUE, B_TRUE);
|
|
}
|
|
|
|
// buf must already be allocated
|
|
char *real_getobname(object_t *o, char *buf, int count, int wantcondition, int adjustforblind, int wantblesscurse) {
|
|
char *pluralname;
|
|
char prefix[BUFLEN];
|
|
char basename[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
int shopitem = B_FALSE;
|
|
flag_t *f;
|
|
|
|
// default to normal name
|
|
if (hasflag(o->flags, F_SHOPITEM)) {
|
|
shopitem = B_TRUE;
|
|
}
|
|
|
|
if (shopitem) {
|
|
strcpy(basename,o->type->name);
|
|
} else {
|
|
strcpy(basename,gethiddenname(o));
|
|
}
|
|
|
|
if (!shopitem) {
|
|
if (gamestarted && adjustforblind && isblind(player) ) {
|
|
// override with onclass names
|
|
if (o->type->obclass->id == OC_SCROLL) {
|
|
strcpy(basename, "scroll");
|
|
} else if (o->type->obclass->id == OC_POTION) {
|
|
strcpy(basename, "potion");
|
|
} else if (o->type->obclass->id == OC_RING) {
|
|
strcpy(basename, "ring");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if ((o->type->id == OT_POT_WATER) && (o->blessed == B_BLESSED) && isblessknown(o) && isknown(o)) {
|
|
strcpy(basename, "potion of holy water");
|
|
}
|
|
if ((o->type->id == OT_POT_COMPETENCE) && (o->blessed == B_CURSED) && isblessknown(o) && isknown(o)) {
|
|
strcpy(basename, "potion of incompetence");
|
|
}
|
|
|
|
// handle ALL
|
|
if (count == ALL) {
|
|
count = o->amt;
|
|
}
|
|
|
|
// figure out prefix
|
|
if ((count == 1) && !hasflag(o->flags, F_NO_A)) {
|
|
pluralname = strdup(basename);
|
|
|
|
if (hasflag(o->flags, F_UNIQUE)) { // TODO: && o->identified
|
|
strcpy(prefix, "The");
|
|
} else {
|
|
if (!hasflag(o->flags, F_NOBLESS) && isblessknown(o)) {
|
|
if (o->blessed == B_UNCURSED) {
|
|
strcpy(prefix, "an");
|
|
} else {
|
|
strcpy(prefix, "a");
|
|
}
|
|
} else {
|
|
if (isvowel(basename[0])) {
|
|
strcpy(prefix, "an");
|
|
} else {
|
|
strcpy(prefix, "a");
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// multiple objects?
|
|
if (hasflag(o->flags, F_NO_PLURAL)) {
|
|
pluralname = strdup(basename);
|
|
} else {
|
|
pluralname = makeplural(basename);
|
|
}
|
|
sprintf(prefix, "%d",count);
|
|
}
|
|
|
|
sprintf(buf, "%s ", prefix);
|
|
|
|
|
|
// blessed status
|
|
if (!hasflag(o->flags, F_NOBLESS) && wantblesscurse) {
|
|
if (shopitem || isblessknown(o)) {
|
|
switch (o->blessed) {
|
|
case B_BLESSED:
|
|
// blessed water is known as "holy water"
|
|
if ((o->type->id == OT_POT_WATER) && isknown(o)) {
|
|
} else {
|
|
strcat(buf, "blessed ");
|
|
}
|
|
break;
|
|
case B_UNCURSED:
|
|
strcat(buf, "uncursed ");
|
|
break;
|
|
case B_CURSED:
|
|
if ((o->type->id == OT_POT_COMPETENCE) && isknown(o)) {
|
|
} else {
|
|
strcat(buf, "cursed ");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// material changed?
|
|
if (o->material != o->type->material) {
|
|
switch (o->material->id) {
|
|
case MT_ICE:
|
|
strcat(buf, "frozen ");
|
|
break;
|
|
case MT_GOLD:
|
|
strcat(buf, "golden ");
|
|
break;
|
|
case MT_WOOD:
|
|
strcat(buf, "wooden ");
|
|
break;
|
|
default:
|
|
strcat(buf, o->material->name);
|
|
strcat(buf, " ");
|
|
}
|
|
}
|
|
|
|
// include mods (ie. a flaming sword)
|
|
if (hasflag(o->flags, F_ONFIRE)) {
|
|
strcat(buf, "flaming ");
|
|
}
|
|
|
|
// condition
|
|
if (wantcondition) {
|
|
if (!hasflag(o->flags, F_NOOBDAMTEXT)) {
|
|
getobconditionname(o, buf2);
|
|
if (strlen(buf2) > 0) {
|
|
strcat(buf, buf2);
|
|
strcat(buf, " ");
|
|
}
|
|
}
|
|
}
|
|
|
|
// include enchantments (ie. a blessed +5 sword)
|
|
f = hasflag(o->flags, F_BONUS);
|
|
if (f && (f->known || shopitem)) {
|
|
char buf2[BUFLENSMALL];
|
|
int bonus;
|
|
bonus = f->val[0];
|
|
if (bonus != 0) {
|
|
sprintf(buf2, "%s%d ", (bonus < 0) ? "" : "+", bonus);
|
|
strcat(buf, buf2);
|
|
}
|
|
}
|
|
|
|
// object name
|
|
strcat(buf, pluralname);
|
|
free(pluralname);
|
|
|
|
// include mods if identified - ie. xxx of pyromania
|
|
f = hasflag(o->flags, F_FLAMESTRIKE);
|
|
if (f && (f->known || shopitem)) {
|
|
strcat(buf, " of pyromania");
|
|
}
|
|
|
|
// make sure obname doesn't start with a space
|
|
while (buf && (buf[0] == ' ')) {
|
|
strcpy(buf, buf + 1);
|
|
}
|
|
|
|
// append inscription
|
|
if (o->inscription) {
|
|
strcat(buf, " {");
|
|
strcat(buf, o->inscription);
|
|
strcat(buf, "}");
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
float getobpileweight(obpile_t *op) {
|
|
object_t *o;
|
|
float weight = 0;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
weight += getobweight(o);
|
|
}
|
|
return weight;
|
|
}
|
|
|
|
char *getobconditionname(object_t *o, char *buf) {
|
|
flag_t *f;
|
|
float pct;
|
|
|
|
|
|
if (iscorpse(o)) {
|
|
if (isrotting(o)) {
|
|
sprintf(buf, "rotting");
|
|
} else {
|
|
strcpy(buf, "");
|
|
}
|
|
} else {
|
|
f = hasflag(o->flags, F_OBHP);
|
|
if (f) {
|
|
pct = ((float) f->val[0] / (float) f->val[1]) * 100.0;
|
|
} else {
|
|
pct = 100;
|
|
}
|
|
|
|
if (pct >= 100) {
|
|
strcpy(buf, "");
|
|
} else if (pct >= 75) {
|
|
sprintf(buf, "battered");
|
|
} else if (pct >= 50) {
|
|
sprintf(buf, "damaged");
|
|
} else if (pct >= 25) {
|
|
sprintf(buf, "very damaged");
|
|
} else {
|
|
sprintf(buf, "critically damaged");
|
|
}
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
char *getobhurtname(object_t *o, enum DAMTYPE damtype) {
|
|
switch (damtype) {
|
|
case DT_ACID:
|
|
if (o->amt == 1) {
|
|
return "corrodes";
|
|
} else {
|
|
return "corrode";
|
|
}
|
|
case DT_DECAY:
|
|
if (o->amt == 1) {
|
|
return "decays";
|
|
} else {
|
|
return "decay";
|
|
}
|
|
case DT_FIRE:
|
|
if (o->amt == 1) {
|
|
return "burns";
|
|
} else {
|
|
return "burn";
|
|
}
|
|
case DT_MELT:
|
|
if (o->amt == 1) {
|
|
return "is melting";
|
|
} else {
|
|
return "are melting";
|
|
}
|
|
default:
|
|
if (o->amt == 1) {
|
|
return "is damaged";
|
|
} else {
|
|
return "are damaged";
|
|
}
|
|
}
|
|
return "is damaged";
|
|
}
|
|
|
|
float getobweight(object_t *o) {
|
|
float weight;
|
|
|
|
weight = getobunitweight(o) * o->amt;
|
|
|
|
return weight;
|
|
}
|
|
|
|
float getobunitweight(object_t *o) {
|
|
float weight;
|
|
|
|
weight = o->weight;
|
|
|
|
// has its material been changed?
|
|
if (o->material != o->type->material) {
|
|
// changed - some materials will
|
|
// modify the item's weight
|
|
float ratio;
|
|
ratio = o->material->weightrating / o->type->material->weightrating;
|
|
|
|
weight *= ratio;
|
|
}
|
|
|
|
return weight;
|
|
}
|
|
|
|
objecttype_t *getoppositestairs(objecttype_t *ot) {
|
|
flag_t *f;
|
|
f = hasflag(ot->flags, F_OPPOSITESTAIRS);
|
|
assert(f);
|
|
return findot(f->val[0]);
|
|
}
|
|
|
|
char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth) {
|
|
objecttype_t *ot;
|
|
objecttype_t *poss[MAXRANDOMOBCANDIDATES];
|
|
int nposs = 0;
|
|
int selidx;
|
|
int amt;
|
|
flag_t *f;
|
|
int db = B_TRUE;
|
|
char *pluralname;
|
|
char cursestr[BUFLEN];
|
|
int raritymin,raritymax;
|
|
int depth;
|
|
|
|
if (forcedepth != NA) {
|
|
depth = forcedepth;
|
|
} else if (map) {
|
|
depth = map->depth;
|
|
} else {
|
|
depth = rnd(1,MAXDEPTH);
|
|
}
|
|
|
|
getrarity(depth, &raritymin, &raritymax, 25);
|
|
|
|
if (db) dblog("adding random object with rarity value between %d - %d",raritymin,raritymax);
|
|
if (db) {
|
|
objectclass_t *oc;
|
|
switch (cond) {
|
|
case RO_DAMTYPE:
|
|
dblog(" (must have damtype = %s)",getdamname(cval));
|
|
break;
|
|
case RO_OBCLASS:
|
|
oc = findoc(cval);
|
|
dblog(" (must have obclass = %s)",oc->name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// try to find an object of this type which will
|
|
// fit in the map's habitat
|
|
nposs = 0;
|
|
while (nposs == 0) {
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
int rarok = B_FALSE, condok = B_FALSE;
|
|
flag_t *rarflag = NULL;
|
|
// correct rarity?
|
|
|
|
rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL);
|
|
if (!rarflag) {
|
|
if (map) {
|
|
rarflag = hasflagval(ot->flags, F_RARITY, map->habitat, NA, NA, NULL);
|
|
} else {
|
|
rarflag = hasflagval(ot->flags, F_RARITY, NA, NA, NA, NULL);
|
|
}
|
|
}
|
|
if (rarflag) {
|
|
if ((rarflag->val[1] >= raritymin) && (rarflag->val[1] <= raritymax)) {
|
|
rarok = B_TRUE;
|
|
}
|
|
}
|
|
|
|
if (rarok) {
|
|
// matches condition?
|
|
if (cond == RO_NONE) {
|
|
condok = B_TRUE;
|
|
} else if (cond == RO_DAMTYPE) {
|
|
if (hasflagval(ot->flags, F_DAMTYPE, cval, NA, NA, NULL)) {
|
|
condok = B_TRUE;
|
|
}
|
|
} else if (cond == RO_OBCLASS) {
|
|
if (ot->obclass->id == cval) {
|
|
condok = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rarok && condok) {
|
|
//if (db) dblog("-> possibility: %s, rarity=%d",ot->name, rarflag->val[1]);
|
|
poss[nposs] = ot;
|
|
nposs++;
|
|
if (nposs >= MAXRANDOMOBCANDIDATES) break;
|
|
}
|
|
}
|
|
|
|
// nothing found?
|
|
if (nposs == 0) {
|
|
// already at lowest rarity?
|
|
if ((raritymax >= 100) && (raritymin <= 0)) {
|
|
// give up
|
|
strcpy(buf, "");
|
|
if (db) dblog("no possible objects at all! giving up.");
|
|
return NULL;
|
|
}
|
|
|
|
// expand range and try again
|
|
raritymax += 10; if (raritymax > 100) raritymax = 100;
|
|
raritymin -= 10; if (raritymin < 0) raritymin = 0;
|
|
if (db) dblog("no possible objects like this. trying again with rarity %d-%d\n",raritymin,raritymax);
|
|
}
|
|
}
|
|
|
|
if (db) dblog("got %d possibilities.",nposs);
|
|
// pick a random object from our possiblities
|
|
selidx = rnd(0,nposs-1);
|
|
ot = poss[selidx];
|
|
// handle objects 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 (amt > 1) {
|
|
pluralname = makeplural(ot->name);
|
|
} else {
|
|
pluralname = strdup(ot->name);
|
|
}
|
|
|
|
// blessed?
|
|
strcpy(cursestr, "");
|
|
if (!hasflag(ot->flags, F_NOBLESS)) {
|
|
int num;
|
|
int bonus = 0;
|
|
num = rnd(1,100);
|
|
if (num <= 15) {
|
|
strcpy(cursestr, "blessed ");
|
|
// chance of bonus
|
|
while (rnd(1,100) <= 25) {
|
|
bonus++;
|
|
}
|
|
} else if (num <= 30) {
|
|
strcpy(cursestr, "cursed ");
|
|
// chance of penalty
|
|
while (rnd(1,100) <= 25) {
|
|
bonus--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ((ot->obclass->id == OC_WEAPON) ||
|
|
(ot->obclass->id == OC_ARMOUR)) {
|
|
char buf2[BUFLENSMALL];
|
|
int bonus = 0;
|
|
if (strlen(cursestr) > 0) {
|
|
// chance of bonus/penalty
|
|
while (rnd(1,100) <= 25) {
|
|
bonus++;
|
|
}
|
|
if (strstr(cursestr, "cursed")){
|
|
bonus = -bonus;
|
|
}
|
|
}
|
|
sprintf(buf2, "%s%d ", (bonus >= 0) ? "+" : "", bonus);
|
|
strcat(cursestr, buf2);
|
|
}
|
|
|
|
sprintf(buf, "%d %s%s", amt, cursestr, pluralname);
|
|
|
|
|
|
if (db) dblog("random ob: %d x %s ('%s')", amt, ot->name,pluralname);
|
|
free(pluralname);
|
|
return buf;
|
|
}
|
|
|
|
/*
|
|
OLD CODE
|
|
char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth) {
|
|
enum RARITY rarity;
|
|
objecttype_t *ot;
|
|
int roll;
|
|
objecttype_t *poss[MAXRANDOMOBCANDIDATES];
|
|
int nposs = 0;
|
|
int selidx;
|
|
int amt;
|
|
flag_t *f;
|
|
int db = B_TRUE;
|
|
char *pluralname;
|
|
char cursestr[BUFLEN];
|
|
int depth;
|
|
int getrarer;
|
|
int firstgo;
|
|
int moddir = 0;
|
|
|
|
// determine rarity of object to generate
|
|
if (rnd(1,2) == 1) {
|
|
rarity = RR_FREQUENT;
|
|
} else {
|
|
rarity = RR_COMMON;
|
|
}
|
|
|
|
if (forcedepth != NA) {
|
|
depth = forcedepth;
|
|
} else if (map) {
|
|
depth = map->depth;
|
|
} else {
|
|
depth = rnd(1,20);
|
|
}
|
|
|
|
getrarer = 40 + (depth * 2);
|
|
|
|
if (getrarer > 75) getrarer = 75;
|
|
|
|
// start with 'frequent'ly appearing items
|
|
// roll a die. if less than 'getrarer', get rarer.
|
|
// stop when we fail the die roll.
|
|
roll = rnd(1,100);
|
|
while (roll < getrarer) {
|
|
rarity++;
|
|
if (rarity == RR_VERYRARE) break;
|
|
roll = rnd(1,100);
|
|
}
|
|
if (db) dblog("adding random object of rarity %d",rarity);
|
|
if (db) {
|
|
objectclass_t *oc;
|
|
switch (cond) {
|
|
case RO_DAMTYPE:
|
|
dblog(" (must have damtype = %s)",getdamname(cval));
|
|
break;
|
|
case RO_OBCLASS:
|
|
oc = findoc(cval);
|
|
dblog(" (must have obclass = %s)",oc->name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// try to find an object of this type which will
|
|
// fit in the map's habitat
|
|
|
|
moddir = -1;
|
|
firstgo = B_TRUE;
|
|
nposs = 0;
|
|
while (nposs == 0) {
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
int rarok = B_FALSE, condok = B_FALSE;
|
|
// correct rarity?
|
|
if ( map && hasflagval(ot->flags, F_RARITY, map->habitat, rarity, NA, NULL)) {
|
|
rarok = B_TRUE;
|
|
} else if (hasflagval(ot->flags, F_RARITY, NA, rarity, NA, NULL)) {
|
|
rarok = B_TRUE;
|
|
} else {
|
|
rarok = B_FALSE;
|
|
}
|
|
|
|
if (rarok) {
|
|
// matches condition?
|
|
if (cond == RO_NONE) {
|
|
condok = B_TRUE;
|
|
} else if (cond == RO_DAMTYPE) {
|
|
if (hasflagval(ot->flags, F_DAMTYPE, cval, NA, NA, NULL)) {
|
|
condok = B_TRUE;
|
|
}
|
|
} else if (cond == RO_OBCLASS) {
|
|
if (ot->obclass->id == cval) {
|
|
condok = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (rarok && condok) {
|
|
poss[nposs] = ot;
|
|
nposs++;
|
|
if (nposs >= MAXRANDOMOBCANDIDATES) break;
|
|
}
|
|
}
|
|
|
|
|
|
// nothing found?
|
|
if (nposs == 0) {
|
|
// already at lowest rarity?
|
|
if (rarity == RR_FREQUENT) {
|
|
if (firstgo) {
|
|
moddir = 1;
|
|
} else {
|
|
// give up
|
|
strcpy(buf, "");
|
|
if (db) dblog("no possible objects at all! giving up.");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
firstgo = B_FALSE;
|
|
|
|
// lower/raise rarity and try again
|
|
rarity += moddir;
|
|
if (rarity >= RR_NEVER) {
|
|
// give up
|
|
strcpy(buf, "");
|
|
if (db) dblog("no possible objects at all! giving up.");
|
|
return NULL;
|
|
}
|
|
if (db) dblog("no possible objects like this. trying again with rarity %d\n",rarity);
|
|
}
|
|
}
|
|
|
|
if (db) dblog("got %d possibilities.",nposs);
|
|
// pick a random object from our possiblities
|
|
selidx = rnd(0,nposs-1);
|
|
ot = poss[selidx];
|
|
// handle objects 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 (amt > 1) {
|
|
pluralname = makeplural(ot->name);
|
|
} else {
|
|
pluralname = strdup(ot->name);
|
|
}
|
|
|
|
// blessed?
|
|
strcpy(cursestr, "");
|
|
if (!hasflag(ot->flags, F_NOBLESS)) {
|
|
int num;
|
|
int bonus = 0;
|
|
num = rnd(1,100);
|
|
if (num <= 15) {
|
|
strcpy(cursestr, "blessed ");
|
|
// chance of bonus
|
|
while (rnd(1,100) <= 25) {
|
|
bonus++;
|
|
}
|
|
} else if (num <= 30) {
|
|
strcpy(cursestr, "cursed ");
|
|
// chance of penalty
|
|
while (rnd(1,100) <= 25) {
|
|
bonus--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ((ot->obclass->id == OC_WEAPON) ||
|
|
(ot->obclass->id == OC_ARMOUR)) {
|
|
char buf2[BUFLENSMALL];
|
|
int bonus = 0;
|
|
if (strlen(cursestr) > 0) {
|
|
// chance of bonus/penalty
|
|
while (rnd(1,100) <= 25) {
|
|
bonus++;
|
|
}
|
|
if (strstr(cursestr, "cursed")){
|
|
bonus = -bonus;
|
|
}
|
|
}
|
|
sprintf(buf2, "%s%d ", (bonus >= 0) ? "+" : "", bonus);
|
|
strcat(cursestr, buf2);
|
|
}
|
|
|
|
sprintf(buf, "%d %s%s", amt, cursestr, pluralname);
|
|
|
|
|
|
if (db) dblog("random ob: %d x %s ('%s')", amt, ot->name,pluralname);
|
|
free(pluralname);
|
|
return buf;
|
|
}
|
|
*/
|
|
|
|
char *getrandomob(map_t *map, char *buf) {
|
|
return real_getrandomob(map, buf, RO_NONE, NA, NA);
|
|
}
|
|
|
|
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) {
|
|
return real_getrandomob(map, buf, RO_DAMTYPE, damtype, NA);
|
|
}
|
|
|
|
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf) {
|
|
return real_getrandomob(map, buf, RO_OBCLASS, cid, NA);
|
|
}
|
|
|
|
char *getschoolname(enum SPELLSCHOOL sch) {
|
|
switch (sch) {
|
|
case SS_ABILITY: return "Abilities";
|
|
case SS_ALLOMANCY: return "Allomancy";
|
|
case SS_DIVINE: return "Divine Powers";
|
|
case SS_WILD: return "Wild Magic";
|
|
case SS_MENTAL: return "Mental Powers";
|
|
case SS_ELEMENTAL: return "Elemental Magic";
|
|
case SS_MODIFICATION: return "Transmutation Magic";
|
|
case SS_DEATH: return "Death Magic";
|
|
case SS_LIFE: return "Life Magic";
|
|
case SS_DIVINATION: return "Divination Magic";
|
|
case SS_TRANSLOCATION: return "Translocation Magic";
|
|
case SS_SUMMONING: return "Summoning Magic";
|
|
case SS_GRAVITY: return "Gravitation Magic";
|
|
case SS_LAST: return "!invalid school!";
|
|
}
|
|
return "unknown school";
|
|
}
|
|
|
|
int getshatterdam(object_t *o) {
|
|
int shatterdam = 0;
|
|
if (willshatter(o->material->id)) {
|
|
int maxshatterdam;
|
|
maxshatterdam = ceil(getobweight(o));
|
|
if (maxshatterdam < 1) maxshatterdam = 1;
|
|
|
|
shatterdam = rnd(1, maxshatterdam);
|
|
}
|
|
return shatterdam;
|
|
}
|
|
|
|
int getthrowdam(object_t *o) {
|
|
double dam = 0;
|
|
flag_t *f;
|
|
// base damage is = kilograms.
|
|
// ie. 1 kg object does 1 damage
|
|
// ie. 5 kg object does 5 damage
|
|
// ie. 100 kg object does 100 damage (person)
|
|
// ie. 1 tonne object does 1000 damage (car)
|
|
dam = ceil((double)getobunitweight(o));
|
|
|
|
// modify for bonus
|
|
f = hasflag(o->flags, F_BONUS);
|
|
if (f) {
|
|
dam += f->val[0];
|
|
}
|
|
|
|
// note: damage will also be modified based on speed in fireat()
|
|
|
|
// adjust for material
|
|
switch (o->material->id) {
|
|
// soft materials do less damage
|
|
case MT_PAPER:
|
|
case MT_WETPAPER:
|
|
case MT_CLOTH:
|
|
dam /= 2;
|
|
break;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// misisle objects do extra damage
|
|
if (hasflag(o->flags, F_MISSILE)) {
|
|
dam *= 2;
|
|
}
|
|
|
|
return (int)dam;
|
|
}
|
|
|
|
int hasedibleob(obpile_t *op) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (isedible(o)) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
object_t *hasknownob(obpile_t *op, enum OBTYPE oid) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->type->id == oid) {
|
|
if (isknown(o)) {
|
|
return o;
|
|
}
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
object_t *hasob(obpile_t *op, enum OBTYPE oid) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->type->id == oid) return o;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
object_t *hasobofclass(obpile_t *op, enum OBCLASS cid) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->type->obclass->id == cid) return o;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
object_t *hasobmulti(obpile_t *op, enum OBTYPE *oid, int noids) {
|
|
object_t *o;
|
|
int n;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
for (n = 0; n < noids; n++) {
|
|
if (o->type->id == oid[n]) return o;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
object_t *hasobwithflag(obpile_t *op, enum FLAG flagid) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (hasflag(o->flags, flagid)) return o;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
object_t *hasobwithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int val2, char *text) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (hasflagval(o->flags, flagid, val0, val1, val2, text)) return o;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
object_t *hasobid(obpile_t *op, int id) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->id == id) return o;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// fully identify a single object.
|
|
void identify(object_t *o) {
|
|
flag_t *f;
|
|
if (!isknown(o)) {
|
|
makeknown(o->type->id);
|
|
}
|
|
addflag(o->flags, F_IDENTIFIED, B_TRUE, -1, -1, NULL);
|
|
o->blessknown = B_TRUE;
|
|
for (f = o->flags->first ; f ; f = f->next) {
|
|
if (!f->known) f->known = B_TRUE;
|
|
}
|
|
}
|
|
|
|
void initobjects(void) {
|
|
//int ch;
|
|
//int i;
|
|
//objecttype_t *ot;
|
|
|
|
// generate counts for hidden names
|
|
numscrollnames = countnames(scrollname);
|
|
numpotnames = countnames(potionname);
|
|
numringnames = countnames(ringname);
|
|
|
|
// materials
|
|
addmaterial(MT_NOTHING, "nothing", 0);
|
|
addmaterial(MT_MAGIC, "magical energy", 0);
|
|
addmaterial(MT_FIRE, "fire", 0);
|
|
addmaterial(MT_GAS, "gas", 0.5);
|
|
addmaterial(MT_PAPER, "paper", 1);
|
|
addflag(lastmaterial->flags, F_DTCONVERT, DT_FIRE, NA, NA, "pile of ash");
|
|
addflag(lastmaterial->flags, F_MATCONVERT, MT_WATER, NA, NA, "lump of soggy paper");
|
|
addflag(lastmaterial->flags, F_MATCONVERTTEXT, MT_WATER, NA, NA, "goes soggy");
|
|
addflag(lastmaterial->flags, F_MATCONVERTTEXTPL, MT_WATER, NA, NA, "go soggy");
|
|
addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_FLESH, "flesh", 2);
|
|
addmaterial(MT_WETPAPER, "wet paper", 3);
|
|
addmaterial(MT_CLOTH, "cloth", 3);
|
|
addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_FOOD, "food", 3);
|
|
addmaterial(MT_PLASTIC, "plastic", 3);
|
|
addmaterial(MT_RUBBER, "rubber", 4);
|
|
addmaterial(MT_LEATHER, "leather", 4);
|
|
addmaterial(MT_BONE, "bone", 5);
|
|
addmaterial(MT_ICE, "ice",6);
|
|
addmaterial(MT_WOOD, "wood", 6);
|
|
addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_WATER, "water", 7);
|
|
addmaterial(MT_BLOOD, "blood", 8);
|
|
addmaterial(MT_SLIME, "slime", 9);
|
|
addmaterial(MT_STONE, "stone", 10);
|
|
addmaterial(MT_METAL, "metal", 13);
|
|
addmaterial(MT_GLASS, "glass", 13);
|
|
addmaterial(MT_GOLD, "gold", 16);
|
|
//addmaterial(MT_GOLD, "gold", 16);
|
|
|
|
// object classes
|
|
addoc(OC_DFEATURE, "Dungeon Features", "Doors, etc.", '\\');
|
|
addoc(OC_MONEY, "Money", "The standard currency of Nexus.", '$');
|
|
addoc(OC_SCROLL, "Scrolls", "An arcane roll of parchment, inscribed with many magical glyphs.", '?');
|
|
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
//addflag(lastobjectclass->flags, F_DTCONVERT, DT_WATER, NA, NA, "lump of soggy paper");
|
|
//addflag(lastobjectclass->flags, F_MATCONVERT, MT_WATER, NA, NA, "lump of soggy paper");
|
|
//addflag(lastobjectclass->flags, F_MATCONVERTTEXT, MT_WATER, NA, NA, "goes soggy");
|
|
//addflag(lastobjectclass->flags, F_MATCONVERTTEXTPL, MT_WATER, NA, NA, "go soggy");
|
|
|
|
|
|
addoc(OC_POTION, "Potions", "A strange concoction contained within a small flask.", '!');
|
|
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_POURABLE, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_RING, "Rings", "A circular band, worn on the finger.", '=');
|
|
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_GOESON, BP_RIGHTHAND, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_GOESON, BP_LEFTHAND, NA, NA, NULL);
|
|
addoc(OC_WEAPON, "Weapons", "An instrument used for the purpose of causing harm or death.", ')');
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_ARMOUR, "Armour/Clothing", "Protective gear.", ']');
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_ROCK, "Rocks/Gems", "Boring (or not so boring) rocks.", '*');
|
|
addoc(OC_FOOD, "Food", "Yum!", '%');
|
|
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_CORPSE, "Corpses", "Dead flesh which was once living.", '%');
|
|
addflag(lastobjectclass->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_OBHP, 50, 50, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_OBHPDRAIN, 1, DT_DECAY, NA, NULL); // ie. corpses last for 50 turns
|
|
addoc(OC_TECH, "Tools/Technology", "Useful items, from the common to the obscure.", '~');
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_MISC, "Miscellaneous", "This could be anything.", '\\');
|
|
addoc(OC_EFFECT, "Environmental Effects", "Smoke, fire, etc.", '}');
|
|
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_SPELL, "Spells", "A magical spell", '&'); // this is a "virtual" object class
|
|
addoc(OC_ABILITY, "Abilities", "A special ability", '&'); // this is a "virtual" object class
|
|
|
|
// object types
|
|
|
|
// dungeon features
|
|
addot(OT_WOODENDOOR, "wooden door", "A sturdy wooden door.", MT_WOOD, 150, OC_DFEATURE);
|
|
// GLYPH here is a special case in getglyph
|
|
addflag(lastot->flags, F_DOOR, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
|
|
addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
|
|
|
|
addot(OT_WOODENTABLE, "wooden table", "A waist-height wooden table.", MT_WOOD, 25, OC_DFEATURE);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "\\");
|
|
addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
|
|
//addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
|
addflag(lastot->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
|
|
|
|
addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 100, OC_DFEATURE);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, "");
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'");
|
|
addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_BLOCKSTHROW, B_TRUE, NA, NA, NULL);
|
|
// addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
|
|
|
|
addot(OT_STAIRSDOWN, "staircase going down", "A stone staircase winding downwards.", MT_STONE, 3000, OC_DFEATURE);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ">");
|
|
addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPPOSITESTAIRS, OT_STAIRSUP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_STAIRSUP, "staircase going up", "A stone staircase climbing upwards.", MT_STONE, 3000, OC_DFEATURE);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "<");
|
|
addflag(lastot->flags, F_CLIMBABLE, D_UP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPPOSITESTAIRS, OT_STAIRSDOWN, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_VENDINGMACHINE, "vending machine", "A gold-operated vending machine.", MT_METAL, 500, OC_DFEATURE);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, "");
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "_");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
|
|
// money etc
|
|
addot(OT_GOLD, "gold coin", "Sparkling nuggets of gold, the standard currency of Nexus.", MT_GOLD, 0.1, OC_MONEY);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 100, NA, "");
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 100, NA, "");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addot(OT_STONE, "stone", "A medium-sized roundish stone.", MT_STONE, 0.5, OC_ROCK);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, "");
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addot(OT_ASH, "pile of ash", "A pile of ash", MT_STONE, 0.1, OC_ROCK);
|
|
addflag(lastot->flags, F_GLYPH, B_TRUE, NA, NA, ",");
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, "");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addot(OT_GEMOFSEEING, "gem of seeing", "Magically enhances your eyesight.", MT_STONE, 1, OC_ROCK);
|
|
addflag(lastot->flags, F_HOLDCONFER, F_XRAYVIS, 2, NA, NULL);
|
|
addflag(lastot->flags, F_HOLDCONFER, F_DETECTAURAS, B_TRUE, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 10, NA, NULL);
|
|
|
|
// food
|
|
addot(OT_BERRY, "berry", "Juicy, brightly coloured berries.", MT_FOOD, 0.1, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 8, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 15, NA, "");
|
|
addot(OT_NUT, "peanut", "A species in the legume family.", MT_FOOD, 0.1, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 12, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 12, NA, "");
|
|
addot(OT_BANANA, "banana", "Ba-na-na-na-na-na na-na na-na-na.", MT_FOOD, 0.5, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addot(OT_APPLE, "apple", "A crunchy apple.", MT_FOOD, 0.5, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addot(OT_MUSHROOM, "mushroom", "A large brown mushroom.", MT_FOOD, 0.2, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, "");
|
|
addot(OT_BREADSTALE, "loaf of stale bread", "A small loaf of old, stale bread.", MT_FOOD, 0.5, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 80, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addot(OT_CHEESE, "chunk of cheese", "A chunk of hard cheese.", MT_FOOD, 0.5, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 85, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addot(OT_ROASTMEAT, "chunk of roast meat", "A chunk of flame-roasted flesh.", MT_FOOD, 1, OC_FOOD); // weight normally comes from corpse type
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addot(OT_BREADFRESH, "loaf of fresh bread", "A freshly-baked loaf of bread.", MT_FOOD, 0.5, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addot(OT_CHOCOLATE, "block of chocolate", "An entire block of chocolate.", MT_FOOD, 0.5, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 110, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL);
|
|
// corpses
|
|
addot(OT_CORPSEEYEBAT, "eyebat corpse", "The dead body of an eyebat.", MT_FLESH, 5, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, "");
|
|
addot(OT_CORPSEBAT, "bat corpse", "The dead body of a bat.", MT_FLESH, 5, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, "");
|
|
addot(OT_CORPSEFLY, "fly corpse", "The dead body of a giant flying insect.", MT_FLESH, 5, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, "");
|
|
addot(OT_CORPSEGLOWBUG, "glowbug corpse", "The dead body of a glowbug.", MT_FLESH, 1, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 10, NA, "");
|
|
addot(OT_CORPSEGOBLIN, "goblin corpse", "The dead body of a goblin.", MT_FLESH, 20, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 25, NA, "");
|
|
addot(OT_CORPSEHUMAN, "human corpse", "The dead body of a human.", MT_FLESH, 50, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, "");
|
|
addot(OT_CORPSEORK, "orc corpse", "The dead body of an orc.", MT_FLESH, 90, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, "");
|
|
addot(OT_CORPSERODENT, "rodent corpse", "The dead body of some kind of rodent.", MT_FLESH, 5, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 20, NA, "");
|
|
addot(OT_CORPSETROLL, "troll corpse", "The dead body of a troll.", MT_FLESH, 90, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, "");
|
|
addot(OT_CORPSEOGRE, "ogre corpse", "The dead body of an ogre.", MT_FLESH, 100, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 90, NA, "");
|
|
addot(OT_CORPSELIZARD, "lizard corpse", "The dead body of a lizard.", MT_FLESH, 1, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 20, NA, "");
|
|
|
|
addot(OT_FLESHCHUNK, "chunk of flesh", "A chunk of flesh from something.", MT_FLESH, 1, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
|
|
|
|
|
|
// potions
|
|
addot(OT_POT_AMBROSIA, "vial of ambrosia", "The nectar of the gods, said to completely restore the drinker's health.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 35, NA, NULL);
|
|
addot(OT_POT_ACID, "flask of battery acid", "Causes massive internal burning if ingested.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addot(OT_POT_ACROBATICS, "potion of acrobatics", "Allows the drinker to leap large distances.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addot(OT_POT_COMPETENCE, "potion of competence", "Permemantly increases the drinker's strength, intelligence or dexterity.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 25, NA, NULL);
|
|
|
|
addot(OT_POT_ELEMENTENDURE, "potion of endure elements", "Grants the imbiber temporary resistance to both fire and cold.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addot(OT_POT_ELEMENTIMMUNE, "potion of elemental immunity", "Grants the imbiber temporary immunity to both fire and cold.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addot(OT_POT_GASEOUSFORM, "potion of gaseous form", "Turns the drinker into a cloud of gas.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addot(OT_POT_HEALING, "potion of healing", "Restores 10-20 health to whoever drinks it.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addot(OT_POT_HEALINGMIN, "potion of minor healing", "Restores 1-8 health to whoever drinks it.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
|
|
addot(OT_POT_INVULN, "potion of invulnerability", "Grants the drinker temporary immunity to physical harm.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL);
|
|
|
|
addot(OT_POT_MAGIC, "potion of magic", "Fully restores the drinker's magical energy.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
|
|
addot(OT_POT_OIL, "potion of oil", "A bottle of cooking oil.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
|
|
addot(OT_POT_POLYMORPH, "potion of polymorph self", "Transmutes the drinker into another living race.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_POT_SANCTUARY, "potion of sanctuary", "Creates a temporary magical barrier abour the drinker.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
|
|
addot(OT_POT_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
|
|
addot(OT_POT_SPEED, "potion of speed", "Temporarily increasees the drinker's speed.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
|
|
addot(OT_POT_WATER, "potion of water", "Plain, regular water.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
addot(OT_POT_JUICE, "potion of fruit juice", "Tasty (but not very fresh) fruit juice!", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
|
|
|
// scrolls
|
|
addot(OT_SCR_NOTHING, "scroll of nothing", "Looks like a magic scroll, but doesn't do anything.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
|
|
addot(OT_MAP, "piece of graph paper", "Paper containing a set of grid-lines, intended for mapping.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_HOLDCONFER, F_PHOTOMEM, NA, IFKNOWN, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
|
|
addot(OT_SCR_CREATEMONSTER, "scroll of create monster", "Summons a (probably hostile) monster to a nearby location.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_CREATEMONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
|
|
addot(OT_SCR_DETECTAURA, "scroll of detect aura", "Senses holiness or evil near the caster.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTAURA, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
|
|
addot(OT_SCR_DETECTLIFE, "scroll of detect life", "Senses life near the caster.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTLIFE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
|
|
addot(OT_SCR_FIREBALL, "scroll of fireball", "Creates a huge ball of fire.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
|
|
addot(OT_SCR_FLAMEPILLAR, "scroll of flame column", "Creates a tall pillar of flame.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEPILLAR, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
|
|
addot(OT_SCR_FREEZEOB, "scroll of freezing touch", "Permenantly changes the next object touched into solid ice.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FREEZEOB, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
|
|
addot(OT_SCR_IDENTIFY, "scroll of identify", "Completely identifies any one item.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
|
|
|
|
addot(OT_SCR_LIGHT, "scroll of light", "Creates a permenant light source centred on the caster.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
|
|
addot(OT_SCR_MAPPING, "scroll of sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
|
|
addot(OT_SCR_MINDSCAN, "scroll of mind scan", "Reveals detailed information about the target.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_MINDSCAN, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
|
|
addot(OT_SCR_TELEPORTRND, "scroll of random teleportation", "Causes the caster to teleport to a random location within the same level.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_TELEPORTRND, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
|
|
addot(OT_SCR_WISH, "scroll of wishing", "Grants the caster any item of their choice (with some limitations).", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_WISH, NA, NA, NULL);
|
|
|
|
|
|
// spells - actually defined as object types
|
|
// MUST DEFINE THESE _AFTER_ SCROLLS
|
|
|
|
///////////////////
|
|
// allomancy
|
|
///////////////////
|
|
// l1
|
|
addot(OT_S_ABSORBMETAL, "absorb metal", "Draws mana from nearby metallic objects.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MPCOST, 0, NA, NA, NULL);
|
|
addot(OT_S_DETECTMETAL, "detect metal", "Senses any metal near the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_PULLMETAL, "pull metal", "Pulls metal objects to the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addot(OT_S_ACCELMETAL, "accelerate metal", "Greatly accelerates a metal object thrown by the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_DETONATE, "detonate", "Causes all metal objects in a location explode.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addot(OT_S_MAGSHIELD, "magnetic shield", "Surrounds the caster with magnetic force, repelling metal objects and attacks.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
// l4
|
|
addot(OT_S_ANIMATEMETAL, "animate metal", "Imbues a metallic weapon with temporary life, enabling it to fight on its own.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
|
|
///////////////////
|
|
// death
|
|
///////////////////
|
|
// l3
|
|
addot(OT_S_WEAKEN, "weaken", "Temporarily lowers the target's muscle strength.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l8
|
|
addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all life on the caster's level!", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL);
|
|
///////////////////
|
|
// divination
|
|
///////////////////
|
|
// l1
|
|
addot(OT_S_DETECTLIFE, "detect life", "Senses life near the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_MAPPING, "sense surroundings", "Magically imbues the caster with a map of his/her surroundings.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
|
|
// l7
|
|
addot(OT_S_DETECTAURA, "detect aura", "Senses holiness or evil near the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL);
|
|
// l8
|
|
addot(OT_S_IDENTIFY, "identification", "Completely identifies any one item.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL);
|
|
///////////////////
|
|
// elemental
|
|
///////////////////
|
|
// l2
|
|
addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
addot(OT_S_CONECOLD, "cone of cold", "Shoots a blast of freezing air.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_FLAMEPILLAR, "flame pillar", "Creates a tall pillar of flame.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l4
|
|
addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ELEMENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL); // TODO: should be "near victim"
|
|
///////////////////
|
|
// gravity
|
|
///////////////////
|
|
// l4
|
|
addot(OT_S_SLOW, "slowness", "Decreases the speed of the target.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l5
|
|
addot(OT_S_GRAVBOOST, "boost gravity", "Greatly increases gravity around the target, stopping them from moving.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l6
|
|
addot(OT_S_HASTE, "haste", "Increases the speed of the target.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL);
|
|
///////////////////
|
|
// life
|
|
///////////////////
|
|
// l1
|
|
addot(OT_S_HEALINGMIN, "minor healing", "Restores 1-8 health to the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL);
|
|
addot(OT_S_TURNUNDEAD, "turn undead", "Instills fear in undead creatures. Power depends on caster's skill.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_HEALING, "healing", "Restores 10-20 health to the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL);
|
|
///////////////////
|
|
// mental
|
|
///////////////////
|
|
// l2
|
|
addot(OT_S_MINDSCAN, "mind scan", "Reveals detailed information about the target.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addot(OT_S_TELEKINESIS, "telekinesis", "Mentally move or manipulate nearby objects.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
// TODO: hardcode how ai casts this
|
|
///////////////////
|
|
// modification
|
|
///////////////////
|
|
// l1
|
|
addot(OT_S_INSCRIBE, "inscribe", "Creates a magical inscription viewable to anyone standing nearby.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
addot(OT_S_LIGHT, "light", "Creates a permenant light source centred on the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_FREEZEOB, "freezing touch", "Permenantly changes the next object touched into solid ice.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
// l4
|
|
addot(OT_S_GASEOUSFORM, "gaseous form", "Changes the caster into a cloud of gas.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL);
|
|
// l6
|
|
addot(OT_S_POLYMORPHRND, "polymorph", "Transmutes the target into a random living race.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l7
|
|
addot(OT_S_POLYMORPH, "controlled polymorph", "Transmutes the target into a specified living race.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 7, NA, NA, NULL);
|
|
// TODO: hardcode how ai casts this spell
|
|
///////////////////
|
|
// summoning
|
|
///////////////////
|
|
// l2
|
|
addot(OT_S_CREATEMONSTER, "create monster", "Summons a (probably hostile) monster to a nearby location.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL);
|
|
///////////////////
|
|
// translocation
|
|
///////////////////
|
|
// l4
|
|
addot(OT_S_TELEPORTRND, "random teleportation", "Causes the caster to teleport to a random location within the same level.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL);
|
|
// l5
|
|
addot(OT_S_DISPERSAL, "dispersal", "Scatters everything in the target cell around the area.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
addot(OT_S_TELEPORT, "teleportation", "Causes the caster to teleport to a specified location within the same level.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL);
|
|
// l6
|
|
addot(OT_S_LEVTELEPORT, "level teleport", "Teleports the user to a different dungeon level.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATSELF, NA, NA, NA, NULL);
|
|
|
|
///////////////////
|
|
// wild
|
|
///////////////////
|
|
// l1
|
|
addot(OT_S_MANASPIKE, "mana spike", "Fires a small bolt of pure magical energy.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_ENERGYBOLT, "energy bolt", "Fires a medium-sized bolt of pure magical energy.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTATVICTIM, NA, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_ENERGYBLAST, "energy blast", "Causes a ring of energy to expand from the caster, hitting anything in sight.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL);
|
|
addot(OT_S_FLASH, "flash", "Causes a very bright flash, stunning anyone who sees it.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTANYWHERE, NA, NA, NA, NULL);
|
|
|
|
|
|
// divine powers
|
|
addot(OT_S_WISH, "wish", "Grants the caster any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
|
|
// abilities
|
|
addot(OT_A_JUMP, "jump", "You can leap large distances.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
//addflag(lastot->flags, F_SPELLLETTER, NA, NA, NA, "j");
|
|
|
|
|
|
// assign letters to spells/abilities
|
|
/*
|
|
ch = 'a' - 1;
|
|
|
|
// foreach spell/abil school
|
|
for (i = 0; i < SS_LAST; i++) {
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) {
|
|
// if school matches
|
|
if (hasflagval(ot->flags, F_SPELLSCHOOL, i, NA, NA, NULL)) {
|
|
if (!hasflag(ot->flags, F_SPELLLETTER)) {
|
|
char buf[2];
|
|
int found = B_TRUE;
|
|
|
|
while (found) {
|
|
objecttype_t *ot2;
|
|
// next letter!
|
|
if (ch == 'z') {
|
|
ch = '1';
|
|
} else if (ch == ':') {
|
|
ch = 'A';
|
|
} else {
|
|
ch++;
|
|
}
|
|
buf[0] = ch;
|
|
buf[1] = '\0';
|
|
// check nothing else has our current letter...
|
|
found = B_FALSE;
|
|
for (ot2 = objecttype ; ot2 ; ot2 = ot2->next) {
|
|
if (hasflagval(ot2->flags, F_SPELLLETTER, NA, NA, NA, buf)) {
|
|
found = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
addflag(ot->flags, F_SPELLLETTER, NA, NA, NA, buf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
|
|
/*
|
|
addflag(lastot->flags, F_SPELLLETTER, NA, NA, NA, "e");
|
|
*/
|
|
|
|
// tools
|
|
addot(OT_POCKETWATCH, "pocket watch", "A portable timekeeping device made to be carried in a pocket.", MT_METAL, 0.1, OC_TECH);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addot(OT_DIGITALWATCH, "digital watch", "An electronic timekeeping device which shows the time as a number.", MT_METAL, 0.1, OC_TECH);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_BLINDFOLD, "blindfold", "Short length of wide cloth, used for blocking eyesight.", MT_CLOTH, 0.01, OC_TECH);
|
|
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_BLIND, B_TRUE, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
|
|
addot(OT_C4, "block of c4", "A highly explosive plastic which explodes a medium time after activation.", MT_PLASTIC, 1, OC_TECH);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 25, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CHARGES, 5, 5, NA, NULL);
|
|
addflag(lastot->flags, F_DONTSHOWCHARGES, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RECHARGEWHENOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EXPLODEONDEATH, 30, B_BIG, B_IFACTIVATED, NULL);
|
|
addflag(lastot->flags, F_GRENADE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_BUGLAMP, "glowing flask", "A glass flask with a glowbug corpse inside.", MT_GLASS, 0.3, OC_TECH);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HOLDCONFER, F_PRODUCESLIGHT, 2, IFKNOWN, NULL);
|
|
|
|
addot(OT_CREDITCARD, "credit card", "A rectangular plastic card.", MT_PLASTIC, 0.01, OC_TECH);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_FLASHBANG, "flashbang", "A stun grenade which temporarily blinds all within sight.", MT_METAL, 1, OC_TECH);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CHARGES, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_DONTSHOWCHARGES, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RECHARGEWHENOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_FLASHONDEATH, 4, NA, B_IFACTIVATED, NULL);
|
|
addflag(lastot->flags, F_FLASHONDAM, 4, NA, B_IFACTIVATED, NULL);
|
|
addflag(lastot->flags, F_GRENADE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_GRENADE, "grenade", "An explosive weapon which explodes a short time after activation.", MT_METAL, 1, OC_TECH);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 30, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CHARGES, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_DONTSHOWCHARGES, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RECHARGEWHENOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EXPLODEONDEATH, 10, NA, B_IFACTIVATED, NULL);
|
|
addflag(lastot->flags, F_EXPLODEONDAM, 10, NA, B_IFACTIVATED, NULL);
|
|
addflag(lastot->flags, F_GRENADE, B_TRUE, NA, NA, NULL);
|
|
|
|
|
|
addot(OT_INFOVISOR, "infovisor", "Sleek looking metal visor which displays info directly into the retina.", MT_METAL, 0.2, OC_TECH);
|
|
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_EXTRAINFO, B_TRUE, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 30, NA, NULL);
|
|
|
|
addot(OT_INSECTICIDE, "can of insecticide", "A spraycan containing poisonous chemicals.", MT_METAL, 0.5, OC_TECH);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, "Where will you spray?");
|
|
addflag(lastot->flags, F_RNDCHARGES, 5, 10, NA, NULL);
|
|
|
|
addot(OT_JETPACK, "jet pack", "A portable ion-thruster which allows the wearer to fly.", MT_METAL, 10, OC_TECH);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 30, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RNDCHARGES, 10, 30, NA, NULL);
|
|
addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACTIVATECONFER, F_FLYING, B_TRUE, NA, NULL);
|
|
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 1, NA, NULL);
|
|
|
|
addot(OT_LOCKHACKER, "lock hacker", "A sophisticated machine to manipulate physical locks.", MT_METAL, 3, OC_TECH);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 20, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_LANTERNLED, "LED lantern", "A low-powered but efficient lantern which will last almost forever.", MT_METAL, 0.5, OC_TECH);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 20, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 2, NA, NULL);
|
|
|
|
addot(OT_LANTERNOIL, "oil lantern", "An oil-powered lantern which produces a lot of light.", MT_METAL, 1, OC_TECH);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 55, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERONOFF, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACTIVATECONFER, F_PRODUCESLIGHT, 3, NA, NULL);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, IFACTIVE, NULL);
|
|
addflag(lastot->flags, F_RNDCHARGES, 100, 200, NA, NULL);
|
|
addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL);
|
|
|
|
addot(OT_LOCKPICK, "lockpick", "An angled piece of metal, used to open locks.", MT_METAL, 0.05, OC_TECH);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 50, B_DIEONFAIL, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_PAPERCLIP, "paperclip", "A thin, looped wire for holding paper together.", MT_METAL, 0.01, OC_TECH);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 25, B_DIEONFAIL, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
// can use as a (very bad) weapon too...
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 1, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 50, NA, NA, NULL);
|
|
|
|
addot(OT_PICKAXE, "pickaxe", "A heavy tool for breaking rock.", MT_METAL, 8, OC_TECH);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_TELEPAD, "teleport beacon", "A metal cone which will teleport the user to the nearest similar cone.", MT_METAL, 3, OC_TECH);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_XRAYGOGGLES, "pair of xray goggles", "Bulky looking goggles which allow you to see through walls.", MT_METAL, 0.3, OC_TECH);
|
|
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_XRAYVIS, 2, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 25, NA, NULL);
|
|
|
|
// misc
|
|
|
|
|
|
addot(OT_EMPTYFLASK, "empty flask", "An empty glass flask.", MT_GLASS, 0.2, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "!");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
addot(OT_EMPTYVIAL, "empty vial", "An empty glass vial.", MT_GLASS, 0.1, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "!");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addot(OT_BROKENGLASS, "piece of broken glass", "Sharp shards of broken glass.", MT_GLASS, 0.1, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 8, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "^");
|
|
addflag(lastot->flags, F_SHARP, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addot(OT_CALTROP, "caltrop", "Connected metal spikes arranged such that one will always point upwards.", MT_METAL, 0.2, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "^");
|
|
addflag(lastot->flags, F_SHARP, 2, 5, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addot(OT_ICECHUNK, "chunk of ice", "A chunk of ice.", MT_ICE, 0.5, OC_MISC);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 3, NA, NULL);
|
|
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small puddle of water");
|
|
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "melts");
|
|
addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "melt");
|
|
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addot(OT_SOGGYPAPER, "lump of soggy paper", "A useless lump of soggy paper.", MT_WETPAPER, 0.1, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, NA, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "?");
|
|
|
|
addot(OT_VOMITPOOL, "pool of vomit", "A disgusting pool of regurgitated food.", MT_WATER, 0, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_SLIMEPOOL, "pool of slime", "A disgusting mass of sticky slime.", MT_WATER, 0, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 2, NA, NULL);
|
|
|
|
addot(OT_PUDDLEWATER, "small puddle of water", "A small puddle of water.", MT_WATER, 0, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_BLOODSTAIN, "blood stain", "A small pool of blood.", MT_BLOOD, 0, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_WOODENBARREL, "wooden barrel", "A solid wooden barrel.", MT_WOOD, 20, OC_MISC);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "(");
|
|
addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 3, 6, NA, NULL);
|
|
|
|
addot(OT_WOODENSTOOL, "wooden footstool", "A small, wooden footstool.", MT_WOOD, 5, OC_MISC);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "\\");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL);
|
|
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
|
|
|
|
addot(OT_BONE, "bone", "A bone from an unknown creature.", MT_BONE, 0.1, OC_MISC);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
|
|
// effects
|
|
addot(OT_FIRELARGE, "large fire", "A large, roaring inferno.", MT_FIRE, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little");
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "medium fire");
|
|
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_WALKDAM, 12, DT_FIRE, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL);
|
|
addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire");
|
|
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little");
|
|
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_WALKDAM, 7, DT_FIRE, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL);
|
|
addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "}");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "goes out");
|
|
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_WALKDAM, 3, DT_FIRE, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL);
|
|
|
|
|
|
addot(OT_SMOKECLOUD, "cloud of smoke", "A thick cloud of black smoke.", MT_GAS, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "thins out a little");
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of smoke");
|
|
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_SMOKEPUFF, "puff of smoke", "A small puff of black smoke.", MT_GAS, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "disperses");
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_POISONCLOUD, "cloud of gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "thins out a little");
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of gas");
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_WALKDAM, 2, DT_POISONGAS, NA, NULL);
|
|
|
|
addot(OT_POISONPUFF, "puff of gas", "A small puff of poisonous gas.", MT_GAS, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "{");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "disperses");
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_WALKDAM, 2, DT_POISONGAS, NA, NULL);
|
|
|
|
addot(OT_MAGICBARRIER, "magical barrier", "A glowing, impassable barrier of magical energy.", MT_MAGIC, 0, OC_EFFECT);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "#");
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_IMPASSABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIETEXT, B_TRUE, NA, NA, "vanishes");
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL);
|
|
|
|
// armour - body
|
|
addot(OT_COTTONSHIRT, "cotton shirt", "A comfortable white cotton shirt.", MT_CLOTH, 0.7, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
|
|
addot(OT_ARMOURLEATHER, "leather armour", "Body armour created from soft leather.", MT_LEATHER, 10, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
|
|
addot(OT_FLAKJACKET, "flak jacket", "Metal body armour, designed to stop bullets.", MT_METAL, 20, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 8, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -20, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 40, 40, NA, NULL);
|
|
addot(OT_OVERALLS, "pair of overalls", "Well-made, brightly coloured workman overalls.", MT_CLOTH, 1, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
|
addot(OT_SILKSHIRT, "silk shirt", "A lightweight, comfortable white silk shirt.", MT_CLOTH, 0.5, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
|
|
// armour - shoulders
|
|
addot(OT_CLOAK, "cloak", "A standard leather cloak.", MT_LEATHER, 4, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 6, 6, NA, NULL);
|
|
addot(OT_VELVETROBE, "velvet robe", "A luxurious velvet robe.", MT_CLOTH, 4, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -20, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL);
|
|
// armour - legs
|
|
addot(OT_CLOTHTROUSERS, "pair of cloth trousers", "A rough pair of cloth trousers.", MT_CLOTH, 2, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addot(OT_RIDINGTROUSERS, "pair of riding trousers", "A fitted pair of leather trousers.", MT_LEATHER, 2, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
|
|
addot(OT_COMBATPANTS, "pair of combat pants", "An armoured pair of camoflauged trousers.", MT_CLOTH, 2, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_LEGS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 8, 8, NA, NULL);
|
|
// armour - feet
|
|
addot(OT_SANDALS, "pair of sandals", "Comfortable pair of open leather sandals.", MT_LEATHER, 1, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
|
|
addot(OT_SHOESLEATHER, "pair of leather shoes", "Cheap and rather uncomfortable leather shoes.", MT_LEATHER, 2, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
|
|
addot(OT_BOOTSRUBBER, "pair of rubber boots", "A waterproof (but somewhat cumbersome) pair of rubber boots.", MT_RUBBER, 6, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL); // bulky
|
|
addflag(lastot->flags, F_OBHP, 8, 8, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_DTRESIST, DT_ELECTRIC, NA, NULL);
|
|
addot(OT_BOOTSLEATHER, "pair of leather boots", "A stout pair of leather boots.", MT_LEATHER, 4, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_FEET, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
|
|
// armour - gloves
|
|
addot(OT_GLOVESCLOTH, "pair of cloth gloves", "A pair of soft cloth gloves.", MT_CLOTH, 0.15, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addot(OT_GLOVESLEATHER, "pair of leather gloves", "A pair of coarse leather gloves.", MT_LEATHER, 0.25, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
|
|
addot(OT_GAUNTLETS, "pair of gauntlets", "A durable pair of metal gauntlets.", MT_METAL, 2, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HANDS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
|
|
// armour - head
|
|
addot(OT_SUNHAT, "sun hat", "Wide-brimmed hat made for working in the sun.", MT_CLOTH, 1, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
|
|
addot(OT_CAP, "cap", "Close-fitting headwear with a short shade visor at the front.", MT_CLOTH, 1, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
|
|
addot(OT_GASMASK, "gas mask", "A full face mask which protects the wearer from toxic gasses.", MT_METAL, 1, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_POISONGAS, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -5, NA, NULL);
|
|
addot(OT_HELM, "helmet", "A plain metal helmet.", MT_METAL, 2, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
|
|
addot(OT_HELMFOOTBALL, "football helmet", "A metal helmet with a grill in front of the face.", MT_METAL, 1, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -2, NA, NULL);
|
|
addot(OT_GOLDCROWN, "golden crown", "A heavy gold crown, encrusted with jewels.", MT_GOLD, 5, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
|
|
addot(OT_HELMBONE, "bone helmet", "Scary-looking helmet made from the bones of an animal (?).", MT_BONE, 1, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
|
|
// armour - eyes
|
|
addot(OT_SUNGLASSES, "sunglasses", "Tinted eyewear to protect against sunlight.", MT_PLASTIC, 0.01, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 70, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -4, NA, NULL);
|
|
addflag(lastot->flags, F_TINTED, B_TRUE, NA, NA, NULL);
|
|
addot(OT_MOTIONSCANNER, "motion scanner", "Small scanning device which detects nearby lifeforms.", MT_METAL, 1.5, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 30, NA, NULL);
|
|
addflag(lastot->flags, F_HOLDCONFER, F_DETECTLIFE, 10, NA, NULL);
|
|
addot(OT_NVGOGGLES, "nightvis goggles", "Special goggles which allow the wear to see in the dark.", MT_METAL, 1.5, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, B_TRUE, NA, NULL);
|
|
// armour - shields
|
|
addot(OT_BUCKLER, "buckler", "A small, unobtrusive wooden shield.", MT_WOOD, 3.00, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 80, NA, NULL);
|
|
addflag(lastot->flags, F_SHIELD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_SECWEAPON, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
|
|
|
|
// rings
|
|
addot(OT_RING_INVULN, "ring of invulnerability", "Grants the caster complete immunity to physical harm.", MT_METAL, 0.1, OC_RING);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_INVULNERABLE, NA, NA, NULL);
|
|
addot(OT_RING_MPREGEN, "ring of mana", "Slowly regenerates the wearer's mana.", MT_METAL, 0.1, OC_RING);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, "");
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_MPREGEN, 1, NA, NULL);
|
|
addot(OT_RING_PROTFIRE, "ring of fire immunity", "Grants the caster complete immunity to fire.", MT_METAL, 0.1, OC_RING);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, "");
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_FIRE, NA, NULL);
|
|
addot(OT_RING_REGENERATION, "ring of regeneration", "Slowly regenerates the wearer's health, even when not resting.", MT_METAL, 0.1, OC_RING);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 50, NA, "");
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_REGENERATES, 1, NA, NULL);
|
|
addot(OT_RING_RESISTMAG, "ring of magic resistance", "Renders the wearer immune to most magical effects.", MT_METAL, 0.1, OC_RING);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 25, NA, "");
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_RESISTMAG, 1, NA, NULL);
|
|
|
|
// unarmed weapons - note these damage/accuracys can be
|
|
// overridded with the lifeform flag F_HASATTACK
|
|
//
|
|
// DAMTYPE _cannot_ be overridden (yet)!
|
|
addot(OT_FISTS, "fists", "human fists", MT_FLESH, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
|
|
addot(OT_TEETH, "teeth", "teeth object", MT_BONE, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BITE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
|
|
addot(OT_CLAWS, "claws", "claws object", MT_BONE, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CLAW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
|
|
addot(OT_TOUCHPARALYZE, "paralyzing touch", "paralyzing touch object", MT_BONE, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 0, 1, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HITCONFER, F_PARALYZED, B_TRUE, NA, "2-4");
|
|
addot(OT_TOUCHPARALYZE2, "strong paralyzing touch", "strong paralyzing touch object", MT_BONE, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_TOUCH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 0, 1, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HITCONFER, F_PARALYZED, B_TRUE, NA, "5-10");
|
|
|
|
addot(OT_TAIL, "tail", "tail object", MT_FLESH, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
|
|
addot(OT_ZAPPER, "zapper", "zapper object", MT_NOTHING, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_ELECTRIC, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
|
|
// monster weapons
|
|
addot(OT_ACIDATTACK, "acidattack", "acid attack object", MT_WATER, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_ACID, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 60, NA, NA, NULL);
|
|
|
|
// stabbing weapons
|
|
addot(OT_DAGGER, "dagger", "A short stabbing weapon with a pointed blade.", MT_METAL, 1, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 10, B_BLUNTONFAIL, NA, NULL);
|
|
addot(OT_ORNDAGGER, "ornamental dagger", "This dagger is pretty, but not particularly effective.", MT_METAL, 1, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 3, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 10, B_BLUNTONFAIL, NA, NULL);
|
|
addot(OT_SHORTSWORD, "short sword", "A short blade for fighting. Better for stabbing.", MT_METAL, 2.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL);
|
|
addot(OT_RAPIER, "rapier", "A long, narrow French sword lacking a cutting edge. Made for stabbing.", MT_METAL, 2.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 8, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL);
|
|
addot(OT_TRIDENT, "trident", "A three-pronged stabbing weapon.", MT_METAL, 3, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 10, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_QUICKBLADE, "quickblade", "A short blade of exceptional quality, which somehow allows its bearer to attack faster.", MT_METAL, 1, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 35, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_ULTRAFAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addot(OT_COMBATKNIFE, "combat knife", "A sharp knife designed for military use.", MT_METAL, 1, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 2, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 10, B_BLUNTONFAIL, NA, NULL);
|
|
|
|
// chopping weapons
|
|
addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 2, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_SLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 5, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_BATTLEAXE, "battleaxe", "An axe specifically designed for combat.", MT_METAL, 3, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_SLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 10, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_GREATAXE, "greataxe", "An enormous axe made designed for combat.", MT_METAL, 5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_VERYSLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 12, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
|
|
|
|
// slashing weapons
|
|
addot(OT_KNIFE, "knife", "A moderately sharp stabbing tool.", MT_METAL, 1, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 10, B_BLUNTONFAIL, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
|
|
addot(OT_STEAKKNIFE, "steak knife", "A common kitchen knife.", MT_METAL, 0.2, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 3, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL);
|
|
addot(OT_SCYTHE, "scythe", "An agricultural hand tool for mowing grass, or reaping crops.", MT_METAL, 3, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_SLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 2, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 60, NA, NA, NULL);
|
|
addot(OT_SICKLE, "sickle", "A hand-held agricultural tool with a curved blade.", MT_METAL, 0.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addot(OT_SCIMITAR, "scimitar", "A fast, curved blade.", MT_METAL, 2, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 8, 2, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_LONGSWORD, "longsword", "Standard issue long slashing weapon.", MT_METAL, 3, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 8, 3, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_ORNSWORD, "ornamental sword", "A gleaming (but quite blunt) blade.", MT_METAL, 2, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
|
|
// polearms
|
|
addot(OT_QUARTERSTAFF, "quarterstaff", "A long, stout pole.", MT_WOOD, 2, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 8, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
|
|
addot(OT_SPEAR, "spear", "A long pole with a sharpened head.", MT_METAL, 4, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_SLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 8, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
|
|
|
|
// bashing weapons
|
|
addot(OT_STICK, "stick", "A sturdy wooden stick.", MT_WOOD, 0.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_SPANNER, "spanner", "A long, heavy metal wrench.", MT_METAL, 1, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL);
|
|
addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_WOOD, 1.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_MACE, "mace", "A weapon with a heavy head on a solid shaft used to bludgeon opponents.", MT_METAL, 3, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_NORMAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 8, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addot(OT_MORNINGSTAR, "morningstar", "An spiked mace.", MT_METAL, 3.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_SLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 10, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
|
|
addot(OT_GREATCLUB, "great club", "An enormous, very heavy, blunt instrument to hit things with.", MT_WOOD, 5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_VERYSLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 3, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
|
|
|
|
// projectile weapons
|
|
addot(OT_SLING, "sling", "Stretchy piece of rubber for launching projectiles.", MT_RUBBER, 0.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_SLOW, NA, NA, NULL);
|
|
//addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
//addflag(lastot->flags, F_DAM, 3, 4, NA, NULL);
|
|
addflag(lastot->flags, F_FIRESPEED, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AMMOOB, OT_STONE, NA, NA, NULL);
|
|
|
|
addot(OT_REVOLVER, "revolver", "Basic one-handed firearm.", MT_METAL, 1, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addflag(lastot->flags, F_FIREARM, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_FAST, NA, NA, NULL);
|
|
//addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
//addflag(lastot->flags, F_DAM, 3, 4, NA, NULL);
|
|
addflag(lastot->flags, F_FIRESPEED, 10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RANGE, 10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AMMOOB, OT_BULLET, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AMMOOB, OT_RUBBERBULLET, NA, NA, NULL);
|
|
|
|
// ammo
|
|
addot(OT_BULLET, "bullet", "A regular gun bullet.", MT_STONE, 0.1, OC_MISC);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ";");
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, "");
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_RUBBERBULLET, "rubber bullet", "A rubber gun bullet - does not do much damage.", MT_STONE, 0.1, OC_MISC);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ";");
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, "");
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
// holy weapons
|
|
addot(OT_HANDOFGOD, "hand of god", "The ultimate power.", MT_FLESH, 0.1, OC_WEAPON);
|
|
//addflag(lastot->flags, F_RARITY, H_DUNGEON, RR_UNIQUE, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKSPEED, SP_GODLIKE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_HOLY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, 100, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 500, NA, NA, NULL);
|
|
addflag(lastot->flags, F_UNIQUE, B_TRUE, NA, NA, NULL);
|
|
|
|
}
|
|
|
|
// returns the 'armourrating' flag
|
|
flag_t *isarmour(object_t *o) {
|
|
flag_t *f;
|
|
if (hasflag(o->flags, F_GOESON)) {
|
|
f = hasflag(o->flags, F_ARMOURRATING);
|
|
if (f) {
|
|
return f;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int isactivated(object_t *o) {
|
|
if (hasflag(o->flags, F_ACTIVATED)) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isammofor(object_t *ammo, object_t *gun) {
|
|
if (hasflagval(gun->flags, F_AMMOOB, ammo->type->id, NA, NA, NULL)) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
// is armour 'a' better than armour 'b'?
|
|
int isbetterarmourthan(object_t *a, object_t *b) {
|
|
int arma, armb;
|
|
flag_t *f;
|
|
if (!a) return B_FALSE;
|
|
if (!b) return B_TRUE;
|
|
|
|
f = isarmour(a);
|
|
if (f) {
|
|
arma = f->val[0];
|
|
} else {
|
|
arma = 0;
|
|
}
|
|
f = isarmour(b);
|
|
if (f) {
|
|
armb = f->val[0];
|
|
} else {
|
|
armb = 0;
|
|
}
|
|
if (arma > armb) return B_TRUE;
|
|
return B_FALSE;
|
|
|
|
}
|
|
|
|
// compare weapons using max damage
|
|
int isbetterwepthan(object_t *a, object_t *b) {
|
|
flag_t *f;
|
|
int dama,damb;
|
|
|
|
if (!a) return B_FALSE;
|
|
if (!b) return B_TRUE;
|
|
|
|
f = hasflag(a->flags, F_DAM);
|
|
if (f) {
|
|
dama = (f->val[0] * f->val[1]) + f->val[2];
|
|
} else {
|
|
dama = 0;
|
|
}
|
|
f = hasflag(b->flags, F_DAM);
|
|
if (f) {
|
|
damb = (f->val[0] * f->val[1]) + f->val[2];
|
|
} else {
|
|
damb = 0;
|
|
}
|
|
if (dama > damb) return B_TRUE;
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isblessed(object_t *o) {
|
|
if (o->blessed == B_BLESSED) return B_TRUE;
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isblessknown(object_t *o) {
|
|
if (o->blessknown) return B_TRUE;
|
|
if (gamestarted && hasflag(player->flags, F_DETECTAURAS)) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
int iscorpse(object_t *o) {
|
|
if (o->type->obclass->id == OC_CORPSE) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int iscursed(object_t *o) {
|
|
if (o->blessed == B_CURSED) return B_TRUE;
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isdrinkable(object_t *o) {
|
|
switch (o->type->obclass->id) {
|
|
case OC_POTION:
|
|
return B_TRUE;
|
|
default: break;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isedible(object_t *o) {
|
|
if (hasflag(o->flags, F_EDIBLE)) {
|
|
return B_TRUE;
|
|
}
|
|
if (o->material->id == MT_ICE) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
flag_t *isequipped(object_t *o) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_EQUIPPED);
|
|
if (f) {
|
|
return f;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int isequippedon(object_t *o, enum BODYPART bp) {
|
|
if (hasflagval(o->flags, F_EQUIPPED, bp, NA, NA, NULL)) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isfirearm(object_t *o) {
|
|
if (hasflag(o->flags, F_FIREARM)) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isflammable(object_t *o) {
|
|
if (hasflag(o->flags, F_FLAMMABLE)) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isknown(object_t *o) {
|
|
knowledge_t *k;
|
|
// if id'd, return the full name
|
|
if (hasflag(o->flags, F_IDENTIFIED)) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
for (k = knowledge; k ; k = k->next) {
|
|
if (k->id == o->type->id) {
|
|
// it DOES have a hidden name.
|
|
// does the player know about it?
|
|
if (k->known) {
|
|
return B_TRUE;
|
|
} else {
|
|
return B_FALSE;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// no hidden name, return real one
|
|
return B_TRUE;
|
|
}
|
|
|
|
|
|
// is the object fully identified?
|
|
// ie. its type is known ("potion of healing" rather than "red potion")
|
|
// AND
|
|
// you know whether it is cursed or not
|
|
int isidentified(object_t *o) {
|
|
flag_t *f;
|
|
if (!isblessknown(o)) return B_FALSE;
|
|
if (!isknown(o)) return B_FALSE;
|
|
for (f = o->flags->first ; f ; f = f->next) {
|
|
if (!f->known) return B_FALSE;
|
|
}
|
|
|
|
return B_TRUE;
|
|
}
|
|
|
|
int ismetal(enum MATERIAL mat) {
|
|
int metal = B_FALSE;
|
|
switch (mat) {
|
|
case MT_METAL:
|
|
case MT_GOLD:
|
|
metal = B_TRUE;
|
|
break;
|
|
default:
|
|
metal = B_FALSE;
|
|
break;
|
|
}
|
|
return metal;
|
|
}
|
|
|
|
int ismissile(object_t *o) {
|
|
if (hasflag(o->flags, F_MISSILE)) {
|
|
return B_TRUE;
|
|
}
|
|
// special cases...
|
|
switch (o->type->id) {
|
|
case OT_EMPTYFLASK: // (because it will shatter)
|
|
case OT_EMPTYVIAL: // (because it will shatter)
|
|
case OT_BROKENGLASS: // (because it will cut)
|
|
case OT_ICECHUNK: // (because it will cut)
|
|
return B_TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isoperable(object_t *o) {
|
|
if (hasflag(o->flags, F_OPERABLE)) return B_TRUE;
|
|
//if (o->type->obclass->id == OC_TECH) return B_TRUE;
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
// has this object changed proerties from its
|
|
// parent objecttype?
|
|
int isplainob(object_t *o) {
|
|
if (o->material != o->type->material) return B_FALSE;
|
|
if (o->weight != o->type->weight) return B_FALSE;
|
|
if (o->inscription) return B_FALSE;
|
|
if (o->blessed != B_UNCURSED) return B_FALSE;
|
|
if (isblessknown(o)) return B_FALSE;
|
|
|
|
return B_TRUE;
|
|
}
|
|
|
|
int ispourable(object_t *o) {
|
|
if (hasflag(o->flags, F_POURABLE)) {
|
|
if (o->material->id != MT_ICE) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
int ispushable(object_t *o) {
|
|
if (hasflag(o->flags, F_PUSHABLE)) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isreadable(object_t *o) {
|
|
switch (o->type->obclass->id) {
|
|
case OC_SCROLL:
|
|
return B_TRUE;
|
|
default: break;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isrotting(object_t *o) {
|
|
flag_t *f;
|
|
float pct;
|
|
if (!iscorpse(o)) return B_FALSE;
|
|
f = hasflag(o->flags, F_OBHP);
|
|
if (f) {
|
|
pct = ((float) f->val[0] / (float) f->val[1]) * 100.0;
|
|
} else {
|
|
pct = 100;
|
|
}
|
|
if (pct < 25) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isweapon(object_t *o) {
|
|
//if ((o->type->obclass->id == OC_WEAPON) && hasflag(o->flags, F_DAM)) {
|
|
if (o->type->obclass->id == OC_WEAPON) {
|
|
return B_TRUE;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int iswearable(object_t *o) {
|
|
if (hasflag(o->flags, F_GOESON)) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
void killmaterial(material_t *m) {
|
|
material_t *nextone, *lastone;
|
|
|
|
// free mem
|
|
free(m->name);
|
|
killflagpile(m->flags);
|
|
|
|
// remove from list
|
|
nextone = m->next;
|
|
if (nextone != NULL) {
|
|
nextone->prev = m->prev;
|
|
} else { /* last */
|
|
lastmaterial = m->prev;
|
|
}
|
|
|
|
if (m->prev == NULL) {
|
|
/* first */
|
|
nextone = m->next;
|
|
free(material);
|
|
material = nextone;
|
|
} else {
|
|
lastone = m->prev;
|
|
free (lastone->next );
|
|
lastone->next = nextone;
|
|
}
|
|
}
|
|
|
|
void killob(object_t *o) {
|
|
object_t *nextone, *lastone;
|
|
|
|
// remove flags conferred by this object
|
|
if (o->pile->owner) {
|
|
loseobflags(o->pile->owner, o, ALLCONFERRED);
|
|
}
|
|
|
|
// free mem
|
|
if (o->inscription) free(o->inscription);
|
|
|
|
// remove from list
|
|
nextone = o->next;
|
|
if (nextone != NULL) {
|
|
nextone->prev = o->prev;
|
|
} else { /* last */
|
|
o->pile->last = o->prev;
|
|
}
|
|
|
|
if (o->prev == NULL) {
|
|
/* first */
|
|
nextone = o->next;
|
|
o->pile->first = nextone;
|
|
free(o);
|
|
} else {
|
|
lastone = o->prev;
|
|
free (lastone->next );
|
|
lastone->next = nextone;
|
|
}
|
|
}
|
|
|
|
void killobpile(obpile_t *op) {
|
|
while (op->first) {
|
|
killob(op->first);
|
|
}
|
|
free(op);
|
|
}
|
|
|
|
void killoc(objectclass_t *oc) {
|
|
objectclass_t *nextone, *lastone;
|
|
|
|
// free mem
|
|
free(oc->name);
|
|
free(oc->desc);
|
|
if (oc->flags) killflagpile(oc->flags);
|
|
|
|
// remove from list
|
|
nextone = oc->next;
|
|
if (nextone != NULL) {
|
|
nextone->prev = oc->prev;
|
|
} else { /* last */
|
|
lastobjectclass = oc->prev;
|
|
}
|
|
|
|
if (oc->prev == NULL) {
|
|
/* first */
|
|
nextone = oc->next;
|
|
free(objectclass);
|
|
objectclass = nextone;
|
|
} else {
|
|
lastone = oc->prev;
|
|
free (lastone->next );
|
|
lastone->next = nextone;
|
|
}
|
|
}
|
|
|
|
void killot(objecttype_t *ot) {
|
|
objecttype_t *nextone, *lastone;
|
|
|
|
// free mem
|
|
free(ot->name);
|
|
free(ot->desc);
|
|
if (ot->flags) killflagpile(ot->flags);
|
|
|
|
// remove from list
|
|
nextone = ot->next;
|
|
if (nextone != NULL) {
|
|
nextone->prev = ot->prev;
|
|
} else { /* last */
|
|
lastobjecttype = ot->prev;
|
|
}
|
|
|
|
if (ot->prev == NULL) {
|
|
/* first */
|
|
nextone = ot->next;
|
|
free(objecttype);
|
|
objecttype = nextone;
|
|
} else {
|
|
lastone = ot->prev;
|
|
free (lastone->next );
|
|
lastone->next = nextone;
|
|
}
|
|
}
|
|
|
|
|
|
// animate a weapon
|
|
lifeform_t *makeanimated(lifeform_t *lf, object_t *o, int level) {
|
|
cell_t *where;
|
|
flag_t *f;
|
|
lifeform_t *newlf;
|
|
|
|
where = getrandomadjcell(lf->cell, WE_EMPTY);
|
|
if (!where) return NULL;
|
|
|
|
newlf = addlf(where, R_DANCINGWEAPON, level);
|
|
if (newlf) {
|
|
if (isplayer(lf)) {
|
|
addflag(newlf->flags, F_FRIENDLY, B_TRUE, NA, NA, NULL);
|
|
} else if (hasflag(lf->flags, F_HOSTILE)) {
|
|
addflag(newlf->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
|
|
}
|
|
|
|
addflag(lf->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL);
|
|
|
|
o = relinkob(o, newlf->pack);
|
|
weild(lf, o);
|
|
|
|
f = hasflag(o->flags, F_OBHP);
|
|
if (f) {
|
|
newlf->maxhp = f->val[1];
|
|
newlf->hp = newlf->maxhp;
|
|
}
|
|
f = hasflag(o->flags, F_OBATTACKSPEED);
|
|
if (f) {
|
|
killflagsofid(newlf->flags, F_MOVESPEED);
|
|
addflag(newlf->flags, F_MOVESPEED, f->val[0], NA, NA, NULL);
|
|
}
|
|
}
|
|
return newlf;
|
|
}
|
|
|
|
void makeknown(enum OBTYPE otid) {
|
|
knowledge_t *k;
|
|
object_t *o;
|
|
flag_t *f;
|
|
object_t *srcob[MAXPILEOBS*3];
|
|
enum FLAG fttogive[MAXPILEOBS*3];
|
|
int nobs = 0;
|
|
int i;
|
|
|
|
if (player) {
|
|
// if player is holding an object of that type with F_CONFER.. IFKNOWN... and isn't known...
|
|
// then by making the object known, we also need to give them the flag.
|
|
//
|
|
// keep a list of objects and flags here, then give them afterwards.
|
|
for (o = player->pack->first ; o ; o = o->next) {
|
|
if (o->type->id == otid) {
|
|
if (!isknown(o)) {
|
|
for (f = o->flags->first ; f ; f = f->next) {
|
|
if ((f->id == F_HOLDCONFER) && (f->val[2] == IFKNOWN)) {
|
|
srcob[nobs] = o;
|
|
fttogive[nobs] = F_HOLDCONFER;
|
|
nobs++;
|
|
} else if ((f->id == F_EQUIPCONFER) && (f->val[2] == IFKNOWN) && isequipped(o)) {
|
|
srcob[nobs] = o;
|
|
fttogive[nobs] = F_EQUIPCONFER;
|
|
nobs++;
|
|
} else if ((f->id == F_ACTIVATECONFER) && (f->val[2] == IFKNOWN) && isactivated(o)) {
|
|
srcob[nobs] = o;
|
|
fttogive[nobs] = F_ACTIVATECONFER;
|
|
nobs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (k = knowledge; k ; k = k->next) {
|
|
if (k->id == otid) {
|
|
k->known = B_TRUE;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < nobs; i++) {
|
|
giveobflags(player, srcob[i], fttogive[i]);
|
|
}
|
|
}
|
|
|
|
object_t *moveob(object_t *src, obpile_t *dst, int howmany) {
|
|
object_t *o, *existob;
|
|
int i;
|
|
int db = B_TRUE;
|
|
|
|
reason = E_OK;
|
|
|
|
if (db) dblog("DB: moveob() - moving %d x %s",howmany, src->type->name);
|
|
existob = canstackob(dst, src);
|
|
if (existob) {
|
|
if (db) dblog("DB: moveob() - found stack to join");
|
|
if (howmany == ALL) howmany = src->amt;
|
|
existob->amt += howmany;
|
|
src->amt -= howmany;
|
|
if (src->amt == 0) {
|
|
killob(src);
|
|
}
|
|
return existob;
|
|
} else {
|
|
if (db) dblog("DB: moveob() - no stack to join");
|
|
|
|
// space in destination pile?
|
|
if (getnextletter(dst, NULL) == '\0') {
|
|
reason = E_NOSPACE;
|
|
return NULL;
|
|
}
|
|
|
|
// no similar objects in the dest pile.
|
|
if ((howmany == ALL) || (howmany == src->amt)) {
|
|
if (db) dblog("DB: dropping ALL - relinking object to new pile");
|
|
// just move the whole object to the new pile
|
|
o = relinkob(src, dst);
|
|
} else {
|
|
obpile_t *tempop;
|
|
if (db) dblog("DB: moving only some of a stack.");
|
|
|
|
|
|
// create temporary object pile
|
|
tempop = addobpile(NULL, NULL);
|
|
// add new object to the temporary pile
|
|
o = addob(tempop, src->type->name);
|
|
// copy props from original object
|
|
copyobprops(o, src);
|
|
|
|
// just move some of them
|
|
for (i = 0; i < howmany; i++ ) {
|
|
// the first one is already there!
|
|
if (i != 0) {
|
|
// inc counter in temp pile
|
|
o->amt++;
|
|
}
|
|
// dec counter on original
|
|
src->amt--;
|
|
}
|
|
if (src->amt <= 0) {
|
|
killob(src);
|
|
}
|
|
// now move the object entry from the temporary pile to the
|
|
// real destination pile.
|
|
while (tempop->first) {
|
|
o = relinkob(tempop->first, dst);
|
|
}
|
|
free(tempop);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (dst->where && !dst->where->lf && haslos(player, dst->where)) {
|
|
needredraw = B_TRUE;
|
|
drawscreen();
|
|
}
|
|
//o = newobeffects(o);
|
|
|
|
return o;
|
|
}
|
|
|
|
void obaction(object_t *o, char *text) {
|
|
char obname[BUFLEN];
|
|
getobname(o, obname, o->amt);
|
|
if (o->pile->owner) {
|
|
if (isplayer(o->pile->owner)) {
|
|
msg("Your %s %s!", noprefix(obname), text);
|
|
} else if (haslos(player, o->pile->owner->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(o->pile->owner, lfname);
|
|
msg("%s%s %s %s!", lfname, getpossessive(lfname),
|
|
noprefix(obname), text);
|
|
}
|
|
} else if (haslos(player, o->pile->where)) { // on ground
|
|
msg("%s %s!", obname, text);
|
|
}
|
|
}
|
|
|
|
object_t *obexists(enum OBTYPE obid) {
|
|
map_t *m;
|
|
int x,y;
|
|
object_t *o;
|
|
lifeform_t *lf;
|
|
|
|
// do any objects of this id already exist?
|
|
for (m = firstmap ; m ; m = m->next) {
|
|
// check cells
|
|
for (y = 0; y < m->h; y++) {
|
|
for (x = 0; x < m->w; x++) {
|
|
cell_t *c;
|
|
c = getcellat(m, x, y);
|
|
if (c) {
|
|
o = hasob(c->obpile, obid);
|
|
if (o) return o;
|
|
}
|
|
}
|
|
}
|
|
// check lifeforms
|
|
for (lf = m->lf ; lf ; lf = lf->next) {
|
|
o = hasob(lf->pack, obid);
|
|
if (o) return o;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void obdie(object_t *o) {
|
|
char obname[BUFLEN];
|
|
flag_t *f;
|
|
cell_t *obloc;
|
|
|
|
f = hasflag(o->flags, F_DIECONVERT);
|
|
if (f) {
|
|
flag_t *f2;
|
|
char desc[BUFLEN];
|
|
// announce the change
|
|
real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE);
|
|
|
|
f2 = NULL;
|
|
if (o->amt > 1) {
|
|
f2 = hasflag(o->flags, F_DIECONVERTTEXTPL);
|
|
}
|
|
if (!f2) {
|
|
f2 = hasflag(o->flags, F_DIECONVERTTEXT);
|
|
}
|
|
if (f2) {
|
|
sprintf(desc, "%s", f2->text);
|
|
} else if (oblastdamtype(o) == DT_DECAY) {
|
|
sprintf(desc, "%s completed rotted away", (o->amt == 1) ? "has" : "have");
|
|
} else {
|
|
sprintf(desc, "%s destroyed", (o->amt == 1) ? "is" : "are");
|
|
}
|
|
if (strstr(o->type->name, "stain") || (o->type->id == OT_ROASTMEAT)) {
|
|
assert(0 == 1);
|
|
}
|
|
|
|
if (o->pile->owner) {
|
|
if (o->pile->owner->controller == C_PLAYER) {
|
|
msg("Your %s %s!",noprefix(obname), desc);
|
|
} else if (haslos(player, o->pile->owner->cell)) {
|
|
char monname[BUFLEN];
|
|
getlfname(o->pile->owner, monname);
|
|
msg("%s's %s %s!",monname, noprefix(obname), desc);
|
|
}
|
|
} else if (haslos(player, o->pile->where)) {
|
|
capitalise(obname);
|
|
msg("%s %s.",obname, desc);
|
|
}
|
|
|
|
// change into something else
|
|
addob(o->pile, f->text);
|
|
} else {
|
|
char desc[BUFLEN];
|
|
|
|
real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE);
|
|
if (!hasflag(o->flags, F_NOOBDIETEXT)) {
|
|
// announce the death
|
|
f = hasflag(o->flags, F_DIETEXT);
|
|
if (f) {
|
|
sprintf(desc, "%s", f->text);
|
|
} else if (oblastdamtype(o) == DT_DECAY) {
|
|
sprintf(desc, "%s completely rotted away", (o->amt == 1) ? "has" : "have" );
|
|
} else {
|
|
sprintf(desc, "%s destroyed", (o->amt == 1) ? "is" : "are");
|
|
}
|
|
|
|
if (o->pile->owner) {
|
|
if (o->pile->owner->controller == C_PLAYER) {
|
|
msg("Your %s %s!",noprefix(obname), desc);
|
|
} else if (haslos(player, o->pile->owner->cell)) {
|
|
char monname[BUFLEN];
|
|
getlfname(o->pile->owner, monname);
|
|
msg("%s's %s %s!",monname, noprefix(obname), desc);
|
|
}
|
|
} else if (haslos(player, o->pile->where)) {
|
|
msg("%s %s.",obname, desc);
|
|
}
|
|
}
|
|
|
|
// explodes?
|
|
f = hasflag(o->flags, F_EXPLODEONDEATH);
|
|
if (f) {
|
|
if (f->val[2] == B_IFACTIVATED) {
|
|
if (isactivated(o)) {
|
|
explodeob(o, f, (f->val[1] == B_BIG) ? 1 : 0);
|
|
}
|
|
} else {
|
|
explodeob(o, f, (f->val[1] == B_BIG) ? 1 : 0);
|
|
}
|
|
}
|
|
|
|
// flashes?
|
|
f = hasflag(o->flags, F_FLASHONDEATH);
|
|
if (f) {
|
|
if (f->val[2] == B_IFACTIVATED) {
|
|
if (isactivated(o)) {
|
|
brightflash(getoblocation(o),f->val[0], NULL);
|
|
}
|
|
} else {
|
|
brightflash(getoblocation(o),f->val[0], NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
obloc = o->pile->where;
|
|
killob(o);
|
|
// redraw
|
|
if (obloc && !obloc->lf && haslos(player, obloc)) {
|
|
needredraw = B_TRUE;
|
|
drawscreen();
|
|
}
|
|
}
|
|
|
|
int obfits(object_t *o, obpile_t *op) {
|
|
if (countobs(op) >= MAXPILEOBS) {
|
|
return B_FALSE;
|
|
}
|
|
return B_TRUE;
|
|
}
|
|
|
|
enum DAMTYPE oblastdamtype(object_t *o) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_LASTDAMTYPE);
|
|
if (f) {
|
|
return f->val[0];
|
|
}
|
|
return DT_NONE;
|
|
}
|
|
|
|
flag_t *obproduceslight(object_t *o) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_PRODUCESLIGHT);
|
|
if (f) {
|
|
if (f->val[2] == IFACTIVE) {
|
|
if (isactivated(o)) return f;
|
|
} else {
|
|
return f;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// has this object changed proerties from its
|
|
// parent objecttype?
|
|
int obpropsmatch(object_t *a, object_t *b) {
|
|
if (a->type != b->type) return B_FALSE;
|
|
if (a->material != b->material) return B_FALSE;
|
|
if (a->weight != b->weight) return B_FALSE;
|
|
if (a->inscription || b->inscription) return B_FALSE;
|
|
// only really need to check one of them, because at this point
|
|
// we know they are of the same type.
|
|
if (!hasflag(a->flags, F_NOBLESS) && !hasflag(b->flags, F_NOBLESS)) {
|
|
if (a->blessed != b->blessed) return B_FALSE;
|
|
if (isblessknown(a) != isblessknown(b)) return B_FALSE;
|
|
}
|
|
return B_TRUE;
|
|
}
|
|
|
|
int operate(lifeform_t *lf, object_t *o) {
|
|
char buf[BUFLEN],obname[BUFLEN];
|
|
int playercansee;
|
|
cell_t *where = NULL;
|
|
flag_t *f;
|
|
|
|
getobname(o, obname, 1);
|
|
|
|
if ((lf->controller == C_PLAYER) || haslos(player, lf->cell)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
|
|
// must know what a tool is before you can use it
|
|
if (!isknown(o)) {
|
|
if (lf->controller == C_PLAYER) {
|
|
msg("You don't know how to use that (yet)!");
|
|
}
|
|
return B_TRUE;
|
|
}
|
|
|
|
|
|
// ask for target, if required
|
|
f = hasflag(o->flags, F_OPERNEEDTARGET);
|
|
if (f) {
|
|
where = askcoords(f->text, f->val[0]);
|
|
if (!where) {
|
|
// cancel.
|
|
msg("Cancelled.");
|
|
return B_TRUE;
|
|
} else {
|
|
if ((f->val[1] & TR_NEEDLOS) && !haslos(lf, where)) {
|
|
msg("You can't see there!");
|
|
return B_TRUE;
|
|
}
|
|
if ((f->val[1] & TR_NEEDLOF) && !haslof(lf, where)) {
|
|
msg("You have no line of fire to there!");
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
touch(lf, o);
|
|
if (hasflag(o->flags, F_DEAD)) return B_TRUE;
|
|
|
|
// TODO: change to be based on item type
|
|
// TODO: move this to the end in case 'operate' fails
|
|
taketime(lf, getmovespeed(lf));
|
|
|
|
/*
|
|
if (lf->controller != C_PLAYER) {
|
|
|
|
if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s operates %s.", buf, obname);
|
|
}
|
|
}
|
|
*/
|
|
|
|
// objects with charges...
|
|
if (hasflag(o->flags, F_OPERUSECHARGE)) { // operating toggles on/off
|
|
int chargesleft;
|
|
chargesleft = getcharges(o);
|
|
if (chargesleft > 0) {
|
|
chargesleft = usecharge(o);
|
|
// TODO: notify if getting low
|
|
} else {
|
|
if (isplayer(lf)) {
|
|
nothinghappens();
|
|
// you know it's out
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
f->known = B_TRUE;
|
|
return B_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (hasflag(o->flags, F_OPERONOFF)) { // operating toggles on/off
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_ACTIVATED);
|
|
if (f) {
|
|
turnoff(lf, o);
|
|
} else {
|
|
turnon(lf, o);
|
|
}
|
|
} else if (hasflag(o->flags, F_FIREARM)) { // special case - change ammo
|
|
object_t *oo;
|
|
// construct list of possible ammo
|
|
clearretobs();
|
|
for (oo = lf->pack->first ; oo ; oo = oo->next) {
|
|
if (isammofor(oo, o)) {
|
|
retobs[nretobs] = oo;
|
|
nretobs++;
|
|
}
|
|
}
|
|
if (nretobs <= 0) {
|
|
sprintf(buf, "You have no ammo for your %s!",noprefix(obname));
|
|
msg(buf);
|
|
return B_TRUE;
|
|
} else {
|
|
sprintf(buf, "Load %s with what ammo",obname);
|
|
oo = askobject(lf->pack, buf, NULL, AO_SPECIFIED);
|
|
if (oo) {
|
|
setammo(lf, oo);
|
|
}
|
|
}
|
|
} else if (o->type->id == OT_INSECTICIDE) {
|
|
int seen = B_FALSE;
|
|
// if above half charges, big spray
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
if (f->val[0] >= (f->val[1] / 2)) {
|
|
// big spray
|
|
int dir;
|
|
cell_t *c;
|
|
for (dir = DC_N; dir <= DC_W; dir += 2) {
|
|
c = getcellindir(where, dir);
|
|
if (c && cellwalkable(NULL, c, NULL)) {
|
|
o = addob(c->obpile, "puff of gas");
|
|
}
|
|
}
|
|
// big spray
|
|
addob(where->obpile, "cloud of gas");
|
|
if (isplayer(lf)) {
|
|
msg("Psssssssst!");
|
|
seen = B_TRUE;
|
|
} else if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
msg("%s%s %s emits a spray of gas.", buf, getpossessive(buf), noprefix(obname));
|
|
seen = B_TRUE;
|
|
}
|
|
} else {
|
|
// little spray
|
|
addob(where->obpile, "puff of gas");
|
|
if (isplayer(lf)) {
|
|
msg("Psst!");
|
|
seen = B_TRUE;
|
|
} else if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
msg("%s%s %s emits a puff of gas.", buf, getpossessive(buf), noprefix(obname));
|
|
seen = B_TRUE;
|
|
}
|
|
}
|
|
// announce
|
|
if (!seen) {
|
|
youhear(where, "something spraying.");
|
|
}
|
|
} else if (o->type->id == OT_POCKETWATCH) {
|
|
if (lf->controller == C_PLAYER) {
|
|
// TODO: if above ground, use wantpm (ie. can see the sun)
|
|
gettimetextfuzzy(buf, B_FALSE);
|
|
msg("It is currently %s.",buf);
|
|
} else if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
msg("%s looks at %s.",buf, obname);
|
|
}
|
|
} else if (o->type->id == OT_DIGITALWATCH) {
|
|
if (lf->controller == C_PLAYER) {
|
|
gettimetext(buf);
|
|
msg("It is currently %s.",buf);
|
|
} else if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s looks at %s.",buf, obname);
|
|
}
|
|
} else if ((o->type->id == OT_LOCKPICK)
|
|
|| (o->type->id == OT_PAPERCLIP)
|
|
|| (o->type->id == OT_CREDITCARD)) {
|
|
char ch;
|
|
int dir;
|
|
// ask direction
|
|
ch = askchar("Lockpick in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
|
|
dir = chartodir(ch);
|
|
if (dir == D_NONE) {
|
|
clearmsg();
|
|
return B_TRUE;
|
|
} else {
|
|
cell_t *c;
|
|
c = getcellindir(player->cell, dir);
|
|
if (c) {
|
|
object_t *targ;
|
|
// something to lockpick there?
|
|
targ = hasobwithflag(c->obpile, F_LOCKED);
|
|
if (targ) {
|
|
lockpick(player, targ, o);
|
|
} else {
|
|
// fail
|
|
msg("There is nothing locked there!");
|
|
}
|
|
} else {
|
|
clearmsg();
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
} else if (o->type->id == OT_LOCKHACKER) {
|
|
char ch;
|
|
int dir;
|
|
// ask direction
|
|
ch = askchar("Manipulate lock in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
|
|
dir = chartodir(ch);
|
|
if (dir == D_NONE) {
|
|
clearmsg();
|
|
return B_TRUE;
|
|
} else {
|
|
cell_t *c;
|
|
c = getcellindir(lf->cell, dir);
|
|
if (c) {
|
|
object_t *oo,*nextoo;
|
|
// lock/unlock everything there
|
|
for (oo = c->obpile->first ; oo ; oo = nextoo) {
|
|
nextoo = oo->next;
|
|
if (hasflag(oo->flags, F_LOCKABLE)) {
|
|
flag_t *f;
|
|
f = hasflag(oo->flags, F_LOCKED);
|
|
if (f) {
|
|
killflag(f);
|
|
if (isplayer(lf)) {
|
|
msg("Your %s beeps.", noprefix(obname));
|
|
} else if (haslos(player, lf->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s%s %s beeps.", lfname, getpossessive(lfname),
|
|
noprefix(obname));
|
|
}
|
|
} else {
|
|
addflag(oo->flags, F_LOCKED, B_TRUE, NA, NA, NULL);
|
|
if (isplayer(lf)) {
|
|
msg("Your %s buzzes.", noprefix(obname));
|
|
} else if (haslos(player, lf->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s%s %s buzzes.", lfname, getpossessive(lfname),
|
|
noprefix(obname));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
clearmsg();
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
} else if (o->type->id == OT_PICKAXE) {
|
|
int ch,dir;
|
|
cell_t *c;
|
|
ch = askchar("Dig in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
|
|
dir = chartodir(ch);
|
|
c = getcellindir(player->cell, dir);
|
|
if (c) {
|
|
if (isdiggable(c)) {
|
|
if (isplayer(lf)) {
|
|
msg("You dig through the wall.");
|
|
} else if (haslos(player, lf->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s digs through a wall.",lfname);
|
|
}
|
|
// replace wall
|
|
setcelltype(c, getemptycelltype(c->map->habitat));
|
|
// redraw screen
|
|
drawscreen();
|
|
// takes extra time
|
|
taketime(lf, getmovespeed(lf)*9);
|
|
} else {
|
|
if (isplayer(lf)) {
|
|
msg("This wall is too hard to dig.");
|
|
}
|
|
}
|
|
} else {
|
|
if (isplayer(lf)) {
|
|
msg("You swing your %s through the air.",noprefix(obname));
|
|
}
|
|
taketime(lf, getmovespeed(lf));
|
|
}
|
|
} else if (o->type->id == OT_TELEPAD) {
|
|
map_t *m;
|
|
cell_t *c,*dst = NULL;
|
|
int x,y;
|
|
int closest = 99999;
|
|
m = lf->cell->map;
|
|
// find closest pad
|
|
for (y = 0; y < m->h; y++) {
|
|
for (x = 0; x < m->w; x++) {
|
|
c = getcellat(m, x, y);
|
|
if (hasob(c->obpile, OT_TELEPAD)) {
|
|
int thisdist;
|
|
thisdist = getcelldist(lf->cell, c);
|
|
if (thisdist < closest) {
|
|
closest = thisdist;
|
|
dst = c;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (dst) {
|
|
// teleport there
|
|
teleportto(lf, dst);
|
|
} else {
|
|
// nothing happens
|
|
if (isplayer(lf)) {
|
|
nothinghappens();
|
|
}
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
int pilehasletter(obpile_t *op, char let) {
|
|
object_t *o;
|
|
int found = B_FALSE;
|
|
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->letter == let) {
|
|
found = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
int pour(lifeform_t *lf, object_t *o) {
|
|
char buf[BUFLEN],obname[BUFLEN],lfname[BUFLEN],dstname[BUFLEN];
|
|
int playercansee;
|
|
char ch;
|
|
object_t *dst;
|
|
|
|
getobname(o, obname, 1);
|
|
getlfname(lf, lfname);
|
|
|
|
if (isplayer(lf) || haslos(player, lf->cell)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
// tip onto what?
|
|
sprintf(buf, "Pour %s onto the ground", obname);
|
|
ch = askchar(buf, "yn", "y", B_TRUE);
|
|
if (ch == 'y') {
|
|
dst = NULL;
|
|
} else {
|
|
sprintf(buf, "Pour %s onto what", obname);
|
|
// tip onto another object
|
|
dst = askobject(lf->pack, buf, NULL, AO_NONE);
|
|
if (!dst) {
|
|
msg("Cancelled.");
|
|
return B_TRUE;
|
|
} else if (dst->type->obclass->id == OC_POTION) {
|
|
getobname(dst, buf, dst->amt);
|
|
msg("%s can't hold any more liquid!",buf);
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
taketime(lf, SPEED_MOVE);
|
|
|
|
if (dst) {
|
|
flag_t *refillflag;
|
|
|
|
// pour 'o' onto 'dst'
|
|
getobname(dst, dstname, dst->amt);
|
|
|
|
// specal cases first...
|
|
refillflag = hasflag(dst->flags, F_REFILLWITH);
|
|
if (refillflag) {
|
|
flag_t *f;
|
|
|
|
if (refillflag->val[0] == o->type->id) {
|
|
// refill destination
|
|
f = hasflag(dst->flags, F_CHARGES);
|
|
if (f) {
|
|
f->val[0] = f->val[1];
|
|
if (isplayer(lf)) {
|
|
msg("You refill your %s.", noprefix(dstname));
|
|
// we now know what the potion was
|
|
if (!isknown(o)) makeknown(o->type->id);
|
|
} else if (haslos(player, lf->cell)) {
|
|
msg("%s refills %s with %s.", lfname, dstname, obname);
|
|
// we now know what the potion was
|
|
if (!isknown(o)) makeknown(o->type->id);
|
|
}
|
|
}
|
|
} else {
|
|
// nothing happens
|
|
if (isplayer(lf)) {
|
|
msg("You refill your %s with %s. It doesn't seem to do much.", obname);
|
|
} else if (haslos(player, lf->cell)) {
|
|
msg("%s refills %s with %s.", lfname, dstname, obname);
|
|
}
|
|
}
|
|
} else if ((o->type->id == OT_POT_WATER) && (o->blessed == B_BLESSED)) { // holy water!
|
|
if (isplayer(lf)) {
|
|
msg("You pour %s onto %s.", obname,dstname);
|
|
}
|
|
o->blessknown = B_TRUE;
|
|
// bless whatever we poured onto
|
|
blessob(dst);
|
|
// we now know that this is holy water
|
|
if (!isknown(o)) makeknown(o->type->id);
|
|
} else if (o->type->id == OT_POT_INVULN) {
|
|
flag_t *f;
|
|
f = hasflag(dst->flags, F_DAMAGABLE);
|
|
if (f) {
|
|
if (isplayer(lf)) {
|
|
msg("Your %s looks invulnerable!",noprefix(dstname));
|
|
if (!isknown(o)) makeknown(o->type->id);
|
|
appendinscription(dst, "invuln");
|
|
}
|
|
killflag(f);
|
|
}
|
|
} else if (o->type->id == OT_POT_RESTORATION) {
|
|
flag_t *f, *nextf;
|
|
if (isplayer(lf)) {
|
|
msg("Your %s looks as good as new!",noprefix(dstname));
|
|
}
|
|
// restore orig material
|
|
if (dst->material != dst->type->material) {
|
|
changemat(dst, dst->type->material->id);
|
|
}
|
|
// remove blessings/curses
|
|
setblessed(o, B_UNCURSED);
|
|
o->blessknown = B_TRUE;
|
|
// remove bonuses
|
|
killflagsofid(o->flags, F_BONUS);
|
|
// remove temporary flags
|
|
for (f = o->flags->first ; f ; f = nextf) {
|
|
nextf = f->next;
|
|
if (f->lifetime > 0) {
|
|
killflag(f);
|
|
}
|
|
}
|
|
|
|
if (!isknown(o)) makeknown(o->type->id);
|
|
} else { // default
|
|
if (isplayer(lf)) {
|
|
msg("You pour %s onto %s.", obname,dstname);
|
|
msg("%s gets wet.", dstname);
|
|
}
|
|
takedamage(dst, 0, DT_WATER);
|
|
}
|
|
} else {
|
|
// pour onto ground
|
|
if (isplayer(lf)) {
|
|
msg("You pour %s onto the ground.", obname);
|
|
} else if (haslof(player, lf->cell)) {
|
|
msg("%s pours %s onto the ground.", lfname, obname);
|
|
}
|
|
addob(lf->cell->obpile, "small puddle of water");
|
|
}
|
|
|
|
// empty the flask
|
|
addemptyob(lf->pack, o);
|
|
// remove src
|
|
removeob(o, 1);
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
void quaff(lifeform_t *lf, object_t *o) {
|
|
char buf[BUFLEN],obname[BUFLEN];
|
|
int willid = B_FALSE;
|
|
int playercansee;
|
|
int forcedrop = B_FALSE;
|
|
int seen;
|
|
|
|
getobname(o, obname, 1);
|
|
|
|
if ((lf->controller == C_PLAYER) || haslos(player, lf->cell)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
taketime(lf, SPEED_DRINK);
|
|
|
|
touch(lf, o);
|
|
if (hasflag(o->flags, F_DEAD)) return;
|
|
|
|
if (o->material->id == MT_ICE) {
|
|
if (lf->controller == C_PLAYER) {
|
|
msg("You can't drink this, it's frozen!");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (lf->controller != C_PLAYER) {
|
|
if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s drinks %s!", buf, obname);
|
|
}
|
|
}
|
|
|
|
// figure out whether to id the object
|
|
willid = B_FALSE;
|
|
if (playercansee) {
|
|
switch (o->type->id) {
|
|
case OT_POT_HEALING:
|
|
case OT_POT_HEALINGMIN:
|
|
if (lf->hp < lf->maxhp) {
|
|
willid = B_TRUE;
|
|
}
|
|
break;
|
|
default:
|
|
willid = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!isknown(o) && willid) {
|
|
// id the potion
|
|
makeknown(o->type->id);
|
|
real_getobname(o, obname, 1, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness
|
|
if (lf->controller == C_PLAYER) {
|
|
// tell the player
|
|
msg("This is %s!",obname);
|
|
more();
|
|
drawmsg();
|
|
}
|
|
}
|
|
|
|
|
|
// handle special cases where the quaff effect
|
|
// is different to the throw effect.
|
|
if (o->type->id == OT_POT_WATER) {
|
|
switch (o->blessed) {
|
|
case B_BLESSED:
|
|
if (hasflag(lf->flags, F_UNDEAD)) {
|
|
if (isplayer(lf)) {
|
|
msg("This tastes like water, but burns like acid!");
|
|
} else if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
msg("%s writhes in agony!", buf);
|
|
}
|
|
losehp(lf, rnd(5,15), DT_HOLY, NULL, "drinking holy water");
|
|
// we now know that it is blessed
|
|
o->blessknown = B_TRUE;
|
|
} else {
|
|
msg("Mmm, holy water.");
|
|
// we now know that it is blessed
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
break;
|
|
case B_UNCURSED:
|
|
msg("Mmm, water.");
|
|
break;
|
|
case B_CURSED:
|
|
msg("Yuck! Something is wrong with this water.");
|
|
break;
|
|
}
|
|
if (isplayer(lf) || haslos(player, lf->cell)) {
|
|
seen = B_TRUE;
|
|
}
|
|
modhunger(lf, -pctof(0.05, (float)HUNGERCONST));
|
|
} else if (o->type->id == OT_POT_JUICE) {
|
|
if (isplayer(lf)) {
|
|
switch (o->blessed) {
|
|
case B_BLESSED:
|
|
msg("Mmm, fruit juice!");
|
|
break;
|
|
case B_UNCURSED:
|
|
msg("Mmm, fruit juice!");
|
|
break;
|
|
case B_CURSED:
|
|
msg("Yuck! This tastes like rotten fruit.");
|
|
break;
|
|
}
|
|
seen = B_TRUE;
|
|
}
|
|
if (o->blessed != B_CURSED) {
|
|
modhunger(lf, -pctof(10, (float)HUNGERCONST));
|
|
}
|
|
} else {
|
|
potioneffects(lf, o->type->id, o->blessed, &seen);
|
|
}
|
|
|
|
if (seen) {
|
|
o->blessknown = B_TRUE;
|
|
makeknown(o->type->id);
|
|
}
|
|
|
|
if (forcedrop) {
|
|
// try to add an empty container to the ground
|
|
addemptyob(lf->cell->obpile, o);
|
|
} else {
|
|
// try to add an empty container to our pack
|
|
addemptyob(lf->pack, o);
|
|
}
|
|
// lose the potion
|
|
removeob(o, 1);
|
|
|
|
}
|
|
|
|
void potioneffects(lifeform_t *lf, enum OBTYPE oid, enum BLESSTYPE isblessed, int *seen) {
|
|
char buf[BUFLEN];
|
|
unsigned int dam;
|
|
int i;
|
|
int first,dir;
|
|
int amt;
|
|
int failed;
|
|
int seenbyplayer;
|
|
|
|
if (isplayer(lf)) {
|
|
seenbyplayer = B_TRUE;
|
|
} else if (haslos(player, lf->cell)) {
|
|
seenbyplayer = B_TRUE;
|
|
} else {
|
|
seenbyplayer = B_FALSE;
|
|
}
|
|
|
|
if (seen) {
|
|
*seen = seenbyplayer;
|
|
}
|
|
|
|
switch (oid) {
|
|
case OT_POT_ACID:
|
|
dam = rnd(5,15);
|
|
losehp(lf, dam, DT_ACID, NULL, "drinking acid");
|
|
if (lf->controller == C_PLAYER) {
|
|
msg("Your suffer massive internal burning!");
|
|
} else if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s writhes in agony!", buf);
|
|
}
|
|
break;
|
|
case OT_POT_ACROBATICS:
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily jumpy.");
|
|
}
|
|
break;
|
|
}
|
|
|
|
// how long for?
|
|
i = geteffecttime(5,10, isblessed);
|
|
|
|
if (lfhasflagval(lf, F_CANWILL, OT_A_JUMP, NA, NA, NULL)) {
|
|
nothinghappens();
|
|
seenbyplayer = B_FALSE;
|
|
if (seen) *seen = B_FALSE;
|
|
} else {
|
|
addtempflag(lf->flags, F_CANWILL, OT_A_JUMP, NA, NA, NULL, i);
|
|
}
|
|
break;
|
|
case OT_POT_AMBROSIA:
|
|
// fix hunger
|
|
i = gethungerlevel(gethungerval(lf));
|
|
if (i > 0) {
|
|
modhunger(lf, -i);
|
|
}
|
|
// fix hp
|
|
if ((lf->hp < lf->maxhp) && !hasmr(lf)) {
|
|
gainhp(lf, lf->maxhp); // ie. full hp
|
|
if (lf->controller == C_PLAYER) {
|
|
msg("You feel completely healed!");
|
|
} else if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
msg("%s looks completely healed!", buf);
|
|
}
|
|
} else {
|
|
if (isplayer(lf)) {
|
|
msg("This makes you feel incredible!");
|
|
}
|
|
}
|
|
break;
|
|
case OT_POT_COMPETENCE:
|
|
failed = B_TRUE;
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily %s.", (isblessed == B_CURSED) ? "incompetent" : "more competent");
|
|
}
|
|
break;
|
|
}
|
|
if (isblessed == B_CURSED) {
|
|
amt = -1;
|
|
} else {
|
|
amt = 1;
|
|
}
|
|
// select a random attribute
|
|
if (isblessed == B_BLESSED) {
|
|
// modify all attributes
|
|
if (!modattr(lf, A_STR, amt)) failed = B_FALSE;
|
|
if (!modattr(lf, A_DEX, amt)) failed = B_FALSE;
|
|
if (!modattr(lf, A_IQ, amt)) failed = B_FALSE;
|
|
} else {
|
|
// modify just one attribute
|
|
i = rnd(1,3);
|
|
switch (i) {
|
|
case 1:
|
|
if (!modattr(lf, A_STR, amt)) failed = B_FALSE;
|
|
break;
|
|
case 2:
|
|
if (!modattr(lf, A_DEX, amt)) failed = B_FALSE;
|
|
break;
|
|
case 3:
|
|
if (!modattr(lf, A_IQ, amt)) failed = B_FALSE;
|
|
break;
|
|
}
|
|
}
|
|
if (failed) {
|
|
if (isplayer(lf)) {
|
|
nothinghappens();
|
|
}
|
|
if (seen) *seen = B_FALSE;
|
|
} else {
|
|
if (seen) *seen = B_TRUE;
|
|
}
|
|
break;
|
|
case OT_POT_ELEMENTENDURE:
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily resistant to the elements.");
|
|
}
|
|
break;
|
|
}
|
|
// how long for?
|
|
i = geteffecttime(15,25,isblessed);
|
|
|
|
if (!lfhasflagval(lf, F_DTRESIST, DT_FIRE, NA, NA, NULL)) {
|
|
addtempflag(lf->flags, F_DTRESIST, DT_FIRE, NA, NA, NULL, i);
|
|
}
|
|
if (!lfhasflagval(lf, F_DTRESIST, DT_COLD, NA, NA, NULL)) {
|
|
addtempflag(lf->flags, F_DTRESIST, DT_COLD, NA, NA, NULL, i);
|
|
}
|
|
break;
|
|
case OT_POT_ELEMENTIMMUNE:
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily immune to the elements.");
|
|
}
|
|
break;
|
|
}
|
|
// how long for?
|
|
i = geteffecttime(15,25,isblessed);
|
|
|
|
if (!lfhasflagval(lf, F_DTIMMUNE, DT_FIRE, NA, NA, NULL)) {
|
|
addtempflag(lf->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL, i);
|
|
}
|
|
if (!lfhasflagval(lf, F_DTIMMUNE, DT_COLD, NA, NA, NULL)) {
|
|
addtempflag(lf->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL, i);
|
|
}
|
|
break;
|
|
case OT_POT_GASEOUSFORM:
|
|
dospelleffects(lf, OT_S_GASEOUSFORM, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_HEALING:
|
|
dospelleffects(lf, OT_S_HEALING, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_HEALINGMIN:
|
|
dospelleffects(lf, OT_S_HEALINGMIN, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_INVULN:
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily invulnerable.");
|
|
}
|
|
break;
|
|
}
|
|
i = geteffecttime(5,15,isblessed);
|
|
|
|
if (!lfhasflagval(lf, F_INVULNERABLE, B_TRUE, NA, NA, NULL)) {
|
|
addtempflag(lf->flags, F_INVULNERABLE, B_TRUE, NA, NA, NULL, i);
|
|
}
|
|
break;
|
|
case OT_POT_MAGIC:
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel your magical energy temporarily pulse.");
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (lf->maxmp > 0) {
|
|
msg("Your magical energy is restored.");
|
|
lf->mp = lf->maxmp;
|
|
} else {
|
|
nothinghappens();
|
|
if (seen) *seen = B_FALSE;
|
|
}
|
|
|
|
break;
|
|
case OT_POT_OIL:
|
|
if (isplayer(lf)) {
|
|
char buf[BUFLEN];
|
|
switch (rnd(1,5)) {
|
|
case 1: strcpy(buf, "cooking"); break;
|
|
case 2: strcpy(buf, "olive"); break;
|
|
case 3: strcpy(buf, "peanut"); break;
|
|
case 4: strcpy(buf, "grapefruit"); break;
|
|
case 5: strcpy(buf, "vegetable"); break;
|
|
}
|
|
msg("Mmm, %s oil.", buf);
|
|
}
|
|
break;
|
|
case OT_POT_POLYMORPH:
|
|
if (isblessed == B_BLESSED) {
|
|
// controlled polymorph
|
|
dospelleffects(lf, OT_S_POLYMORPH, lf, NULL, NULL, isblessed, NULL);
|
|
} else {
|
|
// random polymorph
|
|
dospelleffects(lf, OT_S_POLYMORPHRND, lf, NULL, NULL, isblessed, NULL);
|
|
}
|
|
break;
|
|
case OT_POT_RESTORATION:
|
|
failed = B_TRUE;
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily restored.");
|
|
}
|
|
break;
|
|
}
|
|
if (getattr(lf,A_STR) < lf->baseatt[A_STR]) {
|
|
setattr(lf, A_STR, lf->baseatt[A_STR]);
|
|
if (isplayer(lf)) msg("Your strength is restored!");
|
|
failed = B_FALSE;
|
|
}
|
|
if (getattr(lf,A_DEX) < lf->baseatt[A_DEX]) {
|
|
setattr(lf, A_DEX, lf->baseatt[A_DEX]);
|
|
if (isplayer(lf)) msg("Your dexterity is restored!");
|
|
failed = B_FALSE;
|
|
}
|
|
if (getattr(lf,A_IQ) < lf->baseatt[A_IQ]) {
|
|
setattr(lf, A_IQ, lf->baseatt[A_IQ]);
|
|
if (isplayer(lf)) msg("Your intelligence is restored!");
|
|
failed = B_FALSE;
|
|
}
|
|
|
|
if (failed) {
|
|
if (isplayer(lf)) nothinghappens();
|
|
if (seen) *seen = B_FALSE;
|
|
} else {
|
|
if (seen) *seen = B_TRUE;
|
|
}
|
|
break;
|
|
case OT_POT_SANCTUARY:
|
|
// how long for?
|
|
//i = gethealtime(lf); // TODO: change...
|
|
if (hasmr(lf)) {
|
|
if (isplayer(lf)) {
|
|
nothinghappens();
|
|
}
|
|
break;
|
|
}
|
|
i = 15;
|
|
first = B_TRUE;
|
|
|
|
// add holy barriers all around
|
|
for (dir = DC_N; dir <= DC_NW; dir++) {
|
|
cell_t *c;
|
|
c = getcellindir(lf->cell, dir);
|
|
if (c && isempty(c)) {
|
|
object_t *newob;
|
|
newob = addob(c->obpile, "magical barrier");
|
|
addflag(newob->flags, F_OBHP, i, i, NA, NULL);
|
|
if (first && haslos(player, c)) {
|
|
msg("A magical barrier appears!");
|
|
first = B_FALSE;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case OT_POT_SPEED:
|
|
if (isblessed == B_BLESSED) {
|
|
dospelleffects(lf, OT_S_HASTE, lf, NULL, NULL, B_BLESSED, NULL);
|
|
} else if (isblessed == B_CURSED) {
|
|
dospelleffects(lf, OT_S_SLOW, lf, NULL, NULL, B_UNCURSED, NULL);
|
|
} else { // uncursed
|
|
dospelleffects(lf, OT_S_HASTE, lf, NULL, NULL, B_UNCURSED, NULL);
|
|
}
|
|
if (seen) *seen = B_TRUE;
|
|
break;
|
|
case OT_POT_WATER:
|
|
// this should never happen
|
|
msg("DB: OT_POT_WATER triggered in poteffects.");
|
|
break;
|
|
default: // nothing happens
|
|
break;
|
|
}
|
|
}
|
|
|
|
void readsomething(lifeform_t *lf, object_t *o) {
|
|
flag_t *f;
|
|
char buf[BUFLEN],obname[BUFLEN];
|
|
int playercansee;
|
|
int willid = B_FALSE;
|
|
int needsob = B_FALSE;
|
|
|
|
getobname(o, obname, 1);
|
|
|
|
if ((lf->controller == C_PLAYER) || haslos(player, lf->cell)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
|
|
taketime(lf, SPEED_READ);
|
|
|
|
// some checks first...
|
|
touch(lf, o);
|
|
if (hasflag(o->flags, F_DEAD)) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (lf->controller != C_PLAYER) {
|
|
if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s reads %s!", buf, obname);
|
|
}
|
|
}
|
|
|
|
// figure out whether to id the object
|
|
willid = B_FALSE;
|
|
if (playercansee) {
|
|
switch (o->type->id) {
|
|
case OT_SCR_IDENTIFY: // only id if it does something
|
|
case OT_SCR_CREATEMONSTER: // only id if it does something
|
|
willid = B_FALSE;
|
|
break;
|
|
default:
|
|
willid = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ask for a target object of any type if scroll is unknown?
|
|
switch (o->type->id) {
|
|
case OT_SCR_IDENTIFY:
|
|
needsob = B_TRUE;
|
|
break;
|
|
default:
|
|
needsob = B_FALSE;
|
|
break;
|
|
}
|
|
|
|
if (!isknown(o) && willid) {
|
|
// id the scroll
|
|
makeknown(o->type->id);
|
|
real_getobname(o, obname, 1, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness
|
|
if (lf->controller == C_PLAYER) {
|
|
// tell the player
|
|
msg("This is %s!",obname);
|
|
more();
|
|
drawmsg();
|
|
}
|
|
}
|
|
|
|
|
|
if (o->type->obclass->id == OC_SCROLL) { // cast linked spell
|
|
object_t *targob = NULL;
|
|
f = hasflag(o->flags, F_LINKSPELL);
|
|
if (f) {
|
|
int seen = B_FALSE;
|
|
|
|
// for unidentified scrolls which target an object,
|
|
// let player select ANY object (even if it won't
|
|
// work).
|
|
if (needsob && isplayer(lf) && !isknown(o)) {
|
|
targob = askobject(lf->pack, "Target which object", NULL, AO_NONE);
|
|
}
|
|
|
|
// TODO: castspell the spell with blessed status
|
|
dospelleffects(lf, f->val[0], NULL, targob, NULL, o->blessed, &seen);
|
|
if (seen) {
|
|
// id the scroll now
|
|
makeknown(o->type->id);
|
|
}
|
|
|
|
// removeob one of the object
|
|
if (isplayer(lf)) msg("The scroll crumbles to dust.");
|
|
removeob(o, 1);
|
|
} else if (o->type->id == OT_MAP) {
|
|
if (lf->controller == C_PLAYER) {
|
|
msg("You study your map for a while.");
|
|
}
|
|
} else if (o->type->id == OT_SCR_NOTHING) {
|
|
if (isplayer(lf)) {
|
|
msg("The scroll crumbles to dust.");
|
|
}
|
|
// removeob one of the object
|
|
removeob(o, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
object_t *relinkob(object_t *src, obpile_t *dst) {
|
|
flag_t *f,*nextf;
|
|
if (!obfits(src, dst)) return NULL;
|
|
|
|
if (src->pile->owner) {
|
|
// previous owner loses all flags conferred by this object
|
|
loseobflags(src->pile->owner, src, ALLCONFERRED);
|
|
}
|
|
|
|
// unweild
|
|
for (f = src->flags->first ; f ; f = nextf) {
|
|
nextf = f->next;
|
|
if (f->id == F_EQUIPPED) {
|
|
killflag(f);
|
|
} else if (f->id == F_CURAMMO) {
|
|
killflag(f);
|
|
}
|
|
}
|
|
|
|
// adjust letter...
|
|
// gold should always have letter '$'
|
|
if (src->type->obclass->id == OC_MONEY) {
|
|
src->letter = '$';
|
|
}
|
|
|
|
// adjust letter if going to player?
|
|
if (dst->owner && (dst->owner->controller == C_PLAYER)) {
|
|
src->letter = getnextletter(dst, &src->letter);
|
|
}
|
|
|
|
|
|
|
|
// unlink this object from the current list
|
|
if (src->prev == NULL) {
|
|
// first
|
|
src->pile->first = src->next;
|
|
} else {
|
|
// not first
|
|
src->prev->next = src->next;
|
|
}
|
|
if (src->next == NULL) {
|
|
// last
|
|
src->pile->last = src->prev;
|
|
} else {
|
|
// not last
|
|
src->next->prev = src->prev;
|
|
}
|
|
|
|
// add this object to the end of the list for the new pile
|
|
if (dst->first == NULL) {
|
|
// first element in new list
|
|
dst->first = src;
|
|
src->prev = NULL;
|
|
} else {
|
|
object_t *aa;
|
|
// go to end of list
|
|
aa = dst->last;
|
|
// not first in new list
|
|
src->prev = aa;
|
|
aa->next = src;
|
|
}
|
|
|
|
|
|
dst->last = src;
|
|
src->pile = dst;
|
|
src->next = NULL;
|
|
|
|
if (src->pile->owner) {
|
|
// new owner gains "hold confer" flags conferred by this object
|
|
giveobflags(src->pile->owner, src, F_HOLDCONFER);
|
|
// new owner gains "activate confer" flags conferred by this object if it's active
|
|
if (isactivated(src)) {
|
|
giveobflags(src->pile->owner, src, F_ACTIVATECONFER);
|
|
}
|
|
}
|
|
|
|
if (obproduceslight(src)) {
|
|
calclight((getoblocation(src))->map);
|
|
drawscreen();
|
|
}
|
|
|
|
return src;
|
|
}
|
|
|
|
void removedeadobs(obpile_t *op) {
|
|
object_t *o, *nexto;
|
|
for (o = op->first ; o ; o = nexto) {
|
|
nexto = o->next;
|
|
if (hasflag(o->flags, F_DEAD)) {
|
|
obdie(o);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
// returns the amount left
|
|
int removeob(object_t *o,int howmany) {
|
|
if (howmany == ALL) {
|
|
howmany = o->amt;
|
|
}
|
|
|
|
if (howmany >= o->amt) {
|
|
killob(o);
|
|
return 0;
|
|
} else {
|
|
o->amt -= howmany;
|
|
}
|
|
|
|
return o->amt;
|
|
}
|
|
|
|
void setblessed(object_t *o, enum BLESSTYPE wantbless) {
|
|
o->blessed = wantbless;
|
|
if (wantbless != B_BLESSED) {
|
|
flag_t *f,*nextf;
|
|
// remove glowing from blessings
|
|
for (f = o->flags->first ; f ; f = nextf) {
|
|
nextf = f->next;
|
|
if (f->lifetime == FROMBLESSING) {
|
|
killflag(f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void setinscription(object_t *o, char *text) {
|
|
if (o->inscription) {
|
|
free(o->inscription);
|
|
}
|
|
o->inscription = strdup(text);
|
|
}
|
|
|
|
object_t *splitob(object_t *o) {
|
|
object_t *newob;
|
|
// decrease count on original stack temporarily, in case we
|
|
// can't place the new object (at our weight limit?).
|
|
// doesn't matter if it goes down to zero, as we will put it back up soon.
|
|
o->amt--;
|
|
// give new object
|
|
newob = addobject(o->pile, o->type->name, B_NOSTACK);
|
|
// restore count
|
|
o->amt++;
|
|
if (newob) {
|
|
copyobprops(newob, o);
|
|
killflagsofid(newob->flags, F_STACKABLE);
|
|
// remove old ob
|
|
removeob(o, 1);
|
|
}
|
|
return newob;
|
|
}
|
|
|
|
// returns amount of damage taken
|
|
int takedamage(object_t *o, unsigned int howmuch, int damtype) {
|
|
char predamname[BUFLEN],postdamname[BUFLEN];
|
|
char obname[BUFLEN];
|
|
flag_t *hpflag, *f;
|
|
int damtaken = 0;
|
|
|
|
// some checks need to happen before
|
|
// making sure the damage will happen.
|
|
// for example, even if an object is
|
|
// immune to water damage, water will
|
|
// still put out fire
|
|
|
|
// water puts out fire
|
|
if (damtype == DT_WATER) {
|
|
extinguish(o);
|
|
}
|
|
|
|
adjustdamob(o, &howmuch, damtype);
|
|
if (howmuch <= 0) {
|
|
return 0;
|
|
}
|
|
|
|
// update lastdamtype
|
|
f = hasflag(o->flags, F_LASTDAMTYPE);
|
|
if (f) {
|
|
f->val[0] = damtype;
|
|
} else {
|
|
addflag(o->flags, F_LASTDAMTYPE, damtype, NA, NA, NULL);
|
|
}
|
|
|
|
real_getobname(o, obname, o->amt, B_FALSE, B_TRUE, B_TRUE);
|
|
getobconditionname(o, predamname);
|
|
hpflag = hasflag(o->flags, F_OBHP);
|
|
if (hpflag) {
|
|
damtaken = MAXOF(hpflag->val[0], howmuch);
|
|
// object loses hp
|
|
hpflag->val[0] -= howmuch;
|
|
}
|
|
|
|
if (!hpflag || (hpflag->val[0] <= 0)) {
|
|
// special cases....
|
|
if (damtype == DT_FIRE) {
|
|
if (o->material->id == MT_FLESH) { // fire roasts flesh
|
|
object_t *meat;
|
|
meat = addob(o->pile, "chunk of roast meat");
|
|
// purposely don't use getweight!
|
|
meat->weight = o->weight;
|
|
} else { // fire turns other things to ash
|
|
addob(o->pile, "pile of ash");
|
|
}
|
|
} else if (damtype == DT_BASH) {
|
|
if (o->material->id == MT_GLASS) { // bashing damage breaks glass
|
|
int nshards;
|
|
char buf[BUFLEN];
|
|
nshards = getnumshards(o);
|
|
sprintf(buf, "%d pieces of broken glass", nshards);
|
|
addob(o->pile, buf);
|
|
} else if (o->material->id == MT_ICE) { // bashing breaks ice
|
|
int nshards;
|
|
char buf[BUFLEN];
|
|
nshards = getnumshards(o) / 15;
|
|
sprintf(buf, "%d chunks of ice", nshards);
|
|
addob(o->pile, buf);
|
|
}
|
|
}
|
|
|
|
// object dies!
|
|
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
|
} else if (hpflag) {
|
|
flag_t *f;
|
|
// object was just damaged
|
|
getobconditionname(o, postdamname);
|
|
|
|
|
|
// was it enough to change the status
|
|
if (!hasflag(o->flags, F_NOOBDAMTEXT) && strcmp(predamname, postdamname)) {
|
|
// if it was melting, drop some water here
|
|
if (damtype == DT_MELT) {
|
|
if (hasflag(o->flags, F_EQUIPPED) ) {
|
|
addob(o->pile->owner->cell->obpile, "small puddle of water");
|
|
} else {
|
|
// melts into the ob pile
|
|
addob(o->pile, "small puddle of water");
|
|
}
|
|
}
|
|
|
|
if (o->pile->owner) {
|
|
if (o->pile->owner->controller == C_PLAYER) {
|
|
msg("Your %s %s!",noprefix(obname), getobhurtname(o, damtype));
|
|
} else if (haslos(player, o->pile->owner->cell)) {
|
|
char monname[BUFLEN];
|
|
getlfname(o->pile->owner, monname);
|
|
msg("%s's %s %s!",monname, noprefix(obname), getobhurtname(o, damtype));
|
|
}
|
|
} else if (haslos(player, o->pile->where)) {
|
|
capitalise(obname);
|
|
msg("%s %s!", obname, getobhurtname(o, damtype));
|
|
}
|
|
}
|
|
|
|
|
|
// catches on fire?
|
|
if (damtype == DT_FIRE) {
|
|
if (isflammable(o)) {
|
|
f = hasflag(o->flags, F_ONFIRE);
|
|
if (!f) {
|
|
// on fire for 2 turns
|
|
addtempflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
// explodes?
|
|
f = hasflag(o->flags, F_EXPLODEONDAM);
|
|
if (f) {
|
|
if (f->val[2] == B_IFACTIVATED) {
|
|
if (hasflag(o->flags, F_ACTIVATED)) {
|
|
if (hasflag(o->flags, F_EXPLODEONDEATH)) {
|
|
// object dies!
|
|
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
|
} else {
|
|
// explode
|
|
explodeob(o, f, (f->val[1] == B_BIG) ? 1 : 0);
|
|
}
|
|
|
|
}
|
|
} else {
|
|
if (hasflag(o->flags, F_EXPLODEONDEATH)) {
|
|
// object dies!
|
|
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
|
} else {
|
|
// explode
|
|
explodeob(o, f, (f->val[1] == B_BIG) ? 1 : 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
// flashes?
|
|
f = hasflag(o->flags, F_FLASHONDAM);
|
|
if (f) {
|
|
if (f->val[2] == B_IFACTIVATED) {
|
|
if (hasflag(o->flags, F_ACTIVATED)) {
|
|
// flash, then object dies
|
|
brightflash(getoblocation(o),f->val[0], NULL);
|
|
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
|
}
|
|
} else {
|
|
// flash, then object dies
|
|
brightflash(getoblocation(o),f->val[0], NULL);
|
|
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
|
}
|
|
}
|
|
}
|
|
return damtaken;
|
|
}
|
|
|
|
// throw speed is the damage multiplier
|
|
int fireat(lifeform_t *thrower, object_t *o, cell_t *where, int speed, object_t *firearm) {
|
|
char throwername[BUFLEN];
|
|
char throwernamea[BUFLEN];
|
|
char obname[BUFLEN];
|
|
char targetname[BUFLEN];
|
|
char buf[BUFLEN];
|
|
lifeform_t *target;
|
|
cell_t *srcloc;
|
|
int seen;
|
|
int shattered = B_FALSE;
|
|
char throwverbpast[BUFLEN];
|
|
char throwverbpres[BUFLEN];
|
|
int acc;
|
|
int youhit;
|
|
|
|
reason = E_OK;
|
|
|
|
if (firearm) {
|
|
strcpy(throwverbpres, "fire");
|
|
strcpy(throwverbpast, "fired");
|
|
} else {
|
|
strcpy(throwverbpres, "throw");
|
|
strcpy(throwverbpast, "thrown");
|
|
}
|
|
|
|
|
|
if (isblind(player)) {
|
|
if (isplayer(thrower)) {
|
|
getobname(o, obname, 1);
|
|
} else {
|
|
strcpy(obname, "something");
|
|
}
|
|
} else {
|
|
getobname(o, obname, 1);
|
|
}
|
|
|
|
getlfname(thrower, throwername);
|
|
if (isplayer(thrower)) {
|
|
strcpy(throwernamea, throwername);
|
|
} else {
|
|
if (isvowel(*(noprefix(throwername)))) {
|
|
strcpy(throwernamea, "an ");
|
|
} else {
|
|
strcpy(throwernamea, "a ");
|
|
}
|
|
strcat(throwernamea, noprefix(throwername));
|
|
}
|
|
|
|
srcloc = getoblocation(o);
|
|
|
|
// can't throw weilded cursed objects
|
|
if ((o->blessed == B_CURSED) && (!firearm)) {
|
|
// is object in thrower's pack? we need to check this
|
|
// because of things like telekenises which let us throw
|
|
// things we don't have.
|
|
if (o->pile->owner == thrower) {
|
|
// object equipped?
|
|
if (hasflag(o->flags, F_EQUIPPED)) {
|
|
// throw will fail!
|
|
if (isplayer(thrower)) {
|
|
msg("You can't release your %s - it %s cursed!", noprefix(obname),
|
|
isblessknown(o) ? "is" : "must be");
|
|
o->blessknown = B_TRUE;
|
|
} else if (haslos(player, thrower->cell)) {
|
|
msg("%s tries to throw %s but can't!", throwername, obname);
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
// take time anyway
|
|
//taketime(thrower, SPEED_THROW);
|
|
// fail.
|
|
reason = E_CURSED;
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
// otherwise does player have haslos?
|
|
|
|
// identify as cursed!
|
|
}
|
|
|
|
if (haslos(player, where)) {
|
|
seen = B_TRUE;
|
|
} else {
|
|
seen = B_FALSE;
|
|
}
|
|
|
|
|
|
target = where->lf;
|
|
if (target) {
|
|
getlfname(target, targetname);
|
|
}
|
|
|
|
// touch effects
|
|
if (thrower && !firearm) {
|
|
if (o->pile == thrower->pack) {
|
|
touch(thrower, o);
|
|
}
|
|
}
|
|
|
|
// announce it ("xx throws xx" "at yy")
|
|
if (isplayer(thrower)) {
|
|
if (target) {
|
|
msg("You %s %s at %s.", throwverbpres, obname, targetname);
|
|
} else {
|
|
msg("You %s %s.",throwverbpres, obname);
|
|
}
|
|
} else if (haslos(player, srcloc) && (srcloc == thrower->cell)) {
|
|
char throwstring[BUFLEN];
|
|
|
|
sprintf(throwstring, "%s %ss %s", throwername, throwverbpres,
|
|
obname);
|
|
|
|
if (target && haslos(player, where)) {
|
|
strcat(throwstring, " at ");
|
|
strcat(throwstring, targetname);
|
|
}
|
|
strcat(throwstring, ".");
|
|
msg("%s", throwstring);
|
|
} else if (seen) {
|
|
char throwstring[BUFLEN];
|
|
/*
|
|
if (target) {
|
|
msg("Something %ss %s at %s.", throwverbpres, obname, targetname);
|
|
} else {
|
|
msg("Something %ss %s.",throwverbpres, obname);
|
|
}
|
|
*/
|
|
sprintf(throwstring, "%s %s through the air", obname, (o->amt == 1) ? "flies" : "fly");
|
|
if (target && haslos(player, where)) {
|
|
strcat(throwstring, " towards ");
|
|
strcat(throwstring, targetname);
|
|
}
|
|
strcat(throwstring, ".");
|
|
msg("%s", throwstring);
|
|
}
|
|
|
|
//taketime(thrower, SPEED_THROW);
|
|
|
|
// some obejcts will die when thrown.
|
|
if (o->type->id == OT_ASH) {
|
|
if (haslos(player, srcloc)) {
|
|
msg("%s disperses into the air.", obname);
|
|
}
|
|
removeob(o, 1);
|
|
return B_FALSE;
|
|
}
|
|
|
|
// gravboost?
|
|
if (lfhasflag(thrower, F_GRAVBOOSTED) && (srcloc == thrower->cell)) {
|
|
if (isplayer(thrower) || haslos(player, srcloc)) {
|
|
msg("%s drops and sticks to the ground!", obname);
|
|
}
|
|
|
|
moveob(o, thrower->cell->obpile, 1);
|
|
return B_FALSE;
|
|
}
|
|
|
|
// do throw animation
|
|
if (seen) {
|
|
anim(srcloc, where, getglyph(o));
|
|
}
|
|
|
|
// find out your chances of hitting
|
|
acc = getmissileaccuracy(thrower, where, o, firearm, A_DEX);
|
|
|
|
// roll for hit
|
|
// metal weapon versus magnetic shield?
|
|
if (lfhasflag(target, F_MAGSHIELD) && ismetal(o->material->id)) {
|
|
// announce
|
|
if (seen) {
|
|
msg("%s is repelled from %s!", obname, targetname);
|
|
}
|
|
youhit = B_FALSE;
|
|
} else if (rnd(1,100) <= acc) {
|
|
youhit = B_TRUE;
|
|
} else {
|
|
youhit = B_FALSE;
|
|
}
|
|
|
|
|
|
// if someone is there, they take damage and the object might die
|
|
// this should be "if target && youhit"
|
|
if (target) {
|
|
if (youhit) {
|
|
int dam = 0,shatterdam = 0;
|
|
char damstring[BUFLEN];
|
|
dam = getthrowdam(o) * speed;
|
|
|
|
// special case
|
|
if (o->type->id == OT_RUBBERBULLET) {
|
|
dam = 1;
|
|
}
|
|
|
|
// deal extra cutting damage afterwards?
|
|
shatterdam = getshatterdam(o);
|
|
if (shatterdam > 0) {
|
|
shattered = B_TRUE;
|
|
}
|
|
|
|
// announce
|
|
if (seen) {
|
|
char buf2[BUFLEN];
|
|
sprintf(buf2, "%s hits %s%s",obname,targetname,
|
|
(willshatter(o->material->id)) ? " and shatters!" : "."
|
|
);
|
|
if (lfhasflag(player, F_EXTRAINFO)) {
|
|
char damstring[BUFLEN];
|
|
sprintf(damstring, " [%d dmg]",dam);
|
|
strcat(buf2, damstring);
|
|
}
|
|
msg("%s", buf2);
|
|
} else {
|
|
if (willshatter(o->material->id)) {
|
|
youhear(where, "shattering glass.");
|
|
}
|
|
}
|
|
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, throwernamea);
|
|
|
|
// TODO: at the moment you won't get experience if you telekenetically
|
|
// throw an object at something. is this okay?
|
|
losehp(target, dam, DT_PROJECTILE, (thrower->cell == srcloc) ? thrower : NULL, damstring);
|
|
|
|
if (shatterdam && !isdead(target)) {
|
|
// extra glass damage
|
|
if (seen) {
|
|
msg("%s %s showered in glass shards!", targetname, isplayer(target) ? "are" : "is");
|
|
}
|
|
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, throwernamea);
|
|
losehp(target, shatterdam, DT_SLASH, thrower, damstring);
|
|
}
|
|
} else {
|
|
if (isplayer(thrower)) {
|
|
msg("Your %s misses %s.", noprefix(obname), targetname);
|
|
} else if (haslos(player, where)) {
|
|
msg("%s misses %s.", obname, targetname);
|
|
}
|
|
}
|
|
} else { // no target
|
|
if (willshatter(o->material->id)) {
|
|
if (haslos(player, where)) {
|
|
char *obcaps;
|
|
obcaps = strdup(obname);
|
|
capitalise(obcaps);
|
|
obcaps = strrep(obcaps, "An ", "The ", NULL);
|
|
obcaps = strrep(obcaps, "A ", "The ", NULL);
|
|
msg("%s shatters!",obcaps);
|
|
free(obcaps);
|
|
} else {
|
|
youhear(where, "shattering glass.");
|
|
}
|
|
shattered = B_TRUE;
|
|
}
|
|
}
|
|
|
|
// either remove or move the object
|
|
if (shattered) {
|
|
if (o->material->id == MT_GLASS) {
|
|
int numshards;
|
|
numshards = getnumshards(o);
|
|
// place glass shards
|
|
sprintf(buf, "%d pieces of broken glass",numshards);
|
|
addob(where->obpile, buf);
|
|
} else if (o->material->id == MT_ICE) {
|
|
int numshards;
|
|
numshards = getnumshards(o) / 15;
|
|
if (numshards < 1) numshards = 1;
|
|
|
|
// ice
|
|
sprintf(buf, "%d chunks of ice",numshards);
|
|
addob(where->obpile, buf);
|
|
}
|
|
|
|
// potion effects?
|
|
if (shattered) {
|
|
if (o->type->obclass->id == OC_POTION) {
|
|
int observed;
|
|
switch (o->type->id) {
|
|
case OT_POT_ACID: // take acid damage
|
|
if (seen) {
|
|
makeknown(o->type->id);
|
|
}
|
|
if (target) {
|
|
if (seen) {
|
|
msg("%s %s splashed with acid!", targetname,
|
|
isplayer(target) ? "are" : "is");
|
|
}
|
|
losehp(target, rnd(1,5), DT_ACID, thrower, "a splash of acid");
|
|
} else {
|
|
// all objects take damage
|
|
object_t *oo,*nextoo;
|
|
// announce
|
|
if (seen) {
|
|
msg("Acid splashes all over the floor!");
|
|
}
|
|
// everything here takes acid damage
|
|
for (oo = where->obpile->first ; oo ; oo = nextoo) {
|
|
nextoo = oo->next;
|
|
takedamage(oo, rnd(5,15), DT_ACID);
|
|
}
|
|
}
|
|
break;
|
|
case OT_POT_ELEMENTENDURE:
|
|
case OT_POT_ELEMENTIMMUNE:
|
|
case OT_POT_GASEOUSFORM:
|
|
case OT_POT_POLYMORPH:
|
|
case OT_POT_SANCTUARY: // always make them known
|
|
if (target) {
|
|
if (seen) {
|
|
makeknown(o->type->id);
|
|
}
|
|
potioneffects(target, o->type->id, o->blessed, &observed);
|
|
}
|
|
break;
|
|
case OT_POT_HEALING:
|
|
case OT_POT_HEALINGMIN: // only make them known if it had an effect
|
|
if (target) {
|
|
potioneffects(target, o->type->id, o->blessed, &observed);
|
|
if (observed) {
|
|
makeknown(o->type->id);
|
|
}
|
|
}
|
|
break;
|
|
case OT_POT_WATER:
|
|
if (seen) {
|
|
makeknown(o->type->id);
|
|
}
|
|
if (target) {
|
|
if (seen) {
|
|
msg("%s %s splashed with water.", targetname,
|
|
isplayer(target) ? "are" : "is");
|
|
}
|
|
|
|
if (hasflag(target->flags, F_UNDEAD) && isblessed(o)) {
|
|
if (isplayer(target)) {
|
|
msg("The water burns like acid!");
|
|
} else if (haslos(player, target->cell)) {
|
|
msg("%s writhes in agony!", targetname);
|
|
}
|
|
losehp(target, rnd(5,10), DT_HOLY, NULL, "holy water");
|
|
if (seen) {
|
|
// we now know that it is blessed
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
} else {
|
|
losehp(target, 0, DT_WATER, thrower, "a splash of water");
|
|
}
|
|
} else {
|
|
// all objects take damage
|
|
object_t *oo,*nextoo;
|
|
// announce
|
|
if (seen) {
|
|
msg("Water splashes onto the floor.");
|
|
}
|
|
//TODO: holy water blesses everything?
|
|
// everything here takes water damage
|
|
for (oo = where->obpile->first ; oo ; oo = nextoo) {
|
|
nextoo = oo->next;
|
|
takedamage(oo, 0, DT_WATER);
|
|
}
|
|
addob(where->obpile, "small puddle of water");
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// now remove the object
|
|
removeob(o, 1);
|
|
} else {
|
|
object_t *newob;
|
|
newob = moveob(o, where->obpile, 1);
|
|
// fake its birth time so that it can be damaged
|
|
newob->birthtime = -1;
|
|
takedamage(newob, speed, DT_BASH);
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
void timeeffectsob(object_t *o) {
|
|
flag_t *f, *nextf;
|
|
cell_t *location;
|
|
lifeform_t *owner;
|
|
char obname[BUFLEN];
|
|
|
|
if (hasflag(o->flags, F_DEAD)) return;
|
|
|
|
getobname(o, obname, o->amt);
|
|
|
|
if (o->pile->where) {
|
|
location = o->pile->where;
|
|
} else {
|
|
location = NULL;
|
|
}
|
|
|
|
if (o->pile->owner) {
|
|
owner = o->pile->owner;
|
|
} else {
|
|
owner = NULL;
|
|
}
|
|
|
|
// expire flags
|
|
timeeffectsflags(o->flags);
|
|
|
|
// blessed weapons glow when held near undead
|
|
if (o->blessed && isweapon(o)) {
|
|
cell_t *ourcell;
|
|
flag_t *glowflag = NULL;
|
|
int nearundead = B_FALSE;
|
|
|
|
// are we glowing?
|
|
for (f = o->flags->first ; f ; f = nextf) {
|
|
nextf = f->next;
|
|
if ((f->id == F_PRODUCESLIGHT) && (f->lifetime == FROMBLESSING)) {
|
|
glowflag = f;
|
|
break;
|
|
}
|
|
}
|
|
if (isequipped(o)) {
|
|
// do we need to start/stop glowing?
|
|
ourcell = getoblocation(o);
|
|
if (ourcell) {
|
|
int x,y;
|
|
// check if we are near undead (ie. within 2 sq)
|
|
for (y = ourcell->y - 2; y <= ourcell->y + 2; y++) {
|
|
for (x = ourcell->x - 2; x <= ourcell->x + 2; x++) {
|
|
cell_t *c;
|
|
c = getcellat(ourcell->map, x, y);
|
|
if (c && haslf(c) && hasflag(c->lf->flags, F_UNDEAD)) {
|
|
nearundead = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (nearundead) {
|
|
if (!glowflag) {
|
|
// start glowing
|
|
glowflag = addtempflag(o->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL, FROMBLESSING);
|
|
/*
|
|
if (isplayer(o->pile->owner)) {
|
|
msg("Your %s start%s glowing!",noprefix(obname), (o->amt == 1) ? "s" : "");
|
|
if (!o->blessknown) o->blessknown = B_TRUE;
|
|
} else if (haslos(player, ourcell)) {
|
|
msg("%s start%s glowing!",obname, (o->amt == 1) ? "s" : "");
|
|
if (!o->blessknown) o->blessknown = B_TRUE;
|
|
}
|
|
*/
|
|
if (haslos(player, ourcell)) {
|
|
if (!o->blessknown) o->blessknown = B_TRUE;
|
|
}
|
|
calclight(ourcell->map);
|
|
}
|
|
} else { // not near undead
|
|
if (glowflag) {
|
|
killflag(glowflag);
|
|
glowflag = NULL;
|
|
/*
|
|
if (isplayer(o->pile->owner)) {
|
|
msg("Your %s stop%s glowing.",noprefix(obname), (o->amt == 1) ? "s" : "");
|
|
if (!o->blessknown) o->blessknown = B_TRUE;
|
|
} else if (haslos(player, ourcell)) {
|
|
msg("%s stop%s glowing.",obname, (o->amt == 1) ? "s" : "");
|
|
if (!o->blessknown) o->blessknown = B_TRUE;
|
|
}
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
} else { // not equipped
|
|
if (glowflag) { // if not equipped and glowing...
|
|
// stop glowing
|
|
killflag(glowflag);
|
|
glowflag = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (location) {
|
|
// does object's material change cell type?
|
|
if (o->material->id == MT_FIRE) {
|
|
if (hasflag(location->type->material->flags, F_FLAMMABLE)) {
|
|
// burn!
|
|
// TODO: change to celltype of nearby floor
|
|
// OR to default map empty type.
|
|
if (haslos(player, location)) {
|
|
msg("The %s burns!", location->type->name);
|
|
}
|
|
setcelltype(location, CT_CORRIDOR);
|
|
addob(location->obpile, "pile of ash");
|
|
}
|
|
}
|
|
}
|
|
|
|
// check each flag for this object...
|
|
for (f = o->flags->first ; f ; f = nextf) {
|
|
object_t *oo,*nextoo;
|
|
nextf = f->next;
|
|
|
|
// CHECKS FOR CURRENT OBJECT
|
|
if (f->id == F_ACTIVATED) {
|
|
if (o->type->id == OT_JETPACK) {
|
|
// activated jetpack on the ground?
|
|
if (location) {
|
|
if (haslos(player, location)) {
|
|
char obname[BUFLEN];
|
|
getobname(o, obname, 1);
|
|
msg("%s shoots up into the roof and explodes!",obname);
|
|
}
|
|
removeob(o, o->amt);
|
|
return;
|
|
} else {
|
|
int chargeleft;
|
|
// use up power
|
|
chargeleft = usecharge(o);
|
|
|
|
// out of power?
|
|
if (chargeleft <= 0) {
|
|
if (owner) {
|
|
// announce power loss
|
|
if (isplayer(owner)) {
|
|
msg("Your %s is out of power!",noprefix(obname));
|
|
// you know it's out
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
f->known = B_TRUE;
|
|
}
|
|
}
|
|
|
|
turnoff(NULL, o);
|
|
|
|
if (owner) {
|
|
// user will fall to the ground if not flying in some
|
|
// other way
|
|
if (!lfhasflag(owner, F_FLYING)) {
|
|
if (haslos(player, owner->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(owner, lfname);
|
|
msg("%s crash%s to the ground!",lfname,
|
|
isplayer(owner) ? "" : "es");
|
|
}
|
|
losehp(owner, rnd(1,4), DT_BASH, NULL, "falling");
|
|
}
|
|
}
|
|
} else if (chargeleft <= 10) { // about to run out of power?
|
|
if (isplayer(owner)) {
|
|
msg("Your %s splutters.", noprefix(obname));
|
|
}
|
|
// TODO: add smoke!
|
|
}
|
|
}
|
|
} else if (hasflag(o->flags, F_GRENADE)) {
|
|
flag_t *f2;
|
|
// countdown...
|
|
f2 = hasflag(o->flags, F_CHARGES);
|
|
if (f2) {
|
|
f2->val[0]--;
|
|
if (f2->val[0] <= 0) {
|
|
// blow up!
|
|
takedamage(o, 999, DT_DIRECT);
|
|
return;
|
|
}
|
|
}
|
|
} else if (o->type->id == OT_LANTERNOIL) {
|
|
flag_t *f2;
|
|
// countdown...
|
|
f2 = hasflag(o->flags, F_CHARGES);
|
|
if (f2) {
|
|
f2->val[0]--;
|
|
if (f2->val[0] <= 0) {
|
|
// turnoff
|
|
turnoff(NULL, o);
|
|
obaction(o, "goes out");
|
|
return;
|
|
} else if (f2->val[0] <= 50) {
|
|
if (rnd(1,3)) {
|
|
obaction(o, "flickers");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (f->id == F_OBHPDRAIN) {
|
|
enum DAMTYPE damtype;
|
|
//takedamage(o, f->val[0] * firstlftime, DT_DIRECT);
|
|
if (f->val[1] == NA) {
|
|
damtype = DT_DIRECT;
|
|
} else {
|
|
damtype = f->val[1];
|
|
}
|
|
takedamage(o, f->val[0], damtype);
|
|
if (hasflag(o->flags, F_DEAD)) return;
|
|
}
|
|
|
|
|
|
// damaging objects here will damage other objects
|
|
if (f->id == F_WALKDAM) {
|
|
// everything here takes damage
|
|
//damageallobs(o, o->pile, f->val[0] * timespent, f->val[1]);
|
|
damageallobs(o, o->pile, f->val[0], f->val[1]);
|
|
//if (hasflag(o->flags, F_DEAD)) return;
|
|
}
|
|
|
|
// is object on fire?
|
|
if (f->id == F_ONFIRE) {
|
|
// water puts out fire
|
|
for (oo = o->pile->first ; oo ; oo = nextoo) {
|
|
nextoo = oo->next;
|
|
if ((oo != o) && (oo->material->id == MT_WATER)) {
|
|
extinguish(o);
|
|
continue;
|
|
}
|
|
}
|
|
// if it hasn't been extinguished, fire burns
|
|
takedamage(o, 2, DT_FIRE); // TODO: don't hardcode
|
|
if (hasflag(o->flags, F_DEAD)) return;
|
|
}
|
|
|
|
|
|
|
|
// will current object convert other obs to something else?
|
|
if (f->id == F_MATCONVERT) {
|
|
enum MATERIAL mat;
|
|
mat = f->val[0];
|
|
|
|
for (oo = o->pile->first ; oo ; oo = nextoo) {
|
|
flag_t *f2;
|
|
nextoo = oo->next;
|
|
if ((oo != o) && (oo->material->id == mat)) {
|
|
char buf[BUFLEN];
|
|
object_t *newob;
|
|
// TODO: remove the old object first
|
|
// in case the obpile doesn't have space
|
|
// to fit both the new and old ones.
|
|
// place item of this type here!
|
|
sprintf(buf, "%d %s", o->amt, f->text);
|
|
newob = addob(o->pile, buf);
|
|
if (newob) {
|
|
int cansee;
|
|
// make the weight match.
|
|
newob->weight = o->weight;
|
|
// announce it?
|
|
cansee = B_FALSE;
|
|
if (location && haslos(player, location)) {
|
|
cansee = B_TRUE;
|
|
} else if (o->pile->owner == player) {
|
|
cansee = B_TRUE;
|
|
}
|
|
|
|
if (cansee) {
|
|
f2 = NULL;
|
|
if (o->amt > 1) {
|
|
f2 = hasflagval(o->flags, F_MATCONVERTTEXTPL, mat, NA, NA,NULL);
|
|
}
|
|
if (!f2) {
|
|
f2 = hasflagval(o->flags, F_MATCONVERTTEXT, mat, NA, NA, NULL);
|
|
}
|
|
|
|
if (f2) {
|
|
char *locbuf;
|
|
getobname(o, buf, o->amt);
|
|
locbuf = strdup(buf);
|
|
capitalise(locbuf);
|
|
if (o->pile->owner == player) {
|
|
// Remove prefix
|
|
locbuf = strrep(locbuf, "An ", "", NULL);
|
|
locbuf = strrep(locbuf, "A ", "", NULL);
|
|
}
|
|
msg("%s%s %s.", (o->pile->owner == player) ? "Your " : "", locbuf, f2->text);
|
|
free(locbuf);
|
|
}
|
|
}
|
|
// remove original object
|
|
removeob(o, o->amt);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
} // end for each object flag
|
|
}
|
|
|
|
void turnoff(lifeform_t *lf, object_t *o) {
|
|
char obname[BUFLEN];
|
|
flag_t *f;
|
|
|
|
f = hasflag(o->flags, F_ACTIVATED);
|
|
if (!f) {
|
|
// already off
|
|
return;
|
|
}
|
|
|
|
// reset charges
|
|
if (hasflag(o->flags, F_RECHARGEWHENOFF)) {
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
if (f) {
|
|
f->val[0] = f->val[1];
|
|
}
|
|
}
|
|
|
|
getobname(o, obname, 1);
|
|
if (lf) {
|
|
if (isplayer(lf)) {
|
|
msg("You deactivate your %s.",noprefix(obname));
|
|
} else if (haslos(player, lf->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s deactivates %s.",lfname, obname);
|
|
}
|
|
}
|
|
|
|
if (hasflag(o->flags, F_GRENADE)) {
|
|
object_t *stackob;
|
|
// make it stackable again
|
|
addflag(o->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
// other stacks to join?
|
|
stackob = canstackob(o->pile, o);
|
|
if (stackob) {
|
|
char stackname[BUFLEN];
|
|
// remove it, and inc amt on the stack
|
|
removeob(o, 1);
|
|
stackob->amt++;
|
|
getobname(stackob, stackname, stackob->amt);
|
|
msglower("%c - %s.",stackob->letter, stackname);
|
|
} else {
|
|
// just turn off
|
|
killflag(f);
|
|
}
|
|
} else {
|
|
killflag(f);
|
|
}
|
|
|
|
if (o->pile->owner) {
|
|
loseobflags(o->pile->owner, o, F_ACTIVATECONFER);
|
|
}
|
|
}
|
|
|
|
void turnon(lifeform_t *lf, object_t *o) {
|
|
char obname[BUFLEN];
|
|
flag_t *f;
|
|
|
|
|
|
f = hasflag(o->flags, F_ACTIVATED);
|
|
if (f) {
|
|
// already on
|
|
if (isplayer(lf)) {
|
|
msg("Your %s is already activated!\n", noprefix(obname));
|
|
}
|
|
return;
|
|
}
|
|
|
|
// check charges
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
if (f && (f->val[0] <= 0)) {
|
|
// out of power
|
|
if (isplayer(lf)) {
|
|
nothinghappens();
|
|
}
|
|
return;
|
|
}
|
|
|
|
getobname(o, obname, 1);
|
|
if (isplayer(lf)) {
|
|
msg("You activate your %s.",noprefix(obname));
|
|
} else if (haslos(player, lf->cell)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s activates %s.",lfname, obname);
|
|
}
|
|
|
|
// for grenades, give a new object which is activated
|
|
if (hasflag(o->flags, F_GRENADE)) {
|
|
object_t *newob;
|
|
|
|
newob = splitob(o);
|
|
|
|
if (newob) {
|
|
char newobname[BUFLEN];
|
|
// announce new ob
|
|
addflag(newob->flags, F_ACTIVATED, B_TRUE, NA, NA, NULL);
|
|
getobname(newob, newobname, 1);
|
|
msglower("%c - %s [activated].",newob->letter, newobname);
|
|
} else {
|
|
if (isplayer(lf)) {
|
|
msg("You don't have room for an activated %s!",noprefix(obname));
|
|
}
|
|
}
|
|
} else {
|
|
addflag(o->flags, F_ACTIVATED, B_TRUE, NA, NA, NULL);
|
|
}
|
|
|
|
giveobflags(lf, o, F_ACTIVATECONFER);
|
|
}
|
|
|
|
|
|
// returns charges remaining, -1 if object doesn't have the flag
|
|
int usecharge(object_t *o) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
if (f) {
|
|
f->val[0]--;
|
|
return f->val[0];
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int validateobs(void) {
|
|
objecttype_t *ot;
|
|
int foundspells = B_FALSE;
|
|
int goterror = B_FALSE;
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if ((ot->obclass->id == OC_SPELL) || (ot->obclass->id == OC_ABILITY)) {
|
|
if (!foundspells) foundspells = B_TRUE;
|
|
if (!hasflag(ot->flags, F_SPELLSCHOOL)) {
|
|
printf("ERROR - spell %s doesn't have F_SPELLSCHOOL.\n", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
/*
|
|
if (!hasflag(ot->flags, F_SPELLLETTER)) {
|
|
printf("ERROR - spell %s doesn't have F_SPELLLETTER.\n", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
*/
|
|
|
|
if ((ot->obclass->id == OC_SPELL) && !hasflag(ot->flags, F_SPELLLEVEL)) {
|
|
printf("ERROR - spell %s doesn't have F_SPELLLEVEL.\n", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
} else if (ot->obclass->id == OC_SCROLL) {
|
|
if (foundspells) {
|
|
printf("ERROR in object '%s' - all Scrolls must be defined before Spells.", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
}
|
|
if (hasflagval(ot->flags, F_PICKLOCKS, NA, B_BLUNTONFAIL, NA, NULL) && hasflag(ot->flags, F_STACKABLE)) {
|
|
printf("ERROR in object '%s' - cannot have F_BLUNTONFAIL on stackable objects.", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
if (hasflag(ot->flags, F_FIREARM) && !hasflag(ot->flags, F_RANGE)) {
|
|
printf("ERROR in object '%s' - firearms need to have F_RANGE.", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
}
|
|
|
|
return goterror;
|
|
}
|
|
|
|
int willshatter(enum MATERIAL mat) {
|
|
switch (mat) {
|
|
case MT_GLASS:
|
|
case MT_ICE:
|
|
return B_TRUE;
|
|
default: break;
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
// determine how long a conferred effect should last, based on its blessed/cursed status.
|
|
// blessed: always max
|
|
// uncursed: random number between min & max
|
|
// cursed: always min
|
|
int geteffecttime(int min, int max, enum BLESSTYPE isblessed) {
|
|
int howlong;
|
|
// how long for?
|
|
switch (isblessed) {
|
|
case B_BLESSED:
|
|
howlong = 15;
|
|
break;
|
|
case B_CURSED:
|
|
howlong = 5;
|
|
break;
|
|
default: // ie. B_UNCURSED
|
|
howlong = rnd(5,15);
|
|
break;
|
|
}
|
|
return howlong;
|
|
}
|
|
|
|
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt) {
|
|
int acc,maxrange,howfar;
|
|
// figure out if you miss or not, based on distance and
|
|
// dexterity
|
|
// base:
|
|
// if throwing, 50%
|
|
// if firing, gun accuracy
|
|
// adjust for range:
|
|
// pointblank = +30%
|
|
// max = -30%
|
|
// then modify using dexterity/int/whatever
|
|
// then penalise for throwing non-missiles
|
|
|
|
// base accuracy
|
|
if (firearm) {
|
|
acc = getobaccuracy(firearm);
|
|
} else {
|
|
acc = 50;
|
|
}
|
|
|
|
// adjust for range
|
|
if (firearm || missile) {
|
|
if (firearm) {
|
|
maxrange = getfirearmrange(firearm);
|
|
} else {
|
|
maxrange = getmaxthrowrange(thrower, missile);
|
|
}
|
|
} else {
|
|
maxrange = getvisrange(thrower);
|
|
}
|
|
|
|
howfar = getcelldist(thrower->cell, where);
|
|
|
|
if (howfar == 1) {
|
|
acc += 30;
|
|
} else if (howfar == maxrange) {
|
|
acc -= 30;
|
|
}
|
|
|
|
|
|
// modify for dexterity
|
|
if (whichatt != A_NONE) {
|
|
acc += getstatmod(thrower, whichatt);
|
|
}
|
|
|
|
// penalty for throwing non-missiles
|
|
if (missile && !firearm && !ismissile(missile)) {
|
|
acc -= 20;
|
|
}
|
|
return acc;
|
|
}
|