- [+] thrown objects taking no damage due to hardness

* [+] DIETY is slow.
- [+] map bug - from 0,0, walk NE (off top edge).  i end up at 0,0
      again!!!
* [+] ALLOW ROTATING OF VAULTS
- [+] BUG: dig X only goes 1 cell.
- [+] add a U shaped turn vault.
- [+] change wehre i apply HADRNESS for lfs! - don't use
      adjustdammaterial cause we inherit there
- [+] make obchance/thingchance part of habitat_t
- [+] make sense surroundings take cartography skill into account
* [+] BUG: rotated at() etc not working.
- [+] if you fail stealing, the target should get angry!!!
- [+] make sure to redraw stat bar when mind scan finishes.
- [+] villages
    - [+] initial code
    * [+] town gaurds. stand next to the gate
    - [+] potion shop vault
        - [+] implement
        - [+] potion shop isn't getting potions!!
        - [+] and getting wrong floor type.
        * [+] stop shop from always being at the top left.
        - [+] make sure its x/y arent too close to edge of map (at
              least 5 away)
            - [+] vault param.  f_mapmargin, 5
            - [+] make calcroompos take x/y margin
    - [+] don't put auto obs inside vaults
    - [+] town walls
    - [+] more kinds of shops
    * [+] signs outside shops
    - [+] bug with ai swapping between firearms and twohanded weapons.
          fixed.
    * [+] make _CELLS_ have habitats!
    - [+] move vaultchance to a habitat param instead of
          getvaultchance()
* [+] shopkeepers  (special race)
village things:
- [+] barrels,
- [+] guards,
- [+] statue

- [+] thrown objects should still take damage if blocked via a shield
* [+] hardness (must do dam >= xx to hurt)
* [+] WATER spread mods
* [+] very powerful spells have casttime
- [+] allow linkstairs() to take a parameter rather than always jsut
      searching for the other end
- [+] when digging holes, only use getrandomadjcell if there is an lf
      in the way. and then use WE_NOLF. clear out solid cells
- [+] show armour EVASION penalty in describeob
- [+] teleportation trap.  You reintegrate inside a solid object!  You
      die.--More--.
- [+] riverroom vault
* [+] water:  swap { and ~ again??
- [+] make "large puddle of water" evaporate more quickly
* [+] special glyph case: for deep water
This commit is contained in:
Rob Pearce 2011-06-29 08:48:48 +00:00
parent cf328f849f
commit 7dfeb42e5a
29 changed files with 2176 additions and 594 deletions

View File

@ -1,2 +1,2 @@
nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h vault.c vault.h nexus: Makefile defs.h nexus.c nexus.h ai.c ai.h attack.c attack.h flag.c flag.h io.c io.h lf.c lf.h map.c map.h move.c move.h objects.c objects.h text.c text.h save.c save.h spell.c spell.h vault.c vault.h
gcc -Wall -g -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c vault.c vault.h -lncurses gcc -Wall -g -pg -o nexus nexus.c ai.c attack.c flag.c io.c lf.c map.c move.c objects.c text.c save.c spell.c vault.c vault.h -lncurses

31
ai.c
View File

@ -771,6 +771,12 @@ int aipickup(lifeform_t *lf, object_t *o) {
int aipickupok(lifeform_t *lf, object_t *o) { int aipickupok(lifeform_t *lf, object_t *o) {
int ok = B_FALSE; int ok = B_FALSE;
if (hasflag(o->flags, F_SHOPITEM)) {
// && (getiqname(getattr(lf, A_IQ), NULL) > IQ_ANIMAL)) {
return B_FALSE;
}
if (isedible(o)) { if (isedible(o)) {
if (caneat(lf, o) && !isinbattle(lf)) { if (caneat(lf, o) && !isinbattle(lf)) {
ok = B_TRUE; ok = B_TRUE;
@ -944,13 +950,16 @@ void aiturn(lifeform_t *lf) {
} }
// do we have a better firearm ? // do we have a better firearm ?
curgun = getfirearm(lf); if (curwep && hasflag(curwep->flags, F_TWOHANDED)) {
bestgun = getbestfirearm(lf); } else {
curgun = getfirearm(lf);
bestgun = getbestfirearm(lf);
if (curgun != bestgun) { if (curgun != bestgun) {
if (db) dblog(".oO { i have a better gun than my current one (%s > %s) }",bestgun->type->name, curgun ? curgun->type->name : "nothing"); if (db) dblog(".oO { i have a better gun than my current one (%s > %s) }",bestgun->type->name, curgun ? curgun->type->name : "nothing");
// weild better one // weild better one
if (!weild(lf, bestgun)) return; if (!weild(lf, bestgun)) return;
}
} }
// do we have better ammo? // do we have better ammo?
@ -1693,7 +1702,7 @@ int lookforobs(lifeform_t *lf) {
// if we are in battle only go for it if we covet it // if we are in battle only go for it if we covet it
if (!target || (f->val[1] == B_COVETS)) { if (!target || (f->val[1] == B_COVETS)) {
o = hasbetterweapon(lf, lf->cell->obpile); o = hasbetterweapon(lf, lf->cell->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o) && canpickup(lf, o, 1)) {
if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name); if (db) dblog(".oO { current cell has better weapon (%s) }",o->type->name);
// try to pick it up // try to pick it up
if (!aipickup(lf, o)) return B_TRUE; if (!aipickup(lf, o)) return B_TRUE;
@ -1710,7 +1719,7 @@ int lookforobs(lifeform_t *lf) {
// if we are in battle only go for it if we covet it // if we are in battle only go for it if we covet it
if (!target || (f->val[1] == B_COVETS)) { if (!target || (f->val[1] == B_COVETS)) {
o = hasbetterarmour(lf, lf->cell->obpile); o = hasbetterarmour(lf, lf->cell->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o) && canpickup(lf, o, 1)) {
if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name); if (db) dblog(".oO { current cell has better armour (%s) }",o->type->name);
// try to pick it up // try to pick it up
if (!aipickup(lf, o)) return B_TRUE; if (!aipickup(lf, o)) return B_TRUE;
@ -1774,7 +1783,8 @@ int lookforobs(lifeform_t *lf) {
if (!target || if (!target ||
((f->val[1] != B_COVETS) && (celldist <= targdist)) ) { ((f->val[1] != B_COVETS) && (celldist <= targdist)) ) {
o = hasbetterweapon(lf, c->obpile); o = hasbetterweapon(lf, c->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o) &&
canpickup(lf, o, 1)) {
if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name); if (db) dblog(".oO { remote cell has better weapon (%s). setting f_targetcell }",o->type->name);
gothere = B_TRUE; gothere = B_TRUE;
} }
@ -1791,7 +1801,8 @@ int lookforobs(lifeform_t *lf) {
((f->val[1] != B_COVETS) && (celldist <= targdist)) ) { ((f->val[1] != B_COVETS) && (celldist <= targdist)) ) {
o = hasbetterarmour(lf, c->obpile); o = hasbetterarmour(lf, c->obpile);
if (o && !isdangerousob(o, lf, B_TRUE) && canpickup(lf, o, 1)) { if (o && !isdangerousob(o, lf, B_TRUE) && aipickupok(lf, o) &&
canpickup(lf, o, 1)) {
if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name); if (db) dblog(".oO { remote cell has better armour (%s). setting f_targetcell }",o->type->name);
gothere = B_TRUE; gothere = B_TRUE;
} }

View File

@ -1046,7 +1046,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
noise(lf->cell, NULL, 3, "sounds of fighting.", NULL); noise(lf->cell, NULL, 3, "sounds of fighting.", NULL);
} }
if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARD)) { if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARDNESS)) {
char buf[BUFLEN]; char buf[BUFLEN];
sprintf(buf, "punching %s", obname); sprintf(buf, "punching %s", obname);
if ( losehp(lf, 1, DT_BASH, lf, buf)) { if ( losehp(lf, 1, DT_BASH, lf, buf)) {

92
defs.h
View File

@ -36,6 +36,15 @@ enum COLOUR {
C_BOLDGREEN = 14, C_BOLDGREEN = 14,
}; };
enum SPEECHVOL {
SV_SILENT = 0,
SV_WHISPER = 1,
SV_TALK = 2,
SV_SHOUT = 3,
SV_ROAR = 4,
SV_BELLOW = 3,
};
enum SKILL { enum SKILL {
SK_NONE = 0, SK_NONE = 0,
SK_ARMOUR = 1, SK_ARMOUR = 1,
@ -158,6 +167,7 @@ enum CHECKTYPE {
SC_POISON, SC_POISON,
SC_RESISTMAG, SC_RESISTMAG,
SC_SEARCH, SC_SEARCH,
SC_STEAL,
SC_STEALTH, SC_STEALTH,
SC_WILL, SC_WILL,
}; };
@ -263,7 +273,9 @@ enum MODTYPE {
#define MAXRETCELLS 80 #define MAXRETCELLS 80
#define MAXCHOICES 200 #define MAXFLAGS 500
#define MAXCHOICES 400
#define MAXDEPTH 25 // max dungeon depth #define MAXDEPTH 25 // max dungeon depth
@ -425,10 +437,14 @@ enum CELLTYPE {
CT_WALL, CT_WALL,
CT_WALLGLASS, CT_WALLGLASS,
CT_WALLMETAL, CT_WALLMETAL,
CT_WALLWOOD,
CT_ROOMWALL, CT_ROOMWALL,
// empty // empty
CT_CORRIDOR, CT_CORRIDOR,
CT_DIRT, CT_DIRT,
CT_VILLAGEGROUND,
CT_FLOORSHOP,
CT_FLOORWOOD,
CT_GRASS, CT_GRASS,
CT_LOOPCORRIDOR, CT_LOOPCORRIDOR,
CT_LOWFLOOR, CT_LOWFLOOR,
@ -619,6 +635,7 @@ enum RACE {
// human monsters // human monsters
R_HUMAN, R_HUMAN,
R_BANDIT, R_BANDIT,
R_TOWNGUARD,
// monsters // monsters
R_BEHOLDER, R_BEHOLDER,
R_BUGBEAR, R_BUGBEAR,
@ -728,6 +745,7 @@ enum JOB {
J_PLUMBER, J_PLUMBER,
J_PRINCE, J_PRINCE,
J_ROGUE, J_ROGUE,
J_SHOPKEEPER,
J_WIZARD, J_WIZARD,
}; };
@ -778,7 +796,10 @@ enum OBTYPE {
OT_STATUE, OT_STATUE,
OT_DOORWOOD, OT_DOORWOOD,
OT_DOORIRON, OT_DOORIRON,
OT_IRONGATE, OT_GATEIRON,
OT_GATEWOOD,
OT_FENCEWOOD,
OT_SIGN,
OT_WOODENTABLE, OT_WOODENTABLE,
OT_WOODENBARREL, OT_WOODENBARREL,
OT_WOODENSTOOL, OT_WOODENSTOOL,
@ -1014,6 +1035,7 @@ enum OBTYPE {
OT_S_WATERJET, OT_S_WATERJET,
// -- summoning // -- summoning
OT_S_FLOATINGDISC, OT_S_FLOATINGDISC,
OT_S_CLEARLEVEL,
OT_S_CREATEMONSTER, OT_S_CREATEMONSTER,
OT_S_SUMMONWEAPON, OT_S_SUMMONWEAPON,
// -- translocation // -- translocation
@ -1034,6 +1056,7 @@ enum OBTYPE {
OT_S_CREATEVAULT, OT_S_CREATEVAULT,
OT_S_GIFT, OT_S_GIFT,
OT_S_WISH, OT_S_WISH,
OT_A_BLINDALL,
OT_A_DEBUG, OT_A_DEBUG,
OT_A_ENHANCE, OT_A_ENHANCE,
OT_A_LEARN, OT_A_LEARN,
@ -1365,6 +1388,7 @@ enum DEPTH {
#define WE_EMPTY 2 #define WE_EMPTY 2
#define WE_PORTAL 3 #define WE_PORTAL 3
#define WE_NOTWALL 4 #define WE_NOTWALL 4
#define WE_NOLF 5
enum NOISETYPE { enum NOISETYPE {
N_GETANGRY, N_GETANGRY,
@ -1427,6 +1451,7 @@ enum FLAG {
F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold) F_NO_A, // this obname doesn't need to start with 'a' for singular (eg. gold)
F_CONTAINSOB, // for vending machiens. v0 is ob letter F_CONTAINSOB, // for vending machiens. v0 is ob letter
// text is an object it contains. // text is an object it contains.
F_SIGNTEXT, // for 'sign' objects. f->text is what is says.
F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc F_IDWHENUSED, // fully identify an object when worn/weilded/operated/etc
F_STARTBLESSED, // v0 = b_blessed or b_cursed F_STARTBLESSED, // v0 = b_blessed or b_cursed
F_REPELBLESSED, // v0 = b_blessed or b_cursed. repels other obejcts F_REPELBLESSED, // v0 = b_blessed or b_cursed. repels other obejcts
@ -1440,7 +1465,11 @@ enum FLAG {
F_NOFEEL, // when blind, don't show "you can feel xxx" F_NOFEEL, // when blind, don't show "you can feel xxx"
F_FEELTEXT, // when blind, show "you can feel"+f->text F_FEELTEXT, // when blind, show "you can feel"+f->text
// for items in shops // for items in shops
F_SHOPITEM, // causes shops to show this item as identified F_VENDITEM, // causes vending machine to show this item as identified
F_SHOPITEM, // v0 is object value.
// v1 is the shop it is from
// causes shops to show (worth $xx) after the ob's name.
// also used for detecting theft!
F_VALUE, // how much an item is worth (over its base weight+material) F_VALUE, // how much an item is worth (over its base weight+material)
// weapon/armour flags // weapon/armour flags
F_EQUIPPED, // val0 = where it is equipped. CLEAR WHEN OB MOVED! F_EQUIPPED, // val0 = where it is equipped. CLEAR WHEN OB MOVED!
@ -1568,7 +1597,6 @@ enum FLAG {
// text = obid to link to // text = obid to link to
// ob interaction flags // ob interaction flags
F_HARD, // object is hard (ie. punching it will hurt!)
F_REDUCEMOVEMENT, // time to move off here is multiplied by v0. F_REDUCEMOVEMENT, // time to move off here is multiplied by v0.
F_RESTRICTMOVEMENT, // must pass a diff=v0 STR check to move off it. F_RESTRICTMOVEMENT, // must pass a diff=v0 STR check to move off it.
// if v1 is B_TRUE, then it takes 1 damage if you fail. // if v1 is B_TRUE, then it takes 1 damage if you fail.
@ -1683,6 +1711,7 @@ enum FLAG {
F_MAXPOWER, // val0 = max power of this spell (1-10) F_MAXPOWER, // val0 = max power of this spell (1-10)
F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2 F_MPCOST, // v0=mp cost of spell. if missing, mpcost if splev^2
F_ONGOING, // this spell has an ongoing cost F_ONGOING, // this spell has an ongoing cost
F_CASTINGTIME, // this spell takes v0 turns to cast
//F_SPELLLETTER, // text[0] = letter to cast this spell //F_SPELLLETTER, // text[0] = letter to cast this spell
F_AICASTTOFLEE, // AI can cast this spell to help flee/heal F_AICASTTOFLEE, // AI can cast this spell to help flee/heal
// v0 is who to target // v0 is who to target
@ -1693,9 +1722,10 @@ enum FLAG {
F_AIHEALITEM, // ai will use this item when low on hp F_AIHEALITEM, // ai will use this item when low on hp
F_AIFLEEITEM, // ai will use this item when fleeing F_AIFLEEITEM, // ai will use this item when fleeing
// if using this on wands, update aiobok() ! // if using this on wands, update aiobok() !
// object _AND_ lifeform flags // object AND lifeform flags
F_NOSTRDAMMOD, // this object/lf does not have attacks modified F_NOSTRDAMMOD, // this object/lf does not have attacks modified
// using their strength // using their strength
F_HARDNESS, // must do >= v0 damage to hurt this
// player only flags // player only flags
F_DONEDARKMSG, // tells the game not to say 'it is very dark here' F_DONEDARKMSG, // tells the game not to say 'it is very dark here'
F_DONELISTEN, // supress further 'you hear xx' messages this turn. F_DONELISTEN, // supress further 'you hear xx' messages this turn.
@ -1740,6 +1770,7 @@ enum FLAG {
// text can be: // text can be:
// x (single number) // x (single number)
// x-y (range) // x-y (range)
F_DONTSTARTASLEEP, // this mosnter never starts off asleep
F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will F_STARTHIDDENPCT, // val0 = pct chance auto-generated monster will
// start off hidden // start off hidden
F_CORPSETYPE, // text field specifies what corpse obtype to leave F_CORPSETYPE, // text field specifies what corpse obtype to leave
@ -1753,9 +1784,18 @@ enum FLAG {
F_VISRANGEMOD, // modifications to visrange F_VISRANGEMOD, // modifications to visrange
F_GUNTARGET, // current projectile weapon target F_GUNTARGET, // current projectile weapon target
F_CASTINGSPELL, // set while the player is casting a spell F_CASTINGSPELL, // set while the player is casting a spell
// v0 is spell id // for instant spells:
// v0 is spell id
// for noninstant spells:
// v0 is spell id
// v1 is spell power
// v2 is counter until casting
// text is: "targlfid;targobid;mapid;cellx;celly;"
F_AVOIDCURSEDOB, // for AI animals - they will avoid walking on obid 'text' F_AVOIDCURSEDOB, // for AI animals - they will avoid walking on obid 'text'
// (text is a long) // (text is a long)
F_STAYINHABITAT, // lf will not walk onto a cell of a different
// habitat
F_FALLDISTANCE, // how many floors this lf has fallen through. F_FALLDISTANCE, // how many floors this lf has fallen through.
// ABILITY/SPELL FLAGS / ability flags / spell flags // ABILITY/SPELL FLAGS / ability flags / spell flags
F_FAILEDINSPECT, // lf has failed an inspect check for item id v0 F_FAILEDINSPECT, // lf has failed an inspect check for item id v0
@ -1787,6 +1827,8 @@ enum FLAG {
// vanish. // vanish.
// v1 is lifetime left. this decrements each turn. // v1 is lifetime left. this decrements each turn.
// when at zero, lf vanishes. // when at zero, lf vanishes.
F_OWNSSHOP, // v0 is roomid of the shop which this shopkeeper owns.
F_GUARD, // this lf is a guard, who can be called by shopkeepers
F_HATESRACE, // lf will attack lfs with race=v0 or baseid=v0 on F_HATESRACE, // lf will attack lfs with race=v0 or baseid=v0 on
// sight // sight
F_HARMLESS, // it is safe to rest around this lf F_HARMLESS, // it is safe to rest around this lf
@ -2012,7 +2054,8 @@ enum FLAG {
// nutrition // nutrition
F_HUNGER, // val0 = hunger, higher = hungrier F_HUNGER, // val0 = hunger, higher = hungrier
// for jobs // for jobs (job flags)
F_NOPLAYER, // players can't pick this job
F_HASPET, // this job starts with a pet of race f->text F_HASPET, // this job starts with a pet of race f->text
F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0. F_IFPCT, // only add the NEXT job flag if rnd(1,100) <= v0.
F_ELSE, F_ELSE,
@ -2048,13 +2091,18 @@ enum FLAG {
F_VAULTGOESIN, // this vault randomly appears in habitat type v0. F_VAULTGOESIN, // this vault randomly appears in habitat type v0.
// can be repeated multiple times // can be repeated multiple times
// if a vault doesnt have this flag, it can go anywhere // if a vault doesnt have this flag, it can go anywhere
F_VAULTISSHOP, // this vault is a shop, so add f_shopitem to objects
// here.
F_VAULTSCATTER, // v0=thingtype, v1=pctchance F_VAULTSCATTER, // v0=thingtype, v1=pctchance
// text=x1,y1,x2,y2,mincount-maxcount,thingname // text=x1,y1,x2,y2,mincount-maxcount,thingname
// if maxcount is PCT, mincount is a percentage // if maxcount is PCT, mincount is a percentage
// of the total space. // of the total space.
F_VAULTMAYROTATE, // may rotate this vault in 90degree increments.
F_VAULTRANDOMMAP, // v0=minwidth, v1=minheight. this vault's map is F_VAULTRANDOMMAP, // v0=minwidth, v1=minheight. this vault's map is
// v0/1 can be NA. // v0/1 can be NA.
// just a normal random room // just a normal random room
F_KEEPMARGIN, // this vault must be at least v0 from e/w of map
// and at least v1 from n/s of map
F_NULL = -1 F_NULL = -1
}; };
@ -2263,6 +2311,11 @@ enum COMMAND {
CMD_WEILD, CMD_WEILD,
}; };
typedef struct coord_s {
int x,y;
} coord_t;
// command types // command types
typedef struct command_s { typedef struct command_s {
enum COMMAND id; enum COMMAND id;
@ -2281,6 +2334,7 @@ enum HABITAT {
H_DUNGEON = 1, H_DUNGEON = 1,
H_FOREST = 2, H_FOREST = 2,
H_PIT = 3, H_PIT = 3,
H_VILLAGE = 4,
H_ALL = 999 H_ALL = 999
}; };
@ -2290,6 +2344,7 @@ typedef struct regiontype_s {
int maxdepth; int maxdepth;
int stairsperlev; int stairsperlev;
int deeperdir; int deeperdir;
int majorbranch;
struct regiontype_s *next, *prev; struct regiontype_s *next, *prev;
} regiontype_t; } regiontype_t;
@ -2328,6 +2383,9 @@ typedef struct region_s {
typedef struct habitat_s { typedef struct habitat_s {
enum HABITAT id; enum HABITAT id;
char *name; char *name;
int randthingpct; // % chance each empty cell has something
int randobpct; // % chance that 'something' is an ob rather than monster
int randvaultpct; // % chance that a room will be a vault
enum CELLTYPE emptycelltype,solidcelltype; enum CELLTYPE emptycelltype,solidcelltype;
struct habitat_s *next, *prev; struct habitat_s *next, *prev;
} habitat_t; } habitat_t;
@ -2380,14 +2438,22 @@ typedef struct vlegend_s {
struct vlegend_s *next, *prev; struct vlegend_s *next, *prev;
} vlegend_t; } vlegend_t;
// in map[0], data is the real data
// in others, data is an index into map[0]
typedef struct vaultmap_s {
int data[MAX_MAPW*MAX_MAPH];
int mlen;
int w,h;
} vaultmap_t;
typedef struct vault_s { typedef struct vault_s {
char *filename; char *filename;
char *id; char *id;
int numid;
int valid; int valid;
int state; int state;
char map[MAX_MAPW*MAX_MAPH]; struct vaultmap_s map[4];
int mlen; int nmaps;
int w,h;
struct vlegend_s *legend, *lastlegend; struct vlegend_s *legend, *lastlegend;
struct vault_s *next, *prev; struct vault_s *next, *prev;
struct flagpile_s *flags; struct flagpile_s *flags;
@ -2402,11 +2468,13 @@ typedef struct cell_s {
map_t *map; // pointer back to map map_t *map; // pointer back to map
int x,y; // map coords int x,y; // map coords
int roomid; int roomid;
vault_t *vault;
struct celltype_s *type; struct celltype_s *type;
struct obpile_s *obpile; struct obpile_s *obpile;
enum LIGHTLEV lit; enum LIGHTLEV lit;
enum LIGHTLEV origlit; // for timed light enum LIGHTLEV origlit; // for timed light
enum LIGHTLEV lastlit; enum LIGHTLEV lastlit;
habitat_t *habitat;
int origlittimer; int origlittimer;
int littimer; int littimer;
@ -2475,6 +2543,7 @@ typedef struct lifeform_s {
int mp,maxmp; int mp,maxmp;
int alive; int alive;
char *lastdam; char *lastdam;
struct material_s *material;
enum DAMTYPE lastdamtype; enum DAMTYPE lastdamtype;
int timespent; int timespent;
@ -2526,6 +2595,9 @@ typedef struct flagpile_s {
lifeform_t *owner; lifeform_t *owner;
struct object_s *ob; struct object_s *ob;
struct flag_s *first,*last; struct flag_s *first,*last;
struct flag_s *item[MAXFLAGS];
int nitems;
} flagpile_t; } flagpile_t;
typedef struct flag_s { typedef struct flag_s {

View File

@ -43,13 +43,15 @@ Flags can be:
- a range (x-y) - a range (x-y)
- a pct of the total region cells (x%) - a pct of the total region cells (x%)
coords can be negative ("count back from right/bottom") coords can be negative ("count back from right/bottom")
pct is optional
autodoors:pct // automatically add at least one door to the edges of autodoors:pct // automatically add at least one door to the edges of
// this room. // this room.
// pct is chance of the exit being a door as opposed // pct is chance of the exit being a door as opposed
// to jsut an opening. // to jsut an opening.
autopop // automatically add obs/mons/pillars to this room autopop // automatically add obs/mons/pillars to this vault as
// if it were a normal room.
dlevmin:xxx // can only randomly appear at or below dungeon dlevmin:xxx // can only randomly appear at or below dungeon
// level xxx (or map difficulty xxx for world map) // level xxx (or map difficulty xxx for world map)
@ -58,6 +60,10 @@ Flags can be:
goesin:xxx // can only randomly appear in habitat xxx goesin:xxx // can only randomly appear in habitat xxx
margin:x,y // must be x/y away from edges of map
mayrotate // vault can be rotated randomly
norandom // this vault doesn't appear randomly. it will only norandom // this vault doesn't appear randomly. it will only
// appear when specifically requested via a region's // appear when specifically requested via a region's
// outline. // outline.

228
flag.c
View File

@ -82,27 +82,65 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
} }
} }
// override values sometimes ////////////////////////////////
/* // ACTUAL FLAG ADDITION IS HERE
if ((id == F_WET) && (val2 == NA)) { ////////////////////////////////
val2 = WETTIME;
}
*/
if (fp->first == NULL) { if (fp->first == NULL) {
fp->first = malloc(sizeof(flag_t)); fp->first = malloc(sizeof(flag_t));
f = fp->first; f = fp->first;
f->prev = NULL; f->prev = NULL;
// also the last
fp->last = f;
f->next = NULL;
} else { } else {
flag_t *ff;
// we will keep flags sorted.
// find correct position in list...
ff = fp->first;
while (ff && (ff->id < id)) {
ff = ff->next;
}
if (ff) {
// start or middle of list
// insert BEFORE this one
flag_t *prev;
prev = ff->prev;
// link to previous element
if (prev) {
prev->next = malloc(sizeof(flag_t));
f = prev->next;
} else {
// first one
fp->first = malloc(sizeof(flag_t));
f = fp->first;
}
f->prev = prev;
// link to next element
f->next = ff;
ff->prev = f;
} else {
// last one. insert at end of list.
f = fp->last;
f->next = malloc(sizeof(flag_t));
f->next->prev = f;
f = f->next;
fp->last = f;
f->next = NULL;
}
/*
// go to end of list // go to end of list
f = fp->last; f = fp->last;
f->next = malloc(sizeof(flag_t)); f->next = malloc(sizeof(flag_t));
f->next->prev = f; f->next->prev = f;
f = f->next; f = f->next;
*/
} }
fp->last = f;
f->next = NULL;
// fill in props // fill in props
f->id = id; f->id = id;
@ -133,6 +171,8 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
f->pile = fp; f->pile = fp;
updatefpindex(fp);
// notify // notify
if ((gamemode == GM_GAMESTARTED)) { if ((gamemode == GM_GAMESTARTED)) {
if (f->pile->owner) { if (f->pile->owner) {
@ -232,6 +272,7 @@ flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) {
fp->last = NULL; fp->last = NULL;
fp->owner = owner; fp->owner = owner;
fp->ob = ob; fp->ob = ob;
fp->nitems = 0;
return fp; return fp;
} }
@ -239,6 +280,8 @@ flagpile_t *addflagpile(lifeform_t *owner, object_t *ob) {
void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) { void copyflag(flagpile_t *dst, flagpile_t *src, enum FLAG id) {
flag_t *f; flag_t *f;
for (f = src->first ; f ; f = f->next) { for (f = src->first ; f ; f = f->next) {
// gone past the requrested id's number - ie. it's not there.
if (f->id > id) break;
if (f->id == id) { if (f->id == id) {
addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text, addflag_real(dst, f->id, f->val[0], f->val[1], f->val[2], f->text,
f->lifetime, f->known, -1); f->lifetime, f->known, -1);
@ -355,11 +398,79 @@ flag_t *hasflagknown(flagpile_t *fp, int id) {
} }
flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) { flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
flag_t *f; flag_t *f,*foundflag = NULL, *searchfrom = NULL;
lifeform_t *owner; lifeform_t *owner;
owner = fp->owner; owner = fp->owner;
int pos;
int l,r;
int iter = 0;
int db = B_FALSE;
if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems);
// binary search for this flag id.
l = 0;
r = fp->nitems-1;
while (!searchfrom) {
if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r);
if (r < l) {
// NOT FOUND.
if (db) dblog(" r < l: not found!");
break;
} else if (fp->item[l]->id > id) {
// NOT FOUND.
if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id);
break;
} else if (fp->item[r]->id < id) {
// NOT FOUND.
if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id);
break;
}
// half way inbetween l and r
pos = ((l+r)/2);
f = fp->item[pos];
if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id);
if (f->id == id) {
// go back to first occurence
while (f->prev && (f->prev->id == id)) {
f = f->prev;
}
searchfrom = f;
break;
} else if (f->id > id) {
// go left
r = pos-1;
} else {
// go right
l = pos+1;
}
}
// now find a valid one
f = searchfrom;
while (f && (f->id == id)) {
int valid = B_TRUE;
if (f == exception) valid = B_FALSE;
if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE;
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) valid = B_FALSE;
if (valid) {
foundflag = f;
break;
} else {
f = f->next;
}
}
if (db) dblog("finished - %s", foundflag ? "found it" : "NOT FOUND");
return foundflag;
/*
for (f = fp->first ; f ; f = f->next) { for (f = fp->first ; f ; f = f->next) {
// gone past the requrested id's number - ie. it's not there.
if (f->id > id) break;
if ((f->id == id) && (f != exception)) { if ((f->id == id) && (f != exception)) {
int valid = B_TRUE; int valid = B_TRUE;
if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE; if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE;
@ -372,6 +483,7 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
} }
} }
} }
*/
return NULL; return NULL;
} }
@ -394,10 +506,82 @@ int getcounter(flagpile_t *fp) {
} }
flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown) { flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, char *text, int wantknown) {
flag_t *f; flag_t *f,*foundflag = NULL, *searchfrom = NULL;
lifeform_t *owner; lifeform_t *owner;
owner = fp->owner; owner = fp->owner;
int pos;
int l,r;
int iter = 0;
int db = B_FALSE;
if (db) dblog("hasflag %d in flagpile with %d entries", id, fp->nitems);
// binary search for this flag id.
l = 0;
r = fp->nitems-1;
while (!searchfrom) {
if (db) dblog(" iter#%d: l=%d,r=%d", iter, l, r);
if (r < l) {
// NOT FOUND.
if (db) dblog(" r < l: not found!");
break;
} else if (fp->item[l]->id > id) {
// NOT FOUND.
if (db) dblog(" leftid %d > wantid %d. not found!",fp->item[l]->id, id);
break;
} else if (fp->item[r]->id < id) {
// NOT FOUND.
if (db) dblog(" rightid %d > wantid %d. not found!",fp->item[r]->id, id);
break;
}
// half way inbetween l and r
pos = ((l+r)/2);
f = fp->item[pos];
if (db) dblog(" iter#%d: pos=%d. item here is %d (looking for %d)", iter, pos, f->id, id);
if (f->id == id) {
// go back to first occurence
while (f->prev && (f->prev->id == id)) {
f = f->prev;
}
searchfrom = f;
break;
} else if (f->id > id) {
// go left
r = pos-1;
} else {
// go right
l = pos+1;
}
}
// now find a valid one
f = searchfrom;
while (f && (f->id == id)) {
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) {
// invalid
} else if ( ((val1 == NA) || (f->val[0] == val1)) &&
((val2 == NA) || (f->val[1] == val2)) &&
((val3 == NA) || (f->val[2] == val3)) &&
((text == NULL) || strstr(f->text, text))) {
if (!wantknown || f->known) {
foundflag = f;
break;
}
}
f = f->next;
}
if (db) dblog("finished - %s", foundflag ? "found it" : "NOT FOUND");
return foundflag;
/*
for (f = fp->first ; f ; f = f->next) { for (f = fp->first ; f ; f = f->next) {
// gone past the requrested id's number - ie. it's not there.
if (f->id > id) break;
if (f->id == id) { if (f->id == id) {
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) { if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) {
// invalid // invalid
@ -414,6 +598,7 @@ flag_t *hasflagval_real(flagpile_t *fp, int id, int val1, int val2, int val3, ch
} }
} }
return NULL; return NULL;
*/
} }
// returns true if we did something // returns true if we did something
@ -422,6 +607,10 @@ int killflagsofid(flagpile_t *fp, enum FLAG fid) {
int donesomething = B_FALSE; int donesomething = B_FALSE;
for (f = fp->first ; f ; f = nextf) { for (f = fp->first ; f ; f = nextf) {
nextf = f->next; nextf = f->next;
// gone past the requrested id's number - ie. it's not there.
if (f->id > fid) break;
if (f->id == fid) { if (f->id == fid) {
killflag(f); killflag(f);
donesomething = B_TRUE; donesomething = B_TRUE;
@ -536,6 +725,8 @@ void killflag(flag_t *f) {
lastone->next = nextone; lastone->next = nextone;
} }
updatefpindex(f->pile);
if (gamemode == GM_GAMESTARTED) { if (gamemode == GM_GAMESTARTED) {
if (redolight) { if (redolight) {
calclight(redolight); calclight(redolight);
@ -752,6 +943,9 @@ void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2) {
if (val1) *val1 = 0; if (val1) *val1 = 0;
if (val2) *val2 = 0; if (val2) *val2 = 0;
for (f = fp->first ; f ; f = f->next) { for (f = fp->first ; f ; f = f->next) {
// gone past the requrested id's number - ie. it's not there.
if (f->id > id) break;
if (f->id == id) { if (f->id == id) {
if (val0) *val0 = *val0 + f->val[0]; if (val0) *val0 = *val0 + f->val[0];
if (val1) *val1 = *val1 + f->val[1]; if (val1) *val1 = *val1 + f->val[1];
@ -766,5 +960,15 @@ void timeeffectsflags(flagpile_t *fp) {
nextf = f->next; nextf = f->next;
timeeffectsflag(f, 1); timeeffectsflag(f, 1);
} }
}
// generate an index
void updatefpindex(flagpile_t *fp) {
flag_t *f;
fp->nitems = 0;
for (f = fp->first ;f ; f = f->next) {
fp->item[fp->nitems] = f;
fp->nitems++;
}
} }

1
flag.h
View File

@ -27,3 +27,4 @@ int modcounter(flagpile_t *fp, int amt);
void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2); void sumflags(flagpile_t *fp, int id, int *val0, int *val1, int *val2);
void timeeffectsflag(flag_t *f, int howlong); void timeeffectsflag(flag_t *f, int howlong);
void timeeffectsflags(flagpile_t *fp); void timeeffectsflags(flagpile_t *fp);
void updatefpindex(flagpile_t *fp);

122
io.c
View File

@ -85,6 +85,7 @@ void addchoice(prompt_t *p, char ch, char *text, char *desc, void *data) {
} }
p->choice[p->nchoices].data = data; p->choice[p->nchoices].data = data;
p->choice[p->nchoices].heading = B_FALSE; p->choice[p->nchoices].heading = B_FALSE;
p->choice[p->nchoices].valid = B_TRUE;
p->nchoices++; p->nchoices++;
} }
@ -648,10 +649,20 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
// prevent showing 'prone' AND 'asleep' // prevent showing 'prone' AND 'asleep'
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "prone"); strcat(extrainfo, "prone");
} } else if (isairborne(c->lf)) {
if (isswimming(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "swimming"); if (lfhasflag(c->lf, F_FLYING)) {
strcat(extrainfo, "flying");
} else if (lfhasflag(c->lf, F_LEVITATING)) {
strcat(extrainfo, "levitating");
} else {
strcat(extrainfo, "airbourne");
}
} else {
if (isswimming(c->lf)) {
if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, "swimming");
}
} }
f = lfhasflag(c->lf, F_ATTACHEDTO); f = lfhasflag(c->lf, F_ATTACHEDTO);
@ -3037,11 +3048,29 @@ void describeob(object_t *o) {
} }
mvwprintw(mainwin, y, 0, "%s",buf); mvwprintw(mainwin, y, 0, "%s",buf);
y++; y++;
f = hasflag(o->flags, F_EVASION);
if (f) {
int evmod;
evmod = adjustarmourpenalty(player, f->val[0]);
if (evmod != 0) {
sprintf(buf, " When worn, it %s your evasion chance by %d%%.", (evmod < 0) ? "reduces" : "increases", abs(evmod));
}
}
f = hasflag(o->flags, F_SCARY); f = hasflag(o->flags, F_SCARY);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, " It may unnerve others when worn."); mvwprintw(mainwin, y, 0, " It may unnerve others when worn.");
y++; y++;
} }
} else {
// non armour, but still wearable.
f = hasflag(o->flags, F_GOESON);
if (f) {
sprintf(buf, "It is worn %s your %s. ",getbodypartequipname(f->val[0]), getbodypartname(f->val[0]));
}
} }
if (o->type->obclass->id == OC_WAND) { if (o->type->obclass->id == OC_WAND) {
@ -3538,6 +3567,13 @@ void describespell(objecttype_t *ot) {
} }
} }
f = hasflag(ot->flags, F_CASTINGTIME);
if (f) {
wprintw(mainwin, "It takes %d turns to cast.\n",f->val[0]);
} else {
wprintw(mainwin, "It takes effect instantly.\n");
}
wprintw(mainwin, "\n"); wprintw(mainwin, "\n");
if (ot->obclass->id == OC_SPELL) { if (ot->obclass->id == OC_SPELL) {
@ -3645,6 +3681,7 @@ void docomms(lifeform_t *lf) {
char buf[BUFLEN]; char buf[BUFLEN];
char lfname[BUFLEN]; char lfname[BUFLEN];
char ch; char ch;
int moneyowing = 0;
enum IQBRACKET iqb; enum IQBRACKET iqb;
flag_t *f; flag_t *f;
@ -3691,9 +3728,19 @@ void docomms(lifeform_t *lf) {
addchoice(&prompt, 'r', "Rest until you are healed.", NULL, NULL); addchoice(&prompt, 'r', "Rest until you are healed.", NULL, NULL);
} }
} }
} else {
addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL);
} }
f = lfhasflag(lf, F_OWNSSHOP);
if (f) {
int shopid;
shopid = f->val[0];
moneyowing = getowing(player, shopid, NULL);
if (moneyowing > 0) {
sprintf(buf, "(pay $%d to the shopkeeper)",moneyowing);
addchoice(&prompt, 'p', buf, NULL, NULL);
}
}
addchoice(&prompt, 'y', "Yeeeeeaaaargh!", NULL, NULL);
addchoice(&prompt, 'n', "(nothing)", NULL, NULL); addchoice(&prompt, 'n', "(nothing)", NULL, NULL);
ch = getchoice(&prompt); ch = getchoice(&prompt);
@ -3749,6 +3796,25 @@ void docomms(lifeform_t *lf) {
case 'n': case 'n':
msg("Cancelled."); msg("Cancelled.");
return; return;
case 'p':
// can we afford this?
if (givemoney(player, lf, moneyowing)) {
// can't afford it
msg("You can't afford to pay $%d.", moneyowing);
} else {
object_t *o;
// mark all items as paid for
for (o = player->pack->first ; o ; o = o->next) {
f = hasflag(o->flags, F_SHOPITEM);
if (f) {
killflag(f);
getobname(o, buf, o->amt);
msg("You buy %s.", buf);
}
}
say(lf, "Pleasure doing business with you!", SV_TALK);
}
break;
case 'r': case 'r':
f = isresting(lf); f = isresting(lf);
if (f) { if (f) {
@ -3980,7 +4046,7 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) {
// remember letter // remember letter
o->letter = ch; o->letter = ch;
// make object fully known // make object fully known
addflag(o->flags, F_SHOPITEM, B_TRUE, NA, NA, NULL); addflag(o->flags, F_VENDITEM, B_TRUE, NA, NA, NULL);
} }
} }
@ -4061,7 +4127,8 @@ void dovendingmachine(lifeform_t *lf, object_t *vm) {
sprintf(buf, "Buy %s for $%d?",obname, getobvalue(o)); sprintf(buf, "Buy %s for $%d?",obname, getobvalue(o));
answer = askchar(buf, "yn","n", B_TRUE); answer = askchar(buf, "yn","n", B_TRUE);
if (answer == 'y') { if (answer == 'y') {
gold->amt -= getobvalue(o); givemoney(player, NULL, getobvalue(o));
//gold->amt -= getobvalue(o);
// clear o->letter // clear o->letter
o->letter = '\0'; o->letter = '\0';
// give object // give object
@ -6433,16 +6500,32 @@ void drawstatus(void) {
if (lfhasflag(player, F_RAGE)) { if (lfhasflag(player, F_RAGE)) {
setcol(statwin, C_RED); setcol(statwin, C_RED);
wprintw(statwin, " Enraged"); wprintw(statwin, " Rage");
unsetcol(statwin, C_RED); unsetcol(statwin, C_RED);
} }
if (isswimming(player)) { if (isswimming(player)) {
setcol(statwin, C_BOLDBLUE); setcol(statwin, C_BOLDBLUE);
wprintw(statwin, " Swimming"); wprintw(statwin, " Swim");
unsetcol(statwin, C_BOLDBLUE); unsetcol(statwin, C_BOLDBLUE);
} }
if (isairborne(player)) {
if (lfhasflag(player, F_FLYING)) {
setcol(statwin, C_BOLDBLUE);
wprintw(statwin, " Fly");
unsetcol(statwin, C_BOLDBLUE);
} else if (lfhasflag(player, F_LEVITATING)) {
setcol(statwin, C_BOLDBLUE);
wprintw(statwin, " Lev");
unsetcol(statwin, C_BOLDBLUE);
} else {
setcol(statwin, C_BOLDBLUE);
wprintw(statwin, " Flt"); // "float"ing
unsetcol(statwin, C_BOLDBLUE);
}
}
// paralysed somehow? // paralysed somehow?
if (isresting(player)) { if (isresting(player)) {
setcol(statwin, C_CYAN); setcol(statwin, C_CYAN);
@ -6452,6 +6535,10 @@ void drawstatus(void) {
setcol(statwin, C_BLUE); setcol(statwin, C_BLUE);
wprintw(statwin, " Asleep"); wprintw(statwin, " Asleep");
unsetcol(statwin, C_BLUE); unsetcol(statwin, C_BLUE);
} else if (isprone(player)) {
setcol(statwin, C_YELLOW);
wprintw(statwin, " Prone");
unsetcol(statwin, C_YELLOW);
} else if (isimmobile(player)) { } else if (isimmobile(player)) {
setcol(statwin, C_RED); setcol(statwin, C_RED);
wprintw(statwin, " Immobile"); wprintw(statwin, " Immobile");
@ -6506,11 +6593,6 @@ void drawstatus(void) {
} }
} }
if (isprone(player) && !lfhasflag(player, F_ASLEEP)) {
setcol(statwin, C_YELLOW);
wprintw(statwin, " Prone");
unsetcol(statwin, C_YELLOW);
}
// burdened somehow? // burdened somehow?
switch (isburdened(player)) { switch (isburdened(player)) {
@ -6781,6 +6863,12 @@ void setobcolour(WINDOW *win, object_t *o, int set) {
} }
if (!o) return; if (!o) return;
// unpaid?
if (hasflag(o->flags, F_SHOPITEM)) {
funcptr(win, C_ORANGE);
return;
}
if (o->blessknown) { if (o->blessknown) {
if (iscursed(o)) { if (iscursed(o)) {
funcptr(win, C_RED); funcptr(win, C_RED);
@ -7647,8 +7735,10 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
// diff materials? // diff materials?
if (lf->race->material->id != MT_FLESH) { if (getlfmaterial(lf) != MT_FLESH) {
mvwprintw(mainwin, y, 0, "%s %s made out of %s.",you(lf), is(lf), lf->race->material->name); material_t *mt;
mt = findmaterial(getlfmaterial(lf));
mvwprintw(mainwin, y, 0, "%s %s made out of %s.",you(lf), is(lf), mt->name);
y++; y++;
} }

458
lf.c
View File

@ -414,6 +414,19 @@ int calcxprace(enum RACE rid) {
return xpval; return xpval;
} }
void callguards(lifeform_t *caller, lifeform_t *victim) {
lifeform_t *l;
for (l = caller->cell->map->lf ; l ; l = l->next) {
if (!isplayer(l) && (l != caller) && (l != victim) && lfhasflag(l, F_GUARD)) {
aiattack(l, victim, PERMENANT);
if (isplayer(victim)) {
addflag(l->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
}
}
}
}
int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) { int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
int castable = B_FALSE; int castable = B_FALSE;
flag_t *f; flag_t *f;
@ -686,34 +699,36 @@ int canpickup(lifeform_t *lf, object_t *o, int amt) {
reason = E_TOOBIG; reason = E_TOOBIG;
return B_FALSE; return B_FALSE;
} }
if (lfhasflag(lf, F_NOPACK)) { if (lf) {
reason = E_NOPACK; if (lfhasflag(lf, F_NOPACK)) {
return B_FALSE; reason = E_NOPACK;
} return B_FALSE;
if (lfhasflag(lf, F_GRAVBOOSTED)) { }
reason = E_GRAVBOOSTED; if (lfhasflag(lf, F_GRAVBOOSTED)) {
return B_FALSE; reason = E_GRAVBOOSTED;
} return B_FALSE;
if ((getlfmaterial(lf) == MT_GAS) || lfhasflag(lf, F_NONCORPOREAL)) { }
reason = E_INSUBSTANTIAL; if ((getlfmaterial(lf) == MT_GAS) || lfhasflag(lf, F_NONCORPOREAL)) {
return B_FALSE; reason = E_INSUBSTANTIAL;
} return B_FALSE;
}
// too heavy to lift? // too heavy to lift?
//max = getlfweight(lf, B_NOOBS) * 2; // twice your body weight //max = getlfweight(lf, B_NOOBS) * 2; // twice your body weight
if (getobunitweight(o) + getobpileweight(lf->pack) > (getmaxcarryweight(lf)*2)) { if (getobunitweight(o) + getobpileweight(lf->pack) > (getmaxcarryweight(lf)*2)) {
reason = E_TOOHEAVY; reason = E_TOOHEAVY;
return B_FALSE; return B_FALSE;
} }
// space in pack? // space in pack?
if (countobs(lf->pack, B_FALSE) >= MAXPILEOBS) { if (countobs(lf->pack, B_FALSE) >= MAXPILEOBS) {
reason = E_NOSPACE; reason = E_NOSPACE;
return B_FALSE; return B_FALSE;
} }
if (getnextletter(lf->pack, NULL) == '\0') { if (getnextletter(lf->pack, NULL) == '\0') {
reason = E_NOSPACE; reason = E_NOSPACE;
return B_FALSE; return B_FALSE;
}
} }
return B_TRUE; return B_TRUE;
} }
@ -1126,7 +1141,10 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
msg("%s %s.", lfname, f->text); msg("%s %s.", lfname, f->text);
} }
} else { } else {
msg("%s casts a spell.", lfname); if (hasflag(sp->flags, F_CASTINGTIME)) {
} else {
msg("%s starts casting a spell.", lfname);
}
} }
} }
@ -1145,12 +1163,55 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
limit(&power, NA, 10); limit(&power, NA, 10);
} }
// stop hiding
killflagsofid(lf->flags, F_HIDING);
// cast the spell // cast the spell
addflag(lf->flags, F_CASTINGSPELL, sid, NA, NA, NULL); f = hasflag(sp->flags, F_CASTINGTIME);
rv = dospelleffects(lf, sid, power, targlf, targob, targcell, B_UNCURSED, NULL, B_FALSE);
f = lfhasflag(lf, F_CASTINGSPELL);
if (f) { if (f) {
killflag(f); int castingtime;
char tempbuf[BUFLEN];
char castingbuf[BUFLEN];
flag_t *castingflag;
castingtime = f->val[0];
strcpy(castingbuf, "");
if (targlf) {
sprintf(tempbuf, "%d;",targlf->id);
} else {
strcpy(tempbuf, "-1;");
}
strcat(castingbuf, tempbuf);
if (targob) {
sprintf(tempbuf, "%ld;",targob->id);
} else {
strcpy(tempbuf, "-1;");
}
strcat(castingbuf, tempbuf);
if (targcell) {
sprintf(tempbuf, "%d;%d;%d;",targcell->map->id,targcell->x, targcell->y);
} else {
strcpy(tempbuf, "-1;-1;-1;");
}
strcat(castingbuf, tempbuf);
castingflag = addflag(lf->flags, F_CASTINGSPELL, sid, power, castingtime, castingbuf);
rv = B_FALSE;
if (isplayer(lf)) {
// announce
msg("You start casting %s.", sp->name);
}
} else { // instant cast
addflag(lf->flags, F_CASTINGSPELL, sid, NA, NA, NULL);
rv = dospelleffects(lf, sid, power, targlf, targob, targcell, B_UNCURSED, NULL, B_FALSE);
f = lfhasflag(lf, F_CASTINGSPELL);
if (f) {
killflag(f);
}
} }
// willing this spell? reset counter! // willing this spell? reset counter!
@ -1160,9 +1221,6 @@ int castspell(lifeform_t *lf, enum OBTYPE sid, lifeform_t *targlf, object_t *tar
} }
} }
// stop hiding
killflagsofid(lf->flags, F_HIDING);
// successful cast? // successful cast?
if (!rv) { if (!rv) {
practice(lf, SK_SPELLCASTING, 1); practice(lf, SK_SPELLCASTING, 1);
@ -1209,6 +1267,8 @@ int checkfordrowning(lifeform_t *lf, object_t *o) {
// in around 3-4 turns. // in around 3-4 turns.
damamt = lf->maxhp / (getattr(lf, A_CON) / 3); damamt = lf->maxhp / (getattr(lf, A_CON) / 3);
limit(&damamt, 1, NA);
if (damamt >= lf->hp) { if (damamt >= lf->hp) {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You drown."); msg("You drown.");
@ -1410,7 +1470,7 @@ int demandbribe(lifeform_t *lf) {
amtwanted = rnd(hd*25, hd*100); amtwanted = rnd(hd*25, hd*100);
getlfname(lf, lfname); getlfname(lf, lfname);
if (say(lf, "Hand over all your gold!", 2)) { if (say(lf, "Hand over all your gold!", SV_TALK)) {
heard = B_TRUE; heard = B_TRUE;
} else { } else {
heard = B_FALSE; heard = B_FALSE;
@ -1451,15 +1511,15 @@ int demandbribe(lifeform_t *lf) {
if ((amtgiven == totmoney) || (amtgiven >= amtwanted)) { if ((amtgiven == totmoney) || (amtgiven >= amtwanted)) {
// always succeed // always succeed
say(lf, "Pleasure doing business with you!", 2); say(lf, "Pleasure doing business with you!", SV_TALK);
satisfied = B_TRUE; satisfied = B_TRUE;
} else { } else {
say(lf, "Then die!", 3); say(lf, "Then die!", SV_SHOUT);
satisfied = B_FALSE; satisfied = B_FALSE;
} }
} else { } else {
// TODO: luck check to receive money ? // TODO: luck check to receive money ?
say(lf, "Then die!", 3); say(lf, "Then die!", SV_SHOUT);
satisfied = B_FALSE; satisfied = B_FALSE;
} }
@ -1832,7 +1892,7 @@ int digcell(lifeform_t *lf, cell_t *c, object_t *o) {
if (c->type->solid) { if (c->type->solid) {
if (isdiggable(c)) { if (isdiggable(c)) {
// replace wall // replace wall
setcelltype(c, c->map->habitat->id); setcelltype(c, c->map->habitat->emptycelltype);
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You dig through the wall."); msg("You dig through the wall.");
needredraw = B_TRUE; needredraw = B_TRUE;
@ -2773,13 +2833,25 @@ race_t *findrace(enum RACE id) {
} }
race_t *findracebyname(char *name) { race_t *findracebyname(char *name) {
race_t *r; race_t *r;
raceclass_t *rc;
// first check for exact matches // first check for exact matches
for (r = firstrace; r ; r = r->next) { for (r = firstrace; r ; r = r->next) {
if (!strcmp(r->name, name)) { if (!strcmp(r->name, name)) {
return r; return r;
} }
} }
// ...then partial matches
// now check raceclasses
for (rc = firstraceclass; rc ; rc = rc->next) {
// using strstarts rather than streq in case there is a job suffix
if (strstarts(name, rc->name)) {
// return a random race from this class
return getreallyrandomrace(rc->id);
}
}
// ...then partial matches in names
for (r = firstrace; r ; r = r->next) { for (r = firstrace; r ; r = r->next) {
if (strstr(r->name, name)) { if (strstr(r->name, name)) {
return r; return r;
@ -2800,6 +2872,15 @@ raceclass_t *findraceclass(enum RACECLASS id) {
return NULL; return NULL;
} }
lifeform_t *findshopkeeper(map_t *m, int roomid) {
lifeform_t *lf;
for (lf = m->lf ; lf ; lf = lf->next) {
if (lfhasflagval(lf, F_OWNSSHOP, roomid, NA, NA, NULL)) {
return lf;
}
}
return NULL;
}
skill_t *findskill(enum SKILL id) { skill_t *findskill(enum SKILL id) {
skill_t *r; skill_t *r;
@ -4180,6 +4261,25 @@ object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp) {
return getequippedob(lf->pack, bp); return getequippedob(lf->pack, bp);
} }
int getowing(lifeform_t *buyer, int shopid, int *retnitems) {
object_t *o;
flag_t *f;
int totcost = 0;
int nitems = 0;
for (o = buyer->pack->first ; o ; o = o->next) {
f = hasflagval(o->flags, F_SHOPITEM, NA, shopid, NA, NULL);
if (f) {
totcost += f->val[0];
nitems++;
}
}
if (retnitems) {
*retnitems = nitems;
}
return totcost;
}
// return the healthiest possible hurt condition that 'lf' will // return the healthiest possible hurt condition that 'lf' will
// recognise when looking at someone else. // recognise when looking at someone else.
// //
@ -4250,7 +4350,7 @@ enum MATERIAL getlfmaterial(lifeform_t *lf) {
} }
} }
return lf->race->material->id; return lf->material->id;
} }
enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid) { enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid) {
@ -4957,7 +5057,6 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
if (db) dblog("finding random lf with rarity val %d-%d and rr <= %d\n",raritymin,raritymax, wantrr); if (db) dblog("finding random lf with rarity val %d-%d and rr <= %d\n",raritymin,raritymax, wantrr);
// try to find a lf of this type which will // try to find a lf of this type which will
// fit in the map's habitat // fit in the map's habitat
nposs = 0; nposs = 0;
@ -4970,7 +5069,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL); rarflag = hasflagval(r->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) { if (!rarflag) {
if (c) { if (c) {
rarflag = hasflagval(r->flags, F_RARITY, c->map->habitat->id, NA, NA, NULL); rarflag = hasflagval(r->flags, F_RARITY, c->habitat->id, NA, NA, NULL);
} else { } else {
rarflag = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL); rarflag = hasflagval(r->flags, F_RARITY, NA, NA, NA, NULL);
} }
@ -5032,8 +5131,7 @@ race_t *getrandomrace(cell_t *c, int forcedepth) {
return r; return r;
} }
race_t *getreallyrandomrace(enum RACECLASS wantrc) {
race_t *getreallyrandomrace(void) {
race_t **poss; race_t **poss;
race_t *r; race_t *r;
int nposs = 0; int nposs = 0;
@ -5042,16 +5140,22 @@ race_t *getreallyrandomrace(void) {
// count races // count races
for (r = firstrace ; r ; r = r->next) { for (r = firstrace ; r ; r = r->next) {
count++; if ((wantrc == RC_ANY) || (r->raceclass->id == wantrc)) {
if (appearsrandomly(r->id)) {
count++;
}
}
} }
poss = malloc(count * sizeof(race_t *)); poss = malloc(count * sizeof(race_t *));
for (r = firstrace ; r ; r = r->next) { for (r = firstrace ; r ; r = r->next) {
if (appearsrandomly(r->id)) { if ((wantrc == RC_ANY) || (r->raceclass->id == wantrc)) {
poss[nposs] = r; if (appearsrandomly(r->id)) {
nposs++; poss[nposs] = r;
nposs++;
}
} }
} }
sel = rnd(0,nposs-1); sel = rnd(0,nposs-1);
@ -5566,9 +5670,52 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
if ((gamemode != GM_GAMESTARTED)) { if ((gamemode != GM_GAMESTARTED)) {
autoweild(lf); autoweild(lf);
} }
// special cases
if (j->id == J_PIRATE) {
flag_t *f;
f = lfhasflagval(lf, F_HASATTACK, OT_FISTS, NA, NA, NULL);
if (f) {
f->val[0] = OT_HOOKHAND;
sprintf(f->text, "1d4");
}
} else if (j->id == J_SHOPKEEPER) {
// shopkeepers are not hostile.
killflagsofid(lf->flags, F_HOSTILE);
killflagsofid(lf->flags, F_HATESRACE);
// mark its home shop
assert(isroom(lf->cell));
addflag(lf->flags, F_OWNSSHOP, lf->cell->roomid, NA, NA, NULL);
}
} }
int givemoney(lifeform_t *from, lifeform_t *to, int amt) {
object_t *gold;
gold = hasob(from->pack, OT_GOLD);
if (!gold) {
return B_TRUE;
}
if (gold->amt < amt) {
return B_TRUE;
}
// lose it
removeob(gold, amt);
// give it to other person
if (to) {
object_t *togold;
togold = hasob(to->pack, OT_GOLD);
if (!togold) {
togold = addob(to->pack, "gold coin");
amt--;
}
togold += amt;
}
return B_FALSE;
}
void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype) { void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype) {
int flagsknown = 0, flagsfound = 0; int flagsknown = 0, flagsfound = 0;
flag_t *f,*newflag; flag_t *f,*newflag;
@ -6058,6 +6205,13 @@ void givestartskills(lifeform_t *lf, flagpile_t *fp) {
killflagsofid(fp, F_STARTSKILL); killflagsofid(fp, F_STARTSKILL);
} }
int hasfreeaction(lifeform_t *lf) {
if (isimmobile(lf)) return B_FALSE;
if (lfhasflag(lf, F_ASLEEP)) return B_FALSE;
if (lfhasflag(lf, F_CASTINGSPELL)) return B_FALSE;
if (lfhasflag(lf, F_EATING)) return B_FALSE;
return B_TRUE;
}
job_t *hasjob(lifeform_t *lf, enum JOB job) { job_t *hasjob(lifeform_t *lf, enum JOB job) {
job_t *j = NULL; job_t *j = NULL;
@ -6673,6 +6827,7 @@ int haslos(lifeform_t *viewer, cell_t *dest) {
void initjobs(void) { void initjobs(void) {
int i; int i;
// job definitions // job definitions
// NOTE: try to always make the job's weapon be the first object defined. // NOTE: try to always make the job's weapon be the first object defined.
// this will make sure that they have the letter 'a'. // this will make sure that they have the letter 'a'.
addjob(J_GOD, "Diety"); addjob(J_GOD, "Diety");
@ -6708,6 +6863,7 @@ void initjobs(void) {
mayusespellschool(lastjob->flags, i, F_CANWILL); mayusespellschool(lastjob->flags, i, F_CANWILL);
} else { } else {
mayusespellschool(lastjob->flags, i, F_CANCAST); mayusespellschool(lastjob->flags, i, F_CANCAST);
//mayusespellschool(lastjob->flags, i, F_CANWILL);
} }
} }
@ -7056,6 +7212,13 @@ void initjobs(void) {
addflag(lastjob->flags, F_IFPCT, 20, NA, NA, NULL); addflag(lastjob->flags, F_IFPCT, 20, NA, NA, NULL);
addflag(lastjob->flags, F_CANCAST, OT_S_HEALING, NA, NA, NULL); addflag(lastjob->flags, F_CANCAST, OT_S_HEALING, NA, NA, NULL);
addflag(lastjob->flags, F_ENDIFMONSTER, NA, NA, NA, NULL); addflag(lastjob->flags, F_ENDIFMONSTER, NA, NA, NA, NULL);
// non-player jobs
addjob(J_SHOPKEEPER, "Shopkeeper");
addflag(lastjob->flags, F_NOPLAYER, B_TRUE, IQ_AVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTATT, A_IQ, IQ_AVERAGE, NA, NULL);
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "100-1000 gold coins");
addflag(lastjob->flags, F_WANTS, OT_GOLD, NA, NA, NULL);
} }
void initrace(void) { void initrace(void) {
@ -7152,6 +7315,30 @@ void initrace(void) {
addflag(lastrace->flags, F_NOJOBTEXT, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOJOBTEXT, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTJOB, 15, J_WIZARD, NA, NULL); addflag(lastrace->flags, F_STARTJOB, 15, J_WIZARD, NA, NULL);
addflag(lastrace->flags, F_STARTJOB, 50, J_ROGUE, NA, NULL); addflag(lastrace->flags, F_STARTJOB, 50, J_ROGUE, NA, NULL);
addrace(R_TOWNGUARD, "town guard", 100, '@', C_GREY, MT_FLESH, RC_HUMANOID);
addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_DOPEY, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_STR, NA, NA, "12-18");
addflag(lastrace->flags, F_DONTSTARTASLEEP, NA, NA, NA, NULL);
addflag(lastrace->flags, F_STAYINHABITAT, NA, NA, NA, NULL);
addflag(lastrace->flags, F_GUARD, NA, NA, NA, NULL);
addflag(lastrace->flags, F_RARITY, H_VILLAGE, 80, NA, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, 4, 4, NA, NULL);
addflag(lastrace->flags, F_NUMAPPEAR, 1, 3, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, NA, NA, "1d2");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "good weapon");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "scale armour");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "good armour");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "good armour");
addflag(lastrace->flags, F_STARTOB, 100, NA, NA, "good armour");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "bow");
addflag(lastrace->flags, F_STARTOB, 50, NA, NA, "1-10 arrows");
addflag(lastrace->flags, F_WANTSBETTERWEP, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_WANTSBETTERARM, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL);
// monsters // monsters
addrace(R_BEHOLDER, "beholder", 5, 'e', C_MAGENTA, MT_FLESH, RC_MAGIC); addrace(R_BEHOLDER, "beholder", 5, 'e', C_MAGENTA, MT_FLESH, RC_MAGIC);
@ -9864,12 +10051,14 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) {
a->mp = 0; a->mp = 0;
a->maxmp = a->mp; a->maxmp = a->mp;
a->material = findmaterial(MT_FLESH); // might be overridden in setrace
// init flags // init flags
a->flags = addflagpile(a, NULL); a->flags = addflagpile(a, NULL);
//addflag(a->flags, F_DEBUG, B_TRUE, NA, NA, NULL); // ooooooooooo //addflag(a->flags, F_DEBUG, B_TRUE, NA, NA, NULL); // ooooooooooo
// set race - this will inherit race flags // set race - this will inherit race flags and material
a->race = NULL; a->race = NULL;
setrace(a, rid, B_FALSE); setrace(a, rid, B_FALSE);
@ -10127,8 +10316,9 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) {
} }
// adjust for lifeform material // don't adjust for lifeform material - we inherit all the material's flags.
//adjustdammaterial(amt, damtype, getlfmaterial(lf)); //adjustdammaterial((unsigned int *)amt, damtype, getlfmaterial(lf));
adjustdamhardness((unsigned int *)amt, damtype, getlfmaterial(lf));
if (isdrunk(lf)) { if (isdrunk(lf)) {
*amt -= rnd(0,3); *amt -= rnd(0,3);
@ -10331,6 +10521,29 @@ int areallies(lifeform_t *lf1, lifeform_t *lf2) {
return B_FALSE; return B_FALSE;
} }
int askforpayment(lifeform_t *shk, lifeform_t *lf) {
char saybuf[BUFLEN];
int totcost = 0;
int nitems,shopid;
flag_t *f;
f = lfhasflag(shk, F_OWNSSHOP);
if (f) {
shopid = f->val[0];
} else {
return B_TRUE;
}
totcost = getowing(lf, shopid, &nitems);
if (nitems == 1) {
sprintf(saybuf, "That will cost you $%d.", totcost);
} else {
sprintf(saybuf, "That brings your bill to $%d.", totcost);
}
say(shk, saybuf, SV_TALK);
return B_FALSE;
}
// make sure player has at least novice skill in all their start weapons/armour // make sure player has at least novice skill in all their start weapons/armour
void autoskill(lifeform_t *lf) { void autoskill(lifeform_t *lf) {
skill_t *sk; skill_t *sk;
@ -10569,6 +10782,9 @@ void loseconcentration(lifeform_t *lf) {
// stop sprinting // stop sprinting
stopsprinting(lf); stopsprinting(lf);
// stop casting spells
killflagsofid(lf->flags, F_CASTINGSPELL);
// boost spells end // boost spells end
stopallspells(lf); stopallspells(lf);
@ -12008,7 +12224,7 @@ int say(lifeform_t *lf, char *text, int volume) {
} else if (volume == 4) { } else if (volume == 4) {
strcpy(verb, "roars"); strcpy(verb, "roars");
strcpy(noun, "roaring voices!"); strcpy(noun, "roaring voices!");
} else if (volume > 4) { } else { // ie > 4
strcpy(verb, "bellows"); strcpy(verb, "bellows");
strcpy(noun, "bellowing voices!"); strcpy(noun, "bellowing voices!");
} }
@ -12248,6 +12464,9 @@ void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph) {
// set race // set race
lf->race = newrace; lf->race = newrace;
// set material
lf->material = lf->race->material;
// inherit flags from race // inherit flags from race
copyflags(lf->flags, lf->race->flags, FROMRACE); copyflags(lf->flags, lf->race->flags, FROMRACE);
// don't want certain race only flags... // don't want certain race only flags...
@ -12440,6 +12659,33 @@ void setlftarget(lifeform_t *lf, lifeform_t *victim) {
} }
*/ */
int setlfmaterial(lifeform_t *lf, enum MATERIAL id) {
if (getlfmaterial(lf) == id) {
return B_TRUE;
}
if (hasactivespell(lf, OT_S_BARKSKIN) && (id != MT_WOOD)) {
stopspell(lf, OT_S_BARKSKIN);
}
lf->material = findmaterial(id);
// announce
if (gamemode == GM_GAMESTARTED) {
if (isplayer(lf)) {
msg("Your body %s to %s%c", (id == lf->race->material->id) ? "reverts" : "turns", lf->material->name,
(id == lf->race->material->id) ? '.' : '!' );
} else if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s%s body %s to %s%c", lfname, getpossessive(lfname),
(id == lf->race->material->id) ? "reverts" : "turns",
lf->material->name,
(id == lf->race->material->id) ? '.' : '!' );
}
}
return B_FALSE;
}
int shoot(lifeform_t *lf) { int shoot(lifeform_t *lf) {
object_t *gun,*ammo; object_t *gun,*ammo;
lifeform_t *targ; lifeform_t *targ;
@ -12556,6 +12802,9 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
case SC_SEARCH: case SC_SEARCH:
attrib = (getskill(lf, SK_SPOTHIDDEN)*4); attrib = (getskill(lf, SK_SPOTHIDDEN)*4);
break; break;
case SC_STEAL:
attrib = (getskill(lf, SK_THIEVERY));
break;
case SC_STEALTH: case SC_STEALTH:
attrib = (getskill(lf, SK_STEALTH)*4); attrib = (getskill(lf, SK_STEALTH)*4);
break; break;
@ -12617,6 +12866,11 @@ int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *r
int bonus = 0; int bonus = 0;
sumflags(lf->flags, F_ENHANCESEARCH, &bonus, NULL, NULL); sumflags(lf->flags, F_ENHANCESEARCH, &bonus, NULL, NULL);
othermod += bonus; othermod += bonus;
} else if (ct == SC_STEAL) {
if (attrib > 0) {
// ie. -3 to 3
othermod += (getstatmod(lf, A_DEX) / 15);
}
} else if (ct == SC_STEALTH) { } else if (ct == SC_STEALTH) {
if (attrib > 0) { if (attrib > 0) {
if (lfhasflag(lf, F_SNEAK)) { if (lfhasflag(lf, F_SNEAK)) {
@ -12828,6 +13082,102 @@ void sortlf(map_t *map, lifeform_t *lf) {
} }
} }
// returns TRUE on failure (ie. nothing to steal)
int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag) {
enum SKILLLEVEL slev;
object_t *o;
int i,nsteals;
int numgot = 0;
int fromground;
char letter = 'a';
slev = getskill(lf, SK_THIEVERY);
if (op->owner) {
fromground = B_FALSE;
} else {
fromground = B_TRUE;
}
//
if (slev >= PR_EXPERT) {
nsteals = 2;
} else {
nsteals = 1;
}
// what do we steal?
for (i = 0; i < nsteals; i++) {
char buf[BUFLEN];
sprintf(buf, "Steal what (%d of %d)?", i+1, nsteals);
initprompt(&prompt, buf);
addchoice(&prompt, '-', "Nothing", NULL, NULL);
for (o = op->first ; o ; o = o->next) {
int ok = B_TRUE;
if ((slev < PR_SKILLED) && (getobunitweight(o) >= 3)) {
// too heavy to steal
ok = B_FALSE;
} else if ((slev < PR_MASTER) && isequipped(o)) {
// equipped
ok = B_FALSE;
} else if (!canpickup(lf, o, 1)) {
// can't pick it up
ok = B_FALSE;
} else if ((wantflag != F_NONE) && !hasflag(o->flags, wantflag)) {
// don't have the right flag
ok = B_FALSE;
}
if (ok) {
getobname(o, buf, 1);
addchoice(&prompt, fromground ? letter++ : o->letter, buf, NULL, o);
}
}
if (prompt.nchoices > 1) {
if (slev >= PR_ADEPT) {
// pick what you want
getchoice(&prompt);
o = (object_t *)prompt.result;
} else {
// random
o = (object_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data;
}
if (o) {
killflagsofid(o->flags, F_SHOPITEM);
o = moveob(o, lf->pack, 1);
if (o) {
char obname[BUFLEN];
char lfname[BUFLEN];
char targname[BUFLEN];
getlfname(lf, lfname);
getobname(o, obname, 1);
if (op->owner) {
getlfname(op->owner, targname);
if (isplayer(lf)) {
msg("You steal %s from %s!", obname, targname);
} else if (cansee(player, lf)) {
msg("%s steals %s from %s!", lfname, obname, targname);
}
} else {
if (isplayer(lf)) {
msg("You steal %s!", obname);
} else if (cansee(player, lf)) {
msg("%s steals %s!", lfname, obname);
}
}
numgot++;
}
}
} else {
// nothing left to steal
if (numgot == 0) {
return B_TRUE;
}
break;
}
} // end foreach steal
return B_FALSE;
}
int stone(lifeform_t *lf) { int stone(lifeform_t *lf) {
char lfname[BUFLEN]; char lfname[BUFLEN];
char statname[BUFLEN]; char statname[BUFLEN];
@ -14199,7 +14549,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose) {
if (newregion->id != curmap->region->id) { if (newregion->id != curmap->region->id) {
newdepth = 1; newdepth = 1;
} }
createmap(newmap, newdepth, newregion, curmap, dir); createmap(newmap, newdepth, newregion, curmap, dir, o);
// if we stayed within the same region, our stairs should // if we stayed within the same region, our stairs should
// now have a destination, since createmap() will automatically check // now have a destination, since createmap() will automatically check
// previous/next levels in the same region. // previous/next levels in the same region.

10
lf.h
View File

@ -12,6 +12,7 @@ void adjustspeedforwater(lifeform_t *lf, int *speed);
void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o); void applywalkdam(lifeform_t *lf, int dam, enum DAMTYPE damtype, object_t *o);
int areallies(lifeform_t *lf1, lifeform_t *lf2); int areallies(lifeform_t *lf1, lifeform_t *lf2);
int areenemies(lifeform_t *lf1, lifeform_t *lf2); int areenemies(lifeform_t *lf1, lifeform_t *lf2);
int askforpayment(lifeform_t *shk, lifeform_t *lf);
void autoskill(lifeform_t *lf); void autoskill(lifeform_t *lf);
void autotarget(lifeform_t *lf); void autotarget(lifeform_t *lf);
void autoweild(lifeform_t *lf); void autoweild(lifeform_t *lf);
@ -22,6 +23,7 @@ void breakallgrabs(lifeform_t *lf);
long calcscore(lifeform_t *lf); long calcscore(lifeform_t *lf);
int calcxp(lifeform_t *lf); int calcxp(lifeform_t *lf);
int calcxprace(enum RACE rid); int calcxprace(enum RACE rid);
void callguards(lifeform_t *caller, lifeform_t *victim);
int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost); int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost);
int candrink(lifeform_t *lf, object_t *o); int candrink(lifeform_t *lf, object_t *o);
int caneat(lifeform_t *lf, object_t *o); int caneat(lifeform_t *lf, object_t *o);
@ -67,6 +69,7 @@ lifeform_t *findlf(map_t *m, int lfid);
race_t *findrace(enum RACE id); race_t *findrace(enum RACE id);
race_t *findracebyname(char *name); race_t *findracebyname(char *name);
raceclass_t *findraceclass(enum RACECLASS id); raceclass_t *findraceclass(enum RACECLASS id);
lifeform_t *findshopkeeper(map_t *m, int roomid);
skill_t *findskill(enum SKILL id); skill_t *findskill(enum SKILL id);
skill_t *findskillbyname(char *name); skill_t *findskillbyname(char *name);
enum SKILLLEVEL findskilllevbyname(char *name); enum SKILLLEVEL findskilllevbyname(char *name);
@ -119,6 +122,7 @@ int getminions(lifeform_t *lf, lifeform_t **minion, int *nminions);
int getnightvisrange(lifeform_t *lf); int getnightvisrange(lifeform_t *lf);
char *getlfconditionname(enum LFCONDITION cond); char *getlfconditionname(enum LFCONDITION cond);
object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp); object_t *getouterequippedob(lifeform_t *lf, enum BODYPART bp);
int getowing(lifeform_t *buyer, int shopid, int *retnitems);
enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf); enum LFCONDITION getseenlfconditioncutoff(lifeform_t *lf);
char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer); char *getseenlfconditionname(lifeform_t *lf, lifeform_t *viewer);
glyph_t *getlfglyph(lifeform_t *lf); glyph_t *getlfglyph(lifeform_t *lf);
@ -156,7 +160,7 @@ int getracerarity(map_t *map, enum RACE rid);
object_t *getrandomarmour(lifeform_t *lf); object_t *getrandomarmour(lifeform_t *lf);
int getrandommonlevel(race_t *r, map_t *m); int getrandommonlevel(race_t *r, map_t *m);
race_t *getrandomrace(cell_t *c, int forcedepth); race_t *getrandomrace(cell_t *c, int forcedepth);
race_t *getreallyrandomrace(void); race_t *getreallyrandomrace(enum RACECLASS wantrc);
enum SKILL getrandomskill(void); enum SKILL getrandomskill(void);
object_t *getrestob(lifeform_t *lf); object_t *getrestob(lifeform_t *lf);
enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id); enum SKILLLEVEL getskill(lifeform_t *lf, enum SKILL id);
@ -175,12 +179,14 @@ void getwantdistance(lifeform_t *lf, int *min, int *max, int attacking);
object_t *getweapon(lifeform_t *lf); object_t *getweapon(lifeform_t *lf);
long getxpforlev(int level); long getxpforlev(int level);
void givejob(lifeform_t *lf, enum JOB jobid); void givejob(lifeform_t *lf, enum JOB jobid);
int givemoney(lifeform_t *from, lifeform_t *to, int amt);
void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype); void giveobflags(lifeform_t *lf, object_t *o, enum FLAG whattype);
int giveskill(lifeform_t *lf, enum SKILL id); int giveskill(lifeform_t *lf, enum SKILL id);
int giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev); int giveskilllev(lifeform_t *lf, enum SKILL id, enum SKILLLEVEL slev);
void givestartobs(lifeform_t *lf, flagpile_t *fp); void givestartobs(lifeform_t *lf, flagpile_t *fp);
void givestartskills(lifeform_t *lf, flagpile_t *fp); void givestartskills(lifeform_t *lf, flagpile_t *fp);
map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs); map_t *gotolev(lifeform_t *lf, int depth, object_t *fromstairs);
int hasfreeaction(lifeform_t *lf);
job_t *hasjob(lifeform_t *lf, enum JOB job); job_t *hasjob(lifeform_t *lf, enum JOB job);
int lfcanbestoned(lifeform_t *lf); int lfcanbestoned(lifeform_t *lf);
flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid); flag_t *lfhasflag(lifeform_t *lf, enum FLAG fid);
@ -278,12 +284,14 @@ void setguntarget(lifeform_t *lf, lifeform_t *targ);
void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph); void setrace(lifeform_t *lf, enum RACE rid, int frompolymorph);
void setlastdam(lifeform_t *lf, char *buf); void setlastdam(lifeform_t *lf, char *buf);
//void setlftarget(lifeform_t *lf, lifeform_t *victim); //void setlftarget(lifeform_t *lf, lifeform_t *victim);
int setlfmaterial(lifeform_t *lf, enum MATERIAL id);
int shoot(lifeform_t *lf); int shoot(lifeform_t *lf);
int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod); int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod);
int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *result); int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *result);
int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, enum CHECKTYPE ct2, int mod2); int skillcheckvs(lifeform_t *lf1, enum CHECKTYPE ct1, int mod1, lifeform_t *lf2, enum CHECKTYPE ct2, int mod2);
int slipon(lifeform_t *lf, object_t *o); int slipon(lifeform_t *lf, object_t *o);
void sortlf(map_t *map, lifeform_t *lf); void sortlf(map_t *map, lifeform_t *lf);
int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag);
int stone(lifeform_t *lf); int stone(lifeform_t *lf);
void stopeating(lifeform_t *lf); void stopeating(lifeform_t *lf);
void stopresting(lifeform_t *lf); void stopresting(lifeform_t *lf);

698
map.c

File diff suppressed because it is too large Load Diff

26
map.h
View File

@ -1,7 +1,7 @@
#include "defs.h" #include "defs.h"
cell_t *addcell(map_t *map, int x, int y); cell_t *addcell(map_t *map, int x, int y);
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell); habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance);
void addhomeobs(lifeform_t *lf); void addhomeobs(lifeform_t *lf);
map_t *addmap(void); map_t *addmap(void);
lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded); lifeform_t *addmonster(cell_t *c, enum RACE raceid, int jobok, int amt, int autogen, int *nadded);
@ -10,7 +10,7 @@ int addrandomthing(cell_t *c, int obchance, int *nadded);
region_t *addregion(enum REGIONTYPE rtype, region_t *parent); region_t *addregion(enum REGIONTYPE rtype, region_t *parent);
regionoutline_t *addregionoutline(enum REGIONTYPE rtype); regionoutline_t *addregionoutline(enum REGIONTYPE rtype);
regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum REGIONTHING whatkind, int value, char *what); regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum REGIONTHING whatkind, int value, char *what);
regiontype_t *addregiontype(enum REGIONTYPE id, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir); regiontype_t *addregiontype(enum REGIONTYPE id, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major);
int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance); int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance);
int cellhaslos(cell_t *c1, cell_t *dest); int cellhaslos(cell_t *c1, cell_t *dest);
void clearcell(cell_t *c); void clearcell(cell_t *c);
@ -29,19 +29,20 @@ void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlo
void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid); void getroomedge(map_t *m, int roomid, int minx, int miny, int maxx, int maxy, int whichside, cell_t **retcell, int *ncells, int onlywantsolid);
object_t *gettopobject(cell_t *where, int forglyph); object_t *gettopobject(cell_t *where, int forglyph);
void calclight(map_t *map); void calclight(map_t *map);
int calcroompos(map_t *map, int w, int h, int *bx, int *by, int force); int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int *by, int force);
int countadjcellsoftype(cell_t *cell, int id); int countadjcellsoftype(cell_t *cell, int id);
int countadjrooms(cell_t *cell);
int countadjcellswithflag(cell_t *cell, enum FLAG fid); int countadjcellswithflag(cell_t *cell, enum FLAG fid);
int countadjwalls(cell_t *cell); int countadjwalls(cell_t *cell);
int countcellexits(cell_t *cell); int countcellexits(cell_t *cell);
void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir); void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
void createforest(map_t *map, int depth, map_t *parentmap, int exitdir); void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob, int nclearings);
void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir); void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int exitdir); void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int exitdir, object_t *entryob);
void createpit(map_t *map, int depth, map_t *parentmap, int exitdir); void createpit(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob);
void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIONTYPE newregiontype, region_t *parent); void createregionlink(map_t *m, cell_t *c, object_t *o, char *obname, enum REGIONTYPE newregiontype, region_t *parent);
int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls); int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int xmargin, int ymargin, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls);
int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth); int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *retx, int *rety);
int dirtox(int dt, int dir); int dirtox(int dt, int dir);
int dirtoy(int dt, int dir); int dirtoy(int dt, int dir);
void dumpmap(map_t *map); void dumpmap(map_t *map);
@ -66,8 +67,6 @@ cell_t *getcellindir(cell_t *cell, int dir);
int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved); int getnewdigdir(cell_t *cell, int lastdir, int turnpct, int *moved);
int getobchance(int habitat); int getobchance(int habitat);
char *getregionname(char *buf, map_t *m, int withlevel); char *getregionname(char *buf, map_t *m, int withlevel);
int getvaultchance(map_t *m);
char getvaultchar(vault_t *v, int x, int y);
int getthingchance(int habitat); int getthingchance(int habitat);
cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand); cell_t *getrandomadjcell(cell_t *c, int wantempty, int allowexpand);
cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob); cell_t *real_getrandomadjcell(cell_t *c, int wantempty, int allowexpand, enum LOFTYPE needlof, enum OBTYPE *dontwantob);
@ -96,10 +95,11 @@ int isloopdirok(cell_t *cell, int dir);
int isnewcellok(cell_t *cell, char *err); int isnewcellok(cell_t *cell, char *err);
int isonmap(map_t *map, int x, int y); int isonmap(map_t *map, int x, int y);
int isoutdoors(map_t *m); int isoutdoors(map_t *m);
int isroom(cell_t *c);
int iswallindir(cell_t *cell, int dir); int iswallindir(cell_t *cell, int dir);
int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy); int linkexits(map_t *m, int roomid, int minx, int miny, int maxx, int maxy);
void linkholes(map_t *map); void linkholes(map_t *map);
int linkstairs(object_t *o); int linkstairs(object_t *o, object_t *o2);
void makedoor(cell_t *cell, int openchance); void makedoor(cell_t *cell, int openchance);
void makelit(cell_t *c, enum LIGHTLEV how, int howlong); void makelit(cell_t *c, enum LIGHTLEV how, int howlong);
void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong); void makelitradius(cell_t *c, int radius, enum LIGHTLEV how, int howlong);

173
move.c
View File

@ -3,6 +3,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "ai.h"
#include "attack.h" #include "attack.h"
#include "defs.h" #include "defs.h"
#include "flag.h" #include "flag.h"
@ -286,8 +287,10 @@ int cellwalkable(lifeform_t *lf, cell_t *cell, enum ERROR *error) {
for (o = cell->obpile->first ; o ; o = o->next) { for (o = cell->obpile->first ; o ; o = o->next) {
if (isimpassableob(o, lf)) { if (isimpassableob(o, lf)) {
if (lf) { if (lf) {
if ((lf->race->material->id == MT_GAS) || enum MATERIAL mid;
(lf->race->material->id == MT_SLIME)) { mid = getlfmaterial(lf);
if ((mid == MT_GAS) ||
(mid == MT_SLIME)) {
// ok // ok
} else if (lfhasflag(lf, F_NONCORPOREAL)) { } else if (lfhasflag(lf, F_NONCORPOREAL)) {
// ok but still set error // ok but still set error
@ -601,30 +604,30 @@ int getwalkoffdir(lifeform_t *lf, int dir) {
switch (dir) { switch (dir) {
case DC_NE: case DC_NE:
if (lf->cell->y == 0) { if (lf->cell->y == 0) {
return DC_N; return D_N;
} else if ( lf->cell->x == (lf->cell->map->w-1)) { } else if ( lf->cell->x == (lf->cell->map->w-1)) {
return DC_E; return D_E;
} }
break; break;
case DC_SE: case DC_SE:
if (lf->cell->y == (lf->cell->map->h-1)) { if (lf->cell->y == (lf->cell->map->h-1)) {
return DC_S; return D_S;
} else if ( lf->cell->x == (lf->cell->map->w-1)) { } else if ( lf->cell->x == (lf->cell->map->w-1)) {
return DC_E; return D_E;
} }
break; break;
case DC_SW: case DC_SW:
if (lf->cell->y == (lf->cell->map->h-1)) { if (lf->cell->y == (lf->cell->map->h-1)) {
return DC_S; return D_S;
} else if ( lf->cell->x == 0) { } else if ( lf->cell->x == 0) {
return DC_W; return D_W;
} }
break; break;
case DC_NW: case DC_NW:
if (lf->cell->y == 0) { if (lf->cell->y == 0) {
return DC_N; return D_N;
} else if ( lf->cell->x == 0) { } else if ( lf->cell->x == 0) {
return DC_W; return D_W;
} }
break; break;
} }
@ -741,6 +744,24 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
return B_FALSE; return B_FALSE;
} }
int makeorthogonal(int dir) {
switch (dir) {
case DC_N:
case D_N:
return D_N;
case DC_E:
case D_E:
return D_E;
case DC_S:
case D_S:
return D_S;
case DC_W:
case D_W:
return D_W;
}
return D_NONE;
}
// see 'movetowards' for description of dirtype // see 'movetowards' for description of dirtype
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) { int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype ) {
int dir; int dir;
@ -870,6 +891,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
flag_t *f; flag_t *f;
int changedlev = B_FALSE; int changedlev = B_FALSE;
int preroom = -1, postroom = -1; int preroom = -1, postroom = -1;
int preshop = -1;
int prespeed = B_FALSE, postspeed = B_FALSE; int prespeed = B_FALSE, postspeed = B_FALSE;
int prewater = B_FALSE; int prewater = B_FALSE;
@ -888,6 +910,9 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// update current cell + room id // update current cell + room id
prespeed = getmovespeed(lf); prespeed = getmovespeed(lf);
preroom = lf->cell->roomid; preroom = lf->cell->roomid;
if (lf->cell->vault && hasflag(lf->cell->vault->flags, F_VAULTISSHOP)) {
preshop = lf->cell->roomid;
}
// getting out of water? // getting out of water?
if (hasobwithflag(lf->cell->obpile, F_DEEPWATER)) { if (hasobwithflag(lf->cell->obpile, F_DEEPWATER)) {
@ -1108,7 +1133,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
// does anyone else see you? // does anyone else see you?
if ((gamemode == GM_GAMESTARTED)) { if (gamemode == GM_GAMESTARTED) {
for (l = newcell->map->lf ; l ; l = l->next) { for (l = newcell->map->lf ; l ; l = l->next) {
if (l != lf) { if (l != lf) {
flag_t *alarm; flag_t *alarm;
@ -1153,6 +1178,54 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
} }
} }
// leaving a shop
if (preshop) {
// are you about to go outside a shop with stolen goods?
if ((lf->cell->roomid == preshop) && (lf->cell->type->id != CT_FLOORSHOP)) {
lifeform_t *shk;
shk = findshopkeeper(lf->cell->map, preshop);
if (shk) {
int nitems = 0;
// do you have any unpaid items from that shop?
if (getowing(lf, preshop, &nitems)) {
char saybuf[BUFLEN];
// warning...
switch (rnd(1,3)) {
case 1: sprintf(saybuf, "Hey! Where do you think you're going?");
break;
case 2: sprintf(saybuf, "AHEM!");
break;
case 3: sprintf(saybuf, "I hope you are going to pay for %s!",
(nitems == 1) ? "that" : "those" );
break;
}
say(shk, saybuf, SV_SHOUT);
didmsg = B_TRUE;
}
}
} else if (lf->cell->roomid != preshop) {
// you've left the shop
lifeform_t *shk;
shk = findshopkeeper(lf->cell->map, preshop);
if (shk && getowing(lf, preshop, NULL)) {
char saybuf[BUFLEN];
// call the guards
switch (rnd(1,3)) {
case 1: sprintf(saybuf, "Stop thief!");
break;
case 2: sprintf(saybuf, "GUARDS!");
break;
case 3: sprintf(saybuf, "I've been robbed!");
break;
}
say(shk, saybuf, SV_ROAR);
didmsg = B_TRUE;
fightback(shk, lf); // shopkeeper attacks
callguards(shk, lf); // guards come running
}
}
}
} }
// status bar // status bar
@ -1216,7 +1289,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
// tell player about things // tell player about things
if (!isdead(lf)) { if (!isdead(lf)) {
// some lifeforms can go through things // some lifeforms can go through things
if (lf->race->material->id == MT_GAS) { if (getlfmaterial(lf) == MT_GAS) {
char obname[BUFLEN]; char obname[BUFLEN];
for (o = newcell->obpile->first ; o ; o = o->next) { for (o = newcell->obpile->first ; o ; o = o->next) {
if (isimpassableob(o, lf)) { if (isimpassableob(o, lf)) {
@ -1228,7 +1301,7 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) {
} }
} }
} }
} else if (lf->race->material->id == MT_SLIME) { } else if (getlfmaterial(lf) == MT_SLIME) {
char obname[BUFLEN]; char obname[BUFLEN];
for (o = newcell->obpile->first ; o ; o = o->next) { for (o = newcell->obpile->first ; o ; o = o->next) {
if (isimpassableob(o, lf)) { if (isimpassableob(o, lf)) {
@ -2274,6 +2347,10 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
int nadjallies = 0; int nadjallies = 0;
int n; int n;
// make sure dircetion is orthogonal
dir = makeorthogonal(dir);
assert(dir != D_NONE);
// announce // announce
if (isplayer(lf)) { if (isplayer(lf)) {
char dirname[BUFLEN]; char dirname[BUFLEN];
@ -2300,7 +2377,7 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
if (!adjmap) { if (!adjmap) {
// make one // make one
adjmap = addmap(); adjmap = addmap();
createmap(adjmap, thismap->depth, thismap->region, thismap, dir); createmap(adjmap, thismap->depth, thismap->region, thismap, dir, NULL);
} }
if (adjmap) { if (adjmap) {
@ -2377,14 +2454,28 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
} }
cell = getcellindir(lf->cell, dir); cell = getcellindir(lf->cell, dir);
if (!cell) {
// won't walk off map
return B_FALSE;
}
if (cell && celldangerous(lf, cell, B_TRUE, error)) { if (celldangerous(lf, cell, B_TRUE, error)) {
if (error) *error = E_WONT;
return B_FALSE;
}
if (!isroom(cell) && hasjob(lf, J_SHOPKEEPER)) {
if (error) *error = E_WONT;
return B_FALSE;
}
if (lfhasflag(lf, F_STAYINHABITAT) && (cell->habitat->id != lf->cell->habitat->id)) {
if (error) *error = E_WONT; if (error) *error = E_WONT;
return B_FALSE; return B_FALSE;
} }
// don't attack other monsters // don't attack other monsters
if (cell && cell->lf) { // if someone is in the way if (cell->lf) { // if someone is in the way
if (lf->race->raceclass->id == RC_INSECT) { if (lf->race->raceclass->id == RC_INSECT) {
if (hasactivespell(cell->lf, OT_S_REPELINSECTS)) { if (hasactivespell(cell->lf, OT_S_REPELINSECTS)) {
if (error) *error = E_WONT; if (error) *error = E_WONT;
@ -2415,35 +2506,33 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
} }
// look for avoided objects (because they are cursed). // look for avoided objects (because they are cursed).
if (cell) { for (o = cell->obpile->first ; o ; o = o->next) {
for (o = cell->obpile->first ; o ; o = o->next) { flag_t *f;
flag_t *f; sprintf(buf, "%ld",o->id);
sprintf(buf, "%ld",o->id); f = lfhasflagval(lf, F_AVOIDCURSEDOB, NA, NA, NA, buf);
f = lfhasflagval(lf, F_AVOIDCURSEDOB, NA, NA, NA, buf); if (f) {
if (f) { // still cursed?
// still cursed? if (iscursed(o)) {
if (iscursed(o)) { if (error) *error = E_WONT;
return B_FALSE;
} else {
// remove the flag.
killflag(f);
}
}
if (hasflag(o->flags, F_TRAP)) {
if (hasflag(o->flags, F_SECRET)) {
// hidden traps?
if (iq >= IQ_SMART) {
if (error) *error = E_WONT; if (error) *error = E_WONT;
return B_FALSE; return B_FALSE;
} else {
// remove the flag.
killflag(f);
} }
} } else {
// non-hidden traps?
if (hasflag(o->flags, F_TRAP)) { if (iq >= IQ_AVERAGE) {
if (hasflag(o->flags, F_SECRET)) { if (error) *error = E_WONT;
// hidden traps? return B_FALSE;
if (iq >= IQ_SMART) {
if (error) *error = E_WONT;
return B_FALSE;
}
} else {
// non-hidden traps?
if (iq >= IQ_AVERAGE) {
if (error) *error = E_WONT;
return B_FALSE;
}
} }
} }
} }

1
move.h
View File

@ -12,6 +12,7 @@ int getdiraway(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int d
int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype); int getdirtowards(cell_t *src, cell_t *dst, lifeform_t *srclf, int wantcheck, int dirtype);
int getwalkoffdir(lifeform_t *lf, int dir); int getwalkoffdir(lifeform_t *lf, int dir);
int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff); int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallcheckdiff);
int makeorthogonal(int dir);
int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype); int moveawayfrom(lifeform_t *lf, cell_t *dst, int dirtype);
int moveclear(lifeform_t *lf, int dir, enum ERROR *error); int moveclear(lifeform_t *lf, int dir, enum ERROR *error);
int moveeffects(lifeform_t *lf); int moveeffects(lifeform_t *lf);

114
nexus.c
View File

@ -16,6 +16,7 @@
#include "nexus.h" #include "nexus.h"
#include "objects.h" #include "objects.h"
#include "save.h" #include "save.h"
#include "spell.h"
#include "text.h" #include "text.h"
#include "vault.h" #include "vault.h"
@ -170,7 +171,9 @@ int main(int argc, char **argv) {
initprompt(&prompt, "Select your job:"); initprompt(&prompt, "Select your job:");
ch = 'a'; ch = 'a';
for (j = firstjob ; j ; j = j->next) { for (j = firstjob ; j ; j = j->next) {
addchoice(&prompt, ch++, j->name, NULL, j); if (!hasflag(j->flags, F_NOPLAYER)) {
addchoice(&prompt, ch++, j->name, NULL, j);
}
} }
j = NULL; j = NULL;
while (!j) { while (!j) {
@ -187,12 +190,12 @@ int main(int argc, char **argv) {
// create world map. // create world map.
wregion = addregion(RG_WORLDMAP, NULL); wregion = addregion(RG_WORLDMAP, NULL);
addmap(); addmap();
createmap(firstmap, 1, wregion, NULL, D_NONE); createmap(firstmap, 1, wregion, NULL, D_NONE, NULL);
//createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE); //createmap(firstmap, 1, RG_FIRSTDUNGEON, H_DUNGEON, NULL, D_NONE);
// create first dungeon // create first dungeon
dregion = findregionbytype(RG_FIRSTDUNGEON); dregion = findregionbytype(RG_FIRSTDUNGEON);
dmap = addmap(); dmap = addmap();
createmap(dmap, 1, dregion, firstmap, D_DOWN); createmap(dmap, 1, dregion, firstmap, D_DOWN, NULL);
} }
// find staircase // find staircase
@ -214,14 +217,8 @@ int main(int argc, char **argv) {
addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous"); addflag(player->flags, F_NAME, NA, NA, NA, "Anonymous");
} }
givejob(player, j->id); givejob(player, j->id);
// special cases for jobs: // extra choices for some jobs
if (j->id == J_PIRATE) { if (j->id == J_WIZARD) {
flag_t *f;
f = lfhasflagval(player, F_HASATTACK, OT_FISTS, NA, NA, NULL);
assert(f);
f->val[0] = OT_HOOKHAND;
sprintf(f->text, "1d4");
} else if (j->id == J_WIZARD) {
skill_t *sk; skill_t *sk;
initprompt(&prompt, "Select your spell specialty:"); initprompt(&prompt, "Select your spell specialty:");
addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR)); addchoice(&prompt, 'a', getskillname(SK_SS_AIR), NULL, findskill(SK_SS_AIR));
@ -572,6 +569,79 @@ void donextturn(map_t *map) {
int donormalmove = B_TRUE; int donormalmove = B_TRUE;
flag_t *f; flag_t *f;
// casting a spell?
if (donormalmove) {
f = lfhasflag(who, F_CASTINGSPELL);
if (f) {
donormalmove = B_FALSE;
f->val[2]--;
if (f->val[2] <= 0) {
char *p;
char buf[BUFLEN];
int lfid,mapid,x,y,power;
long obid;
lifeform_t *targlf;
object_t *targob;
cell_t *targcell;
map_t *targmap;
enum OBTYPE sid;
sid = f->val[0];
power = f->val[1];
// finished!
p = f->text;
p = readuntil(buf, p, ';');
lfid = atoi(p);
p = readuntil(buf, p, ';');
obid = atol(p);
p = readuntil(buf, p, ';');
mapid = atoi(p);
p = readuntil(buf, p, ';');
x = atoi(p);
p = readuntil(buf, p, ';');
y = atoi(p);
if (lfid >= 0) {
targlf = findlf(NULL, lfid);
} else {
targlf = NULL;
}
if (obid >= 0) {
targob = findobidinmap(who->cell->map, obid);
} else {
targob = NULL;
}
if (mapid >= 0) {
targmap = findmap(mapid);
targcell = getcellat(targmap, x, y);
}
taketime(who, getspellspeed(who));
dospelleffects(who, sid, power, targlf, targob, targcell, B_UNCURSED, NULL, B_FALSE);
killflagsofid(who->flags, F_CASTINGSPELL);
} else {
if (isplayer(who)) {
objecttype_t *sp;
sp = findot(f->val[0]);
msg("You continue casting %s.", sp->name);
} else if (cansee(player, who)) {
flag_t *f2;
char lfname[BUFLEN];
// still going...
getlfname(who, lfname);
f2 = lfhasflag(who,F_SPELLCASTTEXT);
if (f2 && strlen(f2->text)) {
msg("%s %s.", lfname, f2->text);
} else {
msg("%s continues casting a spell.", lfname);
}
}
}
}
}
// eating? // eating?
if (donormalmove) { if (donormalmove) {
f = lfhasflag(who, F_EATING); f = lfhasflag(who, F_EATING);
@ -637,8 +707,14 @@ void donextturn(map_t *map) {
// find out what player wants to do // find out what player wants to do
handleinput(); handleinput();
} else { } else {
//char lfname[BUFLEN];
//char buf[BUFLEN];
// do ai move // do ai move
//real_getlfname(who, lfname, B_FALSE);
//sprintf(buf, "aimove %s",lfname);
//dbtimestart(buf);
aiturn(who); aiturn(who);
//dbtimeend(buf);
} }
} }
} }
@ -1332,21 +1408,9 @@ void timeeffectsworld(map_t *map) {
if (!o) { if (!o) {
o = addob(c->obpile, "water"); o = addob(c->obpile, "water");
} }
if (o) {
flag_t *dflag;
dflag = hasflag(o->flags, F_DEEPWATER);
// adjust depth
dflag->val[0] = f->val[2];
}
} else {
// water depth is now zero.
o = hasobwithflag(c->obpile, F_DEEPWATER);
if (o) {
killob(o);
addob(c->obpile, "large puddle of water");
}
} }
setwaterdepth(c, f->val[2]);
} }
killflag(f); killflag(f);
continue; continue;

283
objects.c
View File

@ -429,6 +429,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// for doors // for doors
enum FLAG doorflag[5]; enum FLAG doorflag[5];
int ndoorflags = 0; int ndoorflags = 0;
char *signtext = NULL;
// just in case we don't add any // just in case we don't add any
addedob[0] = NULL; addedob[0] = NULL;
@ -646,6 +647,24 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
corpserace = findracebyname(racename); corpserace = findracebyname(racename);
ot = findot(OT_HEAD); ot = findot(OT_HEAD);
} else if (strstarts(p, "sign ")) {
char *pp;
pp = strchr(p, '\"');
if (pp) {
char sbuf[BUFLEN];
char *sbp;
sbp = sbuf;
pp++;
while (*pp && (*pp != '\"')) {
*sbp = *pp;
sbp++;
pp++;
}
*sbp = '\0';
signtext = strdup(sbuf);
}
ot = findot(OT_SIGN);
} else if (strstr(p, "spellbook of ")) { } else if (strstr(p, "spellbook of ")) {
char *pp; char *pp;
pp = p + 13; pp = p + 13;
@ -718,7 +737,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
//////////////////////////////////// ////////////////////////////////////
// we now have the objecttype! // we now have the objecttype!
//////////////////////////////////// ////////////////////////////////////
if (hasflag(ot->flags, F_ONEPERCELL)) { if (hasflag(ot->flags, F_ONEPERCELL)) {
if (hasob(where, ot->id)) { if (hasob(where, ot->id)) {
nretobs = 0; nretobs = 0;
@ -901,30 +919,36 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
*/ */
for (i = 0; i < nadded; i++) { for (i = 0; i < nadded; i++) {
cell_t *obloc;
o = addedob[i]; o = addedob[i];
obloc = getoblocation(o);
// fill in sign text
if (signtext) {
addflag(o->flags, F_SIGNTEXT, NA, NA, NA, signtext);
}
// fill in door flags // fill in door flags
if (ndoorflags && isdoor(o, NULL)) { if (ndoorflags && isdoor(o, NULL)) {
int n; int n;
for (n = 0; n < ndoorflags; n++) { for (n = 0; n < ndoorflags; n++) {
cell_t *c;
int val[3]; int val[3];
c = getoblocation(o); if (obloc) {
if (c) {
// fill in flag vals // fill in flag vals
switch (doorflag[n]) { switch (doorflag[n]) {
case F_LOCKED: case F_LOCKED:
val[0] = B_TRUE; val[0] = B_TRUE;
val[1] = getdoorlockdiff(c->map->depth); val[1] = getdoorlockdiff(obloc->map->depth);
val[2] = NA; val[2] = NA;
break; break;
case F_JAMMED: case F_JAMMED:
val[0] = rnd(1,c->map->depth+3); val[0] = rnd(1,obloc->map->depth+3);
val[1] = NA; val[1] = NA;
val[2] = NA; val[2] = NA;
break; break;
case F_SECRET: case F_SECRET:
val[0] = getdoorsecretdiff(c->map->depth); val[0] = getdoorsecretdiff(obloc->map->depth);
val[1] = NA; val[1] = NA;
val[2] = NA; val[2] = NA;
break; break;
@ -1398,7 +1422,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
objecttype_t *ot2; objecttype_t *ot2;
strcpy(buf, ""); strcpy(buf, "");
while (!strcmp(buf, "")) { while (!strcmp(buf, "")) {
real_getrandomob(loc->map, buf, RO_NONE, NA, loc->map->depth + rnd(10,15)); real_getrandomob(loc->map, buf, RO_NONE, NA, loc->map->depth + rnd(10,15), NA);
// replace "1 potion" with "a potion" // replace "1 potion" with "a potion"
if (strstr(buf, "1 ") == buf) { if (strstr(buf, "1 ") == buf) {
char temp[BUFLEN]; char temp[BUFLEN];
@ -1601,6 +1625,22 @@ objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material,
return a; return a;
} }
void adjustdamhardness(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat) {
// now check for hardness
if (isphysicaldam(damtype)) {
material_t *m;
m = findmaterial(mat);
if (m) {
flag_t *f;
f = hasflag(m->flags, F_HARDNESS);
if (f && (*dam < f->val[0])) {
*dam = 0;
}
}
}
}
// adjust damage based on material being damaged // adjust damage based on material being damaged
void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat) { void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat) {
// adjust based on material // adjust based on material
@ -1694,6 +1734,7 @@ void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL ma
break; break;
} }
} }
} }
void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) { void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) {
@ -1781,8 +1822,9 @@ void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype) {
} }
} }
// adjust damage for material too // adjust damage for material & hardness too
adjustdammaterial(dam, damtype, o->material->id); adjustdammaterial(dam, damtype, o->material->id);
adjustdamhardness(dam, damtype, o->material->id);
} }
// adjust price for magical effects etc // adjust price for magical effects etc
@ -2715,13 +2757,22 @@ glyph_t *getglyph(object_t *o) {
} }
} }
// override colour // special case
if (o->type->id == OT_WATERDEEP) { if (o->type->id == OT_WATERDEEP) {
cell_t *loc;
// override colour
if (getobdepth(o, player) >= DP_HEAD) { if (getobdepth(o, player) >= DP_HEAD) {
col = C_BOLDBLUE; col = C_BOLDBLUE;
} else { } else {
col = C_BLUE; col = C_BLUE;
} }
loc = getoblocation(o);
if (getcellwaterdepth(loc, player) >= DP_WAIST) {
g = '{';
} else {
g = '~';
}
} }
tempglyph.ch = g; tempglyph.ch = g;
@ -3677,7 +3728,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
char localbuf[BUFLEN]; char localbuf[BUFLEN];
char buf2[BUFLEN]; char buf2[BUFLEN];
char triedbuf[BUFLEN]; char triedbuf[BUFLEN];
int shopitem = B_FALSE; int venditem = B_FALSE;
flag_t *f; flag_t *f;
brand_t *br; brand_t *br;
obmod_t *om; obmod_t *om;
@ -3685,13 +3736,13 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
cell_t *where; cell_t *where;
// default to normal name // default to normal name
if (hasflag(o->flags, F_SHOPITEM)) { if (hasflag(o->flags, F_VENDITEM)) {
shopitem = B_TRUE; venditem = B_TRUE;
} }
where = getoblocation(o); where = getoblocation(o);
if (shopitem) { if (venditem) {
showall = B_TRUE; showall = B_TRUE;
} }
@ -3771,6 +3822,8 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
strcat(basename, dname); strcat(basename, dname);
} }
} // end if sight/smell } // end if sight/smell
} else if ((o->type->id == OT_SIGN) && !hasflag(o->flags, F_SIGNTEXT)) {
strcpy(basename, "blank sign");
} else if (o->type->id == OT_WATERDEEP) { } else if (o->type->id == OT_WATERDEEP) {
sprintf(basename, "%s water", getwaterdepthname(getobdepth(o, player))); sprintf(basename, "%s water", getwaterdepthname(getobdepth(o, player)));
} else { } else {
@ -4063,6 +4116,16 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
} }
// show sign text
if (o->type->id == OT_SIGN) {
f = hasflag(o->flags, F_SIGNTEXT);
if (f) {
strcat(localbuf, " reading '");
strcat(localbuf, f->text);
strcat(localbuf, "'");
}
}
// append inscription // append inscription
if (o->inscription) { if (o->inscription) {
strcat(localbuf, " {"); strcat(localbuf, " {");
@ -4102,6 +4165,14 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
} }
// in a shop?
f = hasflag(o->flags, F_SHOPITEM);
if (f) {
char pricebuf[BUFLEN];
sprintf(pricebuf, " [$%d%s]", f->val[0], o->pile->owner ? ", unpaid" : "");
strcat(localbuf, pricebuf);
}
// apply prefix now! // apply prefix now!
if (count == 1) { if (count == 1) {
if (hasflag(o->flags, F_NO_A)) { if (hasflag(o->flags, F_NO_A)) {
@ -4273,7 +4344,7 @@ objecttype_t *getoppositestairs(objecttype_t *ot) {
return findot(f->val[0]); return findot(f->val[0]);
} }
char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth) { char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth, int forcehabitat) {
objecttype_t *ot; objecttype_t *ot;
objecttype_t *poss[MAXRANDOMOBCANDIDATES]; objecttype_t *poss[MAXRANDOMOBCANDIDATES];
int nposs = 0; int nposs = 0;
@ -4335,7 +4406,9 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
// correct rarity? // correct rarity?
rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL); rarflag = hasflagval(ot->flags, F_RARITY, H_ALL, NA, NA, NULL);
if (!rarflag) { if (!rarflag) {
if (map) { if (forcehabitat != NA) {
rarflag = hasflagval(ot->flags, F_RARITY, forcehabitat, NA, NA, NULL);
} else if (map) {
rarflag = hasflagval(ot->flags, F_RARITY, map->habitat->id, NA, NA, NULL); rarflag = hasflagval(ot->flags, F_RARITY, map->habitat->id, NA, NA, NULL);
} else { } else {
rarflag = hasflagval(ot->flags, F_RARITY, NA, NA, NA, NULL); rarflag = hasflagval(ot->flags, F_RARITY, NA, NA, NA, NULL);
@ -4394,8 +4467,6 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
if (db) dblog("got %d possibilities. now adjusting for RR_",nposs); if (db) dblog("got %d possibilities. now adjusting for RR_",nposs);
// pick a random object from our possiblities // pick a random object from our possiblities
selidx = rnd(0,nposs-1); selidx = rnd(0,nposs-1);
ot = poss[selidx]; ot = poss[selidx];
@ -4489,17 +4560,17 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
} }
char *getrandomob(map_t *map, char *buf) { char *getrandomob(map_t *map, char *buf) {
return real_getrandomob(map, buf, RO_NONE, NA, NA); return real_getrandomob(map, buf, RO_NONE, NA, NA, NA);
} }
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) { char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf) {
return real_getrandomob(map, buf, RO_DAMTYPE, damtype, NA); return real_getrandomob(map, buf, RO_DAMTYPE, damtype, NA, NA);
} }
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod) { char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod) {
//return real_getrandomob(map, buf, RO_OBCLASS, cid, map->depth + depthmod); //return real_getrandomob(map, buf, RO_OBCLASS, cid, map->depth + depthmod);
if (depthmod == NA) depthmod = 0; if (depthmod == NA) depthmod = 0;
return real_getrandomob(map, buf, RO_OBCLASS, cid, getmapdifficulty(map) + depthmod); return real_getrandomob(map, buf, RO_OBCLASS, cid, getmapdifficulty(map) + depthmod, NA);
} }
int getobrarity(object_t *o, enum RARITY *rr) { int getobrarity(object_t *o, enum RARITY *rr) {
@ -4598,6 +4669,31 @@ char *getschoolnameshort(enum SPELLSCHOOL sch) {
return "unknown school"; return "unknown school";
} }
void setwaterdepth(cell_t *c, int depth) {
object_t *o;
if (depth > 0) {
o = hasobwithflag(c->obpile, F_DEEPWATER);
if (o) {
flag_t *f;
// adjust depth
f = hasflag(o->flags, F_DEEPWATER);
f->val[0] = depth;
}
} else {
int nkilled = 0;
// water depth is now zero.
o = hasobwithflag(c->obpile, F_DEEPWATER);
while (o) {
killob(o);
nkilled++;
o = hasobwithflag(c->obpile, F_DEEPWATER);
}
if (nkilled) {
addob(c->obpile, "large puddle of water");
}
}
}
int getshatterdam(object_t *o) { int getshatterdam(object_t *o) {
int shatterdam = 0; int shatterdam = 0;
if (willshatter(o->material->id)) { if (willshatter(o->material->id)) {
@ -5090,7 +5186,7 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addmaterial(MT_FOOD, "food", 3); addmaterial(MT_FOOD, "food", 3);
addmaterial(MT_PLASTIC, "plastic", 3); addmaterial(MT_PLASTIC, "plastic", 3);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 2, NA, NA, NULL);
addmaterial(MT_WAX, "wax", 3); addmaterial(MT_WAX, "wax", 3);
addflag(lastmaterial->flags, F_MATCONVERT, MT_FIRE, NA, NA, "lump of melted wax"); 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_MATCONVERTTEXT, MT_FIRE, NA, NA, "melts");
@ -5100,12 +5196,12 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_BASH, NA, NA, NULL);
addmaterial(MT_BONE, "bone", 5); addmaterial(MT_BONE, "bone", 5);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 3, NA, NA, NULL);
addmaterial(MT_OIL, "oil", 5); addmaterial(MT_OIL, "oil", 5);
addmaterial(MT_ICE, "ice",6); addmaterial(MT_ICE, "ice",6);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 2, NA, NA, NULL);
addmaterial(MT_WOOD, "wood", 6); addmaterial(MT_WOOD, "wood", 6);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 3, NA, NA, NULL);
addflag(lastmaterial->flags, F_FLAMMABLE, 5, NA, NA, NULL); addflag(lastmaterial->flags, F_FLAMMABLE, 5, NA, NA, NULL);
addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL);
addmaterial(MT_ACID, "acid", 7); addmaterial(MT_ACID, "acid", 7);
@ -5113,7 +5209,7 @@ void initobjects(void) {
addmaterial(MT_BLOOD, "blood", 7); addmaterial(MT_BLOOD, "blood", 7);
addmaterial(MT_SLIME, "slime", 9); addmaterial(MT_SLIME, "slime", 9);
addmaterial(MT_STONE, "stone", 10); addmaterial(MT_STONE, "stone", 10);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 5, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_BITE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_BITE, NA, NA, NULL);
@ -5121,7 +5217,7 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); addflag(lastmaterial->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL);
addmaterial(MT_METAL, "metal", 13); addmaterial(MT_METAL, "metal", 13);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 6, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_BITE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_BITE, NA, NA, NULL);
@ -5129,10 +5225,10 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_DTRESIST, DT_SLASH, NA, NA, NULL); addflag(lastmaterial->flags, F_DTRESIST, DT_SLASH, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL); addflag(lastmaterial->flags, F_DTRESIST, DT_PROJECTILE, NA, NA, NULL);
addmaterial(MT_GLASS, "glass", 13); addmaterial(MT_GLASS, "glass", 13);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 3, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastmaterial->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addmaterial(MT_GOLD, "gold", 16); addmaterial(MT_GOLD, "gold", 16);
addflag(lastmaterial->flags, F_HARD, B_TRUE, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 4, NA, NA, NULL);
//addmaterial(MT_GOLD, "gold", 16); //addmaterial(MT_GOLD, "gold", 16);
// object classes // object classes
@ -5261,8 +5357,8 @@ void initobjects(void) {
addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL);
// blocks movement, but you can see and fire through them. // blocks movement, but you can see and fire through them.
addot(OT_IRONGATE, "iron gate", "A gate comprised of a series of vertical iron bars.", MT_METAL, 0, OC_DFEATURE); addot(OT_GATEIRON, "iron gate", "A gate comprised of a series of vertical iron bars, raised slightly above the floor.", MT_METAL, 500, OC_DFEATURE);
addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "|"); addflag(lastot->flags, F_GLYPH, C_GREY, NA, NA, "+");
addflag(lastot->flags, F_DOOR, SZ_MEDIUM, SZ_MAX, NA, NULL); addflag(lastot->flags, F_DOOR, SZ_MEDIUM, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MEDIUM, SZ_MAX, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MEDIUM, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_LOCKABLE, B_TRUE, NA, NA, NULL);
@ -5273,7 +5369,26 @@ void initobjects(void) {
addflag(lastot->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL); addflag(lastot->flags, F_DTIMMUNE, DT_PIERCE, NA, NA, NULL);
addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL); addflag(lastot->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL);
addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL); addflag(lastot->flags, F_DTRESIST, DT_CHOP, NA, NA, NULL);
addot(OT_GATEWOOD, "wooden gate", "A gate comprised of a series of wooden slats.", MT_WOOD, 200, OC_DFEATURE);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "+");
addflag(lastot->flags, F_DOOR, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_LOCKABLE, 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_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
addot(OT_FENCEWOOD, "wooden fence", "A tell fence created from a series of upright logs of wood.", MT_WOOD, 200, OC_DFEATURE);
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_MAX, NA, NULL);
addflag(lastot->flags, F_BLOCKSVIEW, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_BLOCKSLOF, 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, 30, 30, NA, NULL);
addflag(lastot->flags, F_DTVULN, DT_CHOP, NA, NA, NULL);
addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_ROCK); addot(OT_BOULDER, "boulder", "A massive stone boulder.", MT_STONE, 80, OC_ROCK);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, "");
@ -5300,7 +5415,8 @@ void initobjects(void) {
addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL); addflag(lastot->flags, F_OBHP, 80, 80, NA, NULL);
addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_ROCK); addot(OT_STATUE, "statue", "A stone statue of a monster.", MT_STONE, 80, OC_ROCK);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, "");
addflag(lastot->flags, F_RARITY, H_VILLAGE, 80, NA, "");
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'"); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "'");
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL); // will be overridden addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL); // will be overridden
addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PUSHABLE, B_TRUE, NA, NA, NULL);
@ -5380,7 +5496,7 @@ void initobjects(void) {
addot(OT_WATERDEEP, "water", "Deep water.", MT_WATER, 300, OC_TERRAIN); addot(OT_WATERDEEP, "water", "Deep water.", MT_WATER, 300, OC_TERRAIN);
addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BOLDBLUE, NA, NA, "~"); addflag(lastot->flags, F_GLYPH, C_BOLDBLUE, NA, NA, "{");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, 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_COLD, NA, NA, "sheet of ice");
addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 1, DT_COMPASS, "cloud of steam"); addflag(lastot->flags, F_DTCREATEOB, DT_FIRE, 1, DT_COMPASS, "cloud of steam");
@ -5943,6 +6059,7 @@ void initobjects(void) {
addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all nearby life, including the caster!", MT_NOTHING, 0, OC_SPELL); addot(OT_S_INFINITEDEATH, "infinite death", "Annihilates all nearby life, including the caster!", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 8, NA, NA, NULL);
addflag(lastot->flags, F_CASTINGTIME, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
/////////////////// ///////////////////
// divination // divination
@ -6168,8 +6285,6 @@ void initobjects(void) {
addot(OT_S_BARKSKIN, "barkskin", "Covers the caster with a skin of bark, reducing damage but making them vulnerable to fire.", MT_NOTHING, 0, OC_SPELL); addot(OT_S_BARKSKIN, "barkskin", "Covers the caster with a skin of bark, reducing damage but making them vulnerable to fire.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 5, NA, NA, NULL);
addflag(lastot->flags, F_VARPOWER, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addot(OT_S_CHARMANIMAL, "befriend animal", "Temporarily makes a single animal friendly to you.", MT_NOTHING, 0, OC_SPELL); addot(OT_S_CHARMANIMAL, "befriend animal", "Temporarily makes a single animal friendly to you.", MT_NOTHING, 0, OC_SPELL);
@ -6371,15 +6486,18 @@ void initobjects(void) {
addot(OT_S_MINDSCAN, "mind scan", "Reveals detailed information about the target.", MT_NOTHING, 0, OC_SPELL); 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_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l2 // l2
addot(OT_S_SLEEP, "sleep", "Puts the target creature to sleep.", MT_NOTHING, 0, OC_SPELL); 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_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, 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_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_TELEKINESIS, "telekinesis", "Mentally move or manipulate nearby objects.", MT_NOTHING, 0, OC_SPELL); 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_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SPECIAL, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
// l3 // l3
addot(OT_S_PSYARMOUR, "psychic armour", "Mentally block incoming attacks.", MT_NOTHING, 0, OC_SPELL); 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_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
@ -6573,6 +6691,8 @@ void initobjects(void) {
// divine powers (spells/abilities) // divine powers (spells/abilities)
addot(OT_A_BLINDALL, "nosight", "Make everyone on the level blind.", MT_NOTHING, 0, OC_ABILITY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL);
addot(OT_A_DEBUG, "debug", "You can toggle debugging for a lifeform.", MT_NOTHING, 0, OC_ABILITY); 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); 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); addot(OT_A_ENHANCE, "enhance", "Enhance a lifeform's stats.", MT_NOTHING, 0, OC_ABILITY);
@ -6587,6 +6707,10 @@ void initobjects(void) {
addot(OT_S_GIFT, "gift", "Grants the target any item of their choice (with some limitations).", MT_NOTHING, 0, OC_SPELL); 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_SPELLLEVEL, 9, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
addot(OT_S_CLEARLEVEL, "blank level", "Blanks out the current map.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_CREATEVAULT, "create vault", "Create a vault of the given type.", MT_NOTHING, 0, OC_SPELL); addot(OT_S_CREATEVAULT, "create vault", "Create a vault of the given type.", MT_NOTHING, 0, OC_SPELL);
addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 9, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DIVINE, NA, NA, NULL);
@ -7083,7 +7207,7 @@ void initobjects(void) {
addot(OT_ACIDPOOL, "pool of acid", "A pool of corrosive acid.", MT_ACID, 0, OC_MISC); 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_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, 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_GLYPH, NA, NA, NA, "~");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "evaporates"); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "evaporates");
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of acid"); addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "puddle of acid");
@ -7098,7 +7222,7 @@ void initobjects(void) {
addot(OT_ACIDPUDDLE, "puddle of acid", "A small puddle of corrosive acid.", MT_ACID, 0, OC_MISC); 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_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, 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_GLYPH, NA, NA, NA, "~");
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates"); addflag(lastot->flags, F_OBDIETEXT, NA, NA, NA, "evaporates");
addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL); addflag(lastot->flags, F_OBHP, 4, 4, NA, NULL);
@ -7163,7 +7287,7 @@ void initobjects(void) {
addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 60, OC_MISC); addot(OT_MUDPOOL, "pool of mud", "A large puddle of wet mud.", MT_WATER, 60, OC_MISC);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "{"); addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "~");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL);
@ -7183,6 +7307,11 @@ void initobjects(void) {
addflag(lastot->flags, F_DTCONVERT, DT_COLD, NA, NA, "sheet of ice"); 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_DTCONVERT, DT_FIRE, NA, NA, "puff of steam");
addflag(lastot->flags, F_DRINKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DRINKABLE, 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_OBHPDRAIN, 1, 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_LINKOB, OT_POT_WATER, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
//addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1"); //addflag(lastot->flags, F_WALKDAM, DT_WATER, NA, NA, "0d1+1");
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1"); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+1");
@ -7190,13 +7319,18 @@ void initobjects(void) {
addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 20, OC_MISC); addot(OT_PUDDLEWATERL, "large puddle of water", "A large pool of water.", MT_WATER, 20, OC_MISC);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "{"); addflag(lastot->flags, F_GLYPH, C_BLUE, NA, NA, "~");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 85, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 85, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, 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_COLD, NA, NA, "sheet of ice");
addflag(lastot->flags, F_DTCONVERT, DT_FIRE, NA, NA, "cloud of steam"); 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_DRINKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
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_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_WATER, NA, NA, NULL);
addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+2"); addflag(lastot->flags, F_WALKDAMBP, BP_FEET, DT_WATER, FALLTHRU, "0d1+2");
@ -7245,7 +7379,7 @@ void initobjects(void) {
addot(OT_BLOODPOOL, "pool of blood", "A large pool of blood.", MT_BLOOD, 0, OC_MISC); 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_STACKABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOBLESS, 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_GLYPH, NA, NA, NA, "~");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL);
addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, 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_SLIPPERY, 3, NA, NA, NULL);
@ -7259,7 +7393,15 @@ void initobjects(void) {
addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL); addflag(lastot->flags, F_LINKOB, OT_POT_BLOOD, NA, NA, NULL);
addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL);
addot(OT_WOODENBARREL, "wooden barrel", "A solid wooden barrel.", MT_WOOD, 20, OC_MISC); addot(OT_SIGN, "sign", "A marker with something written on it.", MT_WOOD, 25, OC_MISC);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "|");
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, 6, 6, NA, NULL);
addot(OT_WOODENBARREL, "wooden barrel", "A solid wooden barrel.", MT_WOOD, 40, OC_MISC);
addflag(lastot->flags, F_RARITY, H_VILLAGE, 75, RR_COMMON, NULL);
addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL); addflag(lastot->flags, F_RARITY, H_ALL, 75, NA, NULL);
addflag(lastot->flags, F_GLYPH, NA, NA, NA, "("); addflag(lastot->flags, F_GLYPH, NA, NA, NA, "(");
addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL); addflag(lastot->flags, F_IMPASSABLE, SZ_MIN, SZ_LARGE, NA, NULL);
@ -7321,7 +7463,7 @@ void initobjects(void) {
// effects // effects
addot(OT_FIRELARGE, "large fire", "A large, roaring inferno.", MT_FIRE, 0, OC_EFFECT); addot(OT_FIRELARGE, "large fire", "A large, roaring inferno.", MT_FIRE, 0, OC_EFFECT);
addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "~"); addflag(lastot->flags, F_GLYPH, C_ORANGE, NA, NA, "{");
addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "dies down a little"); 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_DIECONVERT, NA, NA, NA, "medium fire");
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
@ -7332,7 +7474,7 @@ void initobjects(void) {
addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL); addflag(lastot->flags, F_PRODUCESLIGHT, 3, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT); addot(OT_FIREMED, "medium fire", "A medium-sized roaring fire.", MT_FIRE, 0, OC_EFFECT);
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "~"); addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "{");
addflag(lastot->flags, F_DIECONVERT, NA, NA, NA, "small fire"); 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_DIECONVERTTEXT, NA, NA, NA, "dies down a little");
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
@ -7343,7 +7485,7 @@ void initobjects(void) {
addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL); addflag(lastot->flags, F_PRODUCESLIGHT, 2, NA, NA, NULL);
addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!"); addflag(lastot->flags, F_THEREISHERE, B_TRUE, NA, NA, "!");
addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT); addot(OT_FIRESMALL, "small fire", "A small blaze.", MT_FIRE, 0, OC_EFFECT);
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "~"); addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "{");
addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "goes out"); addflag(lastot->flags, F_OBDIETEXT, B_TRUE, NA, NA, "goes out");
addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL);
addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL);
@ -8981,6 +9123,12 @@ int iswearable(object_t *o) {
return B_FALSE; return B_FALSE;
} }
void killallobs(obpile_t *op) {
while (op->first) {
killob(op->first);
}
}
void killmaterial(material_t *m) { void killmaterial(material_t *m) {
material_t *nextone, *lastone; material_t *nextone, *lastone;
@ -9042,9 +9190,7 @@ void killob(object_t *o) {
} }
void killobpile(obpile_t *op) { void killobpile(obpile_t *op) {
while (op->first) { killallobs(op);
killob(op->first);
}
free(op); free(op);
} }
@ -9472,9 +9618,27 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
drawscreen(); drawscreen();
} }
// in case you picked up money, something which changes your AR, etc // special effects if a lifeform picked up an object
if (dst->owner && isplayer(dst->owner)) { if (dst->owner) {
statdirty = B_TRUE; flag_t *f;
// picked up an object in a shop
f = hasflag(o->flags, F_SHOPITEM);
if (f) {
lifeform_t *shk;
shk = findshopkeeper(dst->owner->cell->map, f->val[1]);
if (shk && cansee(shk, dst->owner)) {
askforpayment(shk, dst->owner);
}
if (!isplayer(dst->owner)) {
msg("xxxxxxxxxxxx");
}
}
// in case you picked up money, something which changes your AR, etc
if (isplayer(dst->owner)) {
statdirty = B_TRUE;
}
} }
//o = newobeffects(o); //o = newobeffects(o);
@ -12242,6 +12406,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
char throwverbpres[BUFLEN]; char throwverbpres[BUFLEN];
int acc; int acc;
int youhit = B_FALSE; int youhit = B_FALSE;
int missiledam = 0;
object_t *newob; object_t *newob;
cell_t *newloc; cell_t *newloc;
int db = B_TRUE; int db = B_TRUE;
@ -12347,7 +12512,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (target && isdead(target)) { if (target && isdead(target)) {
target = NULL; target = NULL;
} }
if (thrower && target && !isprone(target)) { if (thrower && target && !isprone(target) && !lfhasflag(target, F_CASTINGSPELL)) {
if (areallies(thrower, target) && !firearm) { if (areallies(thrower, target) && !firearm) {
willcatch = B_TRUE; willcatch = B_TRUE;
} }
@ -12563,7 +12728,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
} }
// an actual physical shield? // an actual physical shield?
shield = getshield(target); shield = getshield(target);
if (shield) { if (shield && !lfhasflag(target, F_CASTINGSPELL)) {
// block chance based on shield skill // block chance based on shield skill
// ie. ST_AVERAGE = speed3 = 18 // ie. ST_AVERAGE = speed3 = 18
// ie. gun = speed20 = 120 = impossible // ie. gun = speed20 = 120 = impossible
@ -12585,6 +12750,8 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
takedamage(shield, dam, DT_PROJECTILE); takedamage(shield, dam, DT_PROJECTILE);
youhit = B_FALSE; youhit = B_FALSE;
practice(target, SK_SHIELDS, 1); practice(target, SK_SHIELDS, 1);
missiledam += ((speed*2)+1);
} }
} }
} }
@ -12600,7 +12767,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
!isimmobile(target) && !isimmobile(target) &&
skillcheck(target, SC_DEX, 15*speed, 0)) { skillcheck(target, SC_DEX, 15*speed, 0)) {
willcatch = B_TRUE; willcatch = B_TRUE;
} else if (skillcheck(target, SC_DODGE, 10*speed, 0)) { } else if (!lfhasflag(target, F_CASTINGSPELL) && skillcheck(target, SC_DODGE, 10*speed, 0)) {
// then check if we dodge it... // then check if we dodge it...
youhit = B_FALSE; youhit = B_FALSE;
} }
@ -12692,6 +12859,8 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (firearm) { if (firearm) {
practice(thrower, SK_RANGED, 1); practice(thrower, SK_RANGED, 1);
} }
missiledam += ((speed*2)+1);
} }
} else { // ie. if !youhit } else { // ie. if !youhit
if (!announcedmiss) { if (!announcedmiss) {
@ -12724,10 +12893,10 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
sprintf(dambuf, "%s (%s by %s)",obname,throwverbpast, realthrowernamea); sprintf(dambuf, "%s (%s by %s)",obname,throwverbpast, realthrowernamea);
shatter(newob, youhit, dambuf, thrower); shatter(newob, youhit, dambuf, thrower);
} else { } else {
// object only gets damaged if it hit someone // object only gets damaged if it hit someone/something
if (youhit) { if (missiledam) {
// don't announce damage to the thrown object // don't announce damage to the thrown object
real_takedamage(newob, speed-1, DT_BASH, B_FALSE); real_takedamage(newob, missiledam, DT_BASH, B_FALSE);
} }
} }
@ -13209,7 +13378,7 @@ void trapeffects(object_t *trapob, enum OBTYPE oid, lifeform_t *lf) {
} else if (oid == OT_TRAPTELEPORT) { } else if (oid == OT_TRAPTELEPORT) {
cell_t *newc; cell_t *newc;
// move somewhere else! // move somewhere else!
newc = getrandomcelloftype(lf->cell->map, lf->cell->map->habitat->id); newc = getrandomcelloftype(lf->cell->map, lf->cell->map->habitat->emptycelltype);
if (newc) { if (newc) {
teleportto(lf, newc, B_TRUE); teleportto(lf, newc, B_TRUE);
} }

View File

@ -16,6 +16,7 @@ obmod_t *addobmod(enum OBMOD id, char *prefix);
obpile_t *addobpile(lifeform_t *owner, cell_t *where); obpile_t *addobpile(lifeform_t *owner, cell_t *where);
void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes); void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes);
objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material, float weight, int obclassid); objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material, float weight, int obclassid);
void adjustdamhardness(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat);
void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat); void adjustdammaterial(unsigned int *dam, enum DAMTYPE damtype, enum MATERIAL mat);
void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype); void adjustdamob(object_t *o, unsigned int *dam, enum DAMTYPE damtype);
int adjustarmourpenalty(lifeform_t *lf, float amt); int adjustarmourpenalty(lifeform_t *lf, float amt);
@ -100,7 +101,7 @@ char *getobhurtname(object_t *o, enum DAMTYPE damtype);
float getobweight(object_t *o); float getobweight(object_t *o);
float getobunitweight(object_t *o); float getobunitweight(object_t *o);
objecttype_t *getoppositestairs(objecttype_t *ot); objecttype_t *getoppositestairs(objecttype_t *ot);
char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth); char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth, int forcehabitat);
char *getrandomob(map_t *map, char *buf); char *getrandomob(map_t *map, char *buf);
char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf); char *getrandomobwithdt(map_t *map, enum DAMTYPE damtype, char *buf);
char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod); char *getrandomobwithclass(map_t *map, enum OBCLASS cid, char *buf, int depthmod);
@ -165,6 +166,7 @@ int istried(object_t *o);
int istriedot(objecttype_t *ot); int istriedot(objecttype_t *ot);
int isweapon(object_t *o); int isweapon(object_t *o);
int iswearable(object_t *o); int iswearable(object_t *o);
void killallobs(obpile_t *op);
void killmaterial(material_t *m); void killmaterial(material_t *m);
void killob(object_t *o); void killob(object_t *o);
void killobpile(obpile_t *o); void killobpile(obpile_t *o);
@ -204,6 +206,7 @@ void setblessed(object_t *o, enum BLESSTYPE wantbless);
int sethiddenname(objecttype_t *o, char *text); int sethiddenname(objecttype_t *o, char *text);
void setinscription(object_t *o, char *text); void setinscription(object_t *o, char *text);
void setobcreatedby(object_t *o, lifeform_t *lf); void setobcreatedby(object_t *o, lifeform_t *lf);
void setwaterdepth(cell_t *c, int depth);
int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf); int shatter(object_t *o, int hitlf, char *damstring, lifeform_t *fromlf);
void shufflehiddennames(void); void shufflehiddennames(void);
object_t *splitob(object_t *o); object_t *splitob(object_t *o);

21
save.c
View File

@ -13,6 +13,7 @@
#include "nexus.h" #include "nexus.h"
#include "objects.h" #include "objects.h"
#include "save.h" #include "save.h"
#include "vault.h"
extern long curtime; extern long curtime;
@ -144,6 +145,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
map_t *m; map_t *m;
int x,y,level,newlevel; int x,y,level,newlevel;
int db = B_TRUE; int db = B_TRUE;
int matid;
if (db) dblog("--> Loading lifeform...\n"); if (db) dblog("--> Loading lifeform...\n");
@ -191,6 +193,8 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
buf[strlen(buf)-1] = '\0'; // strip newline buf[strlen(buf)-1] = '\0'; // strip newline
l->lastdam = strdup(buf + 9); // after 'lastdam: ' l->lastdam = strdup(buf + 9); // after 'lastdam: '
fscanf(f, "material: %d\n",&matid);
l->material = findmaterial(matid);
fscanf(f, "timespent: %d\n",&l->timespent); fscanf(f, "timespent: %d\n",&l->timespent);
fscanf(f, "sorted: %d\n",&l->sorted); fscanf(f, "sorted: %d\n",&l->sorted);
@ -318,6 +322,8 @@ map_t *loadmap(char *basefile) {
celltype_t *ct; celltype_t *ct;
int celltypeid; int celltypeid;
long obid; long obid;
int temphab;
int vid;
//if (db) dblog("cell %d,%d...",x,y); //if (db) dblog("cell %d,%d...",x,y);
@ -334,8 +340,14 @@ map_t *loadmap(char *basefile) {
*/ */
// cell info // cell info
fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n", fscanf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
&c->roomid, &celltypeid, &c->known, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer); &c->roomid, &celltypeid, &c->known, &c->knownglyph.ch, &c->knownglyph.colour, &c->visited, &c->lit, &c->origlit, &c->littimer,&temphab,&vid);
c->habitat = findhabitat(temphab);
if (vid == -1) {
c->vault = NULL;
} else {
c->vault = findvaultbyid(vid);
}
ct = findcelltype(celltypeid); ct = findcelltype(celltypeid);
@ -655,6 +667,7 @@ int savelf(FILE *f, lifeform_t *l) {
fprintf(f, "alive: %d\n",l->alive); fprintf(f, "alive: %d\n",l->alive);
fprintf(f, "lastdamtype: %d\n",l->lastdamtype); fprintf(f, "lastdamtype: %d\n",l->lastdamtype);
fprintf(f, "lastdam: %s\n",l->lastdam); fprintf(f, "lastdam: %s\n",l->lastdam);
fprintf(f, "material: %d\n",l->material->id);
fprintf(f, "timespent: %d\n",l->timespent); fprintf(f, "timespent: %d\n",l->timespent);
fprintf(f, "sorted: %d\n",l->sorted); fprintf(f, "sorted: %d\n",l->sorted);
fprintf(f, "polyrevert: %d\n",l->polyrevert); fprintf(f, "polyrevert: %d\n",l->polyrevert);
@ -751,8 +764,8 @@ int savemap(map_t *m) {
cell_t *c; cell_t *c;
c = getcellat(m, x, y); c = getcellat(m, x, y);
// cell info // cell info
fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d\n", fprintf(f, "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
c->roomid, c->type->id, c->known, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer); c->roomid, c->type->id, c->known, c->knownglyph.ch, c->knownglyph.colour, c->visited,c->lit,c->origlit,c->littimer,c->habitat->id, c->vault ? c->vault->numid : -1);
// cell objects // cell objects
for (o = c->obpile->first ; o ; o = o->next) { for (o = c->obpile->first ; o ; o = o->next) {
fprintf(f, "ob:%ld\n",o->id); fprintf(f, "ob:%ld\n",o->id);

278
spell.c
View File

@ -1093,6 +1093,16 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
gainlevel(user); gainlevel(user);
} }
} }
} else if (abilid == OT_A_BLINDALL) {
lifeform_t *lf;
for (lf = user->cell->map->lf ; lf ; lf = lf->next) {
if (!isplayer(lf)) {
addflag(lf->flags, F_BLIND, B_TRUE, NA, NA, NULL);
killflagsofid(lf->flags, F_WANTS);
killflagsofid(lf->flags, F_WANTSOBFLAG);
}
}
msg("all blinded!");
return B_FALSE; return B_FALSE;
} else if (abilid == OT_A_DEBUG) { } else if (abilid == OT_A_DEBUG) {
cell_t *where; cell_t *where;
@ -1159,6 +1169,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
char dirch; char dirch;
char targetname[BUFLEN]; char targetname[BUFLEN];
flag_t *f; flag_t *f;
int heavyamt = 8;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You lack the stability for a heavy blow while swimming."); if (isplayer(user)) msg("You lack the stability for a heavy blow while swimming.");
@ -1166,8 +1177,8 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
wep = getweapon(user); wep = getweapon(user);
if (!wep || !ismeleeweapon(wep) || (getobunitweight(wep) < 8)) { // ie. 8 is weight of a mace if (!wep || !ismeleeweapon(wep) || (getobunitweight(wep) < heavyamt)) { // ie. 8 is weight of a mace
if (isplayer(user)) msg("You need a heavy weapon to perform a heavy blow!"); if (isplayer(user)) msg("You need a heavy weapon (%dkg or more) to perform a heavy blow!", heavyamt);
return B_TRUE; return B_TRUE;
} }
@ -1207,113 +1218,120 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
flag_t *penalty = NULL; flag_t *penalty = NULL;
int failed = B_TRUE; int failed = B_TRUE;
// ask for direction
if (!targcell) {
dirch = askchar("Steal in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
int dir;
dir = chartodir(dirch);
if (dir == D_NONE) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE ;
} else {
targcell = getcellindir(user->cell, dir);
}
}
target = targcell->lf;
if (!target) {
if (isplayer(user)) msg("There is nobody there to steal from!");
return B_TRUE;
}
taketime(user, getactspeed(user));
slev = getskill(user, SK_THIEVERY); slev = getskill(user, SK_THIEVERY);
if (slev == PR_INEPT) { if (slev == PR_INEPT) {
if (isplayer(user)) msg("You are too unskilled to steal anything!"); if (isplayer(user)) msg("You are too unskilled to steal anything!");
return B_TRUE; return B_TRUE;
} }
getlfname(target, targetname); // stealing shop items
if (isroom(user->cell) && hasobwithflagval(user->cell->obpile, F_SHOPITEM, NA, user->cell->roomid, NA, NULL)) {
// stealing from a shop
char yn;
yn = askchar("Steal something from this shop?", "yn","n", B_TRUE);
if (yn == 'y') {
object_t *o;
flag_t *f;
int value;
if (slev == PR_NOVICE) { taketime(user, getactspeed(user));
penalty = addflag(user->flags, F_ACCURACYMOD, -14, NA, NA, NULL);
} else if (slev == PR_BEGINNER) {
penalty = addflag(user->flags, F_ACCURACYMOD, -7, NA, NA, NULL);
}
// use empty handed attack accuracy value = 0;
wep = getweapon(user); for (o = user->cell->obpile->first ; o ; o = o->next) {
if (rolltohit(user, target, wep, NULL)) { f = hasflagval(o->flags, F_SHOPITEM, NA, user->cell->roomid, NA, NULL);
object_t *o; if (f) {
int i,nsteals; value += f->val[0];
//
if (slev >= PR_EXPERT) {
nsteals = 2;
} else {
nsteals = 1;
}
// what do we steal?
for (i = 0; i < nsteals; i++) {
sprintf(buf, "Steal what (%d of %d)?", i+1, nsteals);
initprompt(&prompt, buf);
addchoice(&prompt, '-', "Nothing", NULL, NULL);
for (o = target->pack->first ; o ; o = o->next) {
int ok = B_TRUE;
if ((slev < PR_SKILLED) && (getobunitweight(o) >= 3)) {
// too heavy to steal
ok = B_FALSE;
} else if ((slev < PR_MASTER) && isequipped(o)) {
// equipped
ok = B_FALSE;
} else if (!canpickup(user, o, 1)) {
// can't pick it up
ok = B_FALSE;
}
if (ok) {
getobname(o, buf, 1);
addchoice(&prompt, o->letter, buf, NULL, o);
} }
} }
if (prompt.nchoices > 1) { // skillcheck - difficulty based on total value of objects here
if (slev >= PR_ADEPT) { // 15 + value/50 means:
// pick what you want // $50 is diff 16
getchoice(&prompt); // $100 is diff 17
o = (object_t *)prompt.result; // $200 is diff 19
} else { // $500 is diff 25
// random // $1000 is diff 35
o = (object_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data; if (skillcheck(user, SC_STEAL, 15+(value/50), 0)) {
} // success
if (o) { if (steal(user, user->cell->obpile, F_SHOPITEM)) {
o = moveob(o, user->pack, 1); if (isplayer(user)) {
if (o) { msg("There doesn't seem to be anything here which you could steal.");
getobname(o, buf, 1);
if (isplayer(user)) {
msg("You steal %s from %s!", buf, targetname);
} else if (cansee(player, user)) {
msg("%s steals %s from %s!", username, buf, targetname);
}
failed = B_FALSE;
} }
} }
} else { } else {
break; lifeform_t *shk;
msg("You try to steal something, but fail.");
// failed
shk = findshopkeeper(user->cell->map, user->cell->roomid);
if (shk) { // doesn't need to see you - he SENSES it!
say(shk, "THIEF!", SV_ROAR);
fightback(shk, user);
callguards(shk, user);
}
} }
}
}
if (penalty) {
killflag(penalty);
}
if (failed) {
if (isplayer(user)) {
msg("You try to steal from %s, but fail.", targetname);
} else if (cansee(player, user)) {
msg("%s tries to steal from %s, but fails.", username, targetname);
} }
} else { } else {
practice(user, SK_THIEVERY, 1); // stealing from a lifeform
// ask for direction
if (!targcell) {
dirch = askchar("Steal in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE);
int dir;
dir = chartodir(dirch);
if (dir == D_NONE) {
if (isplayer(user)) msg("Cancelled.");
return B_TRUE ;
} else {
targcell = getcellindir(user->cell, dir);
}
}
target = targcell->lf;
if (!target) {
if (isplayer(user)) msg("There is nobody there to steal from!");
return B_TRUE;
}
taketime(user, getactspeed(user));
getlfname(target, targetname);
if (slev == PR_NOVICE) {
penalty = addflag(user->flags, F_ACCURACYMOD, -14, NA, NA, NULL);
} else if (slev == PR_BEGINNER) {
penalty = addflag(user->flags, F_ACCURACYMOD, -7, NA, NA, NULL);
}
// use empty handed attack accuracy
wep = getweapon(user);
if (rolltohit(user, target, wep, NULL)) {
// success!
failed = B_FALSE;
if (steal(user, target->pack, F_NONE)) {
if (isplayer(user)) {
msg("%s has nothing for you to steal!", targetname);
}
}
} else {
failed = B_TRUE;
}
if (penalty) {
killflag(penalty);
}
if (failed) {
if (isplayer(user)) {
msg("You try to steal from %s, but fail.", targetname);
} else if (cansee(player, user)) {
msg("%s tries to steal from %s, but fails.", username, targetname);
}
// ai will get angry!
if (cansee(target, user) && !isplayer(target)) {
fightback(target, user);
}
} else {
practice(user, SK_THIEVERY, 1);
}
} }
} else if (abilid == OT_A_WARCRY) { } else if (abilid == OT_A_WARCRY) {
// announce // announce
@ -1749,8 +1767,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
targcell = caster->cell; targcell = caster->cell;
target = caster; target = caster;
f = addtempflag(caster->flags, F_MAGICARMOUR, power*2, NA, NA, "skin of bark", FROMSPELL); //f = addtempflag(caster->flags, F_MAGICARMOUR, power*2, NA, NA, "skin of bark", FROMSPELL);
f->obfrom = spellid; //f->obfrom = spellid;
setlfmaterial(target, MT_WOOD);
f = addtempflag(caster->flags, F_DTVULN, DT_FIRE, NA, NA, "2d4", FROMSPELL); f = addtempflag(caster->flags, F_DTVULN, DT_FIRE, NA, NA, "2d4", FROMSPELL);
f->obfrom = spellid; f->obfrom = spellid;
} else if (spellid == OT_S_BLADEBURN) { } else if (spellid == OT_S_BLADEBURN) {
@ -2473,7 +2493,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else { } else {
// random one // random one
r = getreallyrandomrace(); r = getreallyrandomrace(RC_ANY);
} }
@ -2497,16 +2517,50 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
return B_TRUE; return B_TRUE;
} }
} else if (spellid == OT_S_CLEARLEVEL) {
int x,y;
cell_t *c;
for (y = 0; y < caster->cell->map->h ; y++) {
for (x = 0; x < caster->cell->map->w ; x++) {
c = getcellat(caster->cell->map, x, y);
if (c) {
if (c->lf && isplayer(c->lf)) {
} else {
clearcell(c);
setcelltype(c, c->map->habitat->solidcelltype);
}
}
}
}
needredraw = B_TRUE;
} else if (spellid == OT_S_CREATEVAULT) { } else if (spellid == OT_S_CREATEVAULT) {
vault_t *v; vault_t *v;
int vx,vy;
int vw,vh;
// ask for a vaulttype // ask for a vaulttype
v = askvault("Create which vault?"); v = askvault("Create which vault?");
if (createvault(caster->cell->map, caster->cell->map->nrooms, v, NULL, NULL)) { if (createvault(caster->cell->map, caster->cell->map->nrooms, v, &vw, &vh, &vx, &vy)) {
msg("Couldn't create a vault."); msg("Couldn't create a vault.");
} else { } else {
msg("BAM! A vault has appeared nearby."); char ch;
msg("BAM! A vault has appeared nearby."); more();
needredraw = B_TRUE; needredraw = B_TRUE;
ch = askchar("Teleport to the new vault", "yn","y", B_TRUE);
if (ch == 'y') {
int x,y;
cell_t *c;
// find it
for (y = vy; y < vy+vh; y++) {
for (x = vy; x < vx + vw; x++) {
c = getcellat(caster->cell->map, x, y);
if (c && cellwalkable(caster, c, NULL)) {
teleportto(caster, c, B_TRUE);
return B_FALSE;
}
}
}
}
} }
} else if (spellid == OT_S_CUREPOISON) { } else if (spellid == OT_S_CUREPOISON) {
@ -2653,6 +2707,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
ndigs++; ndigs++;
// go to next cell
c = getcellindir(c, dir);
} }
// announce destruction of any walls seen // announce destruction of any walls seen
@ -2963,12 +3019,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
targcell = getcellat(caster->cell->map, x,y); targcell = getcellat(caster->cell->map, x,y);
if (targcell && (getcelldist(caster->cell, targcell) <= range)) { if (targcell && (getcelldist(caster->cell, targcell) <= range)) {
if (targcell->lf && (targcell->lf != caster) && haslof(caster->cell, targcell, B_FALSE, NULL)) { if (targcell->lf && (targcell->lf != caster) && haslof(caster->cell, targcell, B_FALSE, NULL)) {
char lfname[BUFLEN];
// automatic hit // automatic hit
getlfname(targcell->lf, lfname); if (isplayer(targcell->lf)) {
msg("A blast of energy hits you!");
}
/*
if (haslos(caster, targcell)) { if (haslos(caster, targcell)) {
msg("A blast of energy hits %s.",lfname); msg("A blast of energy hits %s.",lfname);
} }
*/
losehp(targcell->lf, rnd(2,6), DT_MAGIC, caster, "an energy blast"); losehp(targcell->lf, rnd(2,6), DT_MAGIC, caster, "an energy blast");
} }
} }
@ -3085,8 +3144,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int depth; int depth;
depth = DP_SHOULDERS + power; depth = DP_SHOULDERS + power;
amt = ((power+1) * (power+1)) - 1; //amt = ((power+1) * (power+1)) - 1;
//amt = power; //amt = power;
amt = power*2;
badoid[0] = OT_WATERDEEP; badoid[0] = OT_WATERDEEP;
badoid[1] = OT_NONE; badoid[1] = OT_NONE;
for (i = 0; i < amt; i++) { for (i = 0; i < amt; i++) {
@ -4021,9 +4081,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
c = getcellat(m, x, y); c = getcellat(m, x, y);
if (c) { if (c) {
if (range == UNLIMITED) { if (range == UNLIMITED) {
setcellknown(c, PR_ADEPT); setcellknown(c, MAXOF(PR_ADEPT, getskill(caster, SK_CARTOGRAPHY)));
} else if (getcelldist(caster->cell, c) <= range) { } else if (getcelldist(caster->cell, c) <= range) {
setcellknown(c, PR_ADEPT); setcellknown(c, MAXOF(PR_ADEPT, getskill(caster, SK_CARTOGRAPHY)));
} }
} }
} }
@ -4131,6 +4191,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// restore player pointer // restore player pointer
player = oldplayer; player = oldplayer;
//showlfstats(where->lf, B_TRUE); //showlfstats(where->lf, B_TRUE);
needredraw = B_TRUE;
statdirty = B_TRUE;
} else { } else {
failed = B_TRUE; failed = B_TRUE;
} }
@ -4580,7 +4643,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!newmap) { if (!newmap) {
// create new map // create new map
newmap = addmap(); newmap = addmap();
createmap(newmap, newdepth, caster->cell->map->region, NULL, D_NONE); createmap(newmap, newdepth, caster->cell->map->region, NULL, D_NONE, NULL);
} }
@ -6945,7 +7008,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
default: default:
if (spellskill == PR_INEPT) { if (spellskill == PR_INEPT) {
if (db) { if (db) {
dblog("-->power = 0 (inept in SORCERY)"); dblog("-->power = 0 (inept in sorcery)");
} }
return 0; return 0;
} }
@ -7096,9 +7159,6 @@ char *getvarpowerspelldesc(enum OBTYPE spellid, int power, char *buf) {
// default // default
strcpy(buf, ""); strcpy(buf, "");
switch (spellid) { switch (spellid) {
case OT_S_BARKSKIN:
sprintf(buf, "+%d Armour Rating, Fire Vulnerability", power*2);
break;
case OT_S_PSYARMOUR: case OT_S_PSYARMOUR:
sprintf(buf, "+%d Armour Rating", power*4); sprintf(buf, "+%d Armour Rating", power*4);
break; break;
@ -7281,7 +7341,9 @@ void stopspell(lifeform_t *caster, enum OBTYPE spellid) {
killob(o); killob(o);
} }
} }
if (spellid == OT_S_FLOATINGDISC) { if ((spellid == OT_S_BARKSKIN) && (getlfmaterial(caster) == MT_WOOD)) {
setlfmaterial(caster, caster->race->material->id);
} else if (spellid == OT_S_FLOATINGDISC) {
map_t *m; map_t *m;
lifeform_t *lf; lifeform_t *lf;
for (m = firstmap ; m ; m = m->next) { for (m = firstmap ; m ; m = m->next) {

25
vaults/crosshatch.vlt Normal file
View File

@ -0,0 +1,25 @@
@id:crosshatch
@map
###########
##.#.#.#.##
#.#.#.#.#.#
##.#.#.#.##
#.#.#.#.#.#
##.#.#.#.##
#.#.#.#.#.#
##.#.#.#.##
#.#.#.#.#.#
##.#.#.#.##
###########
@end
@legend
#:cell:rock wall
@end
@flags
! autoscale, lock xy
goesin:dungeon
autodoors:50
autopop
@end

24
vaults/diagcross.vlt Normal file
View File

@ -0,0 +1,24 @@
@id:diagonal_cross
@map
#X.#####.X#
##..###..##
###..#..###
####...####
####...####
####.#.####
###.###.###
##..###..##
#X.#####.X#
@end
@legend
#:cell:rock wall
X:exit
@end
@flags
! autoscale, lock xy
goesin:dungeon
mayrotate
@end

31
vaults/jimbo.vlt Normal file
View File

@ -0,0 +1,31 @@
! Boss room for Jimbo the dungeonkeeper
@id:jimbos_lair
@map
############
#........|,#
#....-/-.###
+......@.|,#
#..-/-...###
#........|,#
############
@end
@legend
#:cell:rock wall
|:ob:locked iron gate
,:ob:1-4 bones:50
+:ob:wooden door
/:ob:wooden table
-:ob:wooden footstool
@:mon:Jimbo
@end
@flags
goesin:dungeon
norandom
scatter(1,1,-2,-2) ob:wooden footstool:0-3
scatter(1,1,-2,-2) ob:random food:0-2
mayrotate
@end

View File

@ -36,7 +36,7 @@ scatter(0,0,-1,-1) ob:gnoll corpse:1-3:33
! scattered weapons ! scattered weapons
scatter(0,0,-1,-1) ob:common weapon:4-5 scatter(0,0,-1,-1) ob:common weapon:4-5
! TODO: scattered minions around ?? ! TODO: scattered minions around ??
! mayrotate mayrotate
! mayscale ! mayscale
@end @end

24
vaults/riverroom.vlt Normal file
View File

@ -0,0 +1,24 @@
! a room split in half by a river
@id:river_room
@map
##########
#...~~...#
#...~~...#
#...~~...#
#...~~...#
#...~~...#
##########
@end
@legend
#:cell:rock wall
~:cell:low rock floor
~:ob:very deep water
@end
@flags
goesin:dungeon
autodoors:50
mayrotate
@end

29
vaults/shop_armour.vlt Normal file
View File

@ -0,0 +1,29 @@
@id:armour_shop
@map
.#####
.#ppp#
s+ppp#
.#ppp#
.#####
@end
@legend
.:cell:dirt
#:cell:wooden wall
p:cell:shop floor
p:ob:armour
+:cell:dirt
+:ob:wooden door
s:ob:sign "Armour shop"
@end
@flags
shop
! because this is the first lf in a shop, it will
! become the shopkeeper.
scatter(2,1,-2,-2) mon:humanoid:1
norandom
mayrotate
margin:5,5
@end

29
vaults/shop_potion.vlt Normal file
View File

@ -0,0 +1,29 @@
@id:potion_shop
@map
.#####
.#ppp#
s+ppp#
.#ppp#
.#####
@end
@legend
.:cell:dirt
#:cell:wooden wall
p:cell:shop floor
p:ob:potion
+:cell:dirt
+:ob:wooden door
s:ob:sign "Potion shop"
@end
@flags
shop
! because this is the first lf in a shop, it will
! become the shopkeeper.
scatter(2,1,-2,-2) mon:humanoid:1
norandom
mayrotate
margin:5,5
@end

29
vaults/shop_weapon.vlt Normal file
View File

@ -0,0 +1,29 @@
@id:weapon_shop
@map
.#####
.#ppp#
s+ppp#
.#ppp#
.#####
@end
@legend
.:cell:dirt
#:cell:wooden wall
p:cell:shop floor
p:ob:weapon
+:cell:dirt
+:ob:wooden door
s:ob:sign "Weapon shop"
@end
@flags
shop
! because this is the first lf in a shop, it will
! become the shopkeeper.
scatter(2,1,-2,-2) mon:humanoid:1
norandom
mayrotate
margin:5,5
@end

19
vaults/uturn.vlt Normal file
View File

@ -0,0 +1,19 @@
@id:uturn
@map
###########
###.....###
##..###..##
#X.#####.X#
@end
@legend
#:cell:rock wall
X:exit
@end
@flags
! autoscale
goesin:dungeon
mayrotate
@end

View File

@ -16,6 +16,7 @@ $:ob:25-200 gold
@flags @flags
goesin:dungeon goesin:dungeon
mayrotate
! no auto doors. ie this can be in the middle of nowhere. ! no auto doors. ie this can be in the middle of nowhere.
@end @end