10337 lines
324 KiB
C
10337 lines
324 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 hiddenname_t *firsthiddenname, *lasthiddenname;
|
|
extern objecttype_t *objecttype,*lastobjecttype;
|
|
extern objectclass_t *objectclass,*lastobjectclass;
|
|
extern brand_t *firstbrand,*lastbrand;
|
|
extern obmod_t *firstobmod,*lastobmod;
|
|
extern material_t *material,*lastmaterial;
|
|
extern skill_t *firstskill, *lastskill;
|
|
|
|
extern object_t *retobs[MAXPILEOBS+1];
|
|
extern int retobscount[MAXPILEOBS+1];
|
|
extern int nretobs;
|
|
|
|
extern map_t *firstmap;
|
|
|
|
extern enum GAMEMODE gamemode;
|
|
|
|
extern long curtime;
|
|
|
|
extern lifeform_t *player;
|
|
|
|
extern int reason;
|
|
|
|
extern int needredraw;
|
|
|
|
|
|
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_MISSILE,
|
|
OC_ARMOUR,
|
|
OC_POTION,
|
|
OC_SCROLL,
|
|
OC_WAND,
|
|
OC_FOOD,
|
|
OC_CORPSE,
|
|
OC_RING,
|
|
OC_TECH,
|
|
OC_TOOLS,
|
|
OC_BOOK,
|
|
OC_ROCK,
|
|
OC_MISC,
|
|
// omitting OC_SPELL and OC_JUMP because it shouldn't ever be displayed
|
|
OC_NULL
|
|
};
|
|
|
|
|
|
|
|
char *techadjective[] = {
|
|
"crazy",
|
|
"odd",
|
|
"strange",
|
|
"weird",
|
|
"",
|
|
};
|
|
char *technoun[] = {
|
|
"contraption",
|
|
"device",
|
|
"doodad",
|
|
"doohickey",
|
|
"gadget",
|
|
"thing",
|
|
"object",
|
|
"",
|
|
};
|
|
|
|
|
|
char *bookadjective[] = {
|
|
"ancient",
|
|
"clean",
|
|
"creepy",
|
|
"damp",
|
|
"dog-eared",
|
|
"dusty",
|
|
"eerie",
|
|
"fancy",
|
|
"frosty",
|
|
"furry",
|
|
"glowing",
|
|
"hot",
|
|
"humming",
|
|
"icy",
|
|
"jiggling",
|
|
"leatherbound",
|
|
"luminous",
|
|
"mouldy",
|
|
"papyrus",
|
|
"plain",
|
|
"quivering",
|
|
"muddy",
|
|
"slimy",
|
|
"small",
|
|
"soggy",
|
|
"thin",
|
|
"thick",
|
|
"tiny",
|
|
"vibrating",
|
|
"vine-covered",
|
|
"warm",
|
|
"worn",
|
|
"wrinkled",
|
|
"",
|
|
};
|
|
|
|
char *potadjective[] = {
|
|
"bubbling",
|
|
"effervescent",
|
|
"fizzy",
|
|
"fuming",
|
|
"gluggy",
|
|
"luminous", // should produce light
|
|
"steaming",
|
|
"",
|
|
};
|
|
|
|
char *colour[] = {
|
|
"aqua",
|
|
"azure",
|
|
"black",
|
|
"blue",
|
|
"brown",
|
|
"cyan",
|
|
"green",
|
|
"indigo",
|
|
"magenta",
|
|
"night-black",
|
|
"orange",
|
|
"pink",
|
|
"rainbow-coloured",
|
|
"red",
|
|
"violet",
|
|
"yellow",
|
|
"",
|
|
};
|
|
|
|
|
|
long nextoid = 0;
|
|
|
|
brand_t *addbrand(enum BRAND id, char *suffix, enum BODYPART bp) {
|
|
brand_t *a, *om;
|
|
char buf[BUFLEN];
|
|
//flag_t *f;
|
|
|
|
// does this modj already exist?
|
|
om = findbrand(id);
|
|
assert(!om);
|
|
|
|
// add to the end of the list
|
|
if (firstbrand == NULL) {
|
|
firstbrand = malloc(sizeof(brand_t));
|
|
a = firstbrand;
|
|
a->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
a = lastbrand;
|
|
a->next = malloc(sizeof(brand_t));
|
|
a->next->prev = a;
|
|
a = a->next;
|
|
}
|
|
lastbrand = a;
|
|
a->next = NULL;
|
|
|
|
// props
|
|
a->id = id;
|
|
a->bp = bp;
|
|
sprintf(buf, " %s",suffix);
|
|
a->suffix = strdup(buf);
|
|
|
|
a->flags = addflagpile(NULL, NULL);
|
|
|
|
return a;
|
|
}
|
|
|
|
|
|
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 (cansee(player, where->owner)) {
|
|
getlfname(where->owner, buf);
|
|
capitalise(buf);
|
|
msg("%s drops the %s on the ground.", buf, noprefix(emptyname));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return empty;
|
|
}
|
|
|
|
hiddenname_t *addhiddenname(enum OBCLASS obclass, char *text) {
|
|
hiddenname_t *a;
|
|
|
|
// add to the end of the list
|
|
if (firsthiddenname == NULL) {
|
|
firsthiddenname = malloc(sizeof(hiddenname_t));
|
|
a = firsthiddenname;
|
|
a->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
a = lasthiddenname;
|
|
a->next = malloc(sizeof(hiddenname_t));
|
|
a->next->prev = a;
|
|
a = a->next;
|
|
}
|
|
lasthiddenname = a;
|
|
a->next = NULL;
|
|
|
|
// props
|
|
a->obclass = obclass;
|
|
a->text = strdup(text);
|
|
a->used = B_FALSE;
|
|
|
|
return a;
|
|
}
|
|
|
|
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,*p2;
|
|
char numstringmin[BUFLEN];
|
|
char numstringmax[BUFLEN];
|
|
int howmany = 1;
|
|
int i;
|
|
int db = B_FALSE;
|
|
//flag_t *f;
|
|
char *localname;
|
|
int wantblessed = B_UNCURSED;
|
|
race_t *corpserace = NULL;
|
|
brand_t *br;
|
|
obmod_t *om;
|
|
obmod_t *wantom[MAXOBMODS];
|
|
int nom = 0;
|
|
int n;
|
|
|
|
|
|
localname = strdup(name);
|
|
|
|
|
|
// check for premods. eg. "flaming xxx" "frozen xxx" etc
|
|
for (om = firstobmod ; om ; om = om->next) {
|
|
if (db) dblog("DB: checking for '%s' in '%s'",om->prefix, localname);
|
|
if (strstr(localname, om->prefix)) {
|
|
localname = strrep(localname, om->prefix, "", NULL);
|
|
if (db) dblog("DB: found obmod prefix '%s'",om->prefix);
|
|
|
|
wantom[nom] = om;
|
|
nom++;
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
// }
|
|
|
|
|
|
|
|
if (strstr(p, "corpse")) {
|
|
int len;
|
|
char racename[BUFLEN];
|
|
p2 = strstr(p, "corpse");
|
|
len = p2 - p;
|
|
snprintf(racename, len, "%s",p);
|
|
|
|
corpserace = findracebyname(racename);
|
|
ot = findot(OT_CORPSE);
|
|
} else if (strstr(p, "statue of ")) {
|
|
char racename[BUFLEN];
|
|
|
|
// go to end
|
|
p2 = strstr(p, "statue of ");
|
|
p2 += 10; // now on either 'a' or 'an'
|
|
p2++; // now on either ' ' or 'n'
|
|
for (;*p2 != ' ';p2++);
|
|
p2++;
|
|
// now at start of name
|
|
sprintf(racename, "%s",p2);
|
|
|
|
corpserace = findracebyname(racename);
|
|
ot = findot(OT_STATUE);
|
|
} else if (strstr(p, " head")) {
|
|
int len;
|
|
char racename[BUFLEN];
|
|
p2 = strstr(p, " head");
|
|
len = p2 - p + 1;
|
|
snprintf(racename, len, "%s",p);
|
|
|
|
corpserace = findracebyname(racename);
|
|
ot = findot(OT_HEAD);
|
|
} else {
|
|
// 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 );
|
|
if (ot->id == OT_WOODENDOOR) {
|
|
dblog("xxx");
|
|
}
|
|
|
|
// 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, -1);
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// other special changes we need to make based on what was
|
|
// asked for
|
|
if ((gamemode != GM_LOADING) && o) {
|
|
char *p2;
|
|
int bonus = 0;
|
|
|
|
// corpses - fill in details
|
|
if (o->type->id == OT_CORPSE) {
|
|
flag_t *rf, *cf;
|
|
|
|
assert(corpserace);
|
|
|
|
o->weight = corpserace->weight;
|
|
o->material = corpserace->material;
|
|
|
|
// remember the race type
|
|
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL);
|
|
|
|
// override ot_corpse nutrition flag based on race's size
|
|
rf = hasflag(corpserace->flags, F_SIZE);
|
|
if (rf) {
|
|
cf = hasflag(o->flags, F_EDIBLE);
|
|
if (cf) {
|
|
switch (rf->val[0]) {
|
|
case SZ_MINI:
|
|
cf->val[1] = 5;
|
|
break;
|
|
case SZ_TINY:
|
|
cf->val[1] = 25;
|
|
break;
|
|
case SZ_SMALL:
|
|
cf->val[1] = 55;
|
|
break;
|
|
case SZ_MEDIUM:
|
|
cf->val[1] = 90;
|
|
break;
|
|
case SZ_HUMAN:
|
|
cf->val[1] = 100;
|
|
break;
|
|
case SZ_LARGE:
|
|
cf->val[1] = 150;
|
|
break;
|
|
case SZ_HUGE:
|
|
cf->val[1] = 200;
|
|
break;
|
|
case SZ_ENORMOUS:
|
|
cf->val[1] = 250;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else if (o->type->id == OT_STATUE) {
|
|
flag_t *f, *rf;
|
|
float ratio;
|
|
|
|
if (!corpserace) {
|
|
cell_t *where;
|
|
where = getoblocation(o);
|
|
// select random race
|
|
if (where) {
|
|
corpserace = getrandomrace(where->map);
|
|
} else {
|
|
// ie. vending machine
|
|
corpserace = getrandomrace(NULL);
|
|
}
|
|
}
|
|
|
|
ratio = o->material->weightrating / corpserace->material->weightrating;
|
|
|
|
o->weight = corpserace->weight * ratio;
|
|
|
|
// remember the race type
|
|
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL);
|
|
|
|
// set impassable size
|
|
f = hasflag(o->flags, F_IMPASSABLE);
|
|
if (f) {
|
|
rf = hasflag(corpserace->flags, F_SIZE);
|
|
if (rf) {
|
|
f->val[0] = rf->val[0];
|
|
} else {
|
|
killflag(f);
|
|
}
|
|
}
|
|
|
|
// set ob hp
|
|
f = hasflag(o->flags, F_OBHP);
|
|
if (f) {
|
|
rf = hasflag(corpserace->flags, F_HITDICE);
|
|
if (rf) {
|
|
int maxhp;
|
|
maxhp = (rf->val[0] * 4) + rf->val[1];
|
|
f->val[0] = maxhp;
|
|
f->val[1] = maxhp;
|
|
}
|
|
}
|
|
|
|
} else if (o->type->id == OT_HEAD) {
|
|
flag_t *rf, *cf;
|
|
|
|
assert(corpserace);
|
|
|
|
o->weight = corpserace->weight;
|
|
o->material = corpserace->material;
|
|
|
|
// remember the race type
|
|
addflag(o->flags, F_CORPSEOF, corpserace->id, NA, NA, NULL);
|
|
|
|
// override ot_corpse nutrition flag based on race's size
|
|
rf = hasflag(corpserace->flags, F_SIZE);
|
|
if (rf) {
|
|
cf = hasflag(o->flags, F_EDIBLE);
|
|
if (cf) {
|
|
switch (rf->val[0]) {
|
|
case SZ_MINI:
|
|
cf->val[1] = 1;
|
|
break;
|
|
case SZ_TINY:
|
|
cf->val[1] = 2;
|
|
break;
|
|
case SZ_SMALL:
|
|
cf->val[1] = 5;
|
|
break;
|
|
case SZ_MEDIUM:
|
|
cf->val[1] = 25;
|
|
break;
|
|
case SZ_HUMAN:
|
|
cf->val[1] = 50;
|
|
break;
|
|
case SZ_LARGE:
|
|
cf->val[1] = 75;
|
|
break;
|
|
case SZ_HUGE:
|
|
cf->val[1] = 100;
|
|
break;
|
|
case SZ_ENORMOUS:
|
|
cf->val[1] = 150;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
for (n = 0; n < nom; n++) {
|
|
// add flags from obmod
|
|
applyobmod(o, wantom[n]);
|
|
// other effects...
|
|
switch (wantom[n]->id) {
|
|
case OM_FLAMING: // flaming weapons are immune to fire
|
|
if (o->type->obclass->id == OC_WEAPON) {
|
|
if (!isimmuneto(o->flags, DT_FIRE)) {
|
|
addflag(o->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
|
|
}
|
|
}
|
|
break;
|
|
case OM_FROZEN:
|
|
// made of ice
|
|
// note: not using changemat() here to avoid adding f_frozen twice.
|
|
o->material = findmaterial(MT_ICE);
|
|
break;
|
|
case OM_MASTERWORK:
|
|
if (isweapon(o) || isarmour(o)) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_OBHP);
|
|
if (f) {
|
|
f->val[0] *= 2;
|
|
f->val[1] *= 2;
|
|
}
|
|
}
|
|
if (isweapon(o)) {
|
|
flag_t *f;
|
|
// always does near high end of damage range
|
|
f = hasflag(o->flags, F_DAM);
|
|
if (f) {
|
|
int ndice,dsides,bonus;
|
|
ndice = f->val[0];
|
|
dsides = f->val[1];
|
|
bonus = f->val[2]; if (bonus < 0) bonus = 0;
|
|
// half the number of sides on the dice (dsides).
|
|
dsides /= 2; if (dsides < 1) dsides = 1;
|
|
// increase modifier by (ndice * dsides)
|
|
bonus += (ndice * dsides);
|
|
if (bonus <= 0) {
|
|
bonus = NA;
|
|
}
|
|
f->val[0] = ndice;
|
|
f->val[1] = dsides;
|
|
f->val[2] = bonus;
|
|
}
|
|
}
|
|
break;
|
|
case OM_SHODDY:
|
|
if (isweapon(o) || isarmour(o)) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_OBHP);
|
|
if (f) {
|
|
f->val[0] /= 2; if (f->val[0] < 1) f->val[0] = 1;
|
|
f->val[1] /= 2; if (f->val[1] < 1) f->val[1] = 1;
|
|
|
|
}
|
|
}
|
|
if (isweapon(o)) {
|
|
flag_t *f;
|
|
// half the damage
|
|
f = hasflag(o->flags, F_DAM);
|
|
if (f) {
|
|
int dsides,bonus;
|
|
dsides = f->val[1];
|
|
bonus = f->val[2]; if (bonus < 0) bonus = 0;
|
|
// half the number of sides on the dice (dsides).
|
|
dsides /= 2;
|
|
// half modifier
|
|
if (bonus > 0) {
|
|
bonus /= 2; if (bonus <= 0) bonus = NA;
|
|
}
|
|
f->val[1] = dsides;
|
|
f->val[2] = bonus;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// 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, -1);
|
|
|
|
// check for postmods. eg. "xxx of pyromania"
|
|
for (br = firstbrand ; br ; br = br->next) {
|
|
if (strstr(name, br->suffix)) {
|
|
// does this brand apply to this objecttype?
|
|
if (brandappliesto(br, o->type)) {
|
|
copyflags(o->flags, br->flags, FROMBRAND);
|
|
addflag(o->flags, F_HASBRAND, br->id, NA, NA, NULL);
|
|
} else {
|
|
// doesn't exist!
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
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));
|
|
// replace "1 potion" with "a potion"
|
|
if (strstr(buf, "1 ") == buf) {
|
|
char temp[BUFLEN];
|
|
strcpy(temp, buf);
|
|
sprintf(buf, "a %s",temp + 2);
|
|
}
|
|
// make sure you can hold it
|
|
ot2 = findotn(buf);
|
|
if (!ot2 ||
|
|
hasflag(ot2->flags, F_NOPICKUP) ||
|
|
hasflag(ot2->flags, F_IMPASSABLE) ) {
|
|
strcpy(buf, "");
|
|
}
|
|
}
|
|
|
|
addflag(o->flags, F_CONTAINSOB, 'a' + i, NA, NA, buf);
|
|
}
|
|
}
|
|
|
|
// return the last object given
|
|
return o;
|
|
}
|
|
|
|
|
|
// add objects in a circle
|
|
// returns # added.
|
|
int addobburst(cell_t *where, int range, int dirtype, char *name) {
|
|
int (*distfunc)(cell_t *, cell_t *);
|
|
int x,y;
|
|
cell_t *c;
|
|
int nadded = 0;
|
|
|
|
if (!where) return 0;
|
|
|
|
if (dirtype == DT_ORTH) {
|
|
distfunc = getcelldistorth;
|
|
} else {
|
|
distfunc = getcelldist;
|
|
}
|
|
|
|
for (y = where->y - range; y <= where->y + range; y++) {
|
|
for (x = where->x - range; x <= where->x + range; x++) {
|
|
c = getcellat(where->map, x,y);
|
|
if (distfunc(where, c) <= range) {
|
|
if (!c->type->solid) {
|
|
if (addob(c->obpile, name)) nadded++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nadded;
|
|
}
|
|
|
|
|
|
obmod_t *addobmod(enum OBMOD id, char *prefix) {
|
|
obmod_t *a, *om;
|
|
char buf[BUFLEN];
|
|
//flag_t *f;
|
|
|
|
// does this modj already exist?
|
|
om = findobmod(id);
|
|
assert(!om);
|
|
|
|
// add to the end of the list
|
|
if (firstobmod == NULL) {
|
|
firstobmod = malloc(sizeof(obmod_t));
|
|
a = firstobmod;
|
|
a->prev = NULL;
|
|
} else {
|
|
// go to end of list
|
|
a = lastobmod;
|
|
a->next = malloc(sizeof(obmod_t));
|
|
a->next->prev = a;
|
|
a = a->next;
|
|
}
|
|
lastobmod = a;
|
|
a->next = NULL;
|
|
|
|
// props
|
|
a->id = id;
|
|
sprintf(buf, "%s ",prefix);
|
|
a->prefix = strdup(buf);
|
|
|
|
a->flags = addflagpile(NULL, NULL);
|
|
|
|
return a;
|
|
}
|
|
|
|
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_MAGIC) {
|
|
switch (damtype) {
|
|
case DT_DIRECT:
|
|
case DT_NONE:
|
|
break;
|
|
default:
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
} else 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;
|
|
}
|
|
} else if (damtype == DT_WATER) {
|
|
switch (mat) {
|
|
case MT_WATER: // immune to itself
|
|
*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)) {
|
|
if (damtype != DT_DIRECT) {
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
}
|
|
// immune?
|
|
if (isimmuneto(o->flags, damtype)) {
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
if (isresistantto(o->flags, damtype)) {
|
|
*dam /= 2;
|
|
}
|
|
if (isvulnto(o->flags, damtype)) {
|
|
*dam *= 2;
|
|
}
|
|
// poison gas never hurts objects
|
|
if (damtype == DT_POISONGAS) {
|
|
*dam = 0;
|
|
return;
|
|
}
|
|
|
|
// adjust damage
|
|
if (o->blessed == B_BLESSED) {
|
|
// chance 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);
|
|
}
|
|
}
|
|
|
|
|
|
void applyobmod(object_t *o, obmod_t *om) {
|
|
flag_t *f;
|
|
if (om->id == OM_FROZEN) {
|
|
// frozen things don't decay
|
|
f = hasflagval(o->flags, F_OBHPDRAIN, NA, DT_DECAY, NA, NULL);
|
|
if (f) {
|
|
killflag(f);
|
|
}
|
|
// but they do melt!
|
|
addflag(o->flags, F_OBHPDRAIN, 1, DT_MELT, NA, NULL);
|
|
}
|
|
copyflags(o->flags, om->flags, FROMOBMOD);
|
|
|
|
}
|
|
|
|
int blessob(object_t *o) {
|
|
char obname[BUFLEN];
|
|
int rv = B_FALSE;
|
|
lifeform_t *owner;
|
|
|
|
if (hasflag(o->flags, F_NOBLESS)) return B_TRUE;
|
|
|
|
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 (cansee(player, owner)) {
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int canbepoisoned(enum OBTYPE oid) {
|
|
flag_t *f;
|
|
objecttype_t *ot;
|
|
ot = findot(oid);
|
|
|
|
if (!ot) return B_FALSE;
|
|
if (ot->obclass->id != OC_WEAPON) return B_FALSE;
|
|
|
|
f = hasflag(ot->flags, F_DAMTYPE);
|
|
if (f) {
|
|
switch (f->val[0]) {
|
|
case DT_SLASH:
|
|
case DT_PIERCE:
|
|
return B_TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hasflagval(ot->flags, F_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL)) {
|
|
return B_TRUE;
|
|
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
// 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 && cansee(player, o->pile->owner)) {
|
|
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) {
|
|
obmod_t *om;
|
|
// 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);
|
|
}
|
|
// note that it is frozen
|
|
om = findobmod(OM_FROZEN);
|
|
applyobmod(o, om);
|
|
// make it melt
|
|
//addtempflag(o->flags, F_OBHPDRAIN, 1, DT_MELT, NA, NULL, FROMMAT);
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
objecttype_t *checkobnames(char *haystack, char *needle) {
|
|
objecttype_t *ot;
|
|
char *pluralname;
|
|
int db = B_FALSE;
|
|
|
|
// search for exact match
|
|
if (!strcmp(haystack, needle)) {
|
|
// found it!
|
|
if (db) dblog("checkobnames(): got exact match: '%s'",haystack);
|
|
return ot;
|
|
}
|
|
|
|
// search for words ending in "s" (eg. "swords")
|
|
pluralname = strdup(needle);
|
|
//if (db) dblog("findotn(): plural is '%s'",pluralname);
|
|
if (pluralname[strlen(pluralname)-1] == 's') {
|
|
// remove trailing 's'
|
|
pluralname[strlen(pluralname)-1] = '\0';
|
|
// search again (for exact matches)
|
|
if (!strcmp(haystack, pluralname)) {
|
|
if (db) dblog("checkobnames(): got match after stripping 's': '%s' -> '%s'",pluralname, needle);
|
|
free(pluralname);
|
|
return ot;
|
|
}
|
|
|
|
// search for words ending in "es" (eg. tomatoes)
|
|
if ((pluralname[strlen(pluralname)-1] == 'e') &&
|
|
(pluralname[strlen(pluralname)-2] == 'o')
|
|
) {
|
|
// remove trailing 'es'
|
|
pluralname[strlen(pluralname)-1] = '\0';
|
|
pluralname[strlen(pluralname)-2] = '\0';
|
|
//if (db) dblog("findotn(): pluralname without 'es' is '%s'",pluralname);
|
|
// search again
|
|
if (!strcmp(haystack, pluralname)) {
|
|
if (db) dblog("checkobnames(): got match after stripping 'es': '%s' -> '%s'",pluralname, needle);
|
|
free(pluralname);
|
|
return ot;
|
|
}
|
|
}
|
|
}
|
|
free(pluralname);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
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 dumprandomobs(int amt) {
|
|
int i;
|
|
char buf[BUFLEN];
|
|
int min,max;
|
|
int depth;
|
|
depth = player->cell->map->depth;
|
|
getrarity(depth, &min, &max, RARITYVARIANCE);
|
|
dblog("Random object dump for depth %d (rarity %d-%d)",depth,min,max);
|
|
for (i = 0; i < amt; i++) {
|
|
getrandomob(player->cell->map, buf);
|
|
dblog(" %s",buf);
|
|
}
|
|
dblog("END RANDOM OBJECT");
|
|
}
|
|
|
|
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 explode%s!", noprefix(obname), (o->amt == 1) ? "s" : "");
|
|
} else if (cansee(player, o->pile->owner)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(o->pile->owner, lfname);
|
|
msg("%s%s %s explode%s!", lfname, getpossessive(lfname), noprefix(obname), (o->amt == 1) ? "s" : "");
|
|
}
|
|
} else if (haslos(player, c)) {
|
|
msg("%s explode%s!", obname, (o->amt == 1) ? "s" : "");
|
|
}
|
|
explodecells(c, dam * o->amt, 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);
|
|
}
|
|
*/
|
|
// object dies.
|
|
removeob(o, o->amt);
|
|
}
|
|
|
|
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 (cansee(player, o->pile->owner)) {
|
|
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 *findobbyid(obpile_t *op, long oid) {
|
|
object_t *o;
|
|
for (o = op->first; o ; o = o->next) {
|
|
if (o->id == oid) return o;
|
|
}
|
|
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;
|
|
}
|
|
|
|
brand_t *findbrand(enum BRAND id) {
|
|
brand_t *om;
|
|
for (om = firstbrand ; om ; om = om->next) {
|
|
if (om->id == id) return om;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
obmod_t *findobmod(enum OBMOD id) {
|
|
obmod_t *om;
|
|
for (om = firstobmod ; om ; om = om->next) {
|
|
if (om->id == id) return om;
|
|
}
|
|
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;
|
|
knowledge_t *k;
|
|
char *modname;
|
|
char *p;
|
|
int db = B_FALSE;
|
|
brand_t *om;
|
|
|
|
if (!strlen(name)) {
|
|
return NULL;
|
|
}
|
|
|
|
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, "splashes ", "splash ", NULL);
|
|
modname = strrep(modname, "suits ", "suit ", 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 pre mods
|
|
modname = strrep(modname, "flaming ", "", NULL);
|
|
modname = strrep(modname, "headless ", "", NULL);
|
|
|
|
// strip out brands (but not only for certain object classes)
|
|
for (om = firstbrand; om ; om = om->next) {
|
|
modname = strrep(modname, om->suffix, "", 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);
|
|
}
|
|
|
|
if (db) dblog("findotn(): modname is '%s'",modname);
|
|
|
|
// check for exact matches on real name (and plural versions) first
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (checkobnames(ot->name, modname)) {
|
|
free(modname);
|
|
return ot;
|
|
}
|
|
}
|
|
|
|
// then matches on hidden name
|
|
for (k = knowledge; k ; k = k->next) {
|
|
if (checkobnames(k->hiddenname, modname)) {
|
|
free(modname);
|
|
// found it!
|
|
return findot(k->id);
|
|
}
|
|
}
|
|
|
|
// then partial matches on real name
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (strstr(ot->name, modname)) {
|
|
free(modname);
|
|
// found it!
|
|
return ot;
|
|
}
|
|
}
|
|
|
|
free(modname);
|
|
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 fragments(cell_t *centre, char *what, int speed) {
|
|
cell_t *c,*dst;
|
|
int n;
|
|
int dir;
|
|
for (dir = DC_N; dir <= DC_NW; dir++) {
|
|
int maxdist = 0;
|
|
int wantdist = 0;
|
|
int done = B_FALSE;
|
|
// get max distance
|
|
c = centre;
|
|
done = B_FALSE;
|
|
while (!done) {
|
|
c = getcellindir(c, dir);
|
|
if (c && cellwalkable(NULL, c, NULL)) {
|
|
maxdist++;
|
|
} else {
|
|
done = B_TRUE;
|
|
}
|
|
}
|
|
// pick random distance
|
|
if (maxdist == 0) {
|
|
wantdist = 0;
|
|
} else {
|
|
wantdist = rnd(1,maxdist);
|
|
}
|
|
// go that far
|
|
dst = centre;
|
|
for (n = 0; n < wantdist; n++) {
|
|
dst = getcellindir(dst, dir);
|
|
}
|
|
// add object
|
|
addob(dst->obpile, what);
|
|
}
|
|
}
|
|
|
|
void genhiddennames(void) {
|
|
objecttype_t *ot;
|
|
flag_t *f;
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
f = hasflag(ot->flags, F_HASHIDDENNAME);
|
|
if (f) {
|
|
char *thisname;
|
|
if (strlen(f->text)) {
|
|
thisname = strdup(f->text);
|
|
} else {
|
|
thisname = genhiddenname(ot->obclass->id);
|
|
}
|
|
addknowledge(ot->id, thisname, B_UNKNOWN);
|
|
// some descriptions confer other effecst too...
|
|
if (strstr(thisname, "glowing")) {
|
|
addflag(ot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL);
|
|
} else if (strstr(thisname, "flourescent")) {
|
|
addflag(ot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL);
|
|
} else if (strstr(thisname, "luminous")) {
|
|
addflag(ot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL);
|
|
}
|
|
free(thisname);
|
|
}
|
|
}
|
|
}
|
|
|
|
char *genhiddenname(enum OBCLASS id) {
|
|
hiddenname_t *hn;
|
|
|
|
for (hn = firsthiddenname ; hn ; hn = hn->next) {
|
|
if (hn->obclass == id) {
|
|
if (!hn->used) {
|
|
// found one
|
|
hn->used = B_TRUE;
|
|
return hn->text;
|
|
}
|
|
}
|
|
}
|
|
|
|
assert("out of hidden names" == 0);
|
|
return NULL;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
int getobbonus(object_t *o) {
|
|
flag_t *f;
|
|
int bonus = 0;
|
|
for (f = o->flags->first ; f ; f = f->next) {
|
|
if (f->id == F_BONUS) {
|
|
bonus += f->val[0];
|
|
}
|
|
}
|
|
return bonus;
|
|
}
|
|
|
|
// returns the skill associated with this object
|
|
skill_t *getobskill(object_t *o) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_USESSKILL);
|
|
if (f) {
|
|
return findskill(f->val[0]);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
// returns value of obejcts, in gold
|
|
int getobvalue(object_t *o) {
|
|
float price;
|
|
flag_t *f;
|
|
int rarity = 0;
|
|
|
|
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) {
|
|
int min,max;
|
|
getdamrange(o->flags, &min, &max);
|
|
price += (max*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[1] / 5.0);
|
|
}
|
|
// one-off magical effects (linkspell) - use spell price
|
|
if (f->id == F_LINKSPELL) {
|
|
// spelllevel^2 * 20
|
|
price += (pow(getspelllevel(f->val[0]), 2) * 20);
|
|
// ...and spellbooks then cost triple
|
|
if (o->type->obclass->id == OC_BOOK) {
|
|
price *= 3;
|
|
} else if (o->type->obclass->id == OC_SCROLL) {
|
|
// do nothing
|
|
} else if (o->type->obclass->id == OC_WAND) {
|
|
price *= 2.25;
|
|
}
|
|
} else if (f->id == F_MANUALOF) {
|
|
price *= 124;
|
|
}
|
|
}
|
|
|
|
// rarity
|
|
rarity = getobrarity(o);
|
|
|
|
// potions
|
|
if (o->type->obclass->id == OC_POTION) {
|
|
// potion value is based on rarity
|
|
price += ((100 - rarity)*2.75);
|
|
} else if (o->type->obclass->id == OC_TOOLS) {
|
|
// tool value is based on rarity
|
|
price += ((100 - rarity)*5.75);
|
|
} else if (o->type->obclass->id == OC_TECH) {
|
|
// tech value is based on tech level & rarity
|
|
float multiplier = 1;
|
|
switch (gettechlevel(o)) {
|
|
case PR_INEPT:
|
|
multiplier = 3.25;
|
|
break; // do nothing
|
|
case PR_NOVICE:
|
|
multiplier = 5.25;
|
|
break;
|
|
case PR_BEGINNER:
|
|
multiplier = 6.25;
|
|
break;
|
|
case PR_ADEPT:
|
|
multiplier = 7.25;
|
|
break;
|
|
case PR_SKILLED:
|
|
multiplier = 8.25;
|
|
break;
|
|
case PR_EXPERT:
|
|
multiplier = 9.25;
|
|
break;
|
|
case PR_MASTER:
|
|
multiplier = 10.25;
|
|
break;
|
|
}
|
|
price += ((100 - rarity)*multiplier);
|
|
}
|
|
|
|
|
|
// TODO: conferred intrinsics - depends on which one
|
|
|
|
// TODO: conferred spells - use spell price * multiplier
|
|
|
|
// speical material prices like velvet, silk
|
|
if (strstr(o->type->name, "velvet")) {
|
|
price *= 1.5;
|
|
}
|
|
if (strstr(o->type->name, "silk")) {
|
|
price *= 2;
|
|
}
|
|
|
|
// rarity
|
|
if (rarity >= 70) {
|
|
price /= 1.5;
|
|
} else if (rarity <= 40) {
|
|
price *= 1.5;
|
|
} else if (rarity <= 20) {
|
|
price *= 2;
|
|
} else if (rarity <= 10) {
|
|
price *= 5;
|
|
}
|
|
|
|
// blessed/cursed
|
|
if (isblessed(o)) price *= 1.5;
|
|
if (iscursed(o)) price /= 3;
|
|
|
|
// 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_ALL: return "all damage";
|
|
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_PETRIFY: return "petrification";
|
|
case DT_POISONGAS: return "poison gas";
|
|
case DT_POISON: return "poison";
|
|
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";
|
|
case DT_UNARMED: return "unarmed";
|
|
case DT_LIGHT: return "light";
|
|
case DT_CRUSH: return "crushing";
|
|
case DT_FALL: return "falling";
|
|
default: return "unknown";
|
|
}
|
|
return "unknown";
|
|
}
|
|
|
|
char *getdamnamenoun(enum DAMTYPE damtype) {
|
|
switch (damtype) {
|
|
case DT_ALL: return "all damage";
|
|
case DT_ACID: return "acid";
|
|
case DT_MELT: return "melting";
|
|
case DT_PETRIFY: return "petrification";
|
|
case DT_PIERCE: return "piercing damage";
|
|
case DT_POISONGAS: return "poison gas";
|
|
case DT_POISON: return "poison";
|
|
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";
|
|
case DT_UNARMED: return "unarmed damage";
|
|
case DT_LIGHT: return "light damage";
|
|
case DT_CRUSH: return "crushing damage";
|
|
case DT_FALL: return "damage from falling";
|
|
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 getobattackdelay(object_t *o) {
|
|
int delay = 100; // ie. 100%
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_OBATTACKDELAY);
|
|
if (f) {
|
|
delay = f->val[0];
|
|
}
|
|
return delay;
|
|
}
|
|
|
|
float getobhppct(object_t *o) {
|
|
float pct;
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_OBHP);
|
|
if (f) {
|
|
pct = ((float) f->val[0] / (float) f->val[1]) * 100.0;
|
|
} else {
|
|
pct = 100;
|
|
}
|
|
return pct;
|
|
}
|
|
|
|
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:
|
|
case MT_ACID:
|
|
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:
|
|
case MT_WAX:
|
|
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;
|
|
float strmod;
|
|
float modobweight;
|
|
// adjust for lifeform strength
|
|
// mighty = div by 10
|
|
|
|
// this will give us a number in range -44 - 50
|
|
strmod = getstatmod(lf, A_STR);
|
|
// this will give us a number in range 1 - 10
|
|
strmod /= 5;
|
|
if (strmod < 1) strmod = 1;
|
|
|
|
modobweight = getobunitweight(o) / 2;
|
|
modobweight /= strmod;
|
|
|
|
maxdist = 10 - modobweight;
|
|
|
|
if (maxdist < 0) maxdist = 0;
|
|
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);
|
|
numshards *= o->amt;
|
|
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) {
|
|
f = hasflag(o->flags, F_DRINKABLE);
|
|
}
|
|
|
|
if (f) {
|
|
basenutr = (float)f->val[1];
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return basenutr;
|
|
}
|
|
|
|
int getnutrition(object_t *o) {
|
|
float nutrpct;
|
|
float nutrition;
|
|
|
|
if (isrotting(o)) {
|
|
nutrition = -(HUNGERCONST/2);
|
|
} else {
|
|
nutrpct = getnutritionbase(o);
|
|
|
|
if (nutrpct <= 0) {
|
|
nutrition = 0;
|
|
} else {
|
|
nutrition = pctof(nutrpct, (float) HUNGERCONST);
|
|
}
|
|
}
|
|
|
|
if (hasflag(o->flags, F_HEADLESS)) {
|
|
// -25% nutrition
|
|
nutrition *= 0.75;
|
|
}
|
|
|
|
return (int)nutrition;
|
|
}
|
|
|
|
char *getobdesc(object_t *o, char *buf) {
|
|
if (isknown(o)) {
|
|
if (o->type->id == OT_CORPSE) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_CORPSEOF);
|
|
if (f) {
|
|
race_t *corpserace;
|
|
corpserace = findrace(f->val[0]);
|
|
sprintf(buf, "The dead body of %s %s.", isvowel(corpserace->name[0]) ? "an" : "a",
|
|
corpserace->name);
|
|
} else {
|
|
sprintf(buf, "%s", o->type->desc);
|
|
}
|
|
} else if (o->type->id == OT_HEAD) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_CORPSEOF);
|
|
if (f) {
|
|
race_t *corpserace;
|
|
corpserace = findrace(f->val[0]);
|
|
sprintf(buf, "The decapitated head of %s %s.", isvowel(corpserace->name[0]) ? "an" : "a",
|
|
corpserace->name);
|
|
} else {
|
|
sprintf(buf, "%s", o->type->desc);
|
|
}
|
|
} else if (o->type->id == OT_STATUE) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_CORPSEOF);
|
|
if (f) {
|
|
race_t *corpserace;
|
|
corpserace = findrace(f->val[0]);
|
|
sprintf(buf, "A stone statue of %s %s.", isvowel(corpserace->name[0]) ? "an" : "a",
|
|
corpserace->name);
|
|
} else {
|
|
sprintf(buf, "%s", o->type->desc);
|
|
}
|
|
} else if (o->type->id == OC_SCROLL) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_LINKSPELL);
|
|
if (f) {
|
|
objecttype_t *spelltype;
|
|
spelltype = findot(f->val[0]);
|
|
if (spelltype) {
|
|
sprintf(buf, "%s", spelltype->desc);
|
|
} else {
|
|
sprintf(buf, "%s", o->type->desc);
|
|
}
|
|
} else {
|
|
sprintf(buf, "%s", o->type->desc);
|
|
}
|
|
} else {
|
|
sprintf(buf, "%s", o->type->desc);
|
|
}
|
|
} else {
|
|
sprintf(buf, "%s", o->type->obclass->desc);
|
|
}
|
|
return buf;
|
|
}
|
|
|
|
|
|
char *getobextrainfo(object_t *o, char *buf) {
|
|
object_t *ammo = NULL;
|
|
flag_t *f;
|
|
|
|
strcpy(buf, "");
|
|
|
|
if (o->pile->owner) {
|
|
ammo = getammo(o->pile->owner);
|
|
}
|
|
|
|
// charges
|
|
f = hasflag(o->flags, F_CHARGES);
|
|
if (f && f->known) {
|
|
if (!hasflag(o->flags, F_DONTSHOWCHARGES)) {
|
|
char chargestr[BUFLEN];
|
|
if (f->val[0] > 0) {
|
|
sprintf(chargestr, " (%d charges left)",f->val[0]);
|
|
} else {
|
|
sprintf(chargestr, " (empty)");
|
|
}
|
|
strcat(buf, chargestr);
|
|
}
|
|
}
|
|
|
|
// activated
|
|
f = hasflag(o->flags, F_ACTIVATED);
|
|
if (f) {
|
|
strcat(buf, " [activated]");
|
|
}
|
|
|
|
f = hasflag(o->flags,F_EQUIPPED);
|
|
if (f) {
|
|
if (f->val[0] == BP_WEAPON) {
|
|
if (hasflag(o->flags, F_TWOHANDED)) {
|
|
strcat(buf, " (two-handed weapon)");
|
|
} else {
|
|
strcat(buf, " (weapon)");
|
|
}
|
|
} else {
|
|
strcat(buf, " (");
|
|
strcat(buf, getbodypartequipname(f->val[0]));
|
|
strcat(buf, " ");
|
|
strcat(buf, getbodypartname(f->val[0]));
|
|
strcat(buf, ")");
|
|
}
|
|
}
|
|
|
|
// ammo?
|
|
if (ammo && (ammo == o)) {
|
|
strcat(buf, " (current ammo)");
|
|
}
|
|
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, B_TRUE);
|
|
}
|
|
|
|
// buf must already be allocated
|
|
char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wantcondition, int adjustforblind, int wantblesscurse) {
|
|
char *pluralname;
|
|
char prefix[BUFLEN];
|
|
char basename[BUFLEN];
|
|
char buf2[BUFLEN];
|
|
int shopitem = B_FALSE;
|
|
flag_t *f;
|
|
brand_t *br;
|
|
obmod_t *om;
|
|
int hasunknownmod = B_FALSE;
|
|
cell_t *where;
|
|
|
|
// default to normal name
|
|
if (hasflag(o->flags, F_SHOPITEM)) {
|
|
shopitem = B_TRUE;
|
|
}
|
|
|
|
where = getoblocation(o);
|
|
|
|
if (shopitem) {
|
|
strcpy(basename,o->type->name);
|
|
} else {
|
|
strcpy(basename,gethiddenname(o));
|
|
}
|
|
|
|
if (!shopitem) {
|
|
if ((gamemode == GM_GAMESTARTED) && adjustforblind && !haslos(player, where) ) {
|
|
// override with obclass names
|
|
switch (o->type->obclass->id) {
|
|
case OC_BOOK:
|
|
strcpy(basename, "book");
|
|
break;
|
|
case OC_POTION:
|
|
strcpy(basename, "potion");
|
|
break;
|
|
case OC_RING:
|
|
strcpy(basename, "ring");
|
|
break;
|
|
case OC_SCROLL:
|
|
strcpy(basename, "scroll");
|
|
break;
|
|
case OC_WAND:
|
|
strcpy(basename, "wand");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (o->type->obclass->id == OC_RING) {
|
|
strcpy(basename, "ring");
|
|
} else 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");
|
|
}
|
|
|
|
// override corpse name
|
|
if (o->type->id == OT_CORPSE) {
|
|
f = hasflag(o->flags, F_CORPSEOF);
|
|
if (f) {
|
|
race_t *corpserace;
|
|
corpserace = findrace(f->val[0]);
|
|
sprintf(basename, "%s corpse",corpserace->name);
|
|
}
|
|
} else if (o->type->id == OT_HEAD) {
|
|
f = hasflag(o->flags, F_CORPSEOF);
|
|
if (f) {
|
|
race_t *corpserace;
|
|
corpserace = findrace(f->val[0]);
|
|
sprintf(basename, "%s head",corpserace->name);
|
|
}
|
|
} else if (o->type->id == OT_STATUE) {
|
|
f = hasflag(o->flags, F_CORPSEOF);
|
|
if (f) {
|
|
race_t *corpserace;
|
|
corpserace = findrace(f->val[0]);
|
|
sprintf(basename, "statue of a %s",corpserace->name);
|
|
}
|
|
}
|
|
|
|
// 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_GOLD:
|
|
strcat(buf, "golden ");
|
|
break;
|
|
case MT_WOOD:
|
|
strcat(buf, "wooden ");
|
|
break;
|
|
default:
|
|
// strcat(buf, o->material->name);
|
|
// strcat(buf, " ");
|
|
break;
|
|
}
|
|
}
|
|
|
|
// include mods (ie. a flaming sword)
|
|
if (wantpremods) {
|
|
for (om = firstobmod ; om; om = om->next) {
|
|
flag_t *omf;
|
|
int found = B_FALSE;
|
|
for (omf = om->flags->first ; omf ; omf = omf->next){
|
|
if (hasflag(o->flags, omf->id)) {
|
|
found = B_TRUE;
|
|
}
|
|
}
|
|
if (found) {
|
|
strcat(buf, om->prefix);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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
|
|
for (br = firstbrand; br; br = br->next) {
|
|
if (hasflagval(o->flags, F_HASBRAND, br->id, NA, NA, NULL)) {
|
|
flag_t *brf;
|
|
int ok = B_TRUE;
|
|
// are all of the brand flags known?
|
|
for (brf = br->flags->first ; brf ; brf = brf->next) {
|
|
for (f = o->flags->first; f ; f = f->next) {
|
|
if ((f->id == brf->id) && (f->lifetime == FROMBRAND)) {
|
|
if (f->known || shopitem) {
|
|
} else {
|
|
ok = B_FALSE;
|
|
hasunknownmod = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ok) {
|
|
strcat(buf, br->suffix);
|
|
}
|
|
}
|
|
}
|
|
|
|
// make sure obname doesn't start with a space
|
|
while (buf && (buf[0] == ' ')) {
|
|
strcpy(buf, buf + 1);
|
|
}
|
|
|
|
// show portal/stair destination
|
|
f = hasflag(o->flags, F_MAPLINK);
|
|
if (f && f->known) {
|
|
map_t *newmap;
|
|
newmap = findmap(f->val[0]);
|
|
if (newmap) {
|
|
char buf2[BUFLEN];
|
|
sprintf(buf2, " to level %d", newmap->depth);
|
|
strcat(buf, buf2);
|
|
}
|
|
}
|
|
|
|
// append inscription
|
|
if (o->inscription) {
|
|
strcat(buf, " {");
|
|
strcat(buf, o->inscription);
|
|
strcat(buf, "}");
|
|
}
|
|
|
|
// TODO: detect magic - append [magic]
|
|
if ((gamemode == GM_GAMESTARTED) && lfhasflag(player, F_DETECTMAGIC)) {
|
|
int ismagic = B_FALSE;
|
|
if (hasunknownmod) {
|
|
ismagic = B_TRUE;
|
|
}
|
|
switch (o->type->obclass->id) {
|
|
case OC_SCROLL:
|
|
switch (o->type->id) {
|
|
case OT_MAP:
|
|
case OT_SCR_NOTHING:
|
|
// these scrolls are non-magical
|
|
break;
|
|
default:
|
|
ismagic = B_TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
case OC_RING:
|
|
case OC_WAND:
|
|
// all rings/wands are magical
|
|
ismagic = B_TRUE;
|
|
break;
|
|
case OC_POTION:
|
|
switch (o->type->id) {
|
|
case OT_POT_ACID:
|
|
case OT_POT_OIL:
|
|
case OT_POT_WATER:
|
|
case OT_POT_BLOOD:
|
|
case OT_POT_JUICE:
|
|
// these potions are non-magical
|
|
break;
|
|
default:
|
|
ismagic = B_TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
case OC_BOOK:
|
|
if (hasflag(o->flags, F_LINKSPELL)) {
|
|
// ie. spellbooks
|
|
ismagic = B_TRUE;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
|
|
if (ismagic) {
|
|
strcat(buf, " [magic]");
|
|
}
|
|
}
|
|
|
|
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) {
|
|
float pct;
|
|
enum IQBRACKET iqb;
|
|
if (player) {
|
|
iqb = getiqname(getattr(player, A_IQ), NULL);
|
|
} else {
|
|
iqb = IQ_AVERAGE; // this should be sufficient to show everything
|
|
}
|
|
|
|
if (iscorpse(o)) {
|
|
// you only know it's rotting if you have average or higher iq
|
|
if (isrotting(o) && (iqb >= IQ_AVERAGE)) {
|
|
sprintf(buf, "rotting");
|
|
} else {
|
|
strcpy(buf, "");
|
|
}
|
|
} else {
|
|
if (iqb >= IQ_DIMWITTED) {
|
|
|
|
pct = getobhppct(o);
|
|
|
|
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");
|
|
}
|
|
} else {
|
|
strcpy(buf, "");
|
|
}
|
|
}
|
|
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_FALSE;
|
|
char *pluralname;
|
|
char brandname[BUFLEN];
|
|
char cursestr[BUFLEN];
|
|
int raritymin,raritymax;
|
|
int depth;
|
|
int done = B_FALSE;
|
|
|
|
|
|
if (forcedepth != NA) {
|
|
depth = forcedepth;
|
|
} else if (map) {
|
|
depth = map->depth;
|
|
} else {
|
|
depth = rnd(1,MAXDEPTH);
|
|
}
|
|
|
|
getrarity(depth, &raritymin, &raritymax, RARITYVARIANCE);
|
|
|
|
while (!done) {
|
|
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;
|
|
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);
|
|
} else {
|
|
// something found
|
|
done = B_TRUE;
|
|
}
|
|
} // end while !done
|
|
|
|
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);
|
|
}
|
|
|
|
// weapons/armour have random chance of various obmods
|
|
if ((ot->obclass->id == OC_WEAPON) ||
|
|
(ot->obclass->id == OC_ARMOUR)) {
|
|
obmod_t *om;
|
|
// 1 in 6 of masterwork
|
|
if (rnd(1,6) == 1) {
|
|
om = findobmod(OM_MASTERWORK);
|
|
strcat(cursestr, om->prefix);
|
|
} else if (rnd(1,3) == 1) { // 1 in 3 of shoddy
|
|
om = findobmod(OM_SHODDY);
|
|
strcat(cursestr, om->prefix);
|
|
}
|
|
|
|
}
|
|
|
|
if (canbepoisoned(ot->id)) {
|
|
// random chance of being poisoned
|
|
if (rnd(1,6) == 1) {
|
|
obmod_t *om;
|
|
om = findobmod(OM_POISONED);
|
|
strcat(cursestr, om->prefix);
|
|
|
|
}
|
|
}
|
|
|
|
// get random chance of having a brand (1% per depth)...
|
|
// if so...
|
|
strcpy(brandname, "");
|
|
if (rnd(1,100) <= depth) {
|
|
brand_t *om, **poss;
|
|
int numom;
|
|
int nposs = 0;
|
|
|
|
// count number of brands
|
|
numom = 0;
|
|
for (om = firstbrand ; om ; om = om->next) {
|
|
numom++;
|
|
}
|
|
poss = malloc(numom * sizeof(brand_t *));
|
|
|
|
for (om = firstbrand ; om ; om = om->next) {
|
|
if (brandappliesto(om, ot)) {
|
|
poss[nposs] = om;
|
|
nposs++;
|
|
}
|
|
}
|
|
|
|
if (nposs > 0) {
|
|
om = poss[rnd(0,nposs-1)];
|
|
strcpy(brandname, om->suffix);
|
|
}
|
|
free(poss);
|
|
}
|
|
|
|
|
|
sprintf(buf, "%d %s%s%s", amt, cursestr, pluralname,brandname);
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
int getobrarity(object_t *o) {
|
|
cell_t *c;
|
|
map_t *m = NULL;
|
|
flag_t *f;
|
|
// check for rarity on this object's map first
|
|
c = getoblocation(o);
|
|
if (c) {
|
|
m = c->map;
|
|
}
|
|
if (m) {
|
|
f = hasflagval(o->flags, F_RARITY,m->habitat, NA, NA, NULL);
|
|
if (f) {
|
|
return f->val[0];
|
|
}
|
|
}
|
|
// any rarity value at all?
|
|
f = hasflag(o->flags, F_RARITY);
|
|
if (f) {
|
|
return f->val[0];
|
|
}
|
|
// ie. doesn't randomly appear
|
|
return 0;
|
|
}
|
|
|
|
enum SPELLSCHOOL getschool(enum OBTYPE sid) {
|
|
objecttype_t *ot;
|
|
ot = findot(sid);
|
|
if (ot) {
|
|
flag_t *f;
|
|
f = hasflag(ot->flags, F_SPELLSCHOOL);
|
|
if (f) {
|
|
return f->val[0];
|
|
}
|
|
}
|
|
return SS_NONE;
|
|
}
|
|
|
|
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 "Psionic Powers";
|
|
case SS_AIR: return "Elemental/Air Magic";
|
|
case SS_FIRE: return "Elemental/Fire Magic";
|
|
case SS_ICE: return "Elemental/Ice Magic";
|
|
case SS_MODIFICATION: return "Transmutation Magic";
|
|
case SS_DEATH: return "Necromancy";
|
|
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!";
|
|
default:
|
|
break;
|
|
}
|
|
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;
|
|
}
|
|
|
|
enum SKILLLEVEL gettechlevel(object_t *o) {
|
|
flag_t *f;
|
|
enum SKILLLEVEL tlev = PR_INEPT;
|
|
f = hasflag(o->flags, F_TECHLEVEL);
|
|
if (f) {
|
|
tlev = f->val[0];
|
|
}
|
|
return tlev;
|
|
}
|
|
|
|
int getthrowdam(object_t *o) {
|
|
double dam = 0;
|
|
flag_t *f;
|
|
|
|
// modify if it has a damage value
|
|
f = hasflag(o->flags, F_MISSILEDAM);
|
|
if (f) {
|
|
dam = f->val[0];
|
|
} else {
|
|
// 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));
|
|
// missile objects do extra damage
|
|
if (hasflag(o->flags, F_THROWMISSILE)) {
|
|
dam *= 2;
|
|
}
|
|
// max
|
|
if (dam > 20) dam = 20;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
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 *hasobletter(obpile_t *op, char letter) {
|
|
object_t *o;
|
|
for (o = op->first ; o ; o = o->next) {
|
|
if (o->letter == letter) 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 ignite(object_t *o) {
|
|
flag_t *f;
|
|
if (!hasflag(o->flags, F_DAMAGABLE)) {
|
|
addflag(o->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
}
|
|
|
|
f = hasflag(o->flags, F_ONFIRE);
|
|
if (!f) {
|
|
// on fire for 2 turns
|
|
addtempflag(o->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, 2);
|
|
}
|
|
}
|
|
|
|
|
|
void initobjects(void) {
|
|
//int ch;
|
|
int i,n;
|
|
objecttype_t *ot;
|
|
|
|
// generate hidden names
|
|
for (n = 0; strlen(colour[n]); n++) {
|
|
char buf[BUFLEN];
|
|
// add it without an adjective
|
|
sprintf(buf, "%s book", colour[n]);
|
|
addhiddenname(OC_BOOK, buf);
|
|
// add it with all known adjectives
|
|
for (i = 0; strlen(bookadjective[i]) ; i++) {
|
|
sprintf(buf, "%s %s book",bookadjective[i], colour[n]);
|
|
addhiddenname(OC_BOOK, buf);
|
|
}
|
|
}
|
|
|
|
addhiddenname(OC_SCROLL, "scroll titled ABRA CA DABRA");
|
|
addhiddenname(OC_SCROLL, "scroll titled BARBAR");
|
|
addhiddenname(OC_SCROLL, "scroll titled CRATOL JEM");
|
|
addhiddenname(OC_SCROLL, "scroll titled DELENTH YIN");
|
|
addhiddenname(OC_SCROLL, "scroll titled ETEE NOM");
|
|
addhiddenname(OC_SCROLL, "scroll titled FIE JOOHM");
|
|
addhiddenname(OC_SCROLL, "scroll titled GREE VII");
|
|
addhiddenname(OC_SCROLL, "scroll titled HTEB IH");
|
|
addhiddenname(OC_SCROLL, "scroll titled HOCUS POCUS");
|
|
addhiddenname(OC_SCROLL, "scroll titled ILU-MA ZEE");
|
|
addhiddenname(OC_SCROLL, "scroll titled JUNIPO CHECK");
|
|
addhiddenname(OC_SCROLL, "scroll titled KARELS");
|
|
addhiddenname(OC_SCROLL, "scroll titled LUMLEE GWON");
|
|
addhiddenname(OC_SCROLL, "scroll titled MARIGON");
|
|
addhiddenname(OC_SCROLL, "scroll titled MAXIMOR BLATHUS");
|
|
addhiddenname(OC_SCROLL, "scroll titled NORTH");
|
|
addhiddenname(OC_SCROLL, "scroll titled REZZ KINETO");
|
|
addhiddenname(OC_SCROLL, "scroll titled SHAZZARIO");
|
|
addhiddenname(OC_SCROLL, "scroll titled THERIUM LARGOS");
|
|
addhiddenname(OC_SCROLL, "scroll titled VOLTR YI MEN");
|
|
addhiddenname(OC_SCROLL, "scroll titled ZAREL NOR");
|
|
|
|
addhiddenname(OC_POTION, "clear potion");
|
|
|
|
for (n = 0; strlen(colour[n]); n++) {
|
|
char buf[BUFLEN];
|
|
// add it without an adjective
|
|
sprintf(buf, "%s potion", colour[n]);
|
|
addhiddenname(OC_POTION, buf);
|
|
// add it with all known adjectives
|
|
for (i = 0; strlen(potadjective[i]) ; i++) {
|
|
sprintf(buf, "%s %s potion",potadjective[i], colour[n]);
|
|
addhiddenname(OC_POTION, buf);
|
|
}
|
|
}
|
|
|
|
addhiddenname(OC_WAND, "amethyst wand");
|
|
addhiddenname(OC_WAND, "brass wand");
|
|
addhiddenname(OC_WAND, "copper wand");
|
|
addhiddenname(OC_WAND, "diamond wand");
|
|
addhiddenname(OC_WAND, "emerald wand");
|
|
addhiddenname(OC_WAND, "flourescent wand");
|
|
addhiddenname(OC_WAND, "gold wand");
|
|
addhiddenname(OC_WAND, "humming wand");
|
|
addhiddenname(OC_WAND, "iridium wand");
|
|
addhiddenname(OC_WAND, "luminous wand");
|
|
addhiddenname(OC_WAND, "ruby wand");
|
|
addhiddenname(OC_WAND, "zinc wand");
|
|
addhiddenname(OC_WAND, "sapphire wand");
|
|
addhiddenname(OC_WAND, "wooden wand");
|
|
|
|
addhiddenname(OC_RING, "agate ring");
|
|
addhiddenname(OC_RING, "bronze ring");
|
|
addhiddenname(OC_RING, "copper ring");
|
|
addhiddenname(OC_RING, "diamond ring");
|
|
addhiddenname(OC_RING, "emerald ring");
|
|
addhiddenname(OC_RING, "flourite ring");
|
|
addhiddenname(OC_RING, "garnet ring");
|
|
addhiddenname(OC_RING, "gold ring");
|
|
addhiddenname(OC_RING, "jade ring");
|
|
addhiddenname(OC_RING, "polished ring");
|
|
addhiddenname(OC_RING, "quartz ring");
|
|
addhiddenname(OC_RING, "ruby ring");
|
|
addhiddenname(OC_RING, "sapphire ring");
|
|
addhiddenname(OC_RING, "silver ring");
|
|
|
|
|
|
|
|
for (n = 0; strlen(technoun[n]); n++) {
|
|
// add it without an adjective
|
|
addhiddenname(OC_TECH, technoun[n]);
|
|
// add it with all known adjectives
|
|
for (i = 0; strlen(techadjective[i]) ; i++) {
|
|
char buf[BUFLEN];
|
|
sprintf(buf, "%s %s",techadjective[i], technoun[n]);
|
|
addhiddenname(OC_TECH, buf);
|
|
}
|
|
}
|
|
|
|
shufflehiddennames();
|
|
|
|
|
|
// object modifiers - flags can be either known or not, depending on if it's obvious
|
|
addobmod(OM_FLAMING,"flaming");
|
|
addflag_real(lastobmod->flags, F_ONFIRE, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
|
addobmod(OM_FROZEN,"frozen");
|
|
addflag_real(lastobmod->flags, F_FROZEN, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
|
addobmod(OM_HEADLESS,"headless");
|
|
addflag_real(lastobmod->flags, F_HEADLESS, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
|
addobmod(OM_MASTERWORK,"masterwork");
|
|
addflag_real(lastobmod->flags, F_MASTERWORK, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
|
addobmod(OM_SHODDY,"shoddy");
|
|
addflag_real(lastobmod->flags, F_SHODDY, B_TRUE, NA, NA, NULL, PERMENANT, B_KNOWN, -1);
|
|
addobmod(OM_POISONED,"poisoned");
|
|
addflag_real(lastobmod->flags, F_HITCONFER, F_POISONED, SC_POISON, 25, "2-8", PERMENANT, B_KNOWN, -1);
|
|
|
|
// brands modifiers - flags should be UNKNOWN!
|
|
// also don't double up with names of scrolls etc.
|
|
// ie. spellbook of flight, boots of flight.
|
|
addbrand(BR_BALANCE, "of balance", BP_WEAPON);
|
|
addflag_real(lastbrand->flags, F_BALANCE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_PYROMANIA, "of pyromania", BP_WEAPON);
|
|
addflag_real(lastbrand->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_REVENGE, "of revenge", BP_WEAPON);
|
|
addflag_real(lastbrand->flags, F_REVENGE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_SHARPNESS, "of sharpness", BP_WEAPON);
|
|
addflag_real(lastbrand->flags, F_ARMOURPIERCE, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
|
|
addbrand(BR_LEVITATION, "of hovering", BP_FEET);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_LEVITATING, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_FEATHERFALL, "of featherfall", BP_FEET);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_FALL, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
|
|
addbrand(BR_SWIFTNESS, "of swiftness", BP_FEET);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_FASTMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_SLOTH, "of sloth", BP_FEET);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_SLOWMOVE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
|
|
addbrand(BR_STRENGTH, "of strength", BP_HANDS);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_STR, 3, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_WEAKNESS, "of feebleness", BP_HANDS);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_STR, -3, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_DEXTERITY, "of dexterity", BP_HANDS);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_DEX, 3, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_IMPACT, "of impact", BP_WEAPON); // TODO: make thisonly go ont obashing weapons
|
|
addflag_real(lastbrand->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_INTELLIGENCE, "of intelligence", BP_HEAD);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRMOD, A_IQ, 3, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_KNOWLEDGE, "of knowledge", BP_HEAD);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_DETECTAURAS, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_DETECTMAGIC, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_TELEPATHY, "of telepathy", BP_HEAD);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_DETECTLIFE, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_TELEKINESIS, "of the poltergeist", BP_HEAD);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_CANWILL, OT_S_TELEKINESIS, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_GIANTSTRENGTH, "of giant strength", BP_WAIST);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRSET, A_STR, 18, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_FEEBLENESS, "of feebleness", BP_WAIST);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_ATTRSET, A_STR, 3, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_FLIGHT, "of the eagle", BP_WAIST);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_FLYING, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_SPEED, "of swiftness", BP_WAIST);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_FASTACT, 5, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_CONCEALMENT, "of concealment", BP_SHOULDERS);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_INVISIBLE, B_TRUE, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
addbrand(BR_ANTIMAG, "of antimagic", BP_SHOULDERS);
|
|
addflag_real(lastbrand->flags, F_EQUIPCONFER, F_RESISTMAG, 10, NA, NULL, PERMENANT, B_UNKNOWN, -1);
|
|
|
|
// 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_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);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_WAX, "wax", 3);
|
|
addflag(lastmaterial->flags, F_MATCONVERT, MT_FIRE, NA, NA, "lump of melted wax");
|
|
addflag(lastmaterial->flags, F_MATCONVERTTEXT, MT_FIRE, NA, NA, "melts");
|
|
addflag(lastmaterial->flags, F_MATCONVERTTEXTPL, MT_FIRE, NA, NA, "melt");
|
|
addmaterial(MT_RUBBER, "rubber", 4);
|
|
addmaterial(MT_LEATHER, "leather", 4);
|
|
addmaterial(MT_BONE, "bone", 5);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_ICE, "ice",6);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_WOOD, "wood", 6);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastmaterial->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_ACID, "acid", 7);
|
|
addmaterial(MT_WATER, "water", 7);
|
|
addmaterial(MT_BLOOD, "blood", 7);
|
|
addmaterial(MT_SLIME, "slime", 9);
|
|
addmaterial(MT_STONE, "stone", 10);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_METAL, "metal", 13);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_GLASS, "glass", 13);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
addmaterial(MT_GOLD, "gold", 16);
|
|
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL);
|
|
//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_WAND, "Wands", "A limited-use magical wand which casts the imbued spell.", '/');
|
|
addflag(lastobjectclass->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_OPERUSECHARGE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_RNDCHARGES, 2, 12, NA, NULL);
|
|
|
|
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);
|
|
addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_ARMOUR, "Armour/Clothing", "Protective gear.", ']');
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_ENCHANTABLE, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_MISSILE, "Missiles/Ammunition", "An instrument used for the purpose of causing harm or death.", ';');
|
|
addflag(lastobjectclass->flags, F_ENCHANTABLE, 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);
|
|
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, "Technology", "A strange piece of futuristic technology.", '~');
|
|
addflag(lastobjectclass->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastobjectclass->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addoc(OC_TOOLS, "Tools", "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_BOOK, "Books", "Spellbooks, tomes or manuals.", '+');
|
|
addflag(lastobjectclass->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
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, SZ_MAX, 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, SZ_HUMAN, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CRUSHABLE, SZ_LARGE, 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, 80, OC_DFEATURE);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, "");
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'");
|
|
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, 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_THROWMISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "50-100 stones");
|
|
|
|
addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_DFEATURE);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, "");
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'");
|
|
addflag(lastot->flags, F_IMPASSABLE, SZ_LARGE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PUSHABLE, 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_OBHP, 80, 80, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "20-50 stones");
|
|
|
|
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, 70, 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);
|
|
|
|
addot(OT_PORTAL, "magic portal", "A magical portal to a different place...", MT_MAGIC, 0, OC_DFEATURE);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "&");
|
|
addflag(lastot->flags, F_CLIMBABLE, D_IN, 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_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_THROWMISSILE, 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);
|
|
addflag(lastot->flags, F_POWDER, 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_HOLDCONFER, F_DETECTMAGIC, B_TRUE, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, 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, 90, 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, 90, 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.3, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 50, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
|
|
addot(OT_BANANASKIN, "banana skin", "A slippery banana skin.", MT_FOOD, 0.1, OC_FOOD);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_SLIPPERY, 15, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SLIPMOVE, 15, NA, 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, 85, 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, 90, 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, 80, 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, 70, 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, 65, 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_CORPSE, "corpse", "xxx", MT_FLESH, 1, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL);
|
|
addot(OT_HEAD, "head", "xxx", MT_FLESH, 1, OC_CORPSE);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 1, NA, NULL);
|
|
|
|
addot(OT_FLESHCHUNK, "chunk of flesh", "A chunk of flesh from something.", MT_FLESH, 1, OC_FOOD);
|
|
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
|
|
|
|
|
|
// potions (sorted by rarity)
|
|
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);
|
|
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);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small puddle of water");
|
|
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, 90, NA, NULL);
|
|
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, 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, 80, NA, NULL);
|
|
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, 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_RESTORATION, "potion of restoration", "Restores lost abilities to the drinker.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addot(OT_POT_SPEED, "potion of haste", "Temporarily increasees the drinker's speed.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, 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, 75, NA, NULL);
|
|
addflag(lastot->flags, F_THROWMISSILE, 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, 70, 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, 70, NA, NULL);
|
|
addot(OT_POT_INVIS, "potion of invisibility", "Temporarily renders the drinker invisible.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, 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_DIECONVERT, NA, NA, NA, "puddle of acid");
|
|
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_BLOOD, "potion of blood", "A small quantity of blood.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "splash of blood");
|
|
|
|
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, 60, NA, NULL);
|
|
|
|
addot(OT_POT_ETHEREALNESS, "potion of etherealness", "Allows the walker to temporarily pass through walls.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addot(OT_POT_EXPERIENCE, "potion of experience", "Instantly grants the imbiber the next experience level.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 40, NA, NULL);
|
|
|
|
addot(OT_POT_BLOODC, "potion of cockatrice blood", "A small quantity of cockatrice blood.", MT_GLASS, 1, OC_POTION);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "splash of cockatrice blood");
|
|
|
|
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, 50, 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);
|
|
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, 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_THROWMISSILE, B_TRUE, NA, 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);
|
|
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
|
|
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);
|
|
addflag(lastot->flags, F_AIHEALITEM, B_TRUE, NA, 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, 60, 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, 70, 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);
|
|
addflag(lastot->flags, F_AIBOOSTITEM, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, 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, 85, 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, 85, NA, NULL);
|
|
|
|
addot(OT_SCR_DETECTOBS, "scroll of detect objects", "Senses objects near the caster.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTOBS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
|
|
|
|
|
|
addot(OT_SCR_DETECTMAGIC, "scroll of detect magic", "Allows the reader to detect magical enchantments.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTMAGIC, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
|
|
addot(OT_SCR_FLAMEPILLAR, "scroll of flame pillar", "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, 80, NA, NULL);
|
|
|
|
addot(OT_SCR_FLAMEBURST, "scroll of flame burst", "Creates a radial blast of fire out from the caster.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEBURST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
|
|
addot(OT_SCR_ENCHANT, "scroll of enchantment", "Magically enhances a weapon or piece of armour.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_ENCHANT, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, 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, 75, 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_KNOCK, "scroll of knock", "Magically opens a barrier.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, 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);
|
|
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, 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, 80, 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_TELEPORT, "scroll of 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_TELEPORT, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_SCR_REMOVECURSE, "scroll of remove curse", "Removes curses from all weilded equipment.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL);
|
|
|
|
addot(OT_SCR_TURNUNDEAD, "scroll of turn undead", "Instills fear in undead creatures.", MT_PAPER, 0.5, OC_SCROLL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, 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);
|
|
// 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);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, 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);
|
|
addot(OT_S_METALHEAL, "metal healing", "Uses nearby metal for accelerated healing.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ALLOMANCY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_EXPLODEMETAL, "explode metal", "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);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
|
|
///////////////////
|
|
// death
|
|
///////////////////
|
|
// l2
|
|
addot(OT_S_BLINDNESS, "blindness", "Temporarily blinds the target.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_ANIMATEDEAD, "animate dead", "Imbues nearby corpses with life, creating an undead zombie.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
// TODO: should be "castnearob ot_corpse"
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
|
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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_S_PAIN, "pain", "Causes extreme pain in the target whenever they move.", 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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
// l4
|
|
addot(OT_S_PARALYZE, "paralyze", "Disables the target's muscles, leaving them unable to move.", 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_AICASTTOATTACK, ST_VICTIM, 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_AICASTTOATTACK, ST_ANYWHERE, 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);
|
|
addot(OT_S_DETECTOBS, "detect objects", "Senses objects near the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
|
|
// l3
|
|
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, 3, NA, NA, NULL);
|
|
addot(OT_S_DETECTMAGIC, "detect magic", "Allows the caster to detect magical enchantments.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, 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 - air
|
|
///////////////////
|
|
// l2
|
|
addot(OT_S_AIRBLAST, "airblast", "Knocks enemies back with a powerful blast of air.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_CLOUDKILL, "cloudkill", "Creates a cloud of poisonous gas.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
///////////////////
|
|
// elemental - fire
|
|
///////////////////
|
|
// l1
|
|
addot(OT_S_SPARK, "spark", "Creates a tiny spark of flame, sufficient to ignite flammable objects but not enough to deal direct damage.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_FIREDART, "flame dart", "Fires a medium-sized dart of fire, dealing 2-6 fire damage.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, 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_FIRE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
// l4
|
|
addot(OT_S_FLAMEBURST, "flame burst", "Creates a radial blast of fire out from the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL);
|
|
// l5
|
|
addot(OT_S_BURNINGWAVE, "burning wave", "Fire bursts from the ground in a line towards the target.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RANGE, 3, NA, NA, NULL);
|
|
addot(OT_S_FIREBALL, "fireball", "Creates a huge ball of fire.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); // TODO: should be "near victim"
|
|
///////////////////
|
|
// elemental - ice
|
|
///////////////////
|
|
// l2
|
|
addot(OT_S_CONECOLD, "cone of cold", "Shoots a blast of ice cold air, dealing 2-6 cold damage.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ICE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
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);
|
|
///////////////////
|
|
// gravity
|
|
///////////////////
|
|
// l3
|
|
addot(OT_S_GRAVLOWER, "lessen gravity", "Causes the caster to fall very slowly.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_GRAVITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
|
|
// l4
|
|
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, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
|
|
// l5
|
|
addot(OT_S_LEVITATION, "levitation", "Causes the caster hover a metre above the ground.", 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_ONGOING, B_TRUE, NA, NA, NULL);
|
|
// l6
|
|
addot(OT_S_FLIGHT, "flight", "Allows the caster to fly.", 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_ONGOING, B_TRUE, NA, NA, NULL);
|
|
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_AICASTTOATTACK, ST_SELF, 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_AICASTTOFLEE, ST_SELF, 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);
|
|
// l3
|
|
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, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
|
|
///////////////////
|
|
// mental/psionic
|
|
///////////////////
|
|
// l1
|
|
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, 1, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_SLEEP, "sleep", "Puts the target creature to sleep.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, 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);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_PSYARMOUR, "psychic armour", "Mentally block incoming attacks.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
// TODO: hardcode how ai casts this
|
|
// l4
|
|
addot(OT_S_PACIFY, "pacify", "Induces calmness in another, preventing them from attacking.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addot(OT_S_CHARM, "charm", "Causes another lifeform to temporary become friendly.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
|
|
///////////////////
|
|
// 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_KNOCK, "knock", "Magically opens doors or other such barriers.", 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_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
|
addot(OT_S_DARKNESS, "darkness", "Permenantly darkens the area around 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_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_INVISIBILITY, "invisibility", "Temporarily renders the target invisible.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
|
|
addot(OT_S_PASSWALL, "passwall", "Allows the caster to temporarily walk through walls.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 3, 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_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
// l6
|
|
addot(OT_S_PETRIFY, "petrify", "Causes the target mosnter to turn into stone.", 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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_S_POLYMORPH, "polymorph", "Transmutes the target into a new living race. Becomes controlled at high power.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
|
// l7
|
|
|
|
addot(OT_S_ENCHANT, "enchantment", "Magically enhances a weapon or piece of armour.", 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_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
|
///////////////////
|
|
// translocation
|
|
///////////////////
|
|
// l2
|
|
addot(OT_S_BLINK, "blink", "Teleports the caster to a random location within view.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MAXPOWER, 1, NA, NA, NULL);
|
|
addot(OT_S_PULL, "pull", "Pulls lifeforms towards the caster.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_TRANSLOCATION, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
// l4
|
|
addot(OT_S_TELEPORT, "teleportation", "Causes the caster to teleport to a new location within the same level. Becomes controlled at high power.", 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_AICASTTOFLEE, ST_SELF, 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_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
|
|
// l6
|
|
addot(OT_S_GATE, "gate", "Creates a portal 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_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
|
|
///////////////////
|
|
// wild
|
|
///////////////////
|
|
// l1
|
|
addot(OT_S_MANASPIKE, "mana spike", "Fires a small bolt of wild magic, dealing 1d2 magical damage per power level.", 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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MAXPOWER, 3, NA, NA, NULL);
|
|
// l2
|
|
addot(OT_S_ENERGYBOLT, "energy bolt", "Fires a medium-sized bolt of wild magic, dealing 1d4 damage per power level.", 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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
|
|
// l3
|
|
addot(OT_S_ENERGYBLAST, "energy blast", "Causes a ring of energy to expand from the caster, causing 2-6 damage to 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_AICASTTOATTACK, ST_ADJSELF, 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_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
|
|
// l6
|
|
addot(OT_S_DETONATE, "detonate", "Causes a given area to explode with massive force.", MT_NOTHING, 0, OC_SPELL);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_WILD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
|
|
|
|
// divine powers
|
|
addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addot(OT_A_ENHANCE, "enhance", "Enhance a lifeform's stats.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addot(OT_A_LEARN, "learn", "Learn new skills.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
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);
|
|
addot(OT_S_GIFT, "gift", "Grants the target 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_GRAB, "grab", "You can grab hold of nearby enemies to prevent their escape.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
|
|
addot(OT_A_CRUSH, "crush", "You can crush enemies after grabbing them.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NEEDSGRAB, B_TRUE, NA, NA, NULL);
|
|
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);
|
|
addot(OT_A_SPRINT, "sprint", "You can run at high speed over short distances.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
addot(OT_A_EMPLOY, "employ", "Assigns a job to the target lifeform.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addot(OT_A_HEAVYBLOW, "heavy blow", "Mighty blow which knocks enemies backwards.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
|
|
addot(OT_A_INSPECT, "inspect", "Try to identify an unknown object from your pack.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addot(OT_A_STINGACID, "sting (acid)", "You can sting your enemies.", MT_NOTHING, 0, OC_ABILITY);
|
|
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL);
|
|
|
|
|
|
// manuals
|
|
addot(OT_MAN_ATHLETICS, "manual of athletics", "Teaches you the skill 'athletics'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_ATHLETICS, NA, NA, NULL);
|
|
addot(OT_MAN_BACKSTAB, "manual of stabbing", "Teaches you the skill 'backstab'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_BACKSTAB, NA, NA, NULL);
|
|
addot(OT_MAN_FIRSTAID, "manual of first aid", "Teaches you the skill 'first aid'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_FIRSTAID, NA, NA, NULL);
|
|
addot(OT_MAN_LISTEN, "manual of listening", "Teaches you the skill 'listen'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_LISTEN, NA, NA, NULL);
|
|
addot(OT_MAN_LOCKPICKING, "manual of lockpicking", "Teaches you the skill 'lockpicking'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_LOCKPICKING, NA, NA, NULL);
|
|
addot(OT_MAN_RESEARCH, "manual of research", "Teaches you the skill 'research'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_RESEARCH, NA, NA, NULL);
|
|
addot(OT_MAN_MAGITEMUSAGE, "manual of magic item usage", "Teaches you the skill 'magic item usage'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_MAGITEMUSAGE, NA, NA, NULL);
|
|
addot(OT_MAN_SPELLCASTING, "manual of spellcasting", "Teaches you the skill 'spellcasting'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SPELLCASTING, NA, NA, NULL);
|
|
addot(OT_MAN_STEALTH, "manual of stealth", "Teaches you the skill 'stealth'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_STEALTH, NA, NA, NULL);
|
|
addot(OT_MAN_TECHUSAGE, "manual of technology", "Teaches you the skill 'technology'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_TECHUSAGE, NA, NA, NULL);
|
|
// weapon manuals
|
|
addot(OT_MAN_AXES, "manual of axes", "Teaches you the skill 'axes'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_AXES, NA, NA, NULL);
|
|
addot(OT_MAN_CLUBS, "manual of clubs", "Teaches you the skill 'clubs'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_CLUBS, NA, NA, NULL);
|
|
addot(OT_MAN_LONGBLADES, "manual of long blades", "Teaches you the skill 'long blades'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_LONGBLADES, NA, NA, NULL);
|
|
addot(OT_MAN_POLEARMS, "manual of polearms", "Teaches you the skill 'polearms'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_POLEARMS, NA, NA, NULL);
|
|
addot(OT_MAN_SHORTBLADES, "manual of short blades", "Teaches you the skill 'short blades'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SHORTBLADES, NA, NA, NULL);
|
|
addot(OT_MAN_STAVES, "manual of staves", "Teaches you the skill 'staves'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_STAVES, NA, NA, NULL);
|
|
addot(OT_MAN_UNARMED, "manual of unarmed combat", "Teaches you the skill 'unarmed combat'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_UNARMED, NA, NA, NULL);
|
|
// spell manuals
|
|
addot(OT_MAN_SS_ALLOMANCY, "manual of allomancy", "Teaches you the skill 'allomancy'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_ALLOMANCY, NA, NA, NULL);
|
|
addot(OT_MAN_SS_AIR, "manual of air magic", "Teaches you the skill 'air magic'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_AIR, NA, NA, NULL);
|
|
addot(OT_MAN_SS_DEATH, "manual of necromancy", "Teaches you the skill 'necromancy'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_DEATH, NA, NA, NULL);
|
|
addot(OT_MAN_SS_DIVINATION, "manual of divination", "Teaches you the skill 'divination'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_DIVINATION, NA, NA, NULL);
|
|
addot(OT_MAN_SS_FIRE, "manual of fire magic", "Teaches you the skill 'fire magic'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_FIRE, NA, NA, NULL);
|
|
addot(OT_MAN_SS_ICE, "manual of ice magic", "Teaches you the skill 'ice magic'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_ICE, NA, NA, NULL);
|
|
addot(OT_MAN_SS_GRAVITY, "manual of gravitation magic", "Teaches you the skill 'gravitation magic'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_GRAVITY, NA, NA, NULL);
|
|
addot(OT_MAN_SS_LIFE, "manual of life magic", "Teaches you the skill 'life magic'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_LIFE, NA, NA, NULL);
|
|
addot(OT_MAN_SS_MODIFICATION, "manual of modification", "Teaches you the skill 'modification'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_MODIFICATION, NA, NA, NULL);
|
|
addot(OT_MAN_SS_MENTAL, "manual of psionics", "Teaches you the skill 'psionics'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_MENTAL, NA, NA, NULL);
|
|
addot(OT_MAN_SS_SUMMONING, "manual of summoning", "Teaches you the skill 'summoning'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_SUMMONING, NA, NA, NULL);
|
|
addot(OT_MAN_SS_TRANSLOCATION, "manual of translocation", "Teaches you the skill 'translocation'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_TRANSLOCATION, NA, NA, NULL);
|
|
addot(OT_MAN_SS_WILD, "manual of wild magic", "Teaches you the skill 'wild magic'.", MT_PAPER, 3, OC_BOOK);
|
|
addflag(lastot->flags, F_MANUALOF, SK_SS_WILD, NA, NA, NULL);
|
|
|
|
// spellbooks
|
|
addot(OT_SB_ANIMATEDEAD, "spellbook of animate dead", "Teaches the spell 'animate dead'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_ANIMATEDEAD, NA, NA, NULL);
|
|
addot(OT_SB_PAIN, "spellbook of pain", "Teaches the spell 'pain'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_PAIN, NA, NA, NULL);
|
|
addot(OT_SB_PARALYZE, "spellbook of paralyze", "Teaches the spell 'paralyze'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_PARALYZE, NA, NA, NULL);
|
|
addot(OT_SB_WEAKEN, "spellbook of weaken", "Teaches the spell 'weaken'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL);
|
|
addot(OT_SB_BLINDNESS, "spellbook of blindness", "Teaches the spell 'blindness'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_BLINDNESS, NA, NA, NULL);
|
|
addot(OT_SB_INFINITEDEATH, "spellbook of infinite death", "Teaches the spell 'infinite death'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_INFINITEDEATH, NA, NA, NULL);
|
|
// divination
|
|
addot(OT_SB_DETECTLIFE, "spellbook of detect life", "Teaches the spell 'detect life'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTLIFE, NA, NA, NULL);
|
|
addot(OT_SB_DETECTOBS, "spellbook of detect objects", "Teaches the spell 'detect objects'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTOBS, NA, NA, NULL);
|
|
addot(OT_SB_MAPPING, "spellbook of sense surroundings", "Teaches the spell 'surroundings'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_MAPPING, NA, NA, NULL);
|
|
addot(OT_SB_DETECTAURA, "spellbook of detect aura", "Teaches the spell 'detect aura'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETECTAURA, NA, NA, NULL);
|
|
addot(OT_SB_IDENTIFY, "spellbook of identification", "Teaches the spell 'identification'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_IDENTIFY, NA, NA, NULL);
|
|
// elemental - air
|
|
addot(OT_SB_AIRBLAST, "spellbook of airblast", "Teaches the spell 'airblast'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_AIRBLAST, NA, NA, NULL);
|
|
addot(OT_SB_CLOUDKILL, "spellbook of cloudkill", "Teaches the spell 'cloudkill'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_CLOUDKILL, NA, NA, NULL);
|
|
// elemental - fire
|
|
addot(OT_SB_SPARK, "spellbook of spark", "Teaches the spell 'spark'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_SPARK, NA, NA, NULL);
|
|
addot(OT_SB_FIREDART, "spellbook of flame dart", "Teaches the spell 'flame dart'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FIREDART, NA, NA, NULL);
|
|
addot(OT_SB_FLAMEPILLAR, "spellbook of flame pillar", "Teaches the spell 'flame pillar'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEPILLAR, NA, NA, NULL);
|
|
addot(OT_SB_FLAMEBURST, "spellbook of flame burst", "Teaches the spell 'flame burst'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FLAMEBURST, NA, NA, NULL);
|
|
addot(OT_SB_FIREBALL, "spellbook of fireball", "Teaches the spell 'fireball'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL);
|
|
addot(OT_SB_SLOW, "spellbook of slowness", "Teaches the spell 'slowness'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, NA, NA, NULL);
|
|
addot(OT_SB_GRAVLOWER, "spellbook of lessen gravity", "Teaches the spell 'lessen gravity'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_GRAVLOWER, NA, NA, NULL);
|
|
addot(OT_SB_GRAVBOOST, "spellbook of boost gravity", "Teaches the spell 'boost gravity'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_GRAVBOOST, NA, NA, NULL);
|
|
addot(OT_SB_FLIGHT, "spellbook of flight", "Teaches the spell 'flight'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FLIGHT, NA, NA, NULL);
|
|
addot(OT_SB_HASTE, "spellbook of haste", "Teaches the spell 'haste'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL);
|
|
addot(OT_SB_LEVITATION, "spellbook of levitation", "Teaches the spell 'levitation'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_LEVITATION, NA, NA, NULL);
|
|
// elemental - ice
|
|
addot(OT_SB_CONECOLD, "spellbook of cone of cold", "Teaches the spell 'cone of cold'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_CONECOLD, NA, NA, NULL);
|
|
// life
|
|
addot(OT_SB_HEALINGMIN, "spellbook of minor healing", "Teaches the spell 'minor healing'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_HEALINGMIN, NA, NA, NULL);
|
|
addot(OT_SB_TURNUNDEAD, "spellbook of turn undead", "Teaches the spell 'turn undead'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_TURNUNDEAD, NA, NA, NULL);
|
|
addot(OT_SB_HEALING, "spellbook of healing", "Teaches the spell 'healing'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_HEALING, NA, NA, NULL);
|
|
// mental
|
|
addot(OT_SB_MINDSCAN, "spellbook of mind scan", "Teaches the spell 'mind scan'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_MINDSCAN, NA, NA, NULL);
|
|
addot(OT_SB_SLEEP, "spellbook of sleep", "Teaches the spell 'sleep'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_SLEEP, NA, NA, NULL);
|
|
addot(OT_SB_TELEKINESIS, "spellbook of telekinesis", "Teaches the spell 'telekinesis'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_TELEKINESIS, NA, NA, NULL);
|
|
addot(OT_SB_PACIFY, "spellbook of pacify", "Teaches the spell 'pacify'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_PACIFY, NA, NA, NULL);
|
|
addot(OT_SB_PSYARMOUR, "spellbook of psychic armour", "Teaches the spell 'psychic armour'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_PSYARMOUR, NA, NA, NULL);
|
|
addot(OT_SB_CHARM, "spellbook of charm", "Teaches the spell 'charm'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_CHARM, NA, NA, NULL);
|
|
// modification
|
|
addot(OT_SB_INSCRIBE, "spellbook of inscribe", "Teaches the spell 'inscribe'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_INSCRIBE, NA, NA, NULL);
|
|
addot(OT_SB_INVISIBILITY, "spellbook of invisibility", "Teaches the spell 'invisibility'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_INVISIBILITY, NA, NA, NULL);
|
|
addot(OT_SB_KNOCK, "spellbook of knock", "Teaches the spell 'knock'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL);
|
|
addot(OT_SB_LIGHT, "spellbook of light", "Teaches the spell 'light'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, NA, NA, NULL);
|
|
addot(OT_SB_DARKNESS, "spellbook of darkness", "Teaches the spell 'darkness'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DARKNESS, NA, NA, NULL);
|
|
addot(OT_SB_FREEZEOB, "spellbook of freezing touch", "Teaches the spell 'freezing touch'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FREEZEOB, NA, NA, NULL);
|
|
addot(OT_SB_GASEOUSFORM, "spellbook of gaseous form", "Teaches the spell 'gaseous form'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_GASEOUSFORM, NA, NA, NULL);
|
|
|
|
addot(OT_SB_PASSWALL, "spellbook of passwall", "Teaches the spell 'passwall'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_PASSWALL, NA, NA, NULL);
|
|
|
|
addot(OT_SB_PETRIFY, "spellbook of petrify", "Teaches the spell 'petrify'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_PETRIFY, NA, NA, NULL);
|
|
addot(OT_SB_POLYMORPH, "spellbook of polymorph", "Teaches the spell 'polymorph'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPH, NA, NA, NULL);
|
|
// summoning
|
|
addot(OT_SB_CREATEMONSTER, "spellbook of create monster", "Teaches the spell 'create monster'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_CREATEMONSTER, NA, NA, NULL);
|
|
// translocation
|
|
addot(OT_SB_BLINK, "spellbook of blink", "Teaches the spell 'blink'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_BLINK, NA, NA, NULL);
|
|
addot(OT_SB_DISPERSAL, "spellbook of dispersal", "Teaches the spell 'dispersal'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DISPERSAL, NA, NA, NULL);
|
|
addot(OT_SB_TELEPORT, "spellbook of teleportation", "Teaches the spell 'teleportation'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_TELEPORT, NA, NA, NULL);
|
|
addot(OT_SB_GATE, "spellbook of gate", "Teaches the spell 'gate'.", MT_PAPER, 1.5, OC_BOOK);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_GATE, NA, NA, NULL);
|
|
|
|
|
|
// assign rarity to books
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if ((ot->obclass->id == OC_BOOK) && !hasflag(ot->flags, F_RARITY)) {
|
|
flag_t *f;
|
|
f = hasflag(ot->flags, F_LINKSPELL);
|
|
if (f) {
|
|
// find the linked spell
|
|
objecttype_t *spelltype;
|
|
spelltype = findot(f->val[0]);
|
|
if (spelltype) {
|
|
flag_t *f2;
|
|
f2 = hasflag(spelltype->flags, F_SPELLLEVEL);
|
|
if (f2) {
|
|
int rarity;
|
|
// ie. 80 - spelllevel*12
|
|
rarity = 80 - (f2->val[0]*12);
|
|
addflag(ot->flags, F_RARITY, H_ALL, rarity, NA, NULL);
|
|
} else {
|
|
dblog("Spell %s has no spell level - can't determine rarity for spellbook.", spelltype->name);
|
|
exit(1);
|
|
}
|
|
} else {
|
|
dblog("Spellbook %s linked to a spell id that doesn't exist.",ot->name);
|
|
exit(1);
|
|
}
|
|
} else if (hasflag(ot->flags, F_MANUALOF)) {
|
|
addflag(ot->flags, F_RARITY, H_ALL, 50, NA, NULL);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// wands
|
|
addot(OT_WAND_COLD, "wand of cold", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_CONECOLD, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_WAND_DETONATION, "wand of detonation", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DETONATE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_DOOR, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_WAND_INVIS, "wand of invisibility", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_INVISIBILITY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
addot(OT_WAND_DISPERSAL, "wand of dispersal", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_DISPERSAL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER|TT_OBJECT, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AIFLEEITEM, B_TRUE, NA, NA, NULL);
|
|
addot(OT_WAND_FIREBALL, "wand of fireball", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FIREBALL, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_WAND_FIRE, "wand of fire", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_FIREDART, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_WAND_HASTE, "wand of haste", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_HASTE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
|
|
addot(OT_WAND_KNOCK, "wand of opening", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_KNOCK, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_DOOR, NA, NA, NULL);
|
|
addot(OT_WAND_LIGHT, "wand of light", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_LIGHT, 3, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addot(OT_WAND_POLYMORPH, "wand of polymorph", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_POLYMORPH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_WAND_SLOW, "wand of slowness", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_SLOW, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_WAND_WEAKNESS, "wand of enfeeblement", "A limited-use magical wand which casts the imbued spell.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_LINKSPELL, OT_S_WEAKEN, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_MONSTER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
addot(OT_WAND_WONDER, "wand of wonder", "Produces random effects.", MT_METAL, 0.5, OC_WAND);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDTARGET, TT_NONE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
|
|
|
|
// tools
|
|
addot(OT_BLINDFOLD, "blindfold", "Short length of wide cloth, used for blocking eyesight.", MT_CLOTH, 0.01, OC_TOOLS);
|
|
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_VALUE, 20, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
|
|
|
|
addot(OT_BUGLAMP, "glowing flask", "A glass flask with a glowbug corpse inside.", MT_GLASS, 0.3, OC_TOOLS);
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "!");
|
|
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_CANDLE, "candle", "A short wax candle.", MT_WAX, 0.2, OC_TOOLS);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, 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, 1, NA, NULL);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 1, NA, IFACTIVE, NULL);
|
|
addflag(lastot->flags, F_RNDCHARGES, 5, 10, NA, NULL);
|
|
addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers");
|
|
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
|
|
|
|
addot(OT_GUNPOWDER, "pile of gunpowder", "A black metallic powder.", MT_METAL, 0.5, OC_TOOLS);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "pile of black powder");
|
|
addflag(lastot->flags, F_GLYPH, NA, NA, NA, ",");
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EXPLODEONDAM, 15, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DTVULN, DT_FIRE, NA, NA, "2d6");
|
|
addflag(lastot->flags, F_FLAMMABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_POWDER, B_TRUE, NA, NA, NULL);
|
|
|
|
|
|
addot(OT_LANTERNOIL, "oil lantern", "An oil-powered lantern which produces a lot of light.", MT_METAL, 1, OC_TOOLS);
|
|
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);
|
|
addflag(lastot->flags, F_LIGHTSOURCE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CHARGELOWMSG, B_TRUE, NA, NA, "flickers");
|
|
addflag(lastot->flags, F_CHARGEOUTMSG, B_TRUE, NA, NA, "goes out");
|
|
|
|
addot(OT_LOCKPICK, "lockpick", "An angled piece of metal, used to open locks.", MT_METAL, 0.05, OC_TOOLS);
|
|
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, 10, B_DIEONFAIL, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_PICKAXE, "pickaxe", "A heavy tool for breaking rock.", MT_METAL, 8, OC_TOOLS);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_TORCH, "torch", "A metre-long wooden rod with a flammable end.", MT_WOOD, 2, OC_TOOLS);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, 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);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, IFACTIVE, NULL);
|
|
addflag(lastot->flags, F_RNDCHARGES, 50, 100, NA, NULL);
|
|
addflag(lastot->flags, F_REFILLWITH, OT_POT_OIL, NA, NA, NULL);
|
|
|
|
// tech - l0
|
|
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, 2, NA, 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, 4, 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_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 1, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 50, NA, NA, NULL);
|
|
|
|
|
|
// tech - l1
|
|
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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, 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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, 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, 1, 5, NA, NULL);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, 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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_NOVICE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
|
|
// tech - l2
|
|
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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, 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, 15, NA, B_IFACTIVATED, NULL);
|
|
addflag(lastot->flags, F_EXPLODEONDAM, 10, NA, B_IFACTIVATED, NULL);
|
|
addflag(lastot->flags, F_GRENADE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, 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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
|
|
// tech - l3
|
|
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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_ADEPT, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
|
|
// tech - l4
|
|
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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_SKILLED, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, 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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_SKILLED, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
|
|
// tech - l5
|
|
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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_EXPERT, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, 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);
|
|
addflag(lastot->flags, F_TECHLEVEL, PR_EXPERT, NA, NA, NULL);
|
|
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL);
|
|
|
|
// tech - l6 ???
|
|
|
|
|
|
|
|
// 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);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, 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);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, 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_CRUSHABLE, SZ_MEDIUM, NA, 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_ICESHEET, "sheet of ice", "A large sheet of slippery ice.", MT_ICE, 0.5, 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, "_");
|
|
addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "large puddle of water");
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "large 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, 50, 50, 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_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SLIPPERY, 15, NA, 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_MELTEDWAX, "lump of melted wax", "A useless lump of melted wax.", MT_WAX, 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, ",");
|
|
addflag(lastot->flags, F_NOMATCONVERT, 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, "?");
|
|
addflag(lastot->flags, F_NOMATCONVERT, NA, NA, NA, NULL);
|
|
|
|
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);
|
|
addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DRINKABLE, B_TRUE, 0, NA, NULL);
|
|
addflag(lastot->flags, F_TAINTED, B_TRUE, NA, NA, NULL);
|
|
|
|
addot(OT_ACIDPOOL, "pool of acid", "A pool of corrosive acid.", MT_ACID, 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_DIECONVERTTEXT, NA, NA, NA, "evaporates");
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of acid");
|
|
addflag(lastot->flags, F_OBHP, 4, 4, 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, DT_ACID, NA, NA, "2d4");
|
|
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_LINKOB, OT_POT_ACID, NA, NA, NULL);
|
|
|
|
addot(OT_ACIDPUDDLE, "puddle of acid", "A small puddle of corrosive acid.", MT_ACID, 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_DIETEXT, NA, NA, NA, "evaporates");
|
|
addflag(lastot->flags, F_OBHP, 4, 4, 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, DT_ACID, NA, NA, "1d4");
|
|
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_LINKOB, OT_POT_ACID, 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);
|
|
addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice");
|
|
addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "puff of steam");
|
|
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
|
|
|
|
addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool 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, 70, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice");
|
|
addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "cloud of steam");
|
|
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
|
|
|
|
addot(OT_BLOODSTAIN, "blood stain", "A dried stain 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_BLOODCSPLASH, "splash of cockatrice blood", "A small pool of cockatrice 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, 50, NA, NULL);
|
|
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIETEXT, NA, NA, NA, "evaporates");
|
|
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_DRINKABLE, B_TRUE, 0, NA, NULL);
|
|
addflag(lastot->flags, F_LINKOB, OT_POT_BLOODC, NA, NA, NULL);
|
|
|
|
addot(OT_BLOODSPLASH, "splash of blood", "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);
|
|
addflag(lastot->flags, F_SLIPPERY, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "blood stain");
|
|
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dries up");
|
|
addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "dry up");
|
|
addflag(lastot->flags, F_OBHP, 30, 30, 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_DRINKABLE, B_TRUE, 0, NA, NULL);
|
|
addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, 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);
|
|
addflag(lastot->flags, F_SLIPPERY, 3, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "blood stain");
|
|
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dries up");
|
|
addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "dry up");
|
|
addflag(lastot->flags, F_OBHP, 60, 60, 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_DRINKABLE, B_TRUE, 0, NA, NULL);
|
|
addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, 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, SZ_LARGE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CRUSHABLE, SZ_HUGE, 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);
|
|
addflag(lastot->flags, F_STACKABLE, 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,DT_FIRE, NA, NA, "2d4+4");
|
|
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, DT_FIRE, NA, NA, "2d4");
|
|
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, DT_FIRE, NA, NA, "1d4");
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PRODUCESLIGHT, 1, NA, NA, NULL);
|
|
|
|
addot(OT_STEAMCLOUD, "cloud of steam", "A thick cloud of scalding steam.", 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_NODIECONVERTTEXT, NA, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puff of steam");
|
|
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_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_WALKDAM, DT_FIRE, NA, NA, "1d2");
|
|
|
|
addot(OT_STEAMPUFF, "puff of steam", "A small puff of scalding steam.", 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, DT_FIRE, NA, NA, "1d1+1");
|
|
|
|
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_NODIECONVERTTEXT, NA, NA, NA, NULL);
|
|
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, 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_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_WALKDAM, DT_POISONGAS, NA, NA, "1d4");
|
|
|
|
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, DT_POISONGAS, NA, NA, "1d2");
|
|
|
|
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, SZ_MAX, 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, 80, 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_ARMOURRING, "suit of ring mail", "Body armour formed by a series of metallic rings sewn to a leather foundation.", MT_METAL, 15, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 6, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL);
|
|
addot(OT_ARMOURSCALE, "suit of scale armour", "Body armour consisting of many small scales attached to leather.", MT_METAL, 20, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 72, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -15, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 35, 35, NA, NULL);
|
|
addot(OT_ARMOURCHAIN, "suit of chainmail", "Heavy body armour consisting of tightly meshed metal rings.", MT_METAL, 25, 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, 15, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -20, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 45, 45, NA, NULL);
|
|
addot(OT_ARMOURSPLINT, "suit of splint mail", "Heavy armour, consisting of strips of metal attached to a leather backing.", MT_METAL, 35, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 67, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 20, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -25, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 50, 50, NA, NULL);
|
|
addot(OT_ARMOURPLATE, "suit of plate mail", "Heavy armour with embedded metal plates.", MT_METAL, 40, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 65, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 25, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -30, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 60, 60, NA, NULL);
|
|
|
|
addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour, designed to stop a bullet.", MT_METAL, 30, 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, 10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 10, 10, 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);
|
|
addot(OT_ROBE, "robe", "A plain robe.", MT_CLOTH, 4, 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, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 4, 4, 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_BODY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ARMOURRATING, 1, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EVASION, -10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 4, 4, 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);
|
|
// armour - waist
|
|
addot(OT_BELTLEATHER, "leather belt", "A plain leather belt.", MT_LEATHER, 0.2, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 85, NA, NULL);
|
|
addflag(lastot->flags, F_GOESON, BP_WAIST, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 1, 1, 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_BOOTSSPIKED, "pair of spiked boots", "A plain pair of leather boots with spikes on the bottom.", MT_LEATHER, 3, OC_ARMOUR);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 70, 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);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_STABILITY, NA, 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, 5, 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, 10, 10, NA, NULL);
|
|
addot(OT_SHIELD, "shield", "A medium-sized metal shield.", MT_METAL, 4.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, 6, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, -10, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
|
|
addot(OT_SHIELDLARGE, "large shield", "A large (if somewhat cumbersome) shield.", MT_METAL, 6.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, 8, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, -15, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL);
|
|
|
|
// rings
|
|
addot(OT_RING_INVIS, "ring of invisibility", "Renders the wearer invisible.", MT_METAL, 0.1, OC_RING);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 60, NA, "");
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_INVISIBLE, NA, NA, NULL);
|
|
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, 5, NA, NULL);
|
|
addot(OT_RING_SEEINVIS, "ring of sight", "Allows the caster to see the invisible, and in the dark.", MT_METAL, 0.1, OC_RING);
|
|
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, "");
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_SEEINVIS, NA, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_SEEINDARK, 5, NA, NULL);
|
|
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, 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_UNARMED, 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_USESSKILL, SK_UNARMED, 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);
|
|
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
|
|
|
addot(OT_STING, "sting", "sting object", MT_BONE, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_ACID, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ATTACKVERB, NA, NA, NA, "sting");
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
|
|
|
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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
|
|
|
addot(OT_TENTACLE, "tentacle", "tentacle object", MT_FLESH, 0, OC_WEAPON);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 2, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, 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);
|
|
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, 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);
|
|
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, 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, SC_CON, 22, "2-4");
|
|
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
|
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, SC_CON, 30, "5-10");
|
|
addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL);
|
|
|
|
// missiles
|
|
addot(OT_DART, "dart", "A small, sharp projectile weapon.", MT_WOOD, 0.5, OC_MISSILE);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_MISSILEDAM, 2, NA, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, "");
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
|
|
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL);
|
|
|
|
addot(OT_NANODART, "nanodart", "A metal dart with a laser-sharpened point.", MT_METAL, 0.5, OC_MISSILE);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_MISSILEDAM, 2, NA, NA, "");
|
|
addflag(lastot->flags, F_ARMOURPIERCE, 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_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL);
|
|
|
|
addot(OT_JAVELIN, "javelin", "A long, sharp missile weapon.", MT_METAL, 1.5, OC_MISSILE);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_MISSILEDAM, 3, NA, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, "");
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, "");
|
|
addflag(lastot->flags, F_OBHP, 5, 5, NA, "");
|
|
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL);
|
|
|
|
addot(OT_ARROW, "arrow", "A sharp wooden arrow.", MT_WOOD, 0.5, OC_MISSILE);
|
|
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_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
|
|
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL);
|
|
|
|
addot(OT_BOLT, "bolt", "A sharp metal spike, meant for firing from a crossbow.", MT_METAL, 1, OC_MISSILE);
|
|
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, "");
|
|
addflag(lastot->flags, F_NUMAPPEAR, 1, 5, NA, "");
|
|
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, NA, NA, NULL);
|
|
|
|
|
|
addot(OT_BULLET, "bullet", "A regular gun bullet.", MT_STONE, 0.1, OC_MISSILE);
|
|
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_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_MISSILE);
|
|
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_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);
|
|
|
|
// 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_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_THROWMISSILE, 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, 7, B_BLUNTONFAIL, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, 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_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_THROWMISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, 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_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, 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_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 8, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, 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_OBATTACKDELAY, 110, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, 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_OBATTACKDELAY, 90, 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_USESSKILL, SK_SHORTBLADES, 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_DAMTYPE, DT_PIERCE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 4, 1, 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_THROWMISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
|
|
|
|
// chopping weapons
|
|
addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 4, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 4, 1, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
|
|
addot(OT_HANDAXE, "hand axe", "A fast one-handed axe made for combat.", MT_METAL, 2, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, 1, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 85, NA, NA, NULL);
|
|
addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
|
|
addot(OT_BATTLEAXE, "battleaxe", "An axe specifically designed for combat.", MT_METAL, 5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 9, 1, NULL);
|
|
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL);
|
|
addot(OT_GREATAXE, "greataxe", "An enormous axe made designed for combat.", MT_METAL, 8, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_CHOP, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 10, 2, NULL);
|
|
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_AXES, 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_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_THROWMISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, 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_USESSKILL, SK_SHORTBLADES, NA, 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_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_THROWMISSILE, B_TRUE, 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_USESSKILL, SK_SHORTBLADES, NA, 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_OBATTACKDELAY, 150, 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, 65, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, 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_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 60, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
|
|
addot(OT_SCIMITAR, "scimitar", "A sharp, curved blade.", MT_METAL, 2, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 130, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, 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_OBATTACKDELAY, 130, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, 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_OBATTACKDELAY, 130, 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, 70, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL);
|
|
addot(OT_GREATSWORD, "greatsword", "A massive two-handed sword.", MT_METAL, 10, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 12, 6, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, 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_OBATTACKDELAY, 130, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_STAVES, 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_OBATTACKDELAY, 140, 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_THROWMISSILE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OBHP, 15, 15, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, 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_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 2, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, 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_OBATTACKDELAY, 120, 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, 65, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERABLE, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_OPERNEEDDIR, B_TRUE, NA, NA, "Use your spanner in which direction");
|
|
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
|
|
addot(OT_CLUB, "club", "A heavy, blunt wooden instrument to hit things with.", MT_STONE, 1.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 140, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, 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_OBATTACKDELAY, 140, 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_USESSKILL, SK_CLUBS, NA, NA, NULL);
|
|
addot(OT_FLAIL, "flail", "A flexible chain attached to a heavy weight.", MT_METAL, 6, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 2, 4, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
|
|
addot(OT_FLAILHEAVY, "heavy flail", "A flexible chain attached to a very heavy weight.", MT_METAL, 12, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 155, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 2, 6, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
|
|
addot(OT_MORNINGSTAR, "morningstar", "A heavy, spiked mace.", MT_METAL, 3.5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 150, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, NA, NA, NULL);
|
|
addot(OT_GREATCLUB, "great club", "An enormous, very heavy, blunt instrument to hit things with.", MT_STONE, 5, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
|
|
addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_BASH, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAM, 1, 10, 5, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL);
|
|
addflag(lastot->flags, F_USESSKILL, SK_CLUBS, 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_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_BOW, "bow", "A weapon which projects arrows via its elasticity.", MT_WOOD, 3, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, 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_FIRESPEED, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
|
|
addflag(lastot->flags, F_RANGE, 5, NA, NA, NULL);
|
|
addflag(lastot->flags, F_AMMOOB, OT_ARROW, NA, NA, NULL);
|
|
|
|
addot(OT_LONGBOW, "longbow", "A very large (human-sized) bow, capable of firing arrows with great power.", MT_WOOD, 6, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, 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_FIRESPEED, 7, 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_ARROW, NA, NA, NULL);
|
|
|
|
addot(OT_CROSSBOWHAND, "hand crossbow", "A small one-handed crossbow. Fast to fire but slower than a full-sized one.", MT_WOOD, 3, OC_WEAPON);
|
|
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, 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_FIRESPEED, 5, 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_BOLT, 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_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);
|
|
|
|
// 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_DAMTYPE, DT_HOLY, NA, NA, NULL);
|
|
addflag(lastot->flags, F_DAMTYPE, DT_SLASH, 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);
|
|
addflag(lastot->flags, F_USESSKILL, SK_NONE, 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;
|
|
}
|
|
|
|
// modify based on extra props
|
|
if (hasflag(a->flags, F_HASBRAND)) {
|
|
dama *= 3;
|
|
}
|
|
if (hasflag(b->flags, F_HASBRAND)) {
|
|
damb *= 3;
|
|
}
|
|
|
|
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 ((gamemode == GM_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 isdangerousob(object_t *o, lifeform_t *lf, int onlyifknown) {
|
|
enum IQBRACKET iqb;
|
|
iqb = getiqname(getattr(lf, A_IQ), NULL);
|
|
|
|
if (!onlyifknown || (iqb >= IQ_AVERAGE)) {
|
|
if (hasflag(o->flags, F_SHARP)) {
|
|
if (!getequippedob(lf->pack, BP_HANDS) && !isimmuneto(lf->flags, DT_SLASH)) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!onlyifknown || (iqb >= IQ_ANIMAL)) {
|
|
if (hasflag(o->flags, F_ONFIRE)) {
|
|
if (!isimmuneto(lf->flags, DT_FIRE)) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isdrinkable(object_t *o) {
|
|
switch (o->type->obclass->id) {
|
|
case OC_POTION:
|
|
return B_TRUE;
|
|
default: break;
|
|
}
|
|
|
|
if (hasflag(o->flags, F_DRINKABLE)) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
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) {
|
|
// if id'd, return the full name
|
|
if (hasflag(o->flags, F_IDENTIFIED)) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
return isknownot(o->type);
|
|
}
|
|
|
|
int isknownot(objecttype_t *ot) {
|
|
knowledge_t *k;
|
|
// if id'd, return the full name
|
|
|
|
for (k = knowledge; k ; k = k->next) {
|
|
if (k->id == ot->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 isimpassableob(object_t *o, lifeform_t *lf) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_IMPASSABLE);
|
|
if (f) {
|
|
enum LFSIZE lfsize;
|
|
enum LFSIZE blocksize;
|
|
|
|
if (!lf) return B_TRUE;
|
|
|
|
lfsize = getlfsize(lf);
|
|
blocksize = f->val[0];
|
|
|
|
if (lfsize <= blocksize) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
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 isthrowmissile(object_t *o) {
|
|
if (hasflag(o->flags, F_THROWMISSILE)) {
|
|
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:
|
|
case OC_BOOK:
|
|
return B_TRUE;
|
|
default: break;
|
|
}
|
|
|
|
return B_FALSE;
|
|
}
|
|
|
|
int isrotting(object_t *o) {
|
|
flag_t *f;
|
|
float pct;
|
|
|
|
if (hasflag(o->flags, F_TAINTED)) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
int knockbackob(object_t *o, int dir, int howfar, int power, lifeform_t *pusher) {
|
|
int i;
|
|
char obname[BUFLEN];
|
|
int seen;
|
|
cell_t *obcell, *c;
|
|
|
|
getobname(o,obname, o->amt);
|
|
obcell = getoblocation(o);
|
|
if (haslos(player, obcell)) {
|
|
seen = B_TRUE;
|
|
} else {
|
|
seen = B_FALSE;
|
|
}
|
|
|
|
if (dir == D_NONE) {
|
|
// failed!
|
|
return B_TRUE;
|
|
}
|
|
|
|
c = obcell;
|
|
for (i = 0; i < howfar; i++) {
|
|
cell_t *newcell;
|
|
newcell = getcellindir(c, dir);
|
|
if (!newcell) {
|
|
// hit a wall - stop here
|
|
break;
|
|
} else if (newcell->lf) {
|
|
// hit them - stop here
|
|
c = newcell;
|
|
break;
|
|
} else if (!cellwalkable(NULL, newcell, NULL)) {
|
|
// hit a wall - stop here
|
|
break;
|
|
}
|
|
c = newcell;
|
|
}
|
|
fireat(NULL, o, o->amt, c, power, NULL);
|
|
return B_FALSE;
|
|
}
|
|
|
|
// 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_OBATTACKDELAY);
|
|
if (f) {
|
|
int origspeed;
|
|
int newspeed;
|
|
origspeed = getmovespeed(newlf);
|
|
killflagsofid(newlf->flags, F_MOVESPEED);
|
|
newspeed = (int)((float)origspeed * ((float)f->val[0] / 100.0));
|
|
addflag(newlf->flags, F_MOVESPEED, newspeed, NA, NA, NULL);
|
|
}
|
|
}
|
|
return newlf;
|
|
}
|
|
|
|
void makeduller(object_t *o, int howmuch) {
|
|
char obname[BUFLEN];
|
|
int oldbonus,newbonus;
|
|
|
|
// get object name before changing the bonus
|
|
getobname(o,obname, 1);
|
|
|
|
oldbonus = getobbonus(o);
|
|
modbonus(o, -howmuch);
|
|
newbonus = getobbonus(o);
|
|
|
|
if (newbonus < oldbonus) {
|
|
if (o->pile->owner) {
|
|
if (isplayer(o->pile->owner)) {
|
|
msg("Your %s seems duller!",noprefix(obname));
|
|
} else if (cansee(player, o->pile->owner)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(o->pile->owner, lfname);
|
|
msg("%s%s %s seems duller!",lfname, getpossessive(lfname), noprefix(obname));
|
|
}
|
|
} else {
|
|
cell_t *obloc;
|
|
obloc = getoblocation(o);
|
|
if (haslos(player, obloc)) {
|
|
msg("%s seems duller!",obname);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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_FALSE;
|
|
|
|
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);
|
|
}
|
|
|
|
o = 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 (o) {
|
|
//if (dst->owner && isplayer(dst->owner) && lfhasflag(dst->owner, F_DETECTAURAS)) {
|
|
if (dst->owner && isplayer(dst->owner) && isblessknown(o)) {
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
}
|
|
|
|
if (dst->where && !dst->where->lf && haslos(player, dst->where)) {
|
|
needredraw = B_TRUE;
|
|
drawscreen();
|
|
}
|
|
|
|
|
|
//o = newobeffects(o);
|
|
|
|
return o;
|
|
}
|
|
|
|
void modbonus(object_t *o, int amt) {
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_BONUS);
|
|
if (f) {
|
|
f->val[0] += amt;
|
|
} else {
|
|
cell_t *loc;
|
|
int known;
|
|
loc = getoblocation(o);
|
|
if (haslos(player, loc)) {
|
|
known = B_TRUE;
|
|
} else {
|
|
known = B_FALSE;
|
|
}
|
|
f = addflag_real(o->flags, F_BONUS, amt, NA, NA, NULL, PERMENANT, known, -1);
|
|
}
|
|
// enforce limit
|
|
limit(&f->val[0], -7, 7);
|
|
}
|
|
|
|
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 (cansee(player, o->pile->owner)) {
|
|
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;
|
|
|
|
obloc = o->pile->where;
|
|
|
|
f = hasflag(o->flags, F_DIECONVERT);
|
|
if (f) {
|
|
flag_t *f2;
|
|
object_t *newob;
|
|
char desc[BUFLEN];
|
|
if (!hasflag(o->flags, F_NODIECONVERTTEXT)) {
|
|
// announce the change
|
|
real_getobname(o, obname, o->amt, B_TRUE, 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 (cansee(player, o->pile->owner)) {
|
|
// don't announce decay death unless we are holding it
|
|
if (oblastdamtype(o) != DT_DECAY) {
|
|
char monname[BUFLEN];
|
|
getlfname(o->pile->owner, monname);
|
|
msg("%s's %s %s!",monname, noprefix(obname), desc);
|
|
}
|
|
}
|
|
} else if (haslos(player, o->pile->where)) {
|
|
// don't announce decay death unless we are holding it
|
|
if (oblastdamtype(o) != DT_DECAY) {
|
|
capitalise(obname);
|
|
msg("%s %s.",obname, desc);
|
|
}
|
|
}
|
|
}
|
|
|
|
// change into something else
|
|
newob = addob(o->pile, f->text);
|
|
// only set amt if text wasn't "x-y somethings"
|
|
if (!strchr(f->text, '-')) {
|
|
newob->amt = o->amt;
|
|
}
|
|
} else {
|
|
char desc[BUFLEN];
|
|
|
|
real_getobname(o, obname, o->amt, B_TRUE, 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 (cansee(player, o->pile->owner)) {
|
|
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);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
// corpse decaying and on the ground?
|
|
if ((oblastdamtype(o) == DT_DECAY) && (o->type->id == OT_CORPSE)) {
|
|
if (o->pile->where) {
|
|
int minbones,maxbones;
|
|
char bonestr[BUFLEN];
|
|
minbones = o->weight / 10;
|
|
maxbones = o->weight / 5;
|
|
if (minbones <= 0) minbones = 1;
|
|
if (maxbones <= minbones) maxbones = 2;
|
|
sprintf(bonestr, "%d-%d bones",minbones,maxbones);
|
|
addob(o->pile, bonestr);
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
int brandappliesto(brand_t *om, objecttype_t *ot) {
|
|
if (om->bp == BP_WEAPON) {
|
|
if (ot->obclass->id == OC_WEAPON) {
|
|
return B_TRUE;
|
|
}
|
|
} else {
|
|
// TODO: how do we differentiate shields from guns?
|
|
if (hasflagval(ot->flags, F_GOESON, om->bp, NA, NA, NULL)) {
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
|
|
|
|
int obmatchescondition(object_t *o, long opts) {
|
|
int ok = B_TRUE;
|
|
if ((opts & AO_ONLYEQUIPPED) && !hasflag(o->flags, F_EQUIPPED)) {
|
|
ok = B_FALSE;
|
|
}
|
|
if ((opts & AO_EQUIPPEDARMOUR)) {
|
|
flag_t *ff;
|
|
ff = hasflag(o->flags, F_EQUIPPED);
|
|
if (!ff) {
|
|
ok = B_FALSE;
|
|
} else if (ff->val[0] == BP_WEAPON) {
|
|
ok = B_FALSE;
|
|
}
|
|
}
|
|
if ((opts & AO_EDIBLE) && !isedible(o)) ok = B_FALSE;
|
|
if ((opts & AO_READABLE) && !isreadable(o)) ok = B_FALSE;
|
|
if ((opts & AO_ARMOUR) && (o->type->obclass->id != OC_ARMOUR)) ok = B_FALSE;
|
|
if ((opts & AO_WEARABLE) && !iswearable(o)) {
|
|
ok = B_FALSE;
|
|
}
|
|
if ((opts & AO_WEILDABLE) && !isweapon(o)) {
|
|
ok = B_FALSE;
|
|
}
|
|
if ((opts & AO_OPERABLE) && !isoperable(o)) {
|
|
ok = B_FALSE;
|
|
}
|
|
if ((opts & AO_POURABLE) && !ispourable(o)) {
|
|
ok = B_FALSE;
|
|
}
|
|
if ((opts & AO_NOTIDENTIFIED) && isidentified(o)) {
|
|
ok = B_FALSE;
|
|
}
|
|
if ((opts & AO_NOTKNOWN) && isknown(o)) {
|
|
ok = B_FALSE;
|
|
}
|
|
return ok;
|
|
}
|
|
|
|
// returns the amount of light produced
|
|
int obproduceslight(object_t *o) {
|
|
flag_t *f;
|
|
int amt = 0;
|
|
f = hasflag(o->flags, F_PRODUCESLIGHT);
|
|
if (f) {
|
|
int thisamt = 0;
|
|
if (f->val[2] == IFACTIVE) {
|
|
if (isactivated(o)) {
|
|
sumflags(o->flags, F_PRODUCESLIGHT, &thisamt, NULL, NULL);
|
|
}
|
|
} else {
|
|
sumflags(o->flags, F_PRODUCESLIGHT, &thisamt, NULL, NULL);
|
|
}
|
|
amt += thisamt;
|
|
}
|
|
// flaming things should produce fire
|
|
if (amt == 0) {
|
|
if (hasflag(o->flags, F_ONFIRE) || (o->material->id == MT_FIRE)) {
|
|
amt += 1;
|
|
}
|
|
}
|
|
return amt;
|
|
}
|
|
|
|
// 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, cell_t *where) {
|
|
char buf[BUFLEN],obname[BUFLEN];
|
|
int playercansee;
|
|
flag_t *f;
|
|
int willid = B_FALSE;
|
|
|
|
getobname(o, obname, 1);
|
|
|
|
if ((lf->controller == C_PLAYER) || cansee(player, lf)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
|
|
// if not a wand, must know what a tool is before you can use it
|
|
if (!isknown(o) && (o->type->obclass->id != OC_WAND)) {
|
|
if (isplayer(lf)) {
|
|
msg("You don't know how to use %s!", obname);
|
|
}
|
|
return B_TRUE;
|
|
}
|
|
|
|
if (gettechlevel(o) > getskill(lf, SK_TECHUSAGE)) {
|
|
if (isplayer(lf)) {
|
|
msg("This technology is beyond your understanding.");
|
|
}
|
|
return B_TRUE;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
// ask for target, if required
|
|
f = hasflag(o->flags, F_OPERNEEDTARGET);
|
|
if (f && !where) {
|
|
int ttype = TT_NONE;
|
|
// don't give hints about the object
|
|
if (isknown(o)) {
|
|
ttype = f->val[0];
|
|
}
|
|
|
|
if (strlen(f->text) > 0) {
|
|
where = askcoords(f->text, ttype);
|
|
} else {
|
|
sprintf(buf, "Where will you aim %s?",obname);
|
|
where = askcoords(buf, ttype);
|
|
if (!haslos(lf, where)) {
|
|
msg("You can't see there!");
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
if (!where) {
|
|
// cancel.
|
|
msg("Cancelled.");
|
|
return B_TRUE;
|
|
} else {
|
|
if (f->val[1] != NA) {
|
|
cell_t *newwhere = NULL;
|
|
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, B_TRUE, &newwhere)) {
|
|
if (newwhere) {
|
|
// update destination
|
|
where = newwhere;
|
|
} else {
|
|
msg("You have no line of fire to there!");
|
|
return B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
f = hasflag(o->flags, F_OPERNEEDDIR);
|
|
if (f) {
|
|
char ch;
|
|
int dir;
|
|
// ask direction
|
|
ch = askchar(f->text, "yuhjklbn-","-", B_FALSE);
|
|
if (ch == '-') {
|
|
msg("Cancelled.");
|
|
return B_TRUE;
|
|
} else {
|
|
dir = chartodir(ch);
|
|
where = getcellindir(lf->cell, dir);
|
|
}
|
|
}
|
|
|
|
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, getactspeed(lf));
|
|
|
|
/*
|
|
if (lf->controller != C_PLAYER) {
|
|
|
|
if (haslos(player, lf->cell)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s operates %s.", buf, obname);
|
|
}
|
|
}
|
|
*/
|
|
|
|
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->obclass->id == OC_WAND) {
|
|
if (!isplayer(lf) && cansee(player, lf)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s zaps %s.",lfname,obname);
|
|
}
|
|
|
|
|
|
f = hasflag(o->flags, F_LINKSPELL);
|
|
if (f) {
|
|
int isblessed;
|
|
int power;
|
|
isblessed = o->blessed;
|
|
|
|
power = f->val[1];
|
|
if (power == NA) power = 1;
|
|
|
|
if (isblessed) power += 4;
|
|
// certain wands always used the blessed version of spells
|
|
switch (o->type->id) {
|
|
case OT_WAND_LIGHT:
|
|
isblessed = B_TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
dospelleffects(lf, f->val[0], power, where ? where->lf : NULL, NULL, where, isblessed, &willid);
|
|
// special wands
|
|
} else if (o->type->id == OT_WAND_WONDER) {
|
|
int power;
|
|
power = rnd(1,10);
|
|
// random effect
|
|
switch (rnd(0,7)) {
|
|
case 0: // slow
|
|
dospelleffects(lf, OT_S_SLOW, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid);
|
|
break;
|
|
case 1: // gas
|
|
dospelleffects(lf, OT_S_CLOUDKILL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid);
|
|
break;
|
|
case 2: // butterflies around user
|
|
willid = B_TRUE;
|
|
where = getrandomadjcell(lf->cell, WE_NOTSOLID);
|
|
addmonster(where, R_BUTTERFLY, B_FALSE, rnd(10,20));
|
|
if (haslos(player, where)) {
|
|
msg("A swarm of butterflies appears!");
|
|
}
|
|
break;
|
|
case 3: // light
|
|
dospelleffects(lf, OT_S_LIGHT, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid);
|
|
break;
|
|
case 4: // dark
|
|
dospelleffects(lf, OT_S_DARKNESS, power, where ? where->lf : NULL, NULL, where, B_UNCURSED, &willid);
|
|
break;
|
|
case 5: // stone
|
|
dospelleffects(lf, OT_S_PETRIFY, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid);
|
|
break;
|
|
case 6: // fireball
|
|
dospelleffects(lf, OT_S_FIREBALL, power, where ? where->lf : NULL, NULL, where, o->blessed, &willid);
|
|
break;
|
|
case 7: // summon monster
|
|
dospelleffects(lf, OT_S_CREATEMONSTER, rnd(1,4), NULL, NULL, NULL, B_UNCURSED, &willid);
|
|
break;
|
|
//oooooooooo
|
|
}
|
|
}
|
|
|
|
if (!isknown(o) && willid) {
|
|
if (isplayer(lf) || cansee(player, lf)) {
|
|
// tell player
|
|
makeknown(o->type->id);
|
|
if (isplayer(lf)) {
|
|
getobname(o, obname, 1);
|
|
msg("This is %s!",obname);
|
|
}
|
|
}
|
|
}
|
|
// FROM HERE ON ARE INDIVIDUAL ones
|
|
} 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 (cansee(player, lf)) {
|
|
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 (cansee(player, lf)) {
|
|
getlfname(lf, buf);
|
|
msg("%s%s %s emits a puff of gas.", buf, getpossessive(buf), noprefix(obname));
|
|
seen = B_TRUE;
|
|
}
|
|
}
|
|
// announce
|
|
if (!seen) {
|
|
noise(where, NULL, "something spraying.", NULL);
|
|
}
|
|
} else if ((o->type->id == OT_EMPTYFLASK) || (o->type->id == OT_EMPTYVIAL)) {
|
|
object_t *oo,*nextoo;
|
|
if (isplayer(lf)) {
|
|
int donedip = B_FALSE;
|
|
// anything here to fill with?
|
|
for (oo = lf->cell->obpile->first ; (oo && !donedip); oo = nextoo) {
|
|
int dippable = B_FALSE;
|
|
nextoo = oo->next;
|
|
switch (oo->type->id) {
|
|
case OT_BLOODPOOL:
|
|
case OT_BLOODSPLASH:
|
|
case OT_PUDDLEWATER:
|
|
case OT_PUDDLEWATERL:
|
|
dippable = B_TRUE;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
if (dippable) {
|
|
char ch;
|
|
char ques[BUFLEN];
|
|
char liquidname[BUFLEN];
|
|
object_t *newob;
|
|
getobname(oo, liquidname, 1);
|
|
sprintf(ques, "Fill your %s from %s?", noprefix(obname), liquidname);
|
|
ch = askchar(ques, "yn", "y", B_TRUE);
|
|
if (ch == 'y') {
|
|
char newobname[BUFLEN];
|
|
switch (oo->material->id) {
|
|
case MT_BLOOD:
|
|
strcpy(newobname, "potion of blood");
|
|
break;
|
|
case MT_WATER:
|
|
strcpy(newobname, "potion of water");
|
|
break;
|
|
default:
|
|
strcpy(newobname, "");
|
|
break;
|
|
}
|
|
if (strlen(newobname)) {
|
|
// kill the empty flask
|
|
removeob(o, 1);
|
|
// give the new potion
|
|
newob = addob(lf->pack, newobname);
|
|
if (newob) {
|
|
// overwrite newobname
|
|
getobname(newob, newobname, newob->amt);
|
|
msgnocap("%c - %s.",newob->letter, newobname);
|
|
}
|
|
// kill the ground object?
|
|
switch (oo->id) {
|
|
case OT_PUDDLEWATER:
|
|
case OT_BLOODSPLASH:
|
|
removeob(oo, 1);
|
|
break;
|
|
}
|
|
} else {
|
|
msg("That doesn't seem like a very good idea.");
|
|
}
|
|
donedip = B_TRUE;
|
|
} // if (ch == y)
|
|
}
|
|
}
|
|
|
|
if (!donedip) {
|
|
msg("There is nothing here to fill your %s from.",noprefix(obname));
|
|
}
|
|
}
|
|
} else if (o->type->id == OT_POCKETWATCH) {
|
|
if (isplayer(lf)) {
|
|
// TODO: if above ground, use wantpm (ie. can see the sun)
|
|
gettimetextfuzzy(buf, B_FALSE);
|
|
msg("It is currently %s.",buf);
|
|
} else if (cansee(player, lf)) {
|
|
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 (cansee(player, lf)) {
|
|
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 (cansee(player, lf)) {
|
|
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 (cansee(player, lf)) {
|
|
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) {
|
|
// cancel
|
|
clearmsg();
|
|
return B_TRUE;
|
|
}
|
|
if (c->type->solid) {
|
|
if (isdiggable(c)) {
|
|
if (isplayer(lf)) {
|
|
msg("You dig through the wall.");
|
|
} else if (cansee(player, lf)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s digs through a wall.",lfname);
|
|
}
|
|
// replace wall
|
|
setcelltype(c, getemptycelltype(c->map->habitat));
|
|
// redraw screen
|
|
needredraw = B_TRUE;
|
|
drawscreen();
|
|
// takes extra time
|
|
taketime(lf, getactspeed(lf)*9);
|
|
} else {
|
|
// fail
|
|
if (isplayer(lf)) {
|
|
msg("This wall is too hard to dig.");
|
|
}
|
|
}
|
|
} else { // not solid
|
|
int failed = B_FALSE;
|
|
object_t *door;
|
|
|
|
door = hasobwithflag(c->obpile, F_DOOR);
|
|
if (door) {
|
|
int dooropen;
|
|
// only closed doors!
|
|
isdoor(door, &dooropen);
|
|
if (dooropen) {
|
|
door = NULL;
|
|
}
|
|
}
|
|
|
|
if (door) {
|
|
// TODO: metal doors are immune to CHOP damage
|
|
if (!isimmuneto(door->flags, DT_CHOP)) {
|
|
taketime(lf, getactspeed(lf));
|
|
if (isplayer(lf)) {
|
|
msg("You smash open a door!");
|
|
} else if (cansee(player, lf)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s smashes open a door.",lfname);
|
|
}
|
|
removeob(door, door->amt);
|
|
needredraw = B_TRUE;
|
|
drawscreen();
|
|
failed = B_FALSE;
|
|
}
|
|
} else if (hasob(c->obpile, OT_STATUE)) {
|
|
int dam;
|
|
object_t *so;
|
|
char statname[BUFLEN];
|
|
|
|
so = hasob(c->obpile, OT_STATUE);
|
|
getobname(so, statname, so->amt);
|
|
|
|
taketime(lf, getactspeed(lf));
|
|
|
|
// statue takes 1/2 damage
|
|
f = hasflag(so->flags, F_OBHP);
|
|
if (f) {
|
|
dam = (f->val[1] / 2); // ie. half max hp
|
|
} else {
|
|
dam = 1;
|
|
}
|
|
// statue ?
|
|
if (isplayer(lf)) {
|
|
msg("You hit %s with your %s.", statname, noprefix(obname));
|
|
} else if (cansee(player, lf)) {
|
|
char lfname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
msg("%s hits %s with %s.", lfname, statname, obname);
|
|
}
|
|
takedamage(so, dam, DT_CHOP);
|
|
} else {
|
|
if (isplayer(lf)) {
|
|
msg("You swing your %s through the air.",noprefix(obname));
|
|
}
|
|
taketime(lf, getactspeed(lf));
|
|
}
|
|
}
|
|
} else if (o->type->id == OT_SPANNER) {
|
|
int donesomething = B_FALSE;
|
|
if (!where) {
|
|
if (isplayer(lf)) msg("There is nothing to use your spanner on there!");
|
|
} else {
|
|
object_t *o;
|
|
char ch;
|
|
flag_t *f;
|
|
for (o = where->obpile->first ; o ; o = o->next) {
|
|
int isopen;
|
|
if (isdoor(o, &isopen)) {
|
|
if (!isopen) { // ie. if closed.
|
|
f = hasflag(o->flags, F_JAMMED);
|
|
if (f) {
|
|
ch = askchar("The hinges seem jammed. Loosen them", "yn", "y", B_TRUE);
|
|
if (ch == 'y') {
|
|
char obname[BUFLEN];
|
|
getobname(o, obname, 1);
|
|
msg("You loosen the hinges on %s.", obname);
|
|
killflag(f);
|
|
taketime(lf, getactspeed(lf));
|
|
donesomething = B_TRUE;
|
|
}
|
|
} else {
|
|
char obname[BUFLEN];
|
|
getobname(o, obname, 1);
|
|
sprintf(buf, "Tighten the hinges on %s",obname);
|
|
ch = askchar(buf, "yn", "y", B_TRUE);
|
|
if (ch == 'y') {
|
|
msg("You tighten the hinges on %s.", obname);
|
|
addflag(o->flags, F_JAMMED, rnd(1,5), NA, NA, NULL);
|
|
taketime(lf, getactspeed(lf));
|
|
donesomething = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!donesomething) {
|
|
if (isplayer(lf)) msg("There is nothing to use your spanner on there!");
|
|
}
|
|
} 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, B_TRUE);
|
|
} 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;
|
|
int doneask = B_FALSE;
|
|
|
|
getobname(o, obname, 1);
|
|
getlfname(lf, lfname);
|
|
|
|
if (isplayer(lf) || cansee(player, lf)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
// adjacent to a closed door?
|
|
if (isplayer(lf)) {
|
|
int d;
|
|
for (d = DC_N; d <= DC_NW; d++) {
|
|
cell_t *c;
|
|
c = getcellindir(lf->cell, d);
|
|
if (c) {
|
|
object_t *door;
|
|
door = hasobwithflag(c->obpile, F_DOOR);
|
|
if (door) {
|
|
sprintf(buf, "Pour %s onto the door to the %s", obname, getdirname(d));
|
|
ch = askchar(buf, "yn", "n", B_TRUE);
|
|
if (ch == 'y') {
|
|
// finished asking where to pour
|
|
doneask = B_TRUE;
|
|
dst = door;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (!doneask) {
|
|
// 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) {
|
|
cell_t *dstloc;
|
|
flag_t *refillflag;
|
|
|
|
dstloc = getoblocation(dst);
|
|
|
|
// 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 (cansee(player, lf)) {
|
|
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 (cansee(player, lf)) {
|
|
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(dst, B_UNCURSED);
|
|
dst->blessknown = B_TRUE;
|
|
// remove bonuses
|
|
killflagsofid(dst->flags, F_BONUS);
|
|
// remove temporary flags and modify some others
|
|
for (f = dst->flags->first ; f ; f = nextf) {
|
|
nextf = f->next;
|
|
if (f->lifetime > 0) {
|
|
killflag(f);
|
|
} else if (f->id == F_FROZEN) {
|
|
killflag(f);
|
|
} else if (f->id == F_ONFIRE) {
|
|
killflag(f);
|
|
} else if (f->id == F_POISONED) {
|
|
killflag(f);
|
|
} else if (f->id == F_OBHP) {
|
|
f->val[0] = f->val[1];
|
|
}
|
|
}
|
|
// restore hp
|
|
|
|
|
|
if (!isknown(dst)) makeknown(dst->type->id);
|
|
} else if (o->type->id == OT_POT_ACID) {
|
|
// damage destinaiton
|
|
msg("You pour %s onto %s.", obname,dstname);
|
|
takedamage(dst, rnd(5,15), DT_ACID);
|
|
makeknown(o->type->id);
|
|
} else if (isdoor(dst, NULL)) {
|
|
msg("Your pour %s all over %s.", obname, dstname);
|
|
if (o->type->id == OT_POT_OIL) {
|
|
flag_t *f;
|
|
// unjam doors
|
|
f = hasflag(dst->flags, F_JAMMED);
|
|
if (f) {
|
|
killflag(f);
|
|
}
|
|
}
|
|
} else { // default
|
|
if (isplayer(lf)) {
|
|
msg("You pour %s onto %s.", obname,dstname);
|
|
msg("%s gets wet.", dstname);
|
|
}
|
|
takedamage(dst, 0, DT_WATER);
|
|
}
|
|
} else {
|
|
flag_t *f;
|
|
// pour onto ground
|
|
if (isplayer(lf)) {
|
|
msg("You pour %s onto the ground.", obname);
|
|
} else if (haslos(player, lf->cell)) {
|
|
msg("%s pours %s onto the ground.", lfname, obname);
|
|
}
|
|
f = hasflag(o->flags, F_DIECONVERT);
|
|
if (f) {
|
|
addob(lf->cell->obpile, f->text);
|
|
} else {
|
|
if (haslos(player, lf->cell)) {
|
|
msg("The contents evaporate.");
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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) || cansee(player, lf)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
taketime(lf, getactspeed(lf));
|
|
|
|
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 (cansee(player, lf)) {
|
|
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:
|
|
case OT_POT_RESTORATION:
|
|
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_FALSE, B_TRUE, B_FALSE, B_FALSE); // don't adjust for blindness
|
|
if (isplayer(lf)) {
|
|
// tell the player
|
|
msg("This is %s!",obname);
|
|
more();
|
|
drawmsg();
|
|
}
|
|
}
|
|
|
|
if (o->type->obclass->id == OC_POTION) {
|
|
potioneffects(lf, o->type->id, o->blessed, &seen);
|
|
} else if (hasflag(o->flags, F_DRINKABLE)) {
|
|
// drinkable thing which isn't a potion?
|
|
flag_t *f;
|
|
f = hasflag(o->flags, F_LINKOB);
|
|
if (f) {
|
|
potioneffects(lf, f->val[0], o->blessed, NULL);
|
|
} else {
|
|
eat(lf, o);
|
|
}
|
|
}
|
|
|
|
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;
|
|
flag_t *f;
|
|
|
|
if (isplayer(lf)) {
|
|
seenbyplayer = B_TRUE;
|
|
} else if (cansee(player, lf)) {
|
|
seenbyplayer = B_TRUE;
|
|
} else {
|
|
seenbyplayer = B_FALSE;
|
|
}
|
|
|
|
if (seen) {
|
|
*seen = seenbyplayer;
|
|
}
|
|
|
|
switch (oid) {
|
|
case OT_POT_ACID:
|
|
dam = rnd(5,10);
|
|
losehp(lf, dam, DT_ACID, NULL, "drinking acid");
|
|
if (lf->controller == C_PLAYER) {
|
|
msg("Your suffer massive internal burning!");
|
|
} else if (cansee(player, lf)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s writhes in agony!", buf);
|
|
}
|
|
break;
|
|
case OT_POT_ACROBATICS:
|
|
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
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) {
|
|
gainhp(lf, lf->maxhp); // ie. full hp
|
|
if (lf->controller == C_PLAYER) {
|
|
msg("You feel completely healed!");
|
|
} else if (cansee(player, lf)) {
|
|
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 (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
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 (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
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 (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily immune to the elements.");
|
|
}
|
|
break;
|
|
}
|
|
// how long for?
|
|
i = geteffecttime(15,25,isblessed);
|
|
|
|
if (!isimmuneto(lf->flags, DT_FIRE)) {
|
|
addtempflag(lf->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL, i);
|
|
}
|
|
if (!isimmuneto(lf->flags, DT_COLD)) {
|
|
addtempflag(lf->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL, i);
|
|
}
|
|
break;
|
|
case OT_POT_ETHEREALNESS:
|
|
dospelleffects(lf, OT_S_PASSWALL, (isblessed) ? 5 : 1, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_EXPERIENCE:
|
|
// gain xp!
|
|
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel momentarily more experienced.");
|
|
}
|
|
break;
|
|
}
|
|
if (isplayer(lf)) {
|
|
msg("You feel more experienced!");
|
|
}
|
|
gainxp(lf, getxpforlev(lf->level+1) - lf->xp);
|
|
break;
|
|
case OT_POT_GASEOUSFORM:
|
|
dospelleffects(lf, OT_S_GASEOUSFORM, (isblessed) ? 5 : 1, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_HEALING:
|
|
dospelleffects(lf, OT_S_HEALING,isblessed ? 5 : 1, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_HEALINGMIN:
|
|
dospelleffects(lf, OT_S_HEALINGMIN,isblessed ? 5 : 1, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_INVIS:
|
|
dospelleffects(lf, OT_S_INVISIBILITY,isblessed ? 6 : 3, lf, NULL, NULL, isblessed, seen);
|
|
break;
|
|
case OT_POT_INVULN:
|
|
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
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 (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, -10)) {
|
|
if (isplayer(lf)) {
|
|
msg("You feel your magical energy temporarily pulse.");
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (getmaxmp(lf) > 0) {
|
|
msg("Your magical energy is restored.");
|
|
lf->mp = getmaxmp(lf);
|
|
} 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, 5, lf, NULL, NULL, isblessed, NULL);
|
|
} else {
|
|
// random polymorph
|
|
dospelleffects(lf, OT_S_POLYMORPH, 1, lf, NULL, NULL, isblessed, NULL);
|
|
}
|
|
break;
|
|
case OT_POT_RESTORATION:
|
|
failed = B_TRUE;
|
|
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
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)) {
|
|
msg("You feel momentarily restored.");
|
|
}
|
|
}
|
|
break;
|
|
case OT_POT_SANCTUARY:
|
|
// how long for?
|
|
//i = gethealtime(lf); // TODO: change...
|
|
if (getmr(lf) && skillcheck(lf, SC_RESISTMAG, 30, 0)) {
|
|
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, 1, lf, NULL, lf->cell, B_BLESSED, NULL);
|
|
} else if (isblessed == B_CURSED) {
|
|
dospelleffects(lf, OT_S_SLOW, 1, lf, NULL, lf->cell, B_UNCURSED, NULL);
|
|
} else { // uncursed
|
|
dospelleffects(lf, OT_S_HASTE, 1, lf, NULL, lf->cell, B_UNCURSED, NULL);
|
|
}
|
|
if (seen) *seen = B_TRUE;
|
|
break;
|
|
|
|
case OT_POT_WATER:
|
|
switch (isblessed) {
|
|
case B_BLESSED:
|
|
if (hasflag(lf->flags, F_UNDEAD)) {
|
|
if (isplayer(lf)) {
|
|
msg("This tastes like water, but burns like acid!");
|
|
} else if (cansee(player, lf)) {
|
|
getlfname(lf, buf);
|
|
msg("%s writhes in agony!", buf);
|
|
}
|
|
losehp(lf, rnd(5,15), DT_HOLY, NULL, "drinking holy water");
|
|
} else {
|
|
msg("Mmm, holy water.");
|
|
}
|
|
break;
|
|
case B_UNCURSED:
|
|
msg("Mmm, water.");
|
|
break;
|
|
case B_CURSED:
|
|
msg("Yuck! Something is wrong with this water.");
|
|
break;
|
|
}
|
|
if (seen) {
|
|
if (isplayer(lf) || cansee(player, lf)) {
|
|
*seen = B_TRUE;
|
|
}
|
|
}
|
|
modhunger(lf, -pctof(0.05, (float)HUNGERCONST));
|
|
break;
|
|
case OT_POT_BLOOD:
|
|
msg("Yuck, this tastes like blood!");
|
|
break;
|
|
case OT_POT_BLOODC:
|
|
f = lfhasflag(lf, F_BEINGSTONED);
|
|
if (f) {
|
|
killflag(f);
|
|
} else {
|
|
msg("Yuck, this tastes like oddly-flavoured blood!");
|
|
}
|
|
break;
|
|
case OT_POT_JUICE:
|
|
if (isplayer(lf)) {
|
|
switch (isblessed) {
|
|
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;
|
|
}
|
|
if (seen) *seen = B_TRUE;
|
|
}
|
|
if (isblessed != B_CURSED) {
|
|
modhunger(lf, -pctof(10, (float)HUNGERCONST));
|
|
}
|
|
break;
|
|
default: // nothing happens
|
|
break;
|
|
}
|
|
}
|
|
|
|
int 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;
|
|
objecttype_t *linkspell;
|
|
int readtime;
|
|
|
|
if (!haslos(lf, lf->cell)) {
|
|
if (isplayer(lf)) {
|
|
msg("You can't read anything, since you can't see!");
|
|
}
|
|
return B_TRUE;
|
|
}
|
|
|
|
getobname(o, obname, 1);
|
|
|
|
if ((lf->controller == C_PLAYER) || cansee(player, lf)) {
|
|
playercansee = B_TRUE;
|
|
} else {
|
|
playercansee = B_FALSE;
|
|
}
|
|
|
|
|
|
if (o->type->obclass->id == OC_BOOK) {
|
|
readtime = SPEED_READ * 2;
|
|
} else {
|
|
readtime = SPEED_READ;
|
|
}
|
|
taketime(lf, readtime);
|
|
|
|
// some checks first...
|
|
touch(lf, o);
|
|
if (hasflag(o->flags, F_DEAD)) {
|
|
return B_TRUE;
|
|
}
|
|
|
|
|
|
if (lf->controller != C_PLAYER) {
|
|
if (cansee(player, lf)) {
|
|
getlfname(lf, buf);
|
|
capitalise(buf);
|
|
msg("%s reads %s!", buf, obname);
|
|
}
|
|
}
|
|
|
|
// find linked spell
|
|
linkspell = getlinkspell(o);
|
|
|
|
// figure out whether to id the object
|
|
willid = B_FALSE;
|
|
if (playercansee) {
|
|
if (o->type->obclass->id == OC_BOOK) {
|
|
// is this a spellbook?
|
|
if (linkspell) {
|
|
// if so, only id if we are able to read it
|
|
//if (getiqreq(linkspell->id) <= getattr(lf, A_IQ)) {
|
|
if (getspellpower(lf, linkspell->id) > 0) {
|
|
willid = B_TRUE;
|
|
} else {
|
|
willid = B_FALSE;
|
|
}
|
|
} else {
|
|
// ie. a manual
|
|
willid = B_TRUE;
|
|
}
|
|
} else {
|
|
switch (o->type->id) {
|
|
case OT_SCR_IDENTIFY: // only id if it does something
|
|
case OT_SCR_ENCHANT: // only id if it does something
|
|
case OT_SCR_CREATEMONSTER: // only id if it does something
|
|
case OT_SCR_REMOVECURSE: // 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:
|
|
case OT_SCR_ENCHANT:
|
|
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_FALSE, 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;
|
|
int power;
|
|
|
|
power = f->val[1];
|
|
if (power == NA) power = 1;
|
|
|
|
// increase based on your magic item usage skill
|
|
power += (getskill(lf, SK_MAGITEMUSAGE)*2);
|
|
|
|
// blessed scrolls are more powerful
|
|
if (isblessed(o)) power += 4;
|
|
|
|
// enforce maximum
|
|
if (power > 10) power = 10;
|
|
|
|
// 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);
|
|
}
|
|
|
|
dospelleffects(lf, f->val[0], power, 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);
|
|
} else if (o->type->id == OT_SCR_REMOVECURSE) {
|
|
int seen = B_FALSE;
|
|
object_t *oo;
|
|
// remove curses!
|
|
for (oo = lf->pack->first ; oo ; oo = oo->next) {
|
|
if (iscursed(oo)) {
|
|
if (o->blessed || isequipped(oo)) {
|
|
// announce
|
|
if (cansee(player, lf)) {
|
|
char lfname[BUFLEN];
|
|
char obname[BUFLEN];
|
|
getlfname(lf, lfname);
|
|
getobname(oo, obname,oo->amt);
|
|
msg("A black aura breaks away from %s%s %s.",lfname,getpossessive(lfname),noprefix(obname));
|
|
seen = B_TRUE;
|
|
}
|
|
// uncurse it
|
|
oo->blessed = B_UNCURSED;
|
|
oo->blessknown = B_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (seen) {
|
|
// id the scroll now
|
|
makeknown(o->type->id);
|
|
} else {
|
|
if (isplayer(lf)) {
|
|
nothinghappens();
|
|
}
|
|
}
|
|
if (isplayer(lf)) {
|
|
msg("The scroll crumbles to dust.");
|
|
}
|
|
// removeob one of the object
|
|
removeob(o, 1);
|
|
}
|
|
} else if (o->type->obclass->id == OC_BOOK) {
|
|
// is this a spellbook?
|
|
if (linkspell) {
|
|
// if so, can we read it?
|
|
if (getspellpower(lf, linkspell->id) > 0) {
|
|
if (lfhasflagval(lf, F_CANCAST, linkspell->id, NA, NA, NULL)) {
|
|
if (isplayer(lf)) msg("You already know how to cast this spell!");
|
|
} else {
|
|
// learn it
|
|
addflag(lf->flags, F_CANCAST, linkspell->id, NA, NA, NULL);
|
|
}
|
|
} else {
|
|
if (isplayer(lf)) msg("This book is a bit too advanced for you.");
|
|
}
|
|
} else {
|
|
// manuals
|
|
f = hasflag(o->flags, F_MANUALOF);
|
|
if (f) {
|
|
giveskill(lf, f->val[0]);
|
|
}
|
|
if (isplayer(lf)) {
|
|
msg("The book crumbles to dust.");
|
|
}
|
|
// removeob one of the object
|
|
removeob(o, 1);
|
|
}
|
|
}
|
|
return B_FALSE;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
// randomizes hidden names
|
|
void shufflehiddennames(void) {
|
|
int i,n;
|
|
int total;
|
|
hiddenname_t *a, *temp;
|
|
int shuffleamt = 20;
|
|
|
|
|
|
total = 0;
|
|
for (a = firsthiddenname ; a ; a = a->next) {
|
|
total++;
|
|
}
|
|
|
|
if (total <= 1) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < shuffleamt; i++) {
|
|
int which;
|
|
|
|
// select random element (but never the first)
|
|
which = (rand() % (total-1))+1;
|
|
|
|
// go there
|
|
a = firsthiddenname;
|
|
for (n = 0; n < which; n++) {
|
|
if (a->next != NULL) a = a->next;
|
|
}
|
|
temp = a;
|
|
|
|
// remove from list
|
|
temp->prev->next = temp->next;
|
|
|
|
|
|
if (temp->next) {
|
|
temp->next->prev = temp->prev;
|
|
} else {
|
|
lasthiddenname = temp->prev;
|
|
}
|
|
|
|
// re-add this element to the start
|
|
temp->next = firsthiddenname;
|
|
temp->prev = NULL;
|
|
|
|
firsthiddenname->prev = temp;
|
|
firsthiddenname = temp;
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
// catches on fire?
|
|
if (damtype == DT_FIRE) {
|
|
if (isflammable(o)) {
|
|
ignite(o);
|
|
}
|
|
}
|
|
|
|
// damage type converts this into something else?
|
|
f = hasflagval(o->flags, F_DTCONVERT, damtype, NA, NA, NULL);
|
|
if (f && !hasflag(o->flags, F_NODTCONVERT)) {
|
|
object_t *newob;
|
|
newob = addob(o->pile, f->text);
|
|
newob->amt = o->amt;
|
|
|
|
// object dies, but don't announce it
|
|
addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
|
addflag(o->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
|
|
return howmuch;
|
|
}
|
|
|
|
adjustdamob(o, &howmuch, damtype);
|
|
|
|
// effects which have to happen before damage is applied...
|
|
// 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);
|
|
return howmuch;
|
|
}
|
|
}
|
|
} 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);
|
|
return howmuch;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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 howmuch;
|
|
}
|
|
|
|
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_TRUE, 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) {
|
|
// 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 (cansee(player, o->pile->owner)) {
|
|
// don't announce decay damage for object you aren't holding
|
|
if (damtype != DT_DECAY) {
|
|
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)) {
|
|
// don't announce decay damage for object you aren't holding
|
|
if (damtype != DT_DECAY) {
|
|
msg("%s %s!", obname, getobhurtname(o, damtype));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
return damtaken;
|
|
}
|
|
|
|
// throw speed is the damage multiplier
|
|
int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed, object_t *firearm) {
|
|
char throwername[BUFLEN];
|
|
char throwernamea[BUFLEN];
|
|
char realthrowername[BUFLEN];
|
|
char realthrowernamea[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;
|
|
object_t *newob;
|
|
cell_t *newloc;
|
|
int db = B_TRUE;
|
|
|
|
reason = E_OK;
|
|
|
|
if (firearm) {
|
|
strcpy(throwverbpres, "fire");
|
|
strcpy(throwverbpast, "fired");
|
|
} else {
|
|
strcpy(throwverbpres, "throw");
|
|
strcpy(throwverbpast, "thrown");
|
|
}
|
|
|
|
|
|
if (isblind(player)) {
|
|
if (thrower && isplayer(thrower)) {
|
|
getobname(o, obname, amt);
|
|
} else {
|
|
strcpy(obname, "something");
|
|
}
|
|
} else {
|
|
getobname(o, obname, amt);
|
|
}
|
|
|
|
if (thrower) {
|
|
getlfname(thrower, throwername);
|
|
real_getlfname(thrower, realthrowername, B_FALSE);
|
|
|
|
if (isplayer(thrower)) {
|
|
strcpy(throwernamea, throwername);
|
|
} else {
|
|
if (isvowel(*(noprefix(throwername)))) {
|
|
strcpy(throwernamea, "an ");
|
|
} else {
|
|
strcpy(throwernamea, "a ");
|
|
}
|
|
strcat(throwernamea, noprefix(throwername));
|
|
|
|
|
|
if (isvowel(*(noprefix(realthrowername)))) {
|
|
strcpy(realthrowernamea, "an ");
|
|
} else {
|
|
strcpy(realthrowernamea, "a ");
|
|
}
|
|
strcat(realthrowernamea, noprefix(realthrowername));
|
|
}
|
|
} else {
|
|
strcat(throwernamea, "something");
|
|
strcat(realthrowernamea, "something");
|
|
}
|
|
|
|
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 (thrower && (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 (cansee(player, thrower)) {
|
|
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 && isdead(target)) {
|
|
target = NULL;
|
|
}
|
|
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 (thrower && isplayer(thrower)) {
|
|
// player is throwing something
|
|
if (target) {
|
|
msg("You %s %s at %s.", throwverbpres, obname, targetname);
|
|
} else {
|
|
msg("You %s %s.",throwverbpres, obname);
|
|
}
|
|
} else if (thrower && haslos(player, srcloc) && (srcloc == thrower->cell)) {
|
|
char throwstring[BUFLEN];
|
|
|
|
// a monster is throwing something
|
|
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];
|
|
// an object is moving on its own
|
|
|
|
/*
|
|
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, (amt == 1) ? "flies" : "fly");
|
|
if (target && haslos(player, where)) {
|
|
strcat(throwstring, " toward ");
|
|
strcat(throwstring, targetname);
|
|
}
|
|
strcat(throwstring, ".");
|
|
msg("%s", throwstring);
|
|
}
|
|
|
|
|
|
// adjust destination location in case something is in the way.
|
|
haslof(thrower, where, LOF_NEED, &newloc);
|
|
if (newloc) {
|
|
where = newloc;
|
|
target = where->lf;
|
|
if (target && isdead(target)) {
|
|
target = NULL;
|
|
}
|
|
if (target) {
|
|
getlfname(target, targetname);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//taketime(thrower, SPEED_THROW);
|
|
|
|
// some obejcts will die when thrown.
|
|
if (hasflag(o->flags, F_POWDER)) {
|
|
if (haslos(player, srcloc)) {
|
|
msg("%s dispers%s into the air.", obname, (amt == 1) ? "es" : "e");
|
|
}
|
|
removeob(o, amt);
|
|
return B_FALSE;
|
|
}
|
|
|
|
if (thrower) {
|
|
// 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, amt);
|
|
return B_FALSE;
|
|
}
|
|
}
|
|
|
|
// do throw animation
|
|
if (seen) {
|
|
anim(srcloc, where, getglyph(o));
|
|
}
|
|
|
|
// find out your chances of hitting
|
|
if (target) {
|
|
if (thrower) {
|
|
acc = getmissileaccuracy(thrower, where, o, firearm, A_DEX);
|
|
} else {
|
|
// purely based on saving throw...
|
|
acc = 100;
|
|
}
|
|
|
|
// roll for hit
|
|
youhit = B_FALSE;
|
|
// metal weapon versus magnetic shield?
|
|
if (target && 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;
|
|
}
|
|
|
|
// saving throw
|
|
if (youhit) {
|
|
if (skillcheck(target, SC_DODGE, 20, 0)) {
|
|
youhit = B_FALSE;
|
|
}
|
|
}
|
|
|
|
// doesn't matter wheter you hit or ot...
|
|
if (lfhasflag(target, F_UNDEAD) && isblessed(o)) {
|
|
if (seen) {
|
|
msg("%s recoils in fear!", targetname);
|
|
}
|
|
o->blessknown = B_TRUE;
|
|
}
|
|
|
|
|
|
// if someone is there, they take damage and the object might die
|
|
// this should be "if target && youhit"
|
|
if (youhit) {
|
|
int dam = 0,shatterdam = 0;
|
|
char damstring[BUFLEN];
|
|
int reduceamt = 0;
|
|
int throwdam;
|
|
|
|
throwdam = getthrowdam(o);
|
|
dam = throwdam * speed;
|
|
if (db) dblog("fireat(): dam = throwdam(%d) * speed(%d) = %d",throwdam, speed, dam);
|
|
|
|
// 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 hit%s %s%s",obname,(amt == 1) ? "s" : "", 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)) {
|
|
noise(where, NULL, "shattering glass.", NULL);
|
|
}
|
|
}
|
|
sprintf(damstring, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
|
|
|
|
reduceamt = getarmourdamreduction(target, o, dam, DT_PROJECTILE);
|
|
|
|
applyarmourdamreduction(target, o, reduceamt, &dam, DT_PROJECTILE);
|
|
|
|
if (dam > 0) {
|
|
lifeform_t *whogetsxp = NULL;
|
|
// TODO: at the moment you won't get experience if you telekenetically
|
|
// throw an object at something. is this okay?
|
|
if (thrower && (thrower->cell == srcloc)) {
|
|
whogetsxp = thrower;
|
|
}
|
|
losehp(target, dam, DT_PROJECTILE, whogetsxp, damstring);
|
|
}
|
|
|
|
if (reduceamt && (speed >= 3)) {
|
|
applyarmourdamage(target, o, reduceamt, DT_PROJECTILE);
|
|
}
|
|
|
|
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, realthrowernamea);
|
|
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 {
|
|
noise(where, NULL, "shattering glass.", NULL);
|
|
}
|
|
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;
|
|
// some potions have special effects...
|
|
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)*amt, DT_ACID, thrower, "a splash of acid");
|
|
} else {
|
|
// announce
|
|
if (seen) {
|
|
msg("Acid splashes all over the floor!");
|
|
}
|
|
}
|
|
break;
|
|
case OT_POT_ELEMENTENDURE:
|
|
case OT_POT_ELEMENTIMMUNE:
|
|
case OT_POT_ETHEREALNESS:
|
|
case OT_POT_GASEOUSFORM:
|
|
case OT_POT_POLYMORPH:
|
|
case OT_POT_INVIS:
|
|
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_BLOOD:
|
|
if (seen) {
|
|
makeknown(o->type->id);
|
|
}
|
|
if (target) {
|
|
if (seen) {
|
|
msg("%s %s splashed with blood.", targetname,
|
|
isplayer(target) ? "are" : "is");
|
|
}
|
|
} else {
|
|
// announce
|
|
if (seen) {
|
|
msg("Blood splashes onto the floor.");
|
|
}
|
|
}
|
|
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 (cansee(player, target)) {
|
|
msg("%s writhes in agony!", targetname);
|
|
}
|
|
losehp(target, amt*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);
|
|
}
|
|
}
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// heavy ob?
|
|
if (youhit && target) {
|
|
if (getobweight(o) >= getlfweight(target, B_NOOBS)) {
|
|
int dir;
|
|
dir = getdirtowards(srcloc, target->cell, target, B_FALSE, DT_COMPASS);
|
|
knockback(target, dir, 1, thrower);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// move the object to the cell then take dam or kill it.
|
|
newob = moveob(o, where->obpile, amt);
|
|
// fake its birth time so that it can be damaged
|
|
newob->birthtime = -1;
|
|
if (shattered) {
|
|
addflag(newob->flags, F_DEAD, B_TRUE, NA, NA, NULL);
|
|
addflag(newob->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
|
|
} else {
|
|
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 (isblessed(o) && 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 (cansee(player, owner)) {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (hasflag(o->flags, F_LIGHTSOURCE)) {
|
|
flag_t *f2,*mf;
|
|
// countdown...
|
|
f2 = hasflag(o->flags, F_CHARGES);
|
|
if (f2) {
|
|
f2->val[0]--;
|
|
if (f2->val[0] <= 0) {
|
|
// turnoff
|
|
turnoff(NULL, o);
|
|
mf = hasflag(o->flags, F_CHARGEOUTMSG);
|
|
if (mf) obaction(o, mf->text);
|
|
needredraw = B_TRUE;
|
|
return;
|
|
} else if (f2->val[0] <= 50) {
|
|
if (rnd(1,6) == 1) {
|
|
mf = hasflag(o->flags, F_CHARGELOWMSG);
|
|
if (mf) obaction(o, mf->text);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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, roll(f->text), f->val[0]);
|
|
//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) && !hasflag(o->flags, F_NOMATCONVERT)) {
|
|
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 (cansee(player, lf)) {
|
|
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);
|
|
msgnocap("%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 (cansee(player, lf)) {
|
|
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);
|
|
msgnocap("%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;
|
|
skill_t *sk;
|
|
int foundspells = B_FALSE;
|
|
int goterror = B_FALSE;
|
|
flag_t *f;
|
|
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.\n", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
} else if (ot->obclass->id == OC_WEAPON) {
|
|
if (!hasflag(ot->flags, F_USESSKILL) && !hasflag(ot->flags, F_FIREARM)) {
|
|
printf("ERROR in object '%s' - weapon has no associated skill.\n", 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.\n", 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.\n", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
f = hasflag(ot->flags, F_TECHLEVEL);
|
|
if (f && (f->val[0] != PR_INEPT)) {
|
|
if (!hasflag(ot->flags, F_HASHIDDENNAME)) {
|
|
printf("ERROR in object '%s' - has a techlevel but doesn't have a hidden name.\n", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
}
|
|
f = hasflag(ot->flags, F_MANUALOF);
|
|
if (f && !findskill(f->val[0])) {
|
|
printf("ERROR in object '%s' - teachs a skill which doesn't exist.\n", ot->name);
|
|
goterror = B_TRUE;
|
|
}
|
|
}
|
|
|
|
for (sk = firstskill ; sk ; sk = sk->next) {
|
|
int found = B_FALSE;
|
|
// make sure every skill have an object providing it
|
|
for (ot = objecttype ; ot ; ot = ot->next) {
|
|
if (hasflagval(ot->flags, F_MANUALOF, sk->id, NA, NA, NULL)) {
|
|
found = B_TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
printf("ERROR - skill '%s' has no matching manual.\n", sk->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;
|
|
}
|
|
|
|
objecttype_t *getlinkspell(object_t *o) {
|
|
flag_t *f = NULL;
|
|
objecttype_t *spelltype = NULL;
|
|
f = hasflag(o->flags, F_LINKSPELL);
|
|
if (f) {
|
|
// find the linked spell
|
|
spelltype = findot(f->val[0]);
|
|
}
|
|
|
|
return spelltype;
|
|
}
|
|
|
|
// is the given material solid or liquid?
|
|
enum MATSTATE getmaterialstate(enum MATERIAL mat) {
|
|
switch (mat) {
|
|
case MT_NOTHING:
|
|
case MT_FIRE:
|
|
case MT_MAGIC:
|
|
return MS_OTHER;
|
|
case MT_WATER:
|
|
case MT_BLOOD:
|
|
case MT_ACID:
|
|
return MS_LIQUID;
|
|
case MT_GAS:
|
|
return MS_GAS;
|
|
default:
|
|
return MS_SOLID;
|
|
}
|
|
return MS_OTHER; // should never happen
|
|
}
|
|
|
|
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 && !isthrowmissile(missile)) {
|
|
acc -= 20;
|
|
}
|
|
return acc;
|
|
}
|