* [+] fire should set equipped obs on fire too

* [+] trapped doors/objcets
* [+] make careful walking have less chance of triggering some traps
      (eg tripwire)
- [+] dex penalty when drunk
- [+] require dex to put on most shoes
- [+] Diety's short sword of pyromania isn't appearing?
- [+] make sure i can tumble over traps
* [+] able to cut tripwires with slashing/chopping/piercing weapons?
- [+] maybe make cmomando have no weapon skill
- [+] make armour more common
- [+] shouldnt be able to swap place with someone who is sleeping
- [+] if you're not in the water, can't see lfs in water (unless they
      are adjacent)
- [+] You break free from the zombie!  You reintegrate inside a solid
      object!--More--
* [+] shopkeepers will charge an extra fee to identify stuff
- [+] shouldn't get an empty flask when I dirnk from a fountain!
- [+] identify and remove curse scrolls should be COMMON
* [+] provide detailed skill descriptions
- [+] dumpoutlines()
- [+] make minotaurs stay in room
- [+] make minotaurs have good smell
- [+] don't auotreveal vaults.
* [+] should be able to fill flasks from fountains
- [+] don't announce corpse decay death while training.
* [+] add the initial godstone at the bottom of firstdungeon
* [+] make fountains names same as their linked potions
- [+] bug: when filling potions from the ground, ground object was
      never dryaing up
Beggars
- [+] stealing ability sometimes. run away after using this
* [+] various lots of generic f_talktext->"have a coin to spare?"
World map
- [+] 1-2,1-2: habitat: village
- [+] multiple villages
- [+] vault: island with treasure (or acid island?)
- [+] jump into a water  - it splashes small puddles to surrounding
      cells
* [+] let dig spell go up/down.
* [+] fountains, random potion effect or water (blue _ or })
- [+] make thingchance and obchance be habitat_t parameters.
work on game goal
- [+] find a way out of the magical dungeon barriers in the first
      dungeon
- [+] slime
- [+] troll = t
- [+] lizardman
- [+] ogre
- [+] kobold
- [+] fire sprite
- [+] hobgoblin
- [+] bugbear
- [+] gnoll
- [+] giant
- [+] zombie
- [+] skeleton
* [+] ghoul
- [+] ghast
- [+] can operate spanner to
    - [+] jam/unjam a door
* [+] visibility
- [+] initial code for monsters opening doors while giving chase
- [+] acid does more damage to armour
* [+] implement temporary flags. 
* [+] implement unknown flags
- [+] mana spike
- [+] energy bolt
- [+] energy blast (hits all in radius)
- [+] flash (like flashbang)
- [+] telekinesis (open/close doors remotely, grab/throw objects
      remotely)
- [+] mindscan - knoweldge of hp etc
* [+] airblast (push obs, push someone very far, AND lose obs. break
      walls they hit?)
- [+] fireball - sets on fire
- [+] flamepillar
- [+] fire arrow
- [+] spark (light a flammable object)
- [+] flameburst - 2d8+3 damage in a circle
- [+] burning wave - 2d10 damage and set on firea, line towards target
    - [+] range 3
- [+] freezing touch (turns an object to ice)
- [+] knock - opens doors
- [+] gas form
- [+] polymorph
- [+] write on floor
- [+] light
- [+] weaken (lose str)
- [+] poison cloud - change cloudkill to this?
- [+] animate dead
- [+] posession
- [+] minor healing
- [+] healing
- [+] turn undead
- [+] identify
- [+] detect magic
- [+] detect aura
- [+] reveal surroundings
- [+] uncontrolled teleport
- [+] speed
- [+] slow
- [+] boost gravity
- [+] create monster
- [+] divine
    - [+] wish
This commit is contained in:
Rob Pearce 2011-07-21 01:43:45 +00:00
parent 7c86e87f4a
commit ce878f6ae8
17 changed files with 1558 additions and 596 deletions

22
ai.c
View File

@ -235,9 +235,20 @@ cell_t *aigetlastknownpos(lifeform_t *lf, lifeform_t *target, int *lastx, int *l
object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) { object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra) {
int db = B_FALSE; int db = B_FALSE;
enum ATTRBRACKET iqb;
object_t *o; object_t *o;
if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; if (lfhasflag(lf, F_DEBUG)) db = B_TRUE;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
if (iqb <= IQ_ANIMAL) {
// animal and lower intelligence won't use ranged
// attacks.
if (db) dblog(".oO { no ranged attack due to low iq. }");
*ra = RA_NONE;
return NULL;
}
o = getfirearm(lf); o = getfirearm(lf);
if (o && getammo(o)) { if (o && getammo(o)) {
if (db) { if (db) {
@ -591,6 +602,11 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// spell failed. we will keep going through aiturn. // spell failed. we will keep going through aiturn.
} else { } else {
// spell succesful // spell succesful
if (spell == OT_A_STEAL) {
// run away for a few turns
fleefrom(lf, spelllf, rnd(3,7), B_TRUE);
}
return B_FALSE; return B_FALSE;
} }
} }
@ -633,14 +649,10 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
// if we got here, we're either at the correct distance or couldn't // if we got here, we're either at the correct distance or couldn't
// move. // move.
if (attackok) { if (attackok) {
enum ATTRBRACKET iqb;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
// if not adjacent, check for guns, wands, throwing // if not adjacent, check for guns, wands, throwing
if ( (rangedattack != RA_NONE) && if ( (rangedattack != RA_NONE) &&
haslof(lf->cell, target->cell, LOF_NEED, NULL) && // and we have line of fire to them haslof(lf->cell, target->cell, LOF_NEED, NULL) && // and we have line of fire to them
(onein(2) || (getcelldist(lf->cell, target->cell) > 1) ) && // and we're not adjacent to target OR random (onein(2) || (getcelldist(lf->cell, target->cell) > 1) )) { // and we're not adjacent to target OR random
(iqb > IQ_ANIMAL) ) { // and we are smarter than an animal
if (rangedattack == RA_GUN) { if (rangedattack == RA_GUN) {
setguntarget(lf, target); setguntarget(lf, target);
if (!shoot(lf)) { if (!shoot(lf)) {

View File

@ -185,6 +185,13 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
return B_TRUE; return B_TRUE;
} }
}; };
} else {
// otehr attackable ob here?
o = hasobwithflag(c->obpile, F_ATTACKABLE);
if (o) {
attacktype = AT_OB;
attacktarget = o;
} else { } else {
// TODO: attack wall? // TODO: attack wall?
if (isplayer(lf) && !lfhasflag(lf, F_HURRICANESTRIKE)) { if (isplayer(lf) && !lfhasflag(lf, F_HURRICANESTRIKE)) {
@ -193,6 +200,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
return B_TRUE; return B_TRUE;
} }
} }
}
// stop sprinting // stop sprinting
sf = lfhasflag(lf, F_SPRINTING); sf = lfhasflag(lf, F_SPRINTING);
@ -562,7 +570,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
!lfhasflagval(victim, F_TARGETLF, lf->id, NA, NA, NULL) // victim isnt attacking us !lfhasflagval(victim, F_TARGETLF, lf->id, NA, NA, NULL) // victim isnt attacking us
) { ) {
addflag(victim->flags, F_STABBEDBY, lf->id, NA, NA, NULL); addflag(victim->flags, F_STABBEDBY, lf->id, NA, NA, NULL);
dam[0] *= (getskill(lf, SK_BACKSTAB)*2); dam[0] *= (getskill(lf, SK_BACKSTAB));
firstisbackstab = B_TRUE; firstisbackstab = B_TRUE;
} }
// extra damage for being skilled? // extra damage for being skilled?
@ -1131,7 +1139,7 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
if (isunarmed) { if (isunarmed) {
// touch effects // touch effects
touch(lf, o); touch(lf, o);
} else { } else if (hasflag(o->flags, F_IMPASSABLE)) {
// weapon gets damaged ? // weapon gets damaged ?
if (wep && (ndam > 0)) { if (wep && (ndam > 0)) {
if (wepdullable(wep)) { if (wepdullable(wep)) {

43
defs.h
View File

@ -11,10 +11,10 @@
#define WETTIME 10 // how long it takes for things to dry #define WETTIME 10 // how long it takes for things to dry
#define DRUNKTIME 10 // how long it takes for alcohol to wear off #define DRUNKTIME 10 // how long it takes for alcohol to wear off
/* // chances of things happening
#define POISONDAMCHANCE 33 // chance of vomitting when poisoned #define ONEIN_FOUNTAINDRYUP 3
#define POISONDAM 2 // damage taken from vomiting when poisoned
*/ #define SHOPIDENTPRICE 50 // cost to identify a just-purchased item
// ncurses colours // ncurses colours
#define C_NONE (-1) #define C_NONE (-1)
@ -46,9 +46,11 @@ enum NOISECLASS {
}; };
enum SAYPHRASE { enum SAYPHRASE {
SP_BEG,
SP_DRUNK, SP_DRUNK,
SP_PAYWARN, SP_PAYWARN,
SP_PAYTHREAT, SP_PAYTHREAT,
SP_PAYTHANKS,
SP_RECRUIT_ACCEPT, SP_RECRUIT_ACCEPT,
SP_RECRUIT_ASKPRICE, SP_RECRUIT_ASKPRICE,
SP_RECRUIT_DECLINE, SP_RECRUIT_DECLINE,
@ -137,6 +139,7 @@ enum SKILLLEVEL {
PR_EXPERT = 5, PR_EXPERT = 5,
PR_MASTER = 6, PR_MASTER = 6,
}; };
#define MAXSKILLLEVEL 7
// save/load // save/load
@ -258,6 +261,7 @@ enum SENSE {
#define FROMBLESSING (-9866) #define FROMBLESSING (-9866)
#define FROMBRAND (-7865) #define FROMBRAND (-7865)
#define FROMOBMOD (-7864) #define FROMOBMOD (-7864)
#define FROMSKILL (-7863)
#define FROMEXTERNAL_LOW (-7999) #define FROMEXTERNAL_LOW (-7999)
@ -586,6 +590,7 @@ enum OBCLASS {
OC_FLORA, OC_FLORA,
OC_FOOD, OC_FOOD,
OC_FURNITURE, OC_FURNITURE,
OC_GODSTONE,
OC_MISC, OC_MISC,
OC_MISSILE, OC_MISSILE,
OC_MONEY, OC_MONEY,
@ -652,6 +657,7 @@ enum RACE {
// human monsters // human monsters
R_HUMAN, R_HUMAN,
R_BANDIT, R_BANDIT,
R_BEGGAR,
R_DRUNK, R_DRUNK,
R_TOWNGUARD, R_TOWNGUARD,
// monsters // monsters
@ -807,6 +813,7 @@ enum MATERIAL {
MT_SILK = 24, MT_SILK = 24,
MT_OIL = 25, MT_OIL = 25,
MT_PLANT = 26, MT_PLANT = 26,
MT_WIRE = 27,
}; };
// Object Types // Object Types
@ -850,6 +857,7 @@ enum OBTYPE {
OT_ASHCONCEAL, OT_ASHCONCEAL,
OT_ASHSLEEP, OT_ASHSLEEP,
OT_GEMOFSEEING, OT_GEMOFSEEING,
OT_GODSTONEJ,
// flora // flora
OT_FLOWER, OT_FLOWER,
OT_LEAF, OT_LEAF,
@ -1267,6 +1275,7 @@ enum OBTYPE {
// armour - shields // armour - shields
OT_BUCKLER, OT_BUCKLER,
OT_SHIELD, OT_SHIELD,
OT_SHIELDHIDE,
OT_SHIELDLARGE, OT_SHIELDLARGE,
OT_SHIELDTOWER, OT_SHIELDTOWER,
// rings // rings
@ -1531,6 +1540,7 @@ enum FLAG {
F_NOGLYPH, // this object doesn't appear normally F_NOGLYPH, // this object doesn't appear normally
F_COSMETIC, // this object is mostly cosmetic, don't say 'you see xx' F_COSMETIC, // this object is mostly cosmetic, don't say 'you see xx'
F_NOPICKUP, // cannot pick this up F_NOPICKUP, // cannot pick this up
F_ATTACKABLE, // can attack this with 'A'
F_IMPASSABLE, // cannot walk past this if your size is between v0 and v1 F_IMPASSABLE, // cannot walk past this if your size is between v0 and v1
// (inclusive) // (inclusive)
F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it F_CRUSHABLE, // if you are bigger than size v0, walking on this crushes it
@ -1618,11 +1628,19 @@ enum FLAG {
F_PICKLOCKS, // can pick locks? val0=% change, F_PICKLOCKS, // can pick locks? val0=% change,
// val1=b_false, f_dieonfail, f_bluntonfail // val1=b_false, f_dieonfail, f_bluntonfail
F_LOCKABLE,// this object can be locked F_LOCKABLE,// this object can be locked
F_TRAP, // this object is a trap. v0 is sc_disarm difficulty. F_CANBETRAPPED, // this object might start with a trap
// v0 = base pct chance
// v1 = extra pct chance every 5 levels
// v2 = max trap chance
F_TRAPPED, // this object HAS a trap.
// v0 is the trap object type
// v2 = TRUE means we've spotted this.
F_TRAP, // this object _IS_ a trap. v0 is sc_disarm/sc_spot difficulty.
// (NA = impossible) // (NA = impossible)
// if v1 = true, trap will go off if you fail your 2nd disarm // if v1 = true, trap will go off if you fail your 2nd disarm
// check. // check.
// v2 = sc_dodge difficulty // v2 = sc_dodge difficulty
F_OBJECTTRAP, // this trap can go onto an object (door, chest, etc)
// doors // doors
F_DOOR, // this object is a door - ie. can open it F_DOOR, // this object is a door - ie. can open it
// v0 and v1 are like F_IMPASSABLE // v0 and v1 are like F_IMPASSABLE
@ -1723,6 +1741,7 @@ enum FLAG {
F_CHARGES, // generally the number of uses left,v0=min, v1=max F_CHARGES, // generally the number of uses left,v0=min, v1=max
F_DONTSHOWCHARGES, // don't show 'xx charges left' when id'd F_DONTSHOWCHARGES, // don't show 'xx charges left' when id'd
F_RECHARGEWHENOFF, // get power back when you turn it off F_RECHARGEWHENOFF, // get power back when you turn it off
F_RECHARGE, // get v0 charges back each turn.
F_REFILLWITH, // pour obj id val0 onto this to refill its charges F_REFILLWITH, // pour obj id val0 onto this to refill its charges
// //
F_POWDER, // this item is a powder F_POWDER, // this item is a powder
@ -1739,7 +1758,6 @@ enum FLAG {
F_NODIECONVERTTEXT, // don't anounce when this object changes F_NODIECONVERTTEXT, // don't anounce when this object changes
// misc flags // misc flags
F_LINKOB, // val0 = linked object id F_LINKOB, // val0 = linked object id
// for fountains: v2 = ifknown
F_LINKRACE, // val0 = linked race id F_LINKRACE, // val0 = linked race id
// scroll flags // scroll flags
F_LINKSPELL, // val0 = spell this scroll will cast when read F_LINKSPELL, // val0 = spell this scroll will cast when read
@ -1866,6 +1884,9 @@ enum FLAG {
F_STAYINHABITAT, // lf will not walk onto a cell of a different F_STAYINHABITAT, // lf will not walk onto a cell of a different
// habitat // habitat
F_STAYINROOM, // lf will not walk out of roomid v0 F_STAYINROOM, // lf will not walk out of roomid v0
// if v0 is not set, we won't leave our current room.
// if v1 is set (not NA), then we are allowed to chase
// our targets out of the room.
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
@ -2178,6 +2199,7 @@ enum FLAG {
// 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 F_VAULTISSHOP, // this vault is a shop, so add f_shopitem to objects
// here. // here.
F_VAULTISSHRINE, // this vault is a godstone shrine
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
@ -2221,6 +2243,8 @@ enum HUNGER {
#define B_FALSE (0) #define B_FALSE (0)
#define B_TRUE (-1) #define B_TRUE (-1)
#define B_MAYCHASE (-1)
#define B_NODOORS (0) #define B_NODOORS (0)
#define B_DONTKILL (-1) #define B_DONTKILL (-1)
@ -2434,6 +2458,7 @@ enum HABITAT {
typedef struct regiontype_s { typedef struct regiontype_s {
enum REGIONTYPE id; enum REGIONTYPE id;
enum HABITAT defaulthabitat; enum HABITAT defaulthabitat;
char *name;
int maxdepth; int maxdepth;
int stairsperlev; int stairsperlev;
int deeperdir; int deeperdir;
@ -2457,7 +2482,7 @@ typedef struct regionthing_s {
char *what; char *what;
} regionthing_t; } regionthing_t;
#define MAXOUTLINETHINGS 20 #define MAXOUTLINETHINGS 60
typedef struct regionoutline_s { typedef struct regionoutline_s {
int id; int id;
regiontype_t *rtype; regiontype_t *rtype;
@ -2736,6 +2761,10 @@ typedef struct skill_s {
enum SKILL id; enum SKILL id;
char *name; char *name;
char *desc; char *desc;
enum SKILLLEVEL skilldesclev[MAXSKILLLEVEL*2];
char *skilldesctext[MAXSKILLLEVEL*2];
int skilldescmsg[MAXSKILLLEVEL*2];
int nskilldesc;
int traintime; int traintime;
struct skill_s *next, *prev; struct skill_s *next, *prev;
} skill_t; } skill_t;

View File

@ -4,8 +4,10 @@ defs.h:
lf.c: lf.c:
add addskill() add addskill()
add addskilldesc()
if it is a lore skill, update isloreskill() if it is a lore skill, update isloreskill()
if it is a weapon skill, update isweaponskill() if it is a weapon skill, update isweaponskill()
assign to jobs assign to jobs

1
flag.c
View File

@ -479,6 +479,7 @@ flag_t *hasflag_real(flagpile_t *fp, int id, int wantknown, flag_t *exception) {
if (f == exception) valid = B_FALSE; if (f == exception) valid = B_FALSE;
if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE; if ((wantknown != NA) && (f->known != wantknown)) valid = B_FALSE;
if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) valid = B_FALSE; if (owner && (f->lifetime == FROMJOB) && !getjob(owner)) valid = B_FALSE;
//if (owner && (f->lifetime == FROMSKILL) && !getskill(owner, xxx)) valid = B_FALSE;
if (valid) { if (valid) {
foundflag = f; foundflag = f;

99
io.c
View File

@ -60,6 +60,8 @@ extern long curtime;
char msgbuf[HUGEBUFLEN]; char msgbuf[HUGEBUFLEN];
char lastmsgbuf[HUGEBUFLEN]; char lastmsgbuf[HUGEBUFLEN];
char prevmsg[HUGEBUFLEN];
int msgmulti = 1;
extern lifeform_t *player; extern lifeform_t *player;
@ -3253,6 +3255,7 @@ void describeob(object_t *o) {
y++; y++;
} }
// charges remaining
if (o->type->obclass->id == OC_WAND) { if (o->type->obclass->id == OC_WAND) {
if (isidentified(o)) { if (isidentified(o)) {
int charges; int charges;
@ -3264,6 +3267,17 @@ void describeob(object_t *o) {
} }
y++; y++;
} }
} else if (o->type->obclass->id == OC_GODSTONE) {
if (isidentified(o)) {
int charges,max;
getchargeinfo(o, &charges, &max);
if (charges == max) {
mvwprintw(mainwin, y, 0, "It is fully charged.");
} else {
mvwprintw(mainwin, y, 0, "It is depleted.");
}
y++;
}
} }
f = hasflag(o->flags, F_PICKLOCKS); f = hasflag(o->flags, F_PICKLOCKS);
@ -3283,6 +3297,11 @@ void describeob(object_t *o) {
// skip line // skip line
y++; y++;
// been made invulnerable ?
if (hasflagknown(o->type->flags, F_INVULNERABLE) && !hasflag(o->flags, F_DAMAGABLE)) {
mvwprintw(mainwin, y, 0, "It is invulnerable to most damage.");
y++;
} else {
// immunities // immunities
strcpy(buf, ""); strcpy(buf, "");
f = hasflagval(o->flags, F_DTIMMUNE, DT_ALL, NA, NA, NULL); f = hasflagval(o->flags, F_DTIMMUNE, DT_ALL, NA, NA, NULL);
@ -3363,13 +3382,9 @@ void describeob(object_t *o) {
mvwprintw(mainwin, y, 0, buf); mvwprintw(mainwin, y, 0, buf);
y++; y++;
} }
// been made invulnerable ?
if (hasflag(o->type->flags, F_INVULNERABLE) && !hasflag(o->flags, F_DAMAGABLE)) {
mvwprintw(mainwin, y, 0, "It has been rendered invulnerable to most damage.");
y++;
} }
for (f = o->flags->first ; f ; f = f->next) { for (f = o->flags->first ; f ; f = f->next) {
if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) { if ((f->id == F_HITCONFER) && (f->val[0] == F_POISONED) && (f->lifetime == FROMOBMOD)) {
mvwprintw(mainwin, y, 0, "It has been coated with poison."); mvwprintw(mainwin, y, 0, "It has been coated with poison.");
@ -3762,6 +3777,40 @@ void describeob(object_t *o) {
restoregamewindows(); restoregamewindows();
} }
void describeskill(enum SKILL skid) {
skill_t *sk;
char buf[BUFLEN];
int i;
cls();
sk = findskill(skid);
if (!sk) return;
// title
sprintf(buf, "Skill - %s",sk->name);
capitalise(buf);
mvwprintw(mainwin, 0, 0, buf);
mvwprintw(mainwin, 2, 0,"%s\n\n", sk->desc);
// descriptions
wmove(mainwin, 4, 0);
for (i = 0; i < sk->nskilldesc; i++) {
if (sk->skilldesclev[i] == PR_INEPT) {
sprintf(buf, "%s\n",sk->skilldesctext[i]);
} else {
sprintf(buf, "At %s level: %s\n",getskilllevelname(sk->skilldesclev[i]), sk->skilldesctext[i]);
}
textwithcol(mainwin, buf);
}
wrefresh(mainwin);
// wait for key
getch();
real_clearmsg(B_TRUE);
restoregamewindows();
}
void describespell(objecttype_t *ot) { void describespell(objecttype_t *ot) {
char buf[BUFLEN]; char buf[BUFLEN];
flag_t *f; flag_t *f;
@ -4047,9 +4096,25 @@ void docomms(lifeform_t *lf) {
killflag(f); killflag(f);
getobname(o, buf, o->amt); getobname(o, buf, o->amt);
msg("You buy %s.", buf); msg("You buy %s.", buf);
// get it identified?
if (!isknown(o) && (countmoney(player) >= SHOPIDENTPRICE)) {
char buf2[BUFLEN];
char ch2;
sprintf(buf2, "Pay $%d to identify %s?",(int)SHOPIDENTPRICE, buf);
ch2 = askchar(buf2, "yn","n", B_TRUE);
if (ch2 == 'y') {
if (givemoney(player, lf, SHOPIDENTPRICE)) {
identify(o);
real_getobname(o, buf, 1, B_FALSE, B_TRUE, B_FALSE, B_FALSE, B_FALSE); // don't adjust for blindness
msgnocap("%c - %s",o->letter, buf);
} else {
msg("You can't afford to pay $%d.", SHOPIDENTPRICE);
} }
} }
say(lf, "Pleasure doing business with you!", SV_TALK); }
}
}
sayphrase(lf, SP_PAYTHANKS, SV_TALK, NA, NULL);
} }
break; break;
case 'r': case 'r':
@ -5757,6 +5822,9 @@ void initgfx(void) {
// init message buffer // init message buffer
strcpy(msgbuf, ""); strcpy(msgbuf, "");
strcpy(lastmsgbuf, "xxx"); strcpy(lastmsgbuf, "xxx");
sprintf(prevmsg, "!nolastmessage!");
msgmulti = 1;
} }
int drop(object_t *o, int count) { int drop(object_t *o, int count) {
@ -6782,8 +6850,15 @@ void msg_real(char *format, ... ) {
vsprintf( buf, format, args ); vsprintf( buf, format, args );
va_end(args); va_end(args);
if (db) dblog("adding to msgbuf: [%s]",buf); if (streq(buf, prevmsg) && !strchr(buf, '^')) {
msgmulti++;
sprintf(buf, "x%d",msgmulti);
} else {
strcpy(prevmsg, buf);
msgmulti = 1;
}
if (db) dblog("adding to msgbuf: [%s]",buf);
assert(!strchr(buf, '#')); assert(!strchr(buf, '#'));
// ie. can the message buffer fit: // ie. can the message buffer fit:
@ -7321,7 +7396,15 @@ void showlfarmour(lifeform_t *lf) {
if (strlen(rhs)) strcat(rhs, " "); if (strlen(rhs)) strcat(rhs, " ");
strcat(rhs, "(covered) "); strcat(rhs, "(covered) ");
} }
if (!strlen(rhs)) { if (strlen(rhs)) {
flag_t *f;
f = hasflag(o->flags, F_ARMOURRATING);
if (f) {
char numbuf[BUFLENSMALL];
sprintf(numbuf, " [AR:%d]",f->val[0]);
strcat(rhs, numbuf);
}
} else {
strcpy(rhs, "-"); strcpy(rhs, "-");
} }

1
io.h
View File

@ -34,6 +34,7 @@ void clearretobs(void);
void cls(void); void cls(void);
int contains(enum OBCLASS *array, int nargs, enum OBCLASS want); int contains(enum OBCLASS *array, int nargs, enum OBCLASS want);
void describeob(object_t *o); void describeob(object_t *o);
void describeskill(enum SKILL skid);
void describespell(objecttype_t *ot); void describespell(objecttype_t *ot);
void doattackcell(char dirch); void doattackcell(char dirch);
void doclose(void); void doclose(void);

641
lf.c

File diff suppressed because it is too large Load Diff

4
lf.h
View File

@ -6,6 +6,7 @@ job_t *addjob(enum JOB id, char *name);
race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass); race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass);
raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill); raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill);
skill_t *addskill(enum SKILL id, char *name, char *desc, int traintime); skill_t *addskill(enum SKILL id, char *name, char *desc, int traintime);
void addskilldesc(enum SKILL id, enum SKILLLEVEL lev, char *text, int wantmsg);
void addtrail(lifeform_t *lf, int dir); void addtrail(lifeform_t *lf, int dir);
void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype); void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype);
void adjustspeedforwater(lifeform_t *lf, int *speed); void adjustspeedforwater(lifeform_t *lf, int *speed);
@ -60,6 +61,7 @@ void dumpxp(void);
int eat(lifeform_t *lf, object_t *o); int eat(lifeform_t *lf, object_t *o);
void enhancerandomskill(lifeform_t *lf); void enhancerandomskill(lifeform_t *lf);
void enhanceskills(lifeform_t *lf); void enhanceskills(lifeform_t *lf);
void extinguishlf(lifeform_t *lf);
object_t *eyesshaded(lifeform_t *lf); object_t *eyesshaded(lifeform_t *lf);
int fall(lifeform_t *lf, lifeform_t *fromlf, int announce); int fall(lifeform_t *lf, lifeform_t *fromlf, int announce);
int fallasleep(lifeform_t *lf, int howlong); int fallasleep(lifeform_t *lf, int howlong);
@ -75,7 +77,7 @@ 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);
int flee(lifeform_t *lf); int flee(lifeform_t *lf);
void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong); void fleefrom(lifeform_t *lf, lifeform_t *enemy, int howlong, int onpurpose);
int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong); int freezelf(lifeform_t *freezee, lifeform_t *freezer, int howlong);
void gainhp(lifeform_t *lf, int amt); void gainhp(lifeform_t *lf, int amt);
void gainlevel(lifeform_t *lf); void gainlevel(lifeform_t *lf);

105
map.c
View File

@ -426,7 +426,7 @@ void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlo
*ncells = 0; *ncells = 0;
if (!c) { if (!centre) {
return; return;
} }
if (dirtype == DT_ORTH) { if (dirtype == DT_ORTH) {
@ -588,10 +588,16 @@ regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum
} }
ro->nthings++; ro->nthings++;
if (ro->nthings >= MAXOUTLINETHINGS) {
dblog("error - too many outlinethings!");
printf("error - too many outlinethings!\n");
exit(1);
}
return rt; return rt;
} }
regiontype_t *addregiontype(enum REGIONTYPE id, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major) { regiontype_t *addregiontype(enum REGIONTYPE id, char *name, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major) {
regiontype_t *a; regiontype_t *a;
// add to the end of the list // add to the end of the list
@ -611,6 +617,7 @@ regiontype_t *addregiontype(enum REGIONTYPE id, enum HABITAT defaulthabitat, int
// props // props
a->id = id; a->id = id;
a->name = strdup(name);
a->defaulthabitat = defaulthabitat; a->defaulthabitat = defaulthabitat;
a->maxdepth = maxdepth; a->maxdepth = maxdepth;
a->stairsperlev = stairsperlev; a->stairsperlev = stairsperlev;
@ -2081,6 +2088,15 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
if (db) dblog(" checking region outline for things..."); if (db) dblog(" checking region outline for things...");
for (i = 0; i < region->outline->nthings; i++) { for (i = 0; i < region->outline->nthings; i++) {
int matched = B_FALSE; int matched = B_FALSE;
if (db) {
dblog(" Checking outlinething #%d (thing:depth=%d,x=%d,y=%d thismap:depth=%d,x=%d,y=%d ).", i,
region->outline->thing[i].depth,
region->outline->thing[i].x,
region->outline->thing[i].y,
depth,x,y
);
}
if ((region->rtype->id == RG_WORLDMAP) && if ((region->rtype->id == RG_WORLDMAP) &&
(region->outline->thing[i].depth == NA)) { // match on x/y coords (region->outline->thing[i].depth == NA)) { // match on x/y coords
if ((region->outline->thing[i].x == x) && (region->outline->thing[i].y == y)) { if ((region->outline->thing[i].x == x) && (region->outline->thing[i].y == y)) {
@ -2110,6 +2126,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex
} else { } else {
if (db) dblog(" region has no outline."); if (db) dblog(" region has no outline.");
} }
if (db) dblog(" %d things remembered for later.",nthings);
// build it... // build it...
@ -2764,6 +2781,40 @@ printf("dump of map '%s' (%d x %d):\n",map->name, map->w, map->h);
} }
} }
void dumpoutlines(void) {
region_t *r;
int i;
for (r = firstregion ; r ; r = r->next) {
dblog("region:%s",r->rtype->name);
if (r->outline) {
for (i = 0; i < r->outline->nthings; i++ ){
regionthing_t *rt;
char loctext[BUFLEN];
rt = &r->outline->thing[i];
if (rt->depth == NA) {
sprintf(loctext, "%d,%d",rt->x, rt->y);
} else {
sprintf(loctext, "depth %d",rt->depth);
}
if (rt->whatkind == RT_REGIONLINK) {
regiontype_t *rtype;
rtype = findregiontype(rt->value);
dblog(" at %s: link to %s",loctext, rtype->name);
} else if (rt->whatkind == RT_HABITAT) {
habitat_t *h;
h = findhabitat(rt->value);
dblog(" at %s: %s",loctext, h->name);
} else if (rt->whatkind == RT_VAULT) {
vault_t *v;
v = findvault(rt->what);
dblog(" at %s: %s",loctext, v->id);
}
}
}
}
}
// dirtype of DT_ORTH will give a square explosion // dirtype of DT_ORTH will give a square explosion
// dirtype of DT_COMPASS will give a circular explosion // dirtype of DT_COMPASS will give a circular explosion
void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce) { void explodecells(cell_t *c, int dam, int killwalls, object_t *o, int range, int dirtype, int wantannounce) {
@ -3594,7 +3645,7 @@ object_t *hastrailof(obpile_t *op, lifeform_t *lf, enum OBTYPE oid, flag_t **tfl
void initmap(void) { void initmap(void) {
int vx,vy; int vx[4],vy[4],i;
// habitats // habitats
// thingchance, obchance, vaultchance // thingchance, obchance, vaultchance
addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 3, 50, 10); addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 3, 50, 10);
@ -3618,30 +3669,41 @@ void initmap(void) {
addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1); addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1);
// region types // region types
addregiontype(RG_WORLDMAP, H_FOREST, 10, 0, D_NONE, B_TRUE); addregiontype(RG_WORLDMAP, "World map", H_FOREST, 10, 0, D_NONE, B_TRUE);
addregiontype(RG_FIRSTDUNGEON, H_DUNGEON, 30, 3, D_DOWN, B_TRUE); addregiontype(RG_FIRSTDUNGEON, "First Dungeon", H_DUNGEON, 20, 3, D_DOWN, B_TRUE);
addregiontype(RG_PIT, H_PIT, 1, 1, D_DOWN, B_FALSE); addregiontype(RG_PIT, "Pit", H_PIT, 1, 1, D_DOWN, B_FALSE);
// region definitions (outlines) // region definitions (outlines)
addregionoutline(RG_WORLDMAP); addregionoutline(RG_WORLDMAP);
// link to first dungeon // link to first dungeon
addregionthing(lastregionoutline, NA, 0, 0, RT_REGIONLINK, RG_FIRSTDUNGEON, "staircase going down"); addregionthing(lastregionoutline, NA, 0, 0, RT_REGIONLINK, RG_FIRSTDUNGEON, "staircase going down");
// the village // four villages
/* for (i = 0; i < 4; i++) {
vx = 0; vy = 0; vx[i] = 0; vy[i] = 0;
while ((vx == 0) && (vy == 0)) { while ((vx[i] == 0) && (vy[i] == 0)) {
vx = rnd(-2,2); int n, distfromcentre;
vy = rnd(-2,2); distfromcentre = 2 + (i*2);
vx[i] = rnd(-distfromcentre,distfromcentre);
vy[i] = rnd(-distfromcentre,distfromcentre);
// check for other villages in this map...
for (n = 0; n < i; n++) {
if ((vx[n] == vx[i]) && (vy[n] == vy[i])) {
vx[i] = 0; vy[i] = 0; // invalidate!
break;
} }
*/ }
vx = 0; vy = -1; }
addregionthing(lastregionoutline, NA, vx, vy, RT_HABITAT, H_VILLAGE, NULL); addregionthing(lastregionoutline, NA, vx[i], vy[i], RT_HABITAT, H_VILLAGE, NULL);
addregionthing(lastregionoutline, NA, vx, vy, RT_VAULT, NA, "food_shop"); addregionthing(lastregionoutline, NA, vx[i], vy[i], RT_VAULT, NA, "food_shop");
addregionthing(lastregionoutline, NA, vx, vy, RT_VAULT, NA, "pub"); addregionthing(lastregionoutline, NA, vx[i], vy[i], RT_VAULT, NA, "pub");
addregionthing(lastregionoutline, NA, vx, vy, RT_RNDVAULTWITHFLAG, F_VAULTISSHOP, NULL); addregionthing(lastregionoutline, NA, vx[i], vy[i], RT_RNDVAULTWITHFLAG, F_VAULTISSHOP, NULL);
addregionthing(lastregionoutline, NA, vx, vy, RT_RNDVAULTWITHFLAG, F_VAULTISSHOP, NULL); addregionthing(lastregionoutline, NA, vx[i], vy[i], RT_RNDVAULTWITHFLAG, F_VAULTISSHOP, NULL);
addregionthing(lastregionoutline, NA, vx, vy, RT_RNDVAULTWITHFLAG, F_VAULTISSHOP, NULL); addregionthing(lastregionoutline, NA, vx[i], vy[i], RT_RNDVAULTWITHFLAG, F_VAULTISSHOP, NULL);
}
//vx = 0; vy = -1;
addregionoutline(RG_FIRSTDUNGEON); addregionoutline(RG_FIRSTDUNGEON);
addregionthing(lastregionoutline, 6, NA, NA, RT_VAULT, NA, "jimbos_lair"); addregionthing(lastregionoutline, 6, NA, NA, RT_VAULT, NA, "jimbos_lair");
addregionthing(lastregionoutline, 20, NA, NA, RT_RNDVAULTWITHFLAG, F_VAULTISSHRINE, NULL); // godstone on last floor
} }
int isadjacent(cell_t *src, cell_t *dst) { int isadjacent(cell_t *src, cell_t *dst) {
@ -4063,6 +4125,7 @@ void makedoor(cell_t *cell, int openchance) {
// at dungeon lev 50, chance is 5 in 6 // at dungeon lev 50, chance is 5 in 6
chance = rolldie(1,6) - (m->depth / 10); chance = rolldie(1,6) - (m->depth / 10);
if (chance <= 1) { if (chance <= 1) {
addflag(o->flags, F_LOCKED, B_TRUE, getdoorlockdiff(m->depth), NA, NULL); addflag(o->flags, F_LOCKED, B_TRUE, getdoorlockdiff(m->depth), NA, NULL);
} }
@ -4154,7 +4217,7 @@ void mapentereffects(map_t *m) {
lifeform_t *lf; lifeform_t *lf;
killlf(c->lf); killlf(c->lf);
lf = addmonster(c, R_HUMAN, B_TRUE, 1, B_FALSE, NULL); lf = addmonster(c, R_HUMAN, B_TRUE, 1, B_FALSE, NULL);
addflag(lf->flags, F_STAYINROOM, c->roomid, NA, NA, NULL); addflag(lf->flags, F_STAYINROOM, c->roomid, B_MAYCHASE, NA, NULL);
} }
} }
} }

2
map.h
View File

@ -10,7 +10,7 @@ int addrandomthing(cell_t *c, int obchance, int *nadded);
region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid); region_t *addregion(enum REGIONTYPE rtype, region_t *parent, int outlineid);
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, int major); regiontype_t *addregiontype(enum REGIONTYPE id, char *name, 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);

78
move.c
View File

@ -120,6 +120,11 @@ int canswapwith(lifeform_t *lf, lifeform_t *lf2) {
return B_FALSE; return B_FALSE;
} }
// cannot swap with sleeping lfs
if (lfhasflag(lf2, F_ASLEEP)) {
return B_FALSE;
}
// allies can always swap // allies can always swap
if (areallies(lf, lf2)) { if (areallies(lf, lf2)) {
return B_TRUE; return B_TRUE;
@ -683,6 +688,8 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
howfar *= 2; howfar *= 2;
} }
breakallgrabs(lf);
for (i = 0; i < howfar; i++) { for (i = 0; i < howfar; i++) {
if (moveclear(lf, dir, &reason)) { if (moveclear(lf, dir, &reason)) {
if ((i == 0) && seen) { if ((i == 0) && seen) {
@ -690,6 +697,7 @@ int knockback(lifeform_t *lf, int dir, int howfar, lifeform_t *pusher, int fallc
} }
trymove(lf, dir, B_FALSE); trymove(lf, dir, B_FALSE);
} }
if (reason != E_OK) { if (reason != E_OK) {
char buf[BUFLEN]; char buf[BUFLEN];
char thing[BUFLEN]; char thing[BUFLEN];
@ -1045,6 +1053,9 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
msg("%s starts swimming.", lfname); msg("%s starts swimming.", lfname);
didmsg = B_TRUE; didmsg = B_TRUE;
} }
// put out fires
extinguishlf(lf);
// stop sprinting // stop sprinting
stopsprinting(lf); stopsprinting(lf);
} }
@ -1052,7 +1063,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
f = hasflag(o->flags, F_SHARP); f = hasflag(o->flags, F_SHARP);
if (f && hasbp(lf, BP_FEET)) { if (f && hasbp(lf, BP_FEET) && !lfhasflag(lf, F_SNEAK)) {
object_t *boots; object_t *boots;
// has boots on? // has boots on?
boots = getequippedob(lf->pack, BP_FEET); boots = getequippedob(lf->pack, BP_FEET);
@ -1072,7 +1083,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
} }
f = hasflag(o->flags, F_CRUSHABLE); f = hasflag(o->flags, F_CRUSHABLE);
if (f) { if (f && !lfhasflag(lf, F_SNEAK)) {
enum LFSIZE crushsize; enum LFSIZE crushsize;
crushsize = f->val[0]; crushsize = f->val[0];
@ -1128,9 +1139,11 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// or rooms with pillars. would be better to fix // or rooms with pillars. would be better to fix
// haslos() code to handle looking along walls // haslos() code to handle looking along walls
// instead. // instead.
// if you walked into a new fully lit room, reveal it // if you walked into a new fully lit room, which
// ISNT a vault, reveal it.
//
if (getskill(lf, SK_CARTOGRAPHY) >= PR_NOVICE) { if ((getskill(lf, SK_CARTOGRAPHY) >= PR_NOVICE) && (!lf->cell->vault)) {
if ((postroom > 0) && (postroom != preroom)) { if ((postroom > 0) && (postroom != preroom)) {
cell_t *c[MAX_MAPW*MAX_MAPH]; cell_t *c[MAX_MAPW*MAX_MAPH];
int ncells; int ncells;
@ -1454,6 +1467,21 @@ int opendoor(lifeform_t *lf, object_t *o) {
return B_TRUE; return B_TRUE;
} else { } else {
if (lf) { if (lf) {
// has known trap?
if (isplayer(lf)) {
if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) {
if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_AVERAGE) {
char ch;
sprintf(buf,"Really open %s?", obname);
ch = askchar(buf,"yn","n", B_TRUE);
if (ch != 'y') {
msg("Cancelled.");
return B_TRUE;
}
}
}
}
taketime(lf, getactspeed(lf)); taketime(lf, getactspeed(lf));
touch(lf, o); touch(lf, o);
@ -1467,6 +1495,12 @@ int opendoor(lifeform_t *lf, object_t *o) {
*/ */
} }
// trapped?
if (lf && hasflag(o->flags, F_TRAPPED)) {
if (doobtraps(o, lf)) {
return B_TRUE;
}
}
// locked? // locked?
if (hasflag(o->flags, F_LOCKED)) { if (hasflag(o->flags, F_LOCKED)) {
if (lf && isplayer(lf)) { if (lf && isplayer(lf)) {
@ -1502,12 +1536,10 @@ int opendoor(lifeform_t *lf, object_t *o) {
// open it // open it
addflag(o->flags, F_OPEN, B_TRUE, NA, NA, NULL); addflag(o->flags, F_OPEN, B_TRUE, NA, NA, NULL);
f = hasflag(o->flags, F_IMPASSABLE); killflagsofid(o->flags, F_IMPASSABLE);
if (f) killflag(f); killflagsofid(o->flags, F_BLOCKSVIEW);
f = hasflag(o->flags, F_BLOCKSVIEW); killflagsofid(o->flags, F_SECRET);
if (f) killflag(f); killflagsofid(o->flags, F_TRAPPED);
f = hasflag(o->flags, F_SECRET);
if (f) killflag(f);
if (lf) { if (lf) {
if (isplayer(lf)) { if (isplayer(lf)) {
@ -2291,7 +2323,10 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
killflagsofid(lf->flags, F_GRABBEDBY); killflagsofid(lf->flags, F_GRABBEDBY);
killflagsofid(grabbedby->flags, F_GRABBING); killflagsofid(grabbedby->flags, F_GRABBING);
// move - don't clear the 'you break free from' msg // move - don't clear the 'you break free from' msg
// NOW is the move possible?
if (moveclear(lf, dir, &errcode)) {
moveto(lf, cell, B_TRUE, B_TRUE); moveto(lf, cell, B_TRUE, B_TRUE);
}
} else { } else {
if (isplayer(lf)) { if (isplayer(lf)) {
msg("You cannot get away from %s!",gbname); msg("You cannot get away from %s!",gbname);
@ -2453,18 +2488,33 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
return B_FALSE; return B_FALSE;
} }
// shopkeepers will only leave their shops if they have a target // some lfs will only leave their rooms if they have a target
// ie. shopkeepers
f = lfhasflag(lf, F_STAYINROOM); f = lfhasflag(lf, F_STAYINROOM);
if (f) { if (f) {
int roomid; int roomid;
roomid = f->val[0]; roomid = f->val[0];
// if moving out of my room.. if (roomid == NA) {
if ((lf->cell->roomid == roomid) && (lf->cell->roomid != cell->roomid)) { // don't move out of ANY room.
if (!aihastarget(lf)) { if ((lf->cell->roomid != cell->roomid)) {
if ((f->val[1] != NA) && aihastarget(lf)) {
// exception!
} else {
if (error) *error = E_WONT; if (error) *error = E_WONT;
return B_FALSE; return B_FALSE;
} }
} }
} else {
// don't move out of the given room.
if ((lf->cell->roomid == roomid) && (lf->cell->roomid != cell->roomid)) {
if ((f->val[1] != NA) && aihastarget(lf)) {
// exception!
} else {
if (error) *error = E_WONT;
return B_FALSE;
}
}
}
} }
if (lfhasflag(lf, F_STAYINHABITAT) && (cell->habitat->id != lf->cell->habitat->id)) { if (lfhasflag(lf, F_STAYINHABITAT) && (cell->habitat->id != lf->cell->habitat->id)) {

View File

@ -843,7 +843,6 @@ int init(void) {
// random numbers // random numbers
srand(time(NULL)); srand(time(NULL));
gamemode = GM_INIT; gamemode = GM_INIT;
playerglyph.ch = '@'; playerglyph.ch = '@';

621
objects.c

File diff suppressed because it is too large Load Diff

View File

@ -40,7 +40,7 @@ int countobs(obpile_t *op, int onlyifknown);
int countnoncosmeticobs(obpile_t *op, int onlyifknown); int countnoncosmeticobs(obpile_t *op, int onlyifknown);
int curseob(object_t *o); int curseob(object_t *o);
void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype); void damageallobs(object_t *srcob, obpile_t *op, int howmuch, int damtype);
void dumprandomobs(int amt); int doobtraps(object_t *o, lifeform_t *lf);
void dumpobrarity(void); void dumpobrarity(void);
void explodeob(object_t *o, flag_t *f, int bigness); void explodeob(object_t *o, flag_t *f, int bigness);
void extinguish(object_t *o); void extinguish(object_t *o);
@ -54,6 +54,7 @@ objecttype_t *findot(enum OBTYPE id);
objecttype_t *findotn(char *name); // find objecttype by name objecttype_t *findotn(char *name); // find objecttype by name
void fragments(cell_t *centre, char *what, int speed, int howfar); void fragments(cell_t *centre, char *what, int speed, int howfar);
void genhiddennames(void); void genhiddennames(void);
int getchargeinfo(object_t *o, int *cur, int *max);
int getcharges(object_t *o); int getcharges(object_t *o);
int geteffecttime(int min, int max, enum BLESSTYPE isblessed); int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
objecttype_t *getlinkspell(object_t *o); objecttype_t *getlinkspell(object_t *o);
@ -76,6 +77,7 @@ object_t *getrandomammo(lifeform_t *lf);
objecttype_t *getrandomammofor(object_t *o); objecttype_t *getrandomammofor(object_t *o);
brand_t *getrandombrandfor(objecttype_t *ot); brand_t *getrandombrandfor(objecttype_t *ot);
objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity); objecttype_t *getrandomobofclass(enum OBCLASS ocid, int minrarity, int maxrarity);
enum OBTYPE getrandomtrapforob(void);
char *getdamname(enum DAMTYPE damtype); char *getdamname(enum DAMTYPE damtype);
char *getdamnamenoun(enum DAMTYPE damtype); char *getdamnamenoun(enum DAMTYPE damtype);
char *getfillingname(int nutrition); char *getfillingname(int nutrition);
@ -229,6 +231,7 @@ void turnoff(lifeform_t *lf, object_t *o);
void turnon(lifeform_t *lf, object_t *o); void turnon(lifeform_t *lf, object_t *o);
int uncurseob(object_t *o, int *seen); int uncurseob(object_t *o, int *seen);
int usecharge(object_t *o); int usecharge(object_t *o);
int usefountaincharge(object_t *o, flag_t *drinkflag);
int validateobs(void); int validateobs(void);
int wepdullable(object_t *o); int wepdullable(object_t *o);
int willshatter(enum MATERIAL mat); int willshatter(enum MATERIAL mat);

3
save.c
View File

@ -29,6 +29,7 @@ extern enum GAMEMODE gamemode;
int loadall(void) { int loadall(void) {
DIR *dir; DIR *dir;
struct dirent *ent; struct dirent *ent;
int db = B_FALSE;
gamemode = GM_LOADING; gamemode = GM_LOADING;
@ -41,7 +42,7 @@ int loadall(void) {
// load region outlines first. // load region outlines first.
if (loadregions()) { if (loadregions()) {
// this isn't an error - just means no savegames // this isn't an error - just means no savegames
dblog("No region data found."); if (db) dblog("No region data found.");
return B_FALSE; return B_FALSE;
} }

56
spell.c
View File

@ -338,9 +338,15 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// trap there? // trap there?
for (o = targcell->obpile->first ; o ; o = o->next) { for (o = targcell->obpile->first ; o ; o = o->next) {
if (hasflag(o->flags, F_TRAP) && !hasflag(o->flags, F_SECRET)) { if (hasflag(o->flags, F_TRAP) && !hasflag(o->flags, F_SECRET)) {
// ie. a known trapped cell
trapob = o; trapob = o;
trapflag = hasflag(trapob->flags, F_TRAP); trapflag = hasflag(trapob->flags, F_TRAP);
break; break;
} else if (hasflagval(o->flags, F_TRAPPED, NA, NA, B_TRUE, NULL)) {
// ie. a known trapped object
trapob = o;
trapflag = hasflag(trapob->flags, F_TRAPPED);
break;
} }
} }
if (!trapob) { if (!trapob) {
@ -348,8 +354,6 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
return B_TRUE; return B_TRUE;
} }
getobname(trapob, buf, 1);
if (isplayer(user) || cansee(player, user)) { if (isplayer(user) || cansee(player, user)) {
needredraw = B_TRUE; needredraw = B_TRUE;
} }
@ -357,32 +361,60 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// taketime // taketime
taketime(user, getactspeed(user)); taketime(user, getactspeed(user));
// move player there... // if this was a cell trap, move player there.
if (trapflag->id == F_TRAP) {
movelf(user, targcell); movelf(user, targcell);
}
// try to disarm it // try to disarm it
if (skillcheck(user, SC_DISARM, trapflag->val[0], 0)) { if (skillcheck(user, SC_DISARM, trapflag->val[0], 0)) {
if (trapflag->id == F_TRAP) {
// ie. trapped cell
getobname(trapob, buf, 1);
removeob(trapob, trapob->amt);
} else {
// ie. trapped object
killflag(trapflag);
getobname(trapob, buf, 1); // get name AFTER killing the flag!
}
if (isplayer(user)) { if (isplayer(user)) {
msg("You disarm %s.",buf); msg("You disarm %s.",buf);
} else if (cansee(player, user)) { } else if (cansee(player, user)) {
msg("%s disarms %s.",username, buf); msg("%s disarms %s.",username, buf);
} }
removeob(trapob, trapob->amt);
if (isplayer(user) && hasjob(user, J_ROGUE)) { if (isplayer(user) && hasjob(user, J_ROGUE)) {
gainxp(user, trapflag->val[0]); gainxp(user, trapflag->val[0]);
} }
practice(user, SK_TRAPS, 1); practice(user, SK_TRAPS, 1);
} else { } else {
int trapgoesoff = B_FALSE;
// failed. another check to see if it goes off // failed. another check to see if it goes off
if (trapflag->id == F_TRAP) {
getobname(trapob, buf, 1);
if ((trapflag->val[1] == B_TRUE) && !skillcheck(user, SC_DISARM, trapflag->val[0], 0)) { if ((trapflag->val[1] == B_TRUE) && !skillcheck(user, SC_DISARM, trapflag->val[0], 0)) {
trapgoesoff = B_TRUE;
}
} else {
strcpy(buf, "the trap");
if (!skillcheck(user, SC_DISARM, trapflag->val[0], 0)) {
trapgoesoff = B_TRUE;
}
}
if (trapgoesoff) {
if (isplayer(user)) { if (isplayer(user)) {
msg("Oops - you trigger %s!",buf); msg("Oops - you trigger %s!",buf);
} else if (cansee(player, user)) { } else if (cansee(player, user)) {
msg("%s triggers %s!",username, buf); msg("%s triggers %s!",username, buf);
} }
if (trapflag->id == F_TRAP) {
trapeffects(trapob, trapob->type->id, user); trapeffects(trapob, trapob->type->id, user);
} else { } else {
trapeffects(NULL, trapflag->val[0], user);
}
} else {
getobname(trapob, buf, 1);
if (isplayer(user)) { if (isplayer(user)) {
msg("You fail to disarm %s.",buf); msg("You fail to disarm %s.",buf);
} else if (cansee(player, user)) { } else if (cansee(player, user)) {
@ -602,6 +634,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
int dodged = B_FALSE; int dodged = B_FALSE;
cell_t *origcell; cell_t *origcell;
int maxrange = 2; int maxrange = 2;
object_t *o;
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You can't jump while swimming!"); if (isplayer(user)) msg("You can't jump while swimming!");
@ -707,6 +740,14 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
} }
// splash?
for (o = targcell->obpile->first ; o ; o = o->next) {
if ((o->material->id == MT_WATER) && (o->type->id != OT_PUDDLEWATER)) {
addobburst(targcell, 1, DT_COMPASS, "small puddle of water", NULL, LOF_NEED);
break;
}
}
if (victim) { if (victim) {
if (dodged) { if (dodged) {
if (cansee(player, user)) { if (cansee(player, user)) {
@ -1188,6 +1229,9 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} }
} }
// rolling around will put out fires
extinguishlf(user);
} else if (abilid == OT_A_POLYREVERT) { } else if (abilid == OT_A_POLYREVERT) {
flag_t *f; flag_t *f;
if (!target) target = user; if (!target) target = user;
@ -4840,6 +4884,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
min = caster->cell->map->depth - (power*2); min = caster->cell->map->depth - (power*2);
max = caster->cell->map->depth + (power*2); max = caster->cell->map->depth + (power*2);
limit(&min, 1, caster->cell->map->region->rtype->maxdepth);
limit(&max, 1, caster->cell->map->region->rtype->maxdepth);
if (min < 1) min = 1; if (min < 1) min = 1;
// ask which level // ask which level
@ -5106,7 +5152,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (isplayer(caster) || cansee(player, caster)) { if (isplayer(caster) || cansee(player, caster)) {
if (lfhasflag(player, F_SEEINDARK)) { if (lfhasflag(player, F_SEEINDARK)) {
msg("The light burns your eyes!"); msg("The light burns your vision-enhanced eyes!");
// blind for 5-10 turns // blind for 5-10 turns
addtempflag(player->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10)); addtempflag(player->flags, F_BLIND, B_TRUE, NA, NA, NULL, rnd(5,10));
} }