- [+] make "fear" be used to flee, not attack

- [+] CRASH in linkexit()
- [+] make most monsters either have sk_perception at least novice.
- [+] show success rate when studying scrolls
- [+] bug: unable to drink from fountains anymore
- [+] always use multidrop - this will free up 'D'
- [+] forest tree cluster maps are not working - only a single tree in
      each cluster!
- [+] crash - ghost adding footprint to solid cell! 
- [+] amberon's wrath for attacking peaceful should happen once per
      ATTACK, not once per HIT
- [+] show cells outside LOS as blue or darkgrey
- [+] Don't place normal rooms next to the edge of the map either!!
- [+] getradiuscells(scatter) needs an option to include density
    - [+] then make absolute zero have high density
* [+] summoning spells on pentagram will summon a demon instead
- [+] "confusion" / "baffle" mental spell - l2 
- [+] add 'concussion' injury (head bash) - confusion effect.
    - [+] iswoozy checks for this.
- [+] severed limbs -"frominjury" so taht you can heal them
- [+] linkexit() needs to be able to handle making THREE turns:
    - [+] when looking for turnpos, remember each up/down celll
    - [+] if we don't find one ("annot find a way to link up") , go
          through each up/down cell and look left/right
    - [+] fix is in place.
    - [+] tested.
- [+] bug: doors being placed on top of rock walls!!! think this is
      related to fix_deadends.
    - [+] assert statement added.
* [+] bug:  no up stairs generated on first dungeon map! was being
      removed by clearcell() for overlapping rooms.
- [+] mass stun spell - l4. stuns all in los ?
* [+] make "stun" / massstun durations be 2-4 depending on power
- [+] "restricted" jobs/races?
    - [+] don't put shopkeepers in pubs
- [+] make a per-map maxvisrange. the deeper you go, the lower this
      gets (ie . it is darker, less ambientlight)
    - [+] limit getvisrange(lf) by getmapmaxvisrange()
    - [+]  map->habitat->maxvisrange. set this during createhabitat()
    - [+] reduce maxvisrange
    - [+] reduce it to 6
- [+] why can i still see 1 cell?
- [+] why can i still always see my own cell?
- [+] when in pitch black for a certain amount of time, your vision
      adjusts to maxrange=1
    - [+] ie. getnightvisrange(lf) should be modified by
          lf->eyeadjustment
    - [+] reset if you can ever see a lit cell.
    - [+] when this happens to the player:
        - [+] msgs about this
        - [+] also force light recalc
- [+] only recalc light when dirty
    - [+] if we call "haslos()" for a lf and they have losdirty,
          precalclos first.
- [+] vis range problems
    - [+] sunglasses/footballhelm visrangereduce isn't working anymore
        - [+] it's reducing maxvisrange(lf).
        - [+] BUT - my maxvisrange is 5, which is still higher than the
              ambient range.
        - [+] need to apply reductions AFTER ambient light
        - [+] NOW eyeadjustment isn't working.  because cell lit is
              l_temp, not l_notlit.
        - [+] but if this is the case, why can't i see?  anwer: because
              my visrange has been reduced to 0 due to no ambient light!
        - [+] so.... how do i make lightt sources override this?
        - [+] maybe say:  if a cell is lit, i can see it, even if it's
              outside my ambient light.
    - [+] falling over isn't reducing your visrange anymore
- [+] why doesn't eyeadjust make the screen update?
- [+] is regular "haslos" code ever used anymore????
- [+] now i can't see lit cells in the darkness again....fixed
- [+] after you calm something, give it xpval0
    - [+] show message when calm animals fails
- [+] check all spell sc_resistmag oskillcheck difficulties
    - [+] diff should be 20  + (spelllev*2) + power
    - [+] l1 spell should be diff 20
    - [+] l2 should be diff 24 
    - [+] ...
    - [+] l7 should be diff 34
- [+] bleeding injuries should make armour "bloodstained"  (5% chance
      per turn)
- [+] msgs for "the sun is starting to set" and "the sun is starting to
      rise"
    - [+] make 6am, 18pm be constants
- [+] add crushed windpipe -  lower Fitness, cannot sprint
* [+] CRASH when going down stairs! another overlapping room bug i
      think.
- [+] cockatrices and chickens should cluck
- [+] canwill param:  race:xxx;
    - [+] define it
    - [+] use this in "createmonster"
    - [+] use this in "polymorph" when on self
    - [+] then remove f_forcepoly
    - [+] TEST 
- [+] make playerstart vaults able to appear randomly (just don't place
      the the "playerstart" object)
- [+] redo texttospellopts() to make it more friendly
    - [+] give a list of what we want as args, rather than passing lots
          of nulls
    - [+] "pw:",  &localpowervar etc
- [+] make "n_lowhp" noisetext happen at END of lf turn - NOT during
      losehp.
- [+] rename turneffectslf() to startlfturn()
- [+] show hunger level as a bar in @@
- [+] warn before becoming burdened.
- [+] warn when you ARE burdened.  at the end of moveob()
- [+] l6 - absolute zero (turn everyone around you to ice, freeze all
      obs, turn ground to ice)
- [+] some monsters leave non-meat food behind?
    - [+] cactus -> cactus juice/fruit
    - [+] dreamfungus ->  sleeping powerder
- [+] silver weapons (5% chance on eligible weapons)
    - [+] hurt vampires 
    - [+] vulnerable to mat??? - then use fromob in losehp()
        - [+] f_matvuln mt_xxx multiplier
    - [+] add some silver weapons
        - [+] f_canbediffmat  mt_silver  10%
        - [+] if f_canbediffmat  is true, sometimes change material to
              this on creation
        - [+] getobname - if material is differnet, show this
        - [+] dagger
        - [+] sword
        - [+] arrow
        - [+] bolt
        - [+] dart
        - [+] addob should accept 'wantdiffmat'
This commit is contained in:
Rob Pearce 2011-09-09 23:03:32 +00:00
parent 1f6429e305
commit d51dfa11f9
28 changed files with 1961 additions and 1028 deletions

4
ai.c
View File

@ -299,7 +299,7 @@ object_t *aigetrangedattack(lifeform_t *lf, enum RANGEATTACK *ra, int *range) {
if (db) dblog(".oO { will zap %s instead of moving }", o->type->name); if (db) dblog(".oO { will zap %s instead of moving }", o->type->name);
*ra = RA_WAND; *ra = RA_WAND;
*range = getvisrange(lf); // ie unlimited *range = getvisrange(lf, B_TRUE); // ie unlimited
return o; return o;
} }
} }
@ -1764,7 +1764,7 @@ int aispellok(lifeform_t *lf, enum OBTYPE spellid, lifeform_t *victim, enum FLAG
willflag = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL); willflag = lfhasflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (willflag) { if (willflag) {
texttospellopts(f->text, NULL, NULL, NULL, &srange); texttospellopts(f->text, "range:", &srange, NULL);
if (!srange) srange = 5; if (!srange) srange = 5;
} }
// override... // override...

View File

@ -167,6 +167,9 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
int saysorry = B_FALSE; int saysorry = B_FALSE;
flag_t *retflag[MAXCANDIDATES]; flag_t *retflag[MAXCANDIDATES];
int nretflags = 0; int nretflags = 0;
int attackedhelpless = B_FALSE;
int attackedfriend = B_FALSE;
int attackedpeaceful = B_FALSE;
// anyone there? if so just attack. // anyone there? if so just attack.
if (c->lf) { if (c->lf) {
@ -191,10 +194,14 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
// cancel. // cancel.
return B_TRUE; return B_TRUE;
} }
attackedpeaceful = B_TRUE;
} }
attacktype = AT_LF; attacktype = AT_LF;
attacktarget = c->lf; attacktarget = c->lf;
if (areallies(lf, attacktarget)) attackedfriend = B_TRUE;
if (!cansee(attacktarget, lf) || isfleeing(attacktarget)) attackedhelpless = B_TRUE;
} else { } else {
object_t *o; object_t *o;
// has an impassable object? // has an impassable object?
@ -429,6 +436,51 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) {
losehp(lf, 1, DT_DIRECT, NULL, "blood loss"); losehp(lf, 1, DT_DIRECT, NULL, "blood loss");
} }
// god effects...
if (attacktype == AT_LF) {
if (attackedfriend) {
angergodmaybe(R_GODMERCY, 100);
angergodmaybe(R_GODPURITY, 100);
switch (getalignment(attacktarget)) {
case AL_EVIL:
angergodmaybe(R_GODDEATH, 20); // even more
break;
case AL_GOOD:
angergodmaybe(R_GODPURITY, 20); // even more
break;
default:
break;
}
} else if (attackedpeaceful) {
angergodmaybe(R_GODMERCY, 50);
angergodmaybe(R_GODPURITY, 50);
switch (getalignment(attacktarget)) {
case AL_EVIL:
angergodmaybe(R_GODDEATH, 20); // even more
break;
case AL_GOOD:
angergodmaybe(R_GODPURITY, 20); // even more
break;
default:
break;
}
} else if (attackedhelpless) {
angergodmaybe(R_GODMERCY, 100);
angergodmaybe(R_GODPURITY, 100);
if (getalignment(attacktarget) != AL_EVIL) {
pleasegodmaybe(R_GODTHIEVES, 5);
pleasegodmaybe(R_GODDEATH, 10);
}
}
if (lfhasflag(lf, F_USEDPOISON)) {
killflagsofid(lf->flags, F_USEDPOISON);
angergodmaybe(R_GODPURITY, 100);
angergodmaybe(R_GODMERCY, 50);
pleasegodmaybe(R_GODDEATH, 3);
}
}
return B_FALSE; return B_FALSE;
} }
@ -444,8 +496,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
int deflected = B_FALSE; int deflected = B_FALSE;
int weppassthrough = B_FALSE; int weppassthrough = B_FALSE;
int firstisbackstab = B_FALSE; int firstisbackstab = B_FALSE;
int attackedhelpless = B_FALSE;
int attackedfriend = B_FALSE;
int hit = B_FALSE; int hit = B_FALSE;
int critical = 0; int critical = 0;
char wepname[BUFLEN]; char wepname[BUFLEN];
@ -656,17 +706,10 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
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)); dam[0] *= (getskill(lf, SK_BACKSTAB));
firstisbackstab = B_TRUE; firstisbackstab = B_TRUE;
attackedhelpless = B_TRUE;
} }
} }
} }
if (!cansee(victim, lf)) {
attackedhelpless = B_TRUE;
}
if (areallies(lf, victim)) {
attackedfriend = B_TRUE;
}
// extra damage for being skilled? // extra damage for being skilled?
if (wepsk) { if (wepsk) {
slev = getskill(lf, wepsk->id); slev = getskill(lf, wepsk->id);
@ -929,7 +972,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} else { } else {
strcpy(buf, attackername2); strcpy(buf, attackername2);
} }
losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, NULL, B_FALSE); losehp_real(victim, dam[i], damtype[i], lf, buf, B_FALSE, wep, B_FALSE);
// victim's armour loses hp // victim's armour loses hp
if (reduceamt && !critical) { if (reduceamt && !critical) {
@ -1158,38 +1201,6 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag)
} }
} }
if (isplayer(lf)) {
if (attackedfriend) {
angergodmaybe(R_GODMERCY, 100);
angergodmaybe(R_GODPURITY, 100);
switch (getalignment(victim)) {
case AL_EVIL:
angergodmaybe(R_GODDEATH, 20); // even more
break;
case AL_GOOD:
angergodmaybe(R_GODPURITY, 20); // even more
break;
default:
break;
}
}
if (attackedhelpless) {
angergodmaybe(R_GODMERCY, 100);
angergodmaybe(R_GODPURITY, 100);
if (getalignment(victim) != AL_EVIL) {
pleasegodmaybe(R_GODTHIEVES, 5);
pleasegodmaybe(R_GODDEATH, 10);
}
}
if (lfhasflag(lf, F_USEDPOISON)) {
killflagsofid(lf->flags, F_USEDPOISON);
angergodmaybe(R_GODPURITY, 100);
angergodmaybe(R_GODMERCY, 50);
pleasegodmaybe(R_GODDEATH, 3);
}
}
if (aidb) dblog(".oO { doattack about to return B_FALSE }"); if (aidb) dblog(".oO { doattack about to return B_FALSE }");
return B_FALSE; return B_FALSE;
} }
@ -1347,7 +1358,7 @@ void criticalhit(lifeform_t *lf, lifeform_t *victim, enum BODYPART hitpos, enum
break; break;
case BP_HEAD: case BP_HEAD:
if (pctchance(80)) fall(victim, lf, B_TRUE); if (pctchance(80)) fall(victim, lf, B_TRUE);
stun(victim, 2); stun(victim, 1);
// chance of your helmet falling off // chance of your helmet falling off
o = getarmour(victim, BP_HEAD); o = getarmour(victim, BP_HEAD);
if (o) { if (o) {
@ -2061,7 +2072,7 @@ int rolltohit(lifeform_t *lf, lifeform_t *victim, object_t *wep, int *critical)
} }
limit(&critroll, 1, 100); limit(&critroll, 1, 100);
if (critroll <= getcritchance(lf, wep)) *critical = 1; if (critroll <= getcritchance(lf, wep,victim)) *critical = 1;
} }
f = lfhasflag(lf, F_TRUESTRIKE); f = lfhasflag(lf, F_TRUESTRIKE);

Binary file not shown.

28
defs.h
View File

@ -21,6 +21,7 @@
#define DEF_SCREENH 24 #define DEF_SCREENH 24
#define DEF_SHOPIDENTPRICE (50) // cost to identify a just-purchased item #define DEF_SHOPIDENTPRICE (50) // cost to identify a just-purchased item
#define DEF_VAULTMARGIN (3) #define DEF_VAULTMARGIN (3)
#define DEF_VISRANGE (7)
// Map building defaults // Map building defaults
@ -50,6 +51,7 @@
#define B_DONTKILL (-1) #define B_DONTKILL (-1)
#define B_APPENDYOU (-1) #define B_APPENDYOU (-1)
#define B_SPLATTER (-1) #define B_SPLATTER (-1)
#define B_FROMINJURY (-1)
//#define B_TEMP (-1) //#define B_TEMP (-1)
//#define B_PERM (-2) //#define B_PERM (-2)
@ -115,6 +117,7 @@
#define MAXSPELLLEV 6 #define MAXSPELLLEV 6
#define MAXVISRANGE 10 // max visible range in full light #define MAXVISRANGE 10 // max visible range in full light
#define MAXVISLIMIT (MAXVISRANGE*8) #define MAXVISLIMIT (MAXVISRANGE*8)
#define MAX_EYEADJ 20
#define MINCLEARINGRADIUS 2 #define MINCLEARINGRADIUS 2
#define MAXCLEARINGRADIUS 5 #define MAXCLEARINGRADIUS 5
@ -328,6 +331,7 @@ enum COLOUR {
C_BOLDMAGENTA = 12, C_BOLDMAGENTA = 12,
C_ORANGE = 13, C_ORANGE = 13,
C_BOLDGREEN = 14, C_BOLDGREEN = 14,
C_DARKGREY = 15,
}; };
#define BLUEBG 50 #define BLUEBG 50
@ -893,6 +897,7 @@ enum MATERIAL {
MT_OIL = 25, MT_OIL = 25,
MT_PLANT = 26, MT_PLANT = 26,
MT_WIRE = 27, MT_WIRE = 27,
MT_SILVER = 28,
}; };
// Object Types // Object Types
@ -952,6 +957,7 @@ enum OBTYPE {
OT_TREE, OT_TREE,
// food // food
OT_BERRY, OT_BERRY,
OT_CACFRUIT,
OT_GARLIC, OT_GARLIC,
OT_NUT, OT_NUT,
OT_BANANA, OT_BANANA,
@ -1080,6 +1086,7 @@ enum OBTYPE {
OT_S_FLAMEBURST, OT_S_FLAMEBURST,
OT_S_SPARK, OT_S_SPARK,
// -- elemental - ice // -- elemental - ice
OT_S_ABSOLUTEZERO,
OT_S_CHILL, OT_S_CHILL,
OT_S_COLDBURST, OT_S_COLDBURST,
OT_S_COLDRAY, OT_S_COLDRAY,
@ -1112,6 +1119,7 @@ enum OBTYPE {
OT_S_SPEAKDEAD, OT_S_SPEAKDEAD,
OT_S_TURNUNDEAD, OT_S_TURNUNDEAD,
// -- mental / psionic // -- mental / psionic
OT_S_BAFFLE,
OT_S_CHARM, OT_S_CHARM,
OT_S_HUNGER, OT_S_HUNGER,
OT_S_MINDSCAN, OT_S_MINDSCAN,
@ -1120,6 +1128,7 @@ enum OBTYPE {
OT_S_PSYARMOUR, OT_S_PSYARMOUR,
OT_S_SLEEP, OT_S_SLEEP,
OT_S_STUN, OT_S_STUN,
OT_S_STUNMASS,
OT_S_TELEKINESIS, OT_S_TELEKINESIS,
// -- modification // -- modification
OT_S_DARKNESS, OT_S_DARKNESS,
@ -1619,7 +1628,7 @@ enum RANGEATTACK {
}; };
enum FLAG { enum FLAG {
F_NONE, // dummy flag F_NONE = 0, // dummy flag
// map flags // map flags
F_MAPCOORDS, // v0+v1 are x/y coords for this map area F_MAPCOORDS, // v0+v1 are x/y coords for this map area
F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2 F_ROOMEXIT, // there is an exit from room v0 at x=v1,y=v2
@ -1710,7 +1719,9 @@ enum FLAG {
F_DTRESIST, // half dam from damtype val0 F_DTRESIST, // half dam from damtype val0
F_DTVULN, // double dam from damtype val0 F_DTVULN, // double dam from damtype val0
// if dam=0, set dam to textfield dice (eg.text="2d6") // if dam=0, set dam to textfield dice (eg.text="2d6")
F_MATIMMUNE, // immune to damage from obs with material 'mat' F_MATIMMUNE, // immune to damage from obs with material 'v0'
F_MATVULN, // vulnarable to damage from obs with material 'v0'
// v1 = this % of damage is done. ie. 110%
F_DAMAGABLE, // this ob can be damaged via takedamage() F_DAMAGABLE, // this ob can be damaged via takedamage()
F_TINTED, // when worn on eyes, protects against bright lights F_TINTED, // when worn on eyes, protects against bright lights
F_HASBRAND, // has the object mod v0 (ie. OM_FLAMESTRIKE) F_HASBRAND, // has the object mod v0 (ie. OM_FLAMESTRIKE)
@ -1769,6 +1780,8 @@ 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_CANBEDIFFMAT, // v0 is different material id which this ob could be
// v1 is the chance of it being this material
F_CANBETRAPPED, // this object might start with a trap F_CANBETRAPPED, // this object might start with a trap
// v0 = base pct chance // v0 = base pct chance
// v1 = extra pct chance every 5 levels // v1 = extra pct chance every 5 levels
@ -2157,7 +2170,6 @@ enum FLAG {
// v0 = max distance to splatter (or UNLIMITED) // v0 = max distance to splatter (or UNLIMITED)
// text = type of object to splatter // text = type of object to splatter
F_OBESE, // double base weight for race! F_OBESE, // double base weight for race!
F_FORCEPOLY, // when this lf polymorphs, always chance to raceid v0
F_ORIGRACE, // original player race (if you polymorphed) F_ORIGRACE, // original player race (if you polymorphed)
F_ORIGJOB, // original player job (if you polymorphed) F_ORIGJOB, // original player job (if you polymorphed)
F_POLYMORPHED, // lf has been polymorphed F_POLYMORPHED, // lf has been polymorphed
@ -2175,6 +2187,8 @@ enum FLAG {
F_UNDEAD, // this race is classed as undead F_UNDEAD, // this race is classed as undead
F_COLDBLOOD, // this race is coldblooded F_COLDBLOOD, // this race is coldblooded
F_NOBODYPART, // this race doesn't have bodypart val0 F_NOBODYPART, // this race doesn't have bodypart val0
// if v0 is true or b_frominjury, you can regrow it
// via a healing potion.
F_NOPACK, // this race cannot hold objects F_NOPACK, // this race cannot hold objects
F_NOSPELLS, // this race cannot cast spells F_NOSPELLS, // this race cannot cast spells
F_INDUCEFEAR, // causes fear when you attack it F_INDUCEFEAR, // causes fear when you attack it
@ -2201,6 +2215,7 @@ enum FLAG {
F_ATTACHEDTO, // you are attached to lf id v0, and will move with it F_ATTACHEDTO, // you are attached to lf id v0, and will move with it
F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn) F_BEINGSTONED,// turn to stone when v0 drops to zero. (drops 1/turn)
F_BLIND, // cannot see anything F_BLIND, // cannot see anything
F_CONFUSED, // move randomly about
F_DEAF, // cannot hear F_DEAF, // cannot hear
F_NEEDOBFORSPELLS, // lf can only cast spells if it has object v0 F_NEEDOBFORSPELLS, // lf can only cast spells if it has object v0
F_CASTTYPE, // lf uses enum CASTTYPE v0 for spells F_CASTTYPE, // lf uses enum CASTTYPE v0 for spells
@ -2432,6 +2447,7 @@ enum INJURY {
IJ_ARTERYPIERCE, IJ_ARTERYPIERCE,
IJ_BLACKEYE, IJ_BLACKEYE,
IJ_CHESTBLEED, IJ_CHESTBLEED,
IJ_CONCUSSION,
IJ_EYELIDSCRAPED, IJ_EYELIDSCRAPED,
IJ_EYEDESTROYED, IJ_EYEDESTROYED,
IJ_FINGERBROKEN, IJ_FINGERBROKEN,
@ -2444,6 +2460,7 @@ enum INJURY {
IJ_RIBCRACKED, IJ_RIBCRACKED,
IJ_SHOULDERDISLOCATED, IJ_SHOULDERDISLOCATED,
IJ_TENDONCUT, IJ_TENDONCUT,
IJ_WINDPIPECRUSHED,
}; };
@ -2674,6 +2691,7 @@ typedef struct habitat_s {
int randthingpct; // % chance each empty cell has something int randthingpct; // % chance each empty cell has something
int randobpct; // % chance that 'something' is an ob rather than monster int randobpct; // % chance that 'something' is an ob rather than monster
int randvaultpct; // % chance that a room will be a vault int randvaultpct; // % chance that a room will be a vault
int maxvisrange;
enum CELLTYPE emptycelltype,solidcelltype; enum CELLTYPE emptycelltype,solidcelltype;
struct habitat_s *next, *prev; struct habitat_s *next, *prev;
} habitat_t; } habitat_t;
@ -2866,11 +2884,15 @@ typedef struct lifeform_s {
long oblist[MAXPILEOBS]; long oblist[MAXPILEOBS];
int x,y; int x,y;
int losdirty;
int nlos; int nlos;
cell_t **los; cell_t **los;
int *viscell; int *viscell;
int visw; int visw;
int visrange; int visrange;
int eyeadjustment; // have your eyes adjusted to the dark?
// your nightvision is increased by eyeadj / 10
// max is MAX_EYEADJ
// set to TRUE after lf has being created // set to TRUE after lf has being created
int born; int born;

23
flag.c
View File

@ -1,3 +1,4 @@
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -252,7 +253,8 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
lifeform_t *l; lifeform_t *l;
for (l = where->map->lf ; l ; l = l->next) { for (l = where->map->lf ; l ; l = l->next) {
if (haslos(l, where)) { if (haslos(l, where)) {
precalclos(l); setlosdirty(l);
//precalclos(l);
if (isplayer(l)) { if (isplayer(l)) {
redrawscreenatend = B_TRUE; redrawscreenatend = B_TRUE;
} }
@ -288,7 +290,8 @@ flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3,
//dblog("CALCINGLIGHT from flag\n"); //dblog("CALCINGLIGHT from flag\n");
redrawscreenatend = B_TRUE; redrawscreenatend = B_TRUE;
calclight(redolight); calclight(redolight);
precalclos(player); setlosdirty(player);
//precalclos(player);
} }
//dblog("DRAWINGSCREEN from flag\n"); //dblog("DRAWINGSCREEN from flag\n");
@ -355,7 +358,11 @@ int flagcausesloscalc(enum FLAG fid) {
case F_ASLEEP: case F_ASLEEP:
case F_BLIND: case F_BLIND:
case F_BLOCKSVIEW: case F_BLOCKSVIEW:
case F_NIGHTVISRANGEMOD:
case F_PRONE: case F_PRONE:
case F_SEEINDARK:
case F_VISRANGE:
case F_VISRANGEMOD:
return B_TRUE; return B_TRUE;
default: break; default: break;
} }
@ -411,6 +418,7 @@ int flagcausesstatredraw(lifeform_t *lf, enum FLAG fid) {
case F_ASLEEP: case F_ASLEEP:
case F_ATTRMOD: case F_ATTRMOD:
case F_BLIND: case F_BLIND:
case F_CONFUSED:
case F_EATING: case F_EATING:
case F_FASTMOVE: case F_FASTMOVE:
case F_FLYING: case F_FLYING:
@ -831,14 +839,16 @@ void killflag(flag_t *f) {
// - if it was an object flag, then everyone who can see // - if it was an object flag, then everyone who can see
// its cell recalcs their los. // its cell recalcs their los.
if (f->pile->owner) { if (f->pile->owner) {
precalclos(f->pile->owner); setlosdirty(f->pile->owner);
//precalclos(f->pile->owner);
if (isplayer(f->pile->owner)) redoscreen = B_TRUE; if (isplayer(f->pile->owner)) redoscreen = B_TRUE;
} else { } else {
// everyone who can see this cell recalcs their los // everyone who can see this cell recalcs their los
lifeform_t *l; lifeform_t *l;
for (l = redolos->map->lf ; l ; l = l->next) { for (l = redolos->map->lf ; l ; l = l->next) {
if (haslos(l, redolos)) { if (haslos(l, redolos)) {
precalclos(l); setlosdirty(l);
//precalclos(l);
if (isplayer(l)) redoscreen = B_TRUE; if (isplayer(l)) redoscreen = B_TRUE;
} }
} }
@ -846,7 +856,8 @@ void killflag(flag_t *f) {
} }
if (redolight) { if (redolight) {
calclight(redolight); calclight(redolight);
precalclos(player); setlosdirty(player);
//precalclos(player);
needredraw = B_TRUE; needredraw = B_TRUE;
} }
if (redoscreen) { if (redoscreen) {
@ -1123,6 +1134,8 @@ int getflags(flagpile_t *fp, flag_t **retflag, int *nretflags, ... ) {
} }
va_end(flags); va_end(flags);
assert(nwantflags < MAXCANDIDATES);
// now populate retflag[] with matches flags // now populate retflag[] with matches flags
*nretflags = 0; *nretflags = 0;
for (i = 0; i < nwantflags; i++) { for (i = 0; i < nwantflags; i++) {

174
io.c
View File

@ -42,6 +42,8 @@ extern enum ERROR reason;
extern char msghist[MAXHISTORY][BUFLEN]; extern char msghist[MAXHISTORY][BUFLEN];
extern int nmsghist; extern int nmsghist;
extern void (*precalclos)(lifeform_t *);
extern lifeform_t *godlf[]; extern lifeform_t *godlf[];
extern int ngodlfs; extern int ngodlfs;
@ -675,7 +677,7 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
} }
// need a certain amount of iq to recognise drunkenness // need a certain amount of iq to recognise drunkenness
f = isdrunk(c->lf); f = lfhasflag(c->lf, F_DRUNK);
if (f && (iqb >= AT_LTAVERAGE)) { if (f && (iqb >= AT_LTAVERAGE)) {
if (strlen(extrainfo)) strcat(extrainfo, ", "); if (strlen(extrainfo)) strcat(extrainfo, ", ");
strcat(extrainfo, getdrunktext(f)); strcat(extrainfo, getdrunktext(f));
@ -1240,6 +1242,14 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
case F_CONFUSED:
if (isplayer(lf)) {
msg("^WYou feel woozy...");
} else {
msg("^%c%s looks woozy...", lfname, getlfcol(lf, CC_BAD));
}
donesomething = B_TRUE;
break;
case F_DEAF: case F_DEAF:
if (isplayer(lf)) { if (isplayer(lf)) {
msg("^WYou cannot hear anything!"); msg("^WYou cannot hear anything!");
@ -1786,6 +1796,14 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
donesomething = B_TRUE; donesomething = B_TRUE;
} }
break; break;
case F_CONFUSED:
if (isplayer(lf)) {
msg("You feel more steady now.");
} else {
msg("%s looks more steady.", lfname);
}
donesomething = B_TRUE;
break;
case F_DEAF: case F_DEAF:
if (isplayer(lf)) { if (isplayer(lf)) {
msg("Your hearing returns."); msg("Your hearing returns.");
@ -2595,6 +2613,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
int selcount[MAXPILEOBS+1]; int selcount[MAXPILEOBS+1];
char myletters[MAXPILEOBS+1]; char myletters[MAXPILEOBS+1];
char numstring[BUFLEN]; char numstring[BUFLEN];
char pbuf[BUFLEN];
int firstob = 0; int firstob = 0;
int nextpage = -1; int nextpage = -1;
int lastline = SCREENH-4; int lastline = SCREENH-4;
@ -2669,8 +2688,8 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
finished = B_FALSE; finished = B_FALSE;
strcpy(numstring, ""); strcpy(numstring, "");
while (!finished) { while (!finished) {
int y; int y,n,ch,nselected = 0;
int ch; float selweight = 0;
cls(); cls();
@ -2684,18 +2703,43 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
} else { } else {
nextpage = i; nextpage = i;
} }
// count selected items
for (n = 0 ; (mylist[n] != NULL) ; n++) {
if (selected[n]) {
int thiscount;
nselected++;
if (selcount[n] == ALL) thiscount = mylist[n]->amt;
else thiscount = selcount[n];
selweight += (getobunitweight(mylist[n]) * thiscount);
}
}
// draw prompt // draw prompt
if (nextpage != -1) { if (nextpage != -1) {
mvwprintw(mainwin, y, 0, MORESTRING); mvwprintw(mainwin, y, 0, MORESTRING);
} }
if (strlen(numstring) > 0) { if (strlen(numstring) > 0) {
mvwprintw(mainwin, 0, 0, "%s (%s','=all, ESC to quit) [%s]: ",prompt, snprintf(pbuf, BUFLEN,"%s (%s','=all, ESC to quit) [%s]: ",prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : "", (opts & AO_INCLUDENOTHING) ? "- for nothing, " : "",
numstring); numstring);
} else { } else {
mvwprintw(mainwin, 0, 0, "%s (%sESC to quit): ", prompt, snprintf(pbuf, BUFLEN,"%s (%sESC to quit): ", prompt,
(opts & AO_INCLUDENOTHING) ? "- for nothing, " : ""); (opts & AO_INCLUDENOTHING) ? "- for nothing, " : "");
} }
// show how many items we've picked, and how much they weigh
if (nselected) {
char wbuf[BUFLEN];
char selbuf[BUFLEN];
getweighttext(selweight, wbuf, B_TRUE);
sprintf(selbuf, " (%d ob%s, ", nselected, (nselected > 1) ? "s" : "");
strcat(selbuf, wbuf);
strcat(selbuf, ")");
strcat(pbuf, selbuf);
}
mvwprintw(mainwin, 0, 0, "%s", pbuf);
// update screen // update screen
wrefresh(mainwin); wrefresh(mainwin);
// wait for keypess // wait for keypess
@ -2742,7 +2786,7 @@ int askobjectmulti(obpile_t *op, char *prompt, long opts) {
selected[i] = val; selected[i] = val;
if (val == B_TRUE) { if (val == B_TRUE) {
selcount[i] = count; selcount[i] = count;
if (selcount[i] > mylist[i]->amt) selcount[i] = ALL; if (selcount[i] > mylist[i]->amt) selcount[i] = mylist[i]->amt;
} else { } else {
selcount[i] = 0; selcount[i] = 0;
} }
@ -3102,14 +3146,14 @@ void describeob(object_t *o) {
if (o->amt == 1) { if (o->amt == 1) {
char wbuf[BUFLEN]; char wbuf[BUFLEN];
getweighttext(getobweight(o), wbuf); getweighttext(getobweight(o), wbuf, B_FALSE);
snprintf(buf2, BUFLEN, "and weighs %s.",wbuf); snprintf(buf2, BUFLEN, "and weighs %s.",wbuf);
strcat(buf, buf2); strcat(buf, buf2);
} else { } else {
char wbuf[BUFLEN]; char wbuf[BUFLEN];
char wbuf2[BUFLEN]; char wbuf2[BUFLEN];
getweighttext(getobweight(o), wbuf); getweighttext(getobweight(o), wbuf, B_FALSE);
getweighttext(getobunitweight(o), wbuf2); getweighttext(getobunitweight(o), wbuf2, B_FALSE);
snprintf(buf2, BUFLEN, "and weigh %s (%s each).",wbuf, wbuf2); snprintf(buf2, BUFLEN, "and weigh %s (%s each).",wbuf, wbuf2);
strcat(buf, buf2); strcat(buf, buf2);
} }
@ -3277,7 +3321,7 @@ void describeob(object_t *o) {
mvwprintw(mainwin, y, 0, " Its attack delay is %d%%.",delay - 100); mvwprintw(mainwin, y, 0, " Its attack delay is %d%%.",delay - 100);
y++; y++;
critchance = getcritchance(player, o); critchance = getcritchance(player, o, NULL);
if (critchance > 0) { if (critchance > 0) {
mvwprintw(mainwin, y, 0, " You have a %d%% critical hit chance with it.", critchance); mvwprintw(mainwin, y, 0, " You have a %d%% critical hit chance with it.", critchance);
y++; y++;
@ -4938,7 +4982,7 @@ void dolook(cell_t *where, int onpurpose) {
// if wantunknown is set, lsit spells we DONT know. // if wantunknown is set, lsit spells we DONT know.
// otherwise list spells we DO know. // otherwise list spells we DO know.
// only include spells which cost <= mpcutoff // only include spells which cost <= mpcutoff
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid, int mpcutoff) { void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard, int mpcutoff) {
char ch; char ch;
flag_t *f; flag_t *f;
char buf[BUFLEN]; char buf[BUFLEN];
@ -4948,6 +4992,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
int mpcost[MAXCANDIDATES]; int mpcost[MAXCANDIDATES];
char mpdesc[MAXCANDIDATES][BUFLEN]; char mpdesc[MAXCANDIDATES][BUFLEN];
int validspell[MAXCANDIDATES]; int validspell[MAXCANDIDATES];
int err[MAXCANDIDATES]; // will be e_ok, e_notready, e_toopowerful, e_nomp
int deactspell[MAXCANDIDATES]; int deactspell[MAXCANDIDATES];
int nposs = 0; int nposs = 0;
int i,n,lev; int i,n,lev;
@ -4979,13 +5024,16 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
if (f->val[2] == NA) { if (f->val[2] == NA) {
snprintf(mpdesc[nposs], BUFLEN, "(ready)"); snprintf(mpdesc[nposs], BUFLEN, "(ready)");
validspell[nposs] = B_TRUE; validspell[nposs] = B_TRUE;
err[nposs] = E_OK;
} else { } else {
if (f->val[1] == f->val[2]) { if (f->val[1] == f->val[2]) {
snprintf(mpdesc[nposs], BUFLEN, "(ready)"); snprintf(mpdesc[nposs], BUFLEN, "(ready)");
validspell[nposs] = B_TRUE; validspell[nposs] = B_TRUE;
err[nposs] = E_OK;
} else { } else {
snprintf(mpdesc[nposs], BUFLEN, "(%d/%d)",f->val[1],f->val[2]); snprintf(mpdesc[nposs], BUFLEN, "(%d/%d)",f->val[1],f->val[2]);
validspell[nposs] = B_FALSE; validspell[nposs] = B_FALSE;
err[nposs] = E_TOOPOWERFUL;
} }
} }
@ -5039,12 +5087,15 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
} }
if (mpcost[nposs] <= mpcutoff) { if (mpcost[nposs] <= mpcutoff) {
validspell[nposs] = B_TRUE; validspell[nposs] = B_TRUE;
err[nposs] = E_OK;
} else { } else {
validspell[nposs] = B_FALSE; validspell[nposs] = B_FALSE;
err[nposs] = E_NOMP;
} }
} else { } else {
snprintf(mpdesc[nposs], BUFLEN, "(too hard)"); snprintf(mpdesc[nposs], BUFLEN, "(too hard)");
validspell[nposs] = B_FALSE; validspell[nposs] = B_FALSE;
err[nposs] = E_TOOPOWERFUL;
} }
nposs++; nposs++;
} }
@ -5070,6 +5121,7 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
lastschool = SS_LAST; lastschool = SS_LAST;
for (i = 0; i < nposs; i++) { for (i = 0; i < nposs; i++) {
int addit = B_FALSE;
int power; int power;
enum SPELLSCHOOL thisschool = SS_NONE; enum SPELLSCHOOL thisschool = SS_NONE;
ot = findot(poss[i]); ot = findot(poss[i]);
@ -5099,7 +5151,15 @@ void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2,
strcat(costbuf, mpdesc[i]); strcat(costbuf, mpdesc[i]);
snprintf(buf, BUFLEN, "%-30s%s", buf2, costbuf); snprintf(buf, BUFLEN, "%-30s%s", buf2, costbuf);
if (wantinvalid || validspell[i]) { if (validspell[i]) {
addit = B_TRUE;
} else if ((err[i] == E_NOMP) && wantlowmp) {
addit = B_TRUE;
} else if ((err[i] == E_TOOPOWERFUL) && wanttoohard) {
addit = B_TRUE;
}
if (addit) {
// letter doesn't matter // letter doesn't matter
addchoice(pr, 'a', buf2, buf, ot); addchoice(pr, 'a', buf2, buf, ot);
} }
@ -5113,7 +5173,7 @@ void domagic(enum OBTYPE spellid, int cellx, int celly) {
// init the prompt if required. // init the prompt if required.
if (spellid == OT_NONE) { if (spellid == OT_NONE) {
makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:", SS_NONE, B_FALSE, B_TRUE, player->mp); makespellchoicelist(&prompt, player, "Use which spell/ability:","Describe which spell/ability:", SS_NONE, B_FALSE, B_TRUE, B_FALSE, player->mp);
} }
finished = B_FALSE; finished = B_FALSE;
@ -5181,7 +5241,7 @@ void domemmagic(void) {
char ch; char ch;
int slot; int slot;
objecttype_t *ot; objecttype_t *ot;
makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability",SS_NONE, B_FALSE, B_TRUE, player->maxmp); makespellchoicelist(&prompt, player, "Memorise which spell/ability:","Describe which spell/ability",SS_NONE, B_FALSE, B_TRUE, B_TRUE, player->maxmp);
if (prompt.nchoices <= 0) { if (prompt.nchoices <= 0) {
msg("You don't have any spells or abilities!"); msg("You don't have any spells or abilities!");
return; return;
@ -5327,7 +5387,9 @@ int dopickup(obpile_t *op, int forceask) {
} }
for (i = 0; i < nretobs; i++) { for (i = 0; i < nretobs; i++) {
pickup(player, retobs[i],retobscount[i], B_TRUE, B_TRUE); if (pickup(player, retobs[i],retobscount[i], B_TRUE, B_TRUE)) {
break;
}
} }
/* /*
@ -5515,9 +5577,9 @@ void doinventory(obpile_t *op) {
void doquaff(obpile_t *op) { void doquaff(obpile_t *op) {
object_t *o,*liquid = NULL; object_t *o,*liquid = NULL;
// quaffable objects here? // quaffable objects here? (don't need to be able to pick them up)
for (o = player->cell->obpile->first; o ; o = o->next) { for (o = player->cell->obpile->first; o ; o = o->next) {
if (isdrinkable(o) && canquaff(player, o) && canpickup(player, o, 1)) { if (isdrinkable(o) && canquaff(player, o) ) {
char obname[BUFLEN]; char obname[BUFLEN];
char buf[BUFLEN]; char buf[BUFLEN];
char ch; char ch;
@ -6023,6 +6085,10 @@ void drawlevelfor(lifeform_t *lf) {
return; return;
} }
if ((gamemode == GM_GAMESTARTED) && isplayer(lf) && lf->losdirty) {
precalclos(player);
}
//dbtimestart("drawscreen"); //dbtimestart("drawscreen");
map = lf->cell->map; map = lf->cell->map;
@ -6136,6 +6202,7 @@ void initgfx(void) {
init_pair(C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_BLACK); init_pair(C_BOLDMAGENTA, COLOR_MAGENTA, COLOR_BLACK);
init_pair(C_BOLDGREEN, COLOR_GREEN, COLOR_BLACK); init_pair(C_BOLDGREEN, COLOR_GREEN, COLOR_BLACK);
init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK); init_pair(C_ORANGE, COLOR_RED, COLOR_BLACK);
init_pair(C_DARKGREY, COLOR_BLACK, COLOR_BLACK);
init_pair(BLUEBG+C_BLACK, COLOR_BLACK, COLOR_BLUE); init_pair(BLUEBG+C_BLACK, COLOR_BLACK, COLOR_BLUE);
@ -7033,10 +7100,8 @@ void handleinput(void) {
case 'e': // eat case 'e': // eat
doeat(player->pack); doeat(player->pack);
break; break;
case 'd': // drop case 'd': // drop multiple things
dodrop(player->pack, B_SINGLE, player->cell->obpile); //dodrop(player->pack, B_SINGLE, player->cell->obpile);
break;
case 'D': // drop multiple things
dodrop(player->pack, B_MULTIPLE, player->cell->obpile); dodrop(player->pack, B_MULTIPLE, player->cell->obpile);
break; break;
case 'W': // wear case 'W': // wear
@ -7296,6 +7361,7 @@ int needsbold(enum COLOUR col) {
case C_BOLDMAGENTA: case C_BOLDMAGENTA:
case C_BOLDGREEN: case C_BOLDGREEN:
case C_ORANGE: case C_ORANGE:
case C_DARKGREY:
return B_TRUE; return B_TRUE;
default: default:
break; break;
@ -7418,6 +7484,12 @@ void drawstatus(void) {
} }
} }
if (iswoozy(player)) {
setcol(statwin, C_YELLOW);
wprintw(statwin, " Woozy");
unsetcol(statwin, C_YELLOW);
}
// paralysed somehow? // paralysed somehow?
if (isresting(player)) { if (isresting(player)) {
setcol(statwin, C_CYAN); setcol(statwin, C_CYAN);
@ -7515,7 +7587,7 @@ void drawstatus(void) {
} }
// show certain flags // show certain flags
f = isdrunk(player); f = lfhasflag(player, F_DRUNK);
if (f) { if (f) {
char dstring[BUFLEN]; char dstring[BUFLEN];
strcpy(dstring, getdrunktext(f)); strcpy(dstring, getdrunktext(f));
@ -7987,7 +8059,7 @@ void showlfstats(lifeform_t *lf, int showall) {
float w; float w;
w = getlfweight(lf, B_NOOBS); w = getlfweight(lf, B_NOOBS);
doheadingsmall(mainwin, y, 0, ftext, "Weight"); doheadingsmall(mainwin, y, 0, ftext, "Weight");
getweighttext(w, buf); getweighttext(w, buf, B_FALSE);
wprintw(mainwin, buf, w); y++; wprintw(mainwin, buf, w); y++;
} }
@ -8340,11 +8412,35 @@ void showlfstats(lifeform_t *lf, int showall) {
if (showall) { if (showall) {
f = hasflag(lf->flags, F_HUNGER); f = hasflag(lf->flags, F_HUNGER);
if (f) { if (f) {
int i;
char hungerbar[10];
float pct;
enum COLOUR col;
doheadingsmall(mainwin, y2, x2, ftext, "Hunger"); doheadingsmall(mainwin, y2, x2, ftext, "Hunger");
gethungername(lf, gethungerlevel(f->val[0]), buf); // select colour for hungerbar
// hunger can be from -(const*2) up to (const*5)
pct = (((float)f->val[0] + (float)(HUNGERCONST*2)) / ((float)HUNGERCONST*7.0)) * 100;
limitf(&pct, 0, 100);
pct = 100 - pct;
col = gethungercol(gethungerlevel(f->val[0]));
// construct hungerbar
for (i = 0; i < 10; i++) {
if (pct >= (i*10)) {
hungerbar[i] = '*';
} else {
hungerbar[i] = '.';
}
}
//gethungername(lf, gethungerlevel(f->val[0]), buf);
capitalise(buf); capitalise(buf);
wprintw(mainwin, "%-14s", buf); y2++; wprintw(mainwin, "[");
setcol(mainwin, col);
wprintw(mainwin, "%s", hungerbar);
unsetcol(mainwin, col);
wprintw(mainwin, "]");
y2++;
/* /*
if (showall) { if (showall) {
wprintw(mainwin, "%-14s (%d)", buf, f->val[0]); y++; wprintw(mainwin, "%-14s (%d)", buf, f->val[0]); y++;
@ -8731,7 +8827,6 @@ void showlfstats(lifeform_t *lf, int showall) {
wrapprint(mainwin, &y, &x, buf); wrapprint(mainwin, &y, &x, buf);
} }
} }
} else if (mode == 'a') { } else if (mode == 'a') {
centre(mainwin, C_WHITE, 0, "ABILITIES"); centre(mainwin, C_WHITE, 0, "ABILITIES");
y = 2; y = 2;
@ -8741,7 +8836,7 @@ void showlfstats(lifeform_t *lf, int showall) {
f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL); f = lfhasknownflagval(lf, F_CANWILL, ot->id, NA, NA, NULL);
if (f && (f->known)) { if (f && (f->known)) {
char expirebuf[BUFLEN]; char expirebuf[BUFLEN];
char eb2[BUFLEN]; char eb2[BUFLEN],racestr[BUFLEN];
int needgrab = B_FALSE; int needgrab = B_FALSE;
int range; int range;
@ -8753,7 +8848,7 @@ void showlfstats(lifeform_t *lf, int showall) {
} }
// extra options? // extra options?
texttospellopts(f->text, NULL, NULL, &needgrab, &range); texttospellopts(f->text, "needgrab:", &needgrab, "range:", &range, "race:", racestr, NULL);
if (needgrab) { if (needgrab) {
strcat(expirebuf, ",after grab"); strcat(expirebuf, ",after grab");
} }
@ -8762,6 +8857,11 @@ void showlfstats(lifeform_t *lf, int showall) {
snprintf(rbuf, BUFLEN, ",range:%d",range); snprintf(rbuf, BUFLEN, ",range:%d",range);
strcat(expirebuf, rbuf); strcat(expirebuf, rbuf);
} }
if (strlen(racestr)) {
char rbuf[BUFLEN];
snprintf(rbuf, BUFLEN, ",race:%s",racestr);
strcat(expirebuf, rbuf);
}
if (strlen(expirebuf)) { if (strlen(expirebuf)) {
snprintf(eb2, BUFLEN,"(%s)",expirebuf); snprintf(eb2, BUFLEN,"(%s)",expirebuf);
@ -9066,6 +9166,11 @@ void showlfstats(lifeform_t *lf, int showall) {
mvwprintw(mainwin, y, 0, "%s can control teleportation and polymorphic effects.", you(lf)); mvwprintw(mainwin, y, 0, "%s can control teleportation and polymorphic effects.", you(lf));
y++; y++;
} }
f = lfhasknownflag(lf, F_CONFUSED);
if (f) {
mvwprintw(mainwin, y, 0, "%s %s confused.", you(lf), is(lf));
y++;
}
f = lfhasknownflag(lf, F_DEAF); f = lfhasknownflag(lf, F_DEAF);
if (f) { if (f) {
mvwprintw(mainwin, y, 0, "%s %s deaf.", you(lf), is(lf)); mvwprintw(mainwin, y, 0, "%s %s deaf.", you(lf), is(lf));
@ -9301,7 +9406,7 @@ void showlfstats(lifeform_t *lf, int showall) {
f = lfhasflag(lf, F_PAIN); f = lfhasflag(lf, F_PAIN);
if (f && (f->known)) { if (f && (f->known)) {
if (isdrunk(lf)) { if (lfhasflag(lf, F_DRUNK)) {
mvwprintw(mainwin, y, 0, "%s %s in extreme pain, somewhat mitigated by %s inebriation.", you(lf), is(lf), isplayer(lf) ? "your" : "its"); mvwprintw(mainwin, y, 0, "%s %s in extreme pain, somewhat mitigated by %s inebriation.", you(lf), is(lf), isplayer(lf) ? "your" : "its");
} else { } else {
mvwprintw(mainwin, y, 0, "%s %s in extreme pain, and movement will cause %s damage.", you(lf), is(lf), isplayer(lf) ? "you" : "it"); mvwprintw(mainwin, y, 0, "%s %s in extreme pain, and movement will cause %s damage.", you(lf), is(lf), isplayer(lf) ? "you" : "it");
@ -9426,6 +9531,17 @@ void showlfstats(lifeform_t *lf, int showall) {
y++; y++;
} }
} }
// material vulnerbilities
getflags(lf->flags, retflag, &nretflags, F_MATVULN, F_NONE);
for (i = 0; i < nretflags; i++) {
material_t *mt;
mt = findmaterial(retflag[i]->val[0]);
sprintf(buf, "%s take%s %d%% damage from weapons made of %s.", you(lf),
isplayer(lf) ? "" : "s", retflag[i]->val[1], mt->name);
mvwprintw(mainwin, y, 0, buf); y++;
}
} else if (mode == 'i') { } else if (mode == 'i') {
object_t *o; object_t *o;
cls(); cls();

2
io.h
View File

@ -92,7 +92,7 @@ void initgfx(void);
void initprompt(prompt_t *p, char *q1); void initprompt(prompt_t *p, char *q1);
int keycodetokey(int keycode); int keycodetokey(int keycode);
void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints); void listobs(WINDOW *win, object_t **mylist, int *sellist, int *selcount, int firstob, int *counter, int lastline, int *y, char *myletters, int forpickup, int showpoints);
void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantinvalid, int mpcutoff); void makespellchoicelist(prompt_t *pr, lifeform_t *lf, char *ques, char *ques2, enum SPELLSCHOOL wantschool, int wantunknown, int wantlowmp, int wanttoohard,int mpcutoff);
void more(void); void more(void);
void warn(char *format, ... ); void warn(char *format, ... );
void msg(char *format, ... ); void msg(char *format, ... );

1566
lf.c

File diff suppressed because it is too large Load Diff

11
lf.h
View File

@ -50,6 +50,7 @@ int checkfordrowning(lifeform_t *lf, object_t *o);
int check_rest_ok(lifeform_t *lf); int check_rest_ok(lifeform_t *lf);
//void checkxp(enum RACE rid); //void checkxp(enum RACE rid);
float comparelfs(lifeform_t *lf1, lifeform_t *lf2); float comparelfs(lifeform_t *lf1, lifeform_t *lf2);
int confuse(lifeform_t *lf, int howlong);
int countinnateattacks(lifeform_t *lf); int countinnateattacks(lifeform_t *lf);
int countmoney(lifeform_t *lf); int countmoney(lifeform_t *lf);
int countnearbyallies(lifeform_t *lf); int countnearbyallies(lifeform_t *lf);
@ -61,10 +62,12 @@ void die(lifeform_t *lf);
int digcell(lifeform_t *lf, cell_t *c, object_t *o); int digcell(lifeform_t *lf, cell_t *c, object_t *o);
int digdown(lifeform_t *lf, object_t *o); int digdown(lifeform_t *lf, object_t *o);
int digup(lifeform_t *lf, object_t *o); int digup(lifeform_t *lf, object_t *o);
void do_eyesight_adjust(lifeform_t *lf);
void dumplev(void); void dumplev(void);
void dumplf(void); void dumplf(void);
void dumpxp(void); void dumpxp(void);
int eat(lifeform_t *lf, object_t *o); int eat(lifeform_t *lf, object_t *o);
void endlfturn(lifeform_t *lf);
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); void extinguishlf(lifeform_t *lf);
@ -125,6 +128,7 @@ int gethearingrange(lifeform_t *lf);
int gethidemodifier(lifeform_t *lf); int gethidemodifier(lifeform_t *lf);
int gethitdice(lifeform_t *lf); int gethitdice(lifeform_t *lf);
int gethppct(lifeform_t *lf); int gethppct(lifeform_t *lf);
enum COLOUR gethungercol(enum HUNGER hlev);
enum HUNGER gethungerlevel(int hunger); enum HUNGER gethungerlevel(int hunger);
char *gethungername(lifeform_t *lf, enum HUNGER hunger, char *buf); char *gethungername(lifeform_t *lf, enum HUNGER hunger, char *buf);
int gethungerval(lifeform_t *lf); int gethungerval(lifeform_t *lf);
@ -150,7 +154,7 @@ float getmaxliftweight(lifeform_t *lf);
int getmaxmp(lifeform_t *lf); int getmaxmp(lifeform_t *lf);
float getmaxpushweight(lifeform_t *lf); float getmaxpushweight(lifeform_t *lf);
int getmr(lifeform_t *lf); int getmr(lifeform_t *lf);
int getvisrange(lifeform_t *lf); int getvisrange(lifeform_t *lf, int useambient);
void idxtoxy(lifeform_t *lf, int idx, int *x, int *y); void idxtoxy(lifeform_t *lf, int idx, int *x, int *y);
void setviscell(lifeform_t *lf, cell_t *cell, int how); void setviscell(lifeform_t *lf, cell_t *cell, int how);
int getviscell(lifeform_t *lf, cell_t *cell); int getviscell(lifeform_t *lf, cell_t *cell);
@ -235,7 +239,6 @@ int isblind(lifeform_t *lf);
enum BURDENED isburdened(lifeform_t *lf); enum BURDENED isburdened(lifeform_t *lf);
int ischarmable(lifeform_t *lf); int ischarmable(lifeform_t *lf);
int isdead(lifeform_t *lf); int isdead(lifeform_t *lf);
flag_t *isdrunk(lifeform_t *lf);
object_t *isdualweilding(lifeform_t *lf); object_t *isdualweilding(lifeform_t *lf);
int isfleeing(lifeform_t *lf); int isfleeing(lifeform_t *lf);
int isfreebp(lifeform_t *lf, enum BODYPART bp); int isfreebp(lifeform_t *lf, enum BODYPART bp);
@ -264,6 +267,7 @@ int isswimming(lifeform_t *lf);
int isundead(lifeform_t *lf); int isundead(lifeform_t *lf);
flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt); flag_t *isvulnto(flagpile_t *fp, enum DAMTYPE dt);
int isweaponskill(enum SKILL skid); int isweaponskill(enum SKILL skid);
enum FLAG iswoozy(lifeform_t *lf);
void killjob(job_t *job); void killjob(job_t *job);
void killlf(lifeform_t *lf); void killlf(lifeform_t *lf);
void killrace(race_t *race); void killrace(race_t *race);
@ -316,12 +320,14 @@ 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 setlfmaterial(lifeform_t *lf, enum MATERIAL id);
void setlosdirty(lifeform_t *lf);
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);
void startlfturn(lifeform_t *lf);
int steal(lifeform_t *lf, obpile_t *op, enum FLAG wantflag); 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);
@ -336,7 +342,6 @@ void taketime(lifeform_t *lf, long howlong);
int throwat(lifeform_t *thrower, object_t *o, cell_t *where); int throwat(lifeform_t *thrower, object_t *o, cell_t *where);
void timeeffectslf(lifeform_t *lf); void timeeffectslf(lifeform_t *lf);
int tryclimb(lifeform_t *lf, cell_t *where, char *towhat); int tryclimb(lifeform_t *lf, cell_t *where, char *towhat);
void turneffectslf(lifeform_t *lf);
int touch(lifeform_t *lf, object_t *o); int touch(lifeform_t *lf, object_t *o);
void unpoison(lifeform_t *lf); void unpoison(lifeform_t *lf);
void unsummon(lifeform_t *lf, int vanishobs); void unsummon(lifeform_t *lf, int vanishobs);

250
map.c
View File

@ -50,8 +50,8 @@ cell_t *addcell(map_t *m, int x, int y) {
cell->x = x; cell->x = x;
cell->y = y; cell->y = y;
cell->habitat = m->habitat; cell->habitat = m->habitat;
setcelltype(cell, cell->habitat->solidcelltype);
cell->obpile = addobpile(NOOWNER, cell, NOOB); cell->obpile = addobpile(NOOWNER, cell, NOOB);
setcelltype(cell, cell->habitat->solidcelltype);
cell->lf = NULL; cell->lf = NULL;
cell->room = NULL; cell->room = NULL;
cell->lit = L_NOTLIT; cell->lit = L_NOTLIT;
@ -67,7 +67,7 @@ cell_t *addcell(map_t *m, int x, int y) {
return cell; return cell;
} }
habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance) { habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange) {
habitat_t *a; habitat_t *a;
// add to the end of the list // add to the end of the list
if (firsthabitat == NULL) { if (firsthabitat == NULL) {
@ -92,6 +92,7 @@ habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum
a->randthingpct = thingchance; a->randthingpct = thingchance;
a->randobpct = obchance; a->randobpct = obchance;
a->randvaultpct = vaultchance; a->randvaultpct = vaultchance;
a->maxvisrange = maxvisrange;
return a; return a;
} }
@ -472,8 +473,43 @@ map_t *getmapindir(map_t *src, int dir) {
return other; return other;
} }
//
int getmapmaxvisrange(map_t *m) {
int maxrange;
maxrange = m->habitat->maxvisrange;
// modify for darkness outside ?
if (isoutdoors(m)) {
int hours,mins,secs;
float pct;
splittime(&hours,&mins,&secs);
pct = ((float)mins/59.0) * 100.0;
if (hours == 6) { // ie. 6am - 7am
// getting lighter. as minutes approach 59,
// visrange gets closer to maximum.
maxrange = pctof( pct, maxrange);
limit(&maxrange, 1, NA);
} else if (hours == 18) { // ie. 6pm-7pm
// getting darker. as minutes approach 59,
// visrange gets closer to zero.
maxrange = pctof( 100 - pct, maxrange);
limit(&maxrange, 1, NA);
}
} else if (m->habitat->id == H_DUNGEON) {
// in dungeon, reduce distance based on depth (ie. ambient light)
maxrange -= m->depth;
}
limit(&maxrange, 0, MAXVISRANGE);
return maxrange;
}
// populates retcell[] with all cells within given radius of centre // populates retcell[] with all cells within given radius of centre
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells) { // if 'scatter' is >0, then not all cells will be returned - as you approach the edge of the radius,
// chances of getting the cells are lowered
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells, int scatterdensity) {
int (*distfunc)(cell_t *, cell_t *); int (*distfunc)(cell_t *, cell_t *);
int x,y; int x,y;
cell_t *c; cell_t *c;
@ -491,10 +527,22 @@ void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlo
for (y = centre->y - radius; y <= centre->y + radius; y++) { for (y = centre->y - radius; y <= centre->y + radius; y++) {
for (x = centre->x - radius; x <= centre->x + radius; x++) { for (x = centre->x - radius; x <= centre->x + radius; x++) {
c = getcellat(centre->map, x,y); c = getcellat(centre->map, x,y);
if (c && haslof(centre, c, needlof, NULL) && (distfunc(centre, c) <= radius) && if (c) {
(wantcentre || (c != centre)) ) { int distance;
retcell[*ncells] = c; distance = distfunc(centre, c);
(*ncells)++; if (haslof(centre, c, needlof, NULL) && (distance <= radius) &&
(wantcentre || (c != centre)) ) {
int chance;
if (scatterdensity) {
chance = 100 - (((float)distance / (float)radius) * scatterdensity);
} else {
chance = 100;
}
if (pctchance(chance)) {
retcell[*ncells] = c;
(*ncells)++;
}
}
} }
} }
} }
@ -939,6 +987,42 @@ void clearcell(cell_t *c) {
c->knownglyph.colour = C_GREY; c->knownglyph.colour = C_GREY;
} }
} }
void clearcell_exceptflags(cell_t *c, ... ) {
va_list args;
enum FLAG exception[MAXCANDIDATES];
int nexceptions = 0,i;
object_t *o,*nexto;
va_start(args, c);
exception[nexceptions] = va_arg(args, enum FLAG);
while (exception[nexceptions] != F_NONE) {
nexceptions++;
exception[nexceptions] = va_arg(args, enum FLAG);
}
va_end(args);
assert(nexceptions < MAXCANDIDATES);
if (c->lf && !isplayer(c->lf)) {
killlf(c->lf);
}
for (o = c->obpile->first ; o ; o = nexto) {
int exclude = B_FALSE;
nexto = o->next;
for (i = 0; i < nexceptions; i++) {
if (hasflag(o->flags, exception[i])) {
exclude = B_TRUE;
break;
}
}
if (!exclude) killob(o);
}
if (gamemode == GM_GAMESTARTED) {
c->known = B_FALSE;
c->knownglyph.ch = ' ';
c->knownglyph.colour = C_GREY;
}
}
// returns true if something happened // returns true if something happened
int dowaterspread(cell_t *c) { int dowaterspread(cell_t *c) {
@ -1199,6 +1283,9 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) {
if (g->ch == '.') { if (g->ch == '.') {
g->ch = ' '; g->ch = ' ';
} }
// out of LOS - show as dark
// TODO: if terminal supports it, use C_DARKGREY instead.
g->colour = C_BLUE;
} }
break; break;
} }
@ -1827,7 +1914,7 @@ void createdungeon(map_t *map, int depth, map_t *parentmap, int exitdir, object_
if (!roomvault[i]) { if (!roomvault[i]) {
int rx,ry; int rx,ry;
// just do a normal room // just do a normal room
createroom(map, i, NA, NA, 0, 0, &rx, &ry, &roomw[i],&roomh[i], 50, B_FALSE); createroom(map, i, NA, NA, DEF_VAULTMARGIN, DEF_VAULTMARGIN, &rx, &ry, &roomw[i],&roomh[i], 50, B_FALSE);
roomvault[i] = B_FALSE; roomvault[i] = B_FALSE;
} }
} }
@ -2006,6 +2093,8 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
int density; int density;
cell_t *c; cell_t *c;
char buf[BUFLEN]; char buf[BUFLEN];
cell_t *retcell[MAXCANDIDATES];
int nretcells;
//object_t *o; //object_t *o;
// fill entire maze with emptiness // fill entire maze with emptiness
@ -2035,62 +2124,39 @@ void createforest(map_t *map, int depth, map_t *parentmap, int exitdir, object_t
} }
// clearings // clearings
for (i = 0; i < nclearings; i++) { for (i = 0; i < nclearings; i++) {
int w; int w,n;
c = getrandomcell(map); c = getrandomcell(map);
w = rnd(MINCLEARINGRADIUS,MAXCLEARINGRADIUS); w = rnd(MINCLEARINGRADIUS,MAXCLEARINGRADIUS);
for (y = c->y - w; y <= c->y + w; y++) { // clear obs in all clearing cells
for (x = c->x - w; x <= c->x + w; x++) { getradiuscells(c, w, DT_ORTH, LOF_DONTNEED, B_TRUE, retcell, &nretcells, B_FALSE);
cell_t *newc; for (n = 0; n < nretcells; n++) {
int dist = 999; // kill all obs here
newc = getcellat(map, x, y); while (retcell[n]->obpile->first) killob(retcell[n]->obpile->first);
if (newc) { }
dist = getcelldistorth(newc, c);
if (dist <= w) { // fill some cells with dirt
int dirtchance; getradiuscells(c, w, DT_ORTH, LOF_DONTNEED, B_TRUE, retcell, &nretcells, 70);
// kill all obs here for (n = 0; n < nretcells; n++) {
while (newc->obpile->first) killob(newc->obpile->first); setcelltype(retcell[n], CT_DIRT);
// change it into dirt.
// ie. at centre (dist=0) dirt chance is 100%
// ie. at max distance, dirt chance is 30%
dirtchance = 100 - (((float)dist / (float)w) * 70);
if (rnd(1,100) <= dirtchance) {
setcelltype(newc, CT_DIRT);
}
}
}
}
} }
} }
break; break;
case 2: // add clusters of trees case 2: // add clusters of trees
nclearings = rnd(5,10); nclearings = rnd(5,10);
for (i = 0; i < nclearings; i++) { for (i = 0; i < nclearings; i++) {
int w; int w,n;
c = getrandomcell(map); c = getrandomcell(map);
while (c->lf) c = getrandomcell(map); while (c->lf) c = getrandomcell(map);
w = rnd(MINCLEARINGRADIUS,MAXCLEARINGRADIUS); w = rnd(MINCLEARINGRADIUS,MAXCLEARINGRADIUS);
for (y = c->y - w; y <= c->y + w; y++) {
for (x = c->x - w; x <= c->x + w; x++) { getradiuscells(c, w, DT_ORTH, LOF_DONTNEED, B_TRUE, retcell, &nretcells, 80);
cell_t *newc; for (n = 0; n < nretcells; n++) {
int dist = 999; switch (rnd(0,1)) {
newc = getcellat(map, x, y); default: case 0: strcpy(buf, "tree"); break;
if (newc) { case 1: strcpy(buf, "shrub"); break;
dist = getcelldistorth(newc, c);
if (dist <= w) {
int treechance;
treechance = 100 - (((float)dist / (float)w) * 70);
if (rnd(1,100) <= treechance) {
switch (rnd(0,1)) {
default: case 0: strcpy(buf, "tree"); break;
case 1: strcpy(buf, "shrub"); break;
}
addob(c->obpile, buf);
}
}
}
} }
addob(retcell[n]->obpile, buf);
} }
} }
break; break;
@ -2798,7 +2864,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
// if we hit a cell of this roomid, mark this dir as invalid. // if we hit a cell of this roomid, mark this dir as invalid.
for (d = D_N; d <= D_W; d++) { for (d = D_N; d <= D_W; d++) {
dist[d] = 0; dist[d] = 0;
hitsedge[d] = B_TRUE; hitsedge[d] = B_FALSE;
sameroom[d] = B_FALSE; sameroom[d] = B_FALSE;
c = getcellindir(startcell, d); c = getcellindir(startcell, d);
while (c) { while (c) {
@ -2820,7 +2886,6 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
} else if (cellwalkable(NULL, c, NULL)) { } else if (cellwalkable(NULL, c, NULL)) {
if (!wantfilled || c->filled) { if (!wantfilled || c->filled) {
// walkable and not in this vault. finished. // walkable and not in this vault. finished.
hitsedge[d] = B_FALSE;
directendcell[d] = c; directendcell[d] = c;
if (db) dblog(" can make %s path (hits empty cell at dist %d)", getdirname(d), dist[d]); if (db) dblog(" can make %s path (hits empty cell at dist %d)", getdirname(d), dist[d]);
break; break;
@ -2839,7 +2904,6 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
cellwalkable(NULL, pcell, NULL)) { cellwalkable(NULL, pcell, NULL)) {
if (!wantfilled || c->filled) { if (!wantfilled || c->filled) {
// finished. // finished.
hitsedge[d] = B_FALSE;
directendcell[d] = c; directendcell[d] = c;
if (db) dblog(" can make %s path (hits adjacent empty cell at dist %d)", getdirname(d), dist[d]); if (db) dblog(" can make %s path (hits adjacent empty cell at dist %d)", getdirname(d), dist[d]);
break; break;
@ -2851,8 +2915,14 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
// check next cell // check next cell
c = getcellindir(c, d); // getting the same cell! c = getcellindir(c, d); // getting the same cell!
} }
if (!c) {
if (db) dblog(" going %s hits edge of map.", getdirname(d));
hitsedge[d] = B_TRUE;
}
if (dist[d] != 999) { if (dist[d] != 999) {
if (dist[d] < mindist) mindist = dist[d]; if (!hitsedge[d]) {
if (dist[d] < mindist) mindist = dist[d];
}
if (dist[d] > maxdist) maxdist = dist[d]; if (dist[d] > maxdist) maxdist = dist[d];
} }
} }
@ -2911,14 +2981,17 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
int turndist = 0; int turndist = 0;
c2 = getcellindir(c, perpdir[n]); c2 = getcellindir(c, perpdir[n]);
perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns
perpturncell1[nperpcells] = c;
perpturndir1[nperpcells] = perpdir[n];
nperpcells++;
while (c2) { while (c2) {
int gotsolution = B_FALSE; int gotsolution = B_FALSE;
turndist++; turndist++;
perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns
perpturncell1[nperpcells] = c;
perpturndir1[nperpcells] = perpdir[n];
nperpcells++;
if ((roomid >= 0) && (getroomid(c2) == roomid)) { if ((roomid >= 0) && (getroomid(c2) == roomid)) {
if (wantfilled && c2->type->solid) { if (wantfilled && c2->type->solid) {
// see EXCEPTION above. // see EXCEPTION above.
@ -2991,21 +3064,28 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
c = getcellindir(c, turndir); c = getcellindir(c, turndir);
} }
} else { } else {
// We need to make 3 turns. // We need to make 2 turns.
// for each perpcell[], look in startdir + diropposite(startdir) // for each perpcell[], look in startdir + diropposite(startdir)
int dir3[2],i,n; int dir3[2],i,n;
cell_t *turncell2 = NULL; cell_t *turncell2 = NULL;
int turndir2; int turndir2;
dir3[0] = startdir; dir3[0] = startdir;
dir3[1] = diropposite(startdir); dir3[1] = diropposite(startdir);
if (db) dblog(" Need to make two turns. Searching %s and %s from each perpcell.", getdirname(dir3[0]),
getdirname(dir3[1]));
for (i = 0; i < nperpcells; i++) { for (i = 0; i < nperpcells; i++) {
for (n = 0; n < 1; n++) { for (n = 0; n < 2; n++) {
cell_t *c2; cell_t *c2;
int turndist = 0; int turndist = 0;
if (db) dblog_nocr("looking %s from %d,%d: ", getdirname(dir3[n]),
perpcell[i]->x, perpcell[i]->y);
c2 = getcellindir(perpcell[i], dir3[n]); c2 = getcellindir(perpcell[i], dir3[n]);
while (c2) { while (c2) {
int gotsolution = B_FALSE; int gotsolution = B_FALSE;
turndist++; turndist++;
if (db) dblog_nocr("(%d,%d)",c2->x,c2->y);
if ((roomid >= 0) && (getroomid(c2) == roomid)) { if ((roomid >= 0) && (getroomid(c2) == roomid)) {
if (wantfilled && c2->type->solid) { if (wantfilled && c2->type->solid) {
// see EXCEPTION above. // see EXCEPTION above.
@ -3040,29 +3120,27 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
} }
} }
if (gotsolution) { if (gotsolution) {
if (db) dblog(" Solution found: Walk %d %s, then %d %s.", turncell = perpturncell1[i];
startdist, getdirname(startdir), turndir = perpturndir1[i];
turndist, getdirname(perpdir[n])); turncell2 = perpcell[i];
turndir2 = dir3[n];
turncell = perpturncell1[i]; endcell = c2;
turndir = perpturndir1[i];
turncell2 = perpcell[i];
turndir2 = dir3[n];
endcell = c2;
break; break;
} }
// check next cell // check next cell
c2 = getcellindir(c2, perpdir[n]); c2 = getcellindir(c2, dir3[n]);
} // end while c2 } // end while c2
if (turncell2) break; if (turncell2) break;
if (db) dblog("");
} // end for n=1-2 } // end for n=1-2
if (turncell2) break; if (turncell2) break;
} // end foreach perpcell } // end foreach perpcell
// TODO: if we find a solution, fill in turncell2 and make path. // TODO: if we find a solution, fill in turncell2 and make path.
if (turncell2) { if (turncell2) {
if (db) dblog(" 2turn Solution found: Walk %s, then %s, then %s.", if (db) dblog(" Twoturn solution found: Walk %s, then %s, then %s.",
getdirname(startdir), getdirname(turndir), getdirname(turndir2)); getdirname(startdir), getdirname(turndir), getdirname(turndir2));
// make a path up to the turn point. // make a path up to the turn point.
@ -3094,6 +3172,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
} }
} else { } else {
if (db) dblog(" Cannot find a way to link up."); if (db) dblog(" Cannot find a way to link up.");
assert(0 == 1); // for debugging
} }
return B_TRUE; return B_TRUE;
} }
@ -3189,6 +3268,13 @@ int linkexits(map_t *m, int roomid) {
// part of this room // part of this room
for (i = 0; i < nposs; i++) { for (i = 0; i < nposs; i++) {
int ncorridors = 0,d; int ncorridors = 0,d;
// if exit is solid and COMPLETELY surrounded by solid, ignore it.
if (c->type->solid && (countcellexits(c) == 0)){
if (db) dblog("cell is solid and surrounded by solids. ignoring.");
continue;
}
if (db) dblog("linking exit #%d",i); if (db) dblog("linking exit #%d",i);
for (d = D_N; d <= D_W; d++) { for (d = D_N; d <= D_W; d++) {
@ -3316,8 +3402,8 @@ int createroom(map_t *map, int roomid, int overrideminw, int overrideminh, int x
for (x = minx; x <= maxx; x++) { for (x = minx; x <= maxx; x++) {
cell = getcellat(map, x, y); cell = getcellat(map, x, y);
if (cell) { if (cell) {
// kill contents // kill contents, EXCEPT for staircases!
clearcell(cell); clearcell_exceptflags(cell, F_CLIMBABLE, F_NONE);
// make it a border or room // make it a border or room
if ((y == miny) || (y == maxy) || if ((y == miny) || (y == maxy) ||
(x == minx) || (x == maxx)) { (x == minx) || (x == maxx)) {
@ -4321,11 +4407,11 @@ void initmap(void) {
int vx[4],vy[4],i; int vx[4],vy[4],i;
// habitats // habitats
// thingchance, obchance, vaultchance // thingchance, obchance, vaultchance
addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 3, 50, 30); addhabitat(H_DUNGEON, "dungeon", CT_CORRIDOR, CT_WALL, 3, 50, 30, 6);
addhabitat(H_FOREST, "forest", CT_GRASS, CT_WALL, 3, 75, 0); addhabitat(H_FOREST, "forest", CT_GRASS, CT_WALL, 3, 75, 0, MAXVISRANGE);
addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALL, 0, 0, 0); addhabitat(H_HEAVEN, "heaven", CT_CORRIDOR, CT_WALL, 0, 0, 0, MAXVISRANGE);
addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0); addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5);
addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0); addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0, MAXVISRANGE);
// cell types // cell types
addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0); addcelltype(CT_WALL, "rock wall", '#', C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0);
@ -4992,6 +5078,7 @@ int remove_deadends(map_t *m, int howmuch) {
c = m->cell[n]; c = m->cell[n];
if (countcellexits(c) == 1) { if (countcellexits(c) == 1) {
// erase this cell // erase this cell
clearcell(c);
setcelltype(c, solidcell); setcelltype(c, solidcell);
count++; count++;
} }
@ -5050,7 +5137,7 @@ void setcellknown(cell_t *cell, int forcelev) {
void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype) { void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype) {
cell_t *cell[MAXCANDIDATES]; cell_t *cell[MAXCANDIDATES];
int ncells,i; int ncells,i;
getradiuscells(centre, radius, dirtype, LOF_DONTNEED, B_TRUE, cell, &ncells); getradiuscells(centre, radius, dirtype, LOF_DONTNEED, B_TRUE, cell, &ncells, B_FALSE);
for (i = 0; i < ncells; i++) { for (i = 0; i < ncells; i++) {
cell_t *c; cell_t *c;
c = cell[i]; c = cell[i];
@ -5062,6 +5149,9 @@ void setcelltype(cell_t *cell, enum CELLTYPE id) {
assert(cell); assert(cell);
cell->type = findcelltype(id); cell->type = findcelltype(id);
assert(cell->type); assert(cell->type);
if (cell->type->solid) {
assert(!cell->obpile->first);
}
if ((gamemode == GM_GAMESTARTED) && haslos(player, cell)) { if ((gamemode == GM_GAMESTARTED) && haslos(player, cell)) {
needredraw = B_TRUE; needredraw = B_TRUE;
} }

6
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, int thingchance, int obchance, int vaultchance); habitat_t *addhabitat(enum HABITAT id, char *name, enum CELLTYPE emptycell, enum CELLTYPE solidcell, int thingchance, int obchance, int vaultchance, int maxvisrange);
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 rid, char *racename, int jobok, int amt, int autogen, int *nadded); lifeform_t *addmonster(cell_t *c, enum RACE rid, char *racename, int jobok, int amt, int autogen, int *nadded);
@ -14,6 +14,7 @@ regiontype_t *addregiontype(enum REGIONTYPE id, char *name, enum HABITAT default
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);
void clearcell_exceptflags(cell_t *c, ...);
int dowaterspread(cell_t *c); int dowaterspread(cell_t *c);
void fix_reachability(map_t *m); void fix_reachability(map_t *m);
int fix_unreachable_cell(cell_t *badcell); int fix_unreachable_cell(cell_t *badcell);
@ -28,7 +29,8 @@ int getdoorsecretdiff(int depth);
flag_t *getmapcoords(map_t *m, int *x, int *y); flag_t *getmapcoords(map_t *m, int *x, int *y);
int getmapdifficulty(map_t *m); int getmapdifficulty(map_t *m);
map_t *getmapindir(map_t *src, int dir); map_t *getmapindir(map_t *src, int dir);
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells); int getmapmaxvisrange(map_t *m);
void getradiuscells(cell_t *centre, int radius, int dirtype, enum LOFTYPE needlof, int wantcentre, cell_t **retcell, int *ncells, int scatterdensity);
int getroomid(cell_t *c); int getroomid(cell_t *c);
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);

32
move.c
View File

@ -897,7 +897,7 @@ int moveeffects(lifeform_t *lf) {
f = lfhasflag(lf, F_PAIN); f = lfhasflag(lf, F_PAIN);
if (f) { if (f) {
if (!isdrunk(lf)) { if (!lfhasflag(lf, F_DRUNK)) {
int dam; int dam;
if (isplayer(lf)) { if (isplayer(lf)) {
msg("Your body is wracked with pain!"); msg("Your body is wracked with pain!");
@ -1022,7 +1022,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
if (lfproduceslight(lf)) { if (lfproduceslight(lf)) {
calclight(lf->cell->map); calclight(lf->cell->map);
} }
precalclos(lf); setlosdirty(lf);
//precalclos(lf);
if (isplayer(lf) || cansee(player, lf)) { if (isplayer(lf) || cansee(player, lf)) {
needredraw = B_TRUE; needredraw = B_TRUE;
@ -1221,7 +1222,8 @@ int movelf(lifeform_t *lf, cell_t *newcell) {
// much larger creatures moving will cause our los to be recalculated // much larger creatures moving will cause our los to be recalculated
if (getlfsize(lf) - getlfsize(l) >= 2) { if (getlfsize(lf) - getlfsize(l) >= 2) {
precalclos(l); setlosdirty(l);
//precalclos(l);
} }
if (isplayer(l)) { if (isplayer(l)) {
@ -2133,18 +2135,23 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
char buf[BUFLEN]; char buf[BUFLEN];
int dontclearmsg = B_FALSE; int dontclearmsg = B_FALSE;
int moveok; int moveok;
int drunk = B_FALSE; int rndmove = B_FALSE;
flag_t *f; flag_t *f;
f = isdrunk(lf); f = lfhasflag(lf, F_DRUNK);
if (f) { if (f) {
if (!hasjob(lf, J_PIRATE)) { if (!hasjob(lf, J_PIRATE)) {
if (rnd(1,6) <= ((f->lifetime/TM_DRUNKTIME)+1)) { if (rnd(1,6) <= ((f->lifetime/TM_DRUNKTIME)+1)) {
// randomize move // randomize move
dir = rnd(DC_N, DC_NW); rndmove = B_TRUE; // ie. you can walk into walls now.
drunk = B_TRUE; // ie. you can walk into walls now.
} }
} }
} else if (iswoozy(lf)) {
rndmove = B_TRUE;
}
if (rndmove) {
dir = rnd(DC_N, DC_NW);
} }
cell = getcellindir(lf->cell, dir); cell = getcellindir(lf->cell, dir);
@ -2215,7 +2222,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
} }
// now move to new cell // now move to new cell
moveto(lf, cell, drunk ? B_FALSE : onpurpose, dontclearmsg); moveto(lf, cell, rndmove ? B_FALSE : onpurpose, dontclearmsg);
if (onpurpose) { if (onpurpose) {
taketime(lf, getmovespeed(lf)); taketime(lf, getmovespeed(lf));
} }
@ -2305,7 +2312,7 @@ int trymove(lifeform_t *lf, int dir, int onpurpose) {
if (!cell || !haslos(lf, cell)) { if (!cell || !haslos(lf, cell)) {
if (isplayer(lf)) { if (isplayer(lf)) {
// only take damage if we didn't know about this // only take damage if we didn't know about this
if ((cell && !cell->known) || isdrunk(lf)) { if ((cell && !cell->known) || iswoozy(lf)) {
snprintf(buf, BUFLEN, "%sing into a %s", getmoveverb(lf), snprintf(buf, BUFLEN, "%sing into a %s", getmoveverb(lf),
cell ? cell->type->name : "wall"); cell ? cell->type->name : "wall");
losehp(lf, 1, DT_BASH, NULL, buf); losehp(lf, 1, DT_BASH, NULL, buf);
@ -2568,8 +2575,9 @@ int walkoffmap(lifeform_t *lf, int dir, int onpurpose) {
if (isplayer(lf)) { if (isplayer(lf)) {
statdirty = B_TRUE; statdirty = B_TRUE;
needredraw = B_TRUE; needredraw = B_TRUE;
calclight(player->cell->map); calclight(lf->cell->map);
precalclos(lf); setlosdirty(lf);
//precalclos(lf);
drawscreen(); drawscreen();
} }
@ -2592,7 +2600,7 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
rdata = NULL; rdata = NULL;
} }
if (isdrunk(lf)) { if (iswoozy(lf)) {
return B_TRUE; return B_TRUE;
} }

35
nexus.c
View File

@ -325,7 +325,8 @@ int main(int argc, char **argv) {
// calculate initial light // calculate initial light
calclight(player->cell->map); calclight(player->cell->map);
// pre-calc line-of-sight for player // pre-calc line-of-sight for player
precalclos(player); //precalclos(player);
setlosdirty(player);
// don't want any mosnters starting within los/lof of player // don't want any mosnters starting within los/lof of player
for (y = 0; y < player->cell->map->h; y++) { for (y = 0; y < player->cell->map->h; y++) {
@ -360,7 +361,7 @@ int main(int argc, char **argv) {
// basic flow is: // basic flow is:
// //
// donextturn() - process a turn for a lifeform // donextturn() - process a turn for a lifeform
// turneffectslf() Rest effects, Damage from floor objects, etc // startlfturn() Rest effects, Damage from floor objects, etc
// lifeform takes action // lifeform takes action
// checkdeath() - check for object/player death. remove dead things. // checkdeath() - check for object/player death. remove dead things.
// timeeffectsworld() Fires burn out, ice melts, etc // timeeffectsworld() Fires burn out, ice melts, etc
@ -567,12 +568,14 @@ void donextturn(map_t *map) {
assert(who->timespent == 0); assert(who->timespent == 0);
turneffectslf(who); startlfturn(who);
// calculate light // calculate light
calclight(map); calclight(map);
// pre-calculate line of sight for this lifeform // pre-calculate line of sight for this lifeform
precalclos(who); //precalclos(who);
// cope with eyesight adjusting to the dark
do_eyesight_adjust(who);
// update gun targets // update gun targets
autotarget(who); autotarget(who);
@ -743,7 +746,10 @@ void donextturn(map_t *map) {
if (hasflag(player->flags, F_ASLEEP)) { if (hasflag(player->flags, F_ASLEEP)) {
needredraw = B_FALSE; needredraw = B_FALSE;
} }
}
if (!isdead(who)) endlfturn(who);
} // end 'if who'
// check for death etc // check for death etc
checkdeath(); checkdeath();
@ -820,9 +826,9 @@ enum COLOUR getpctcol(float num, float max) {
} else if (pct >= 50) { } else if (pct >= 50) {
return C_BROWN; return C_BROWN;
} else if (pct >= 25) { } else if (pct >= 25) {
return C_RED; return C_YELLOW;
} else { // ie. < 25% } else { // ie. < 25%
return C_ORANGE; return C_RED;
} }
return C_ORANGE; return C_ORANGE;
} }
@ -971,8 +977,8 @@ void initcommands(void) {
addcommand(CMD_PICKUP, ',', "Pick up something from the ground."); addcommand(CMD_PICKUP, ',', "Pick up something from the ground.");
addcommand(CMD_CLOSE, 'c', "Close a door."); addcommand(CMD_CLOSE, 'c', "Close a door.");
addcommand(CMD_COMMS, 'C', "Communicate with an ally."); addcommand(CMD_COMMS, 'C', "Communicate with an ally.");
addcommand(CMD_DROP, 'd', "Drop an item."); //addcommand(CMD_DROP, 'd', "Drop an item.");
addcommand(CMD_DROPMULTI, 'D', "Drop multiple items."); addcommand(CMD_DROPMULTI, 'd', "Drop one or more items.");
addcommand(CMD_EAT, 'e', "Eat something."); addcommand(CMD_EAT, 'e', "Eat something.");
addcommand(CMD_EAT, 'E', "Enhance your skills."); addcommand(CMD_EAT, 'E', "Enhance your skills.");
addcommand(CMD_MAGIC, 'm', "Use magic or abilities."); addcommand(CMD_MAGIC, 'm', "Use magic or abilities.");
@ -1534,6 +1540,17 @@ void timeeffectsworld(map_t *map, int updategametime) {
gamedays++; gamedays++;
} }
} }
// if it's the player's turn, announce sun set/rise
if (isplayer(map->lf) && isoutdoors(map)) {
int h,m,s;
splittime(&h, &m, &s);
if (h == 6) {
msg("The sun is rising.");
} else if (h == 18) {
msg("The sun is setting.");
}
}
if (db) dblog("cur time is %ld\n",curtime); if (db) dblog("cur time is %ld\n",curtime);
} }

182
objects.c
View File

@ -439,6 +439,7 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
int wantlit = B_FALSE; int wantlit = B_FALSE;
int wantrarity = RR_NONE; int wantrarity = RR_NONE;
int wantgoodness = G_NA; int wantgoodness = G_NA;
enum MATERIAL wantdiffmat = MT_NOTHING;
map_t *targetmap = NULL; // for portals map_t *targetmap = NULL; // for portals
cell_t *targetcell = NULL; // for portals cell_t *targetcell = NULL; // for portals
int donesomething; int donesomething;
@ -449,6 +450,8 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
int ndoorflags = 0; int ndoorflags = 0;
char *signtext = NULL; char *signtext = NULL;
int trapchance = 0; int trapchance = 0;
flag_t *retflag[MAXCANDIDATES];
int nretflags = 0;
// just in case we don't add any // just in case we don't add any
addedob[0] = NULL; addedob[0] = NULL;
@ -619,6 +622,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
wantlit = B_TRUE; wantlit = B_TRUE;
p += strlen("lit "); p += strlen("lit ");
donesomething = B_TRUE; donesomething = B_TRUE;
// different materials
} else if (strstarts(p, "silver ")) {
wantdiffmat = MT_SILVER;
p += strlen("silver ");
donesomething = B_TRUE;
// rarity // rarity
} else if (strstarts(p, "common ")) { } else if (strstarts(p, "common ")) {
wantrarity = RR_COMMON; wantrarity = RR_COMMON;
@ -890,6 +898,22 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
howmany = 1; howmany = 1;
} }
// we asked for a different material. is this possible?
if ((wantdiffmat != MT_NOTHING) && !hasflagval(ot->flags, F_CANBEDIFFMAT, wantdiffmat, NA, NA, NULL)) {
wantdiffmat = MT_NOTHING;
}
// chance of being a different material baesd on ob flags
if (wantdiffmat == MT_NOTHING) {
getflags(ot->flags, retflag, &nretflags, F_CANBEDIFFMAT, F_NONE);
for (i = 0; i < nretflags; i++) {
if (pctchance(retflag[i]->val[1])) {
wantdiffmat = retflag[i]->val[0]; break;
}
}
}
if (db) dblog("DB: '%s' -> adding %d x %s",name, howmany, ot->name); if (db) dblog("DB: '%s' -> adding %d x %s",name, howmany, ot->name);
@ -1035,6 +1059,11 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
o = addedob[i]; o = addedob[i];
obloc = getoblocation(o); obloc = getoblocation(o);
if (wantdiffmat != MT_NOTHING) {
changemat(o, wantdiffmat);
}
// fill in sign text // fill in sign text
if (signtext) { if (signtext) {
addflag(o->flags, F_SIGNTEXT, NA, NA, NA, signtext); addflag(o->flags, F_SIGNTEXT, NA, NA, NA, signtext);
@ -1329,7 +1358,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
f->val[0] = wantdepth; f->val[0] = wantdepth;
} }
} }
// chance of masterwork based on wantgoodness // chance of masterwork based on wantgoodness
switch (wantgoodness) { switch (wantgoodness) {
case G_GREAT: case G_GREAT:
@ -1587,7 +1615,7 @@ int addobburst(cell_t *where, int range, int dirtype, char *name, lifeform_t *fr
redrawpause(); redrawpause();
getradiuscells(where, range, dirtype, needlof, B_TRUE, cell, &ncells); getradiuscells(where, range, dirtype, needlof, B_TRUE, cell, &ncells, B_FALSE);
for (i = 0; i < ncells; i++) { for (i = 0; i < ncells; i++) {
cell_t *c; cell_t *c;
c = cell[i]; c = cell[i];
@ -2194,6 +2222,7 @@ int canseeob(lifeform_t *lf, object_t *o) {
enum SKILLLEVEL slev; enum SKILLLEVEL slev;
int cutoffpct; int cutoffpct;
int cutoff; int cutoff;
slev = getskill(lf, SK_PERCEPTION); slev = getskill(lf, SK_PERCEPTION);
switch (slev) { switch (slev) {
case PR_NOVICE: cutoffpct = 80; break; case PR_NOVICE: cutoffpct = 80; break;
@ -2279,7 +2308,6 @@ int changemat(object_t *o, enum MATERIAL mat) {
material_t *m; material_t *m;
flag_t *f, *nextf; flag_t *f, *nextf;
m = findmaterial(mat); m = findmaterial(mat);
if (!m) { if (!m) {
return E_FAILED; return E_FAILED;
@ -2325,14 +2353,13 @@ int changemat(object_t *o, enum MATERIAL mat) {
om = findobmod(OM_FROZEN); om = findobmod(OM_FROZEN);
applyobmod(o, om); applyobmod(o, om);
} }
return B_FALSE; return B_FALSE;
} }
int checkobnames(char *haystack, char *needle) { int checkobnames(char *haystack, char *needle) {
char *pluralname; char *pluralname;
int db = B_FALSE; int db = B_FALSE;
// search for exact match // search for exact match
if (!strcmp(haystack, needle)) { if (!strcmp(haystack, needle)) {
// found it! // found it!
@ -3753,8 +3780,9 @@ int getmaterialvalue(enum MATERIAL mat) {
case MT_RUBBER: case MT_RUBBER:
case MT_GLASS: case MT_GLASS:
case MT_SILK: case MT_SILK:
return 5;
case MT_METAL: case MT_METAL:
return 5;
case MT_SILVER:
return 6; return 6;
case MT_GOLD: case MT_GOLD:
return 7; return 7;
@ -4104,7 +4132,6 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
int venditem = B_FALSE; int venditem = B_FALSE;
flag_t *f; flag_t *f;
brand_t *br; brand_t *br;
obmod_t *om;
int hasunknownmod = B_FALSE; int hasunknownmod = B_FALSE;
cell_t *where; cell_t *where;
int no_a = B_FALSE; int no_a = B_FALSE;
@ -4388,7 +4415,6 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
} }
} }
// blessed status // blessed status
if (!hasflag(o->flags, F_NOBLESS) && wantblesscurse) { if (!hasflag(o->flags, F_NOBLESS) && wantblesscurse) {
if (showall || isblessknown(o)) { if (showall || isblessknown(o)) {
@ -4429,26 +4455,22 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan
case MT_WOOD: case MT_WOOD:
strcat(localbuf, "wooden "); strcat(localbuf, "wooden ");
break; break;
case MT_ICE: // we'll use the 'frozen' obmod instead
break;
default: default:
// strcat(localbuf, o->material->name); strcat(localbuf, o->material->name);
// strcat(localbuf, " "); strcat(localbuf, " ");
break; break;
} }
} }
// include mods (ie. a flaming sword) // include mods (ie. a flaming sword)
if (wantpremods) { if (wantpremods) {
obmod_t *om;
for (om = firstobmod ; om; om = om->next) { for (om = firstobmod ; om; om = om->next) {
flag_t *omf; if (hasobmod(o, om)) {
int found = B_FALSE;
for (omf = om->flags->first ; omf ; omf = omf->next){
if (hasflagval(o->flags, omf->id, omf->val[0], omf->val[1], omf->val[2], NULL)) {
found = B_TRUE;
}
}
if (found) {
strcat(localbuf, om->prefix); strcat(localbuf, om->prefix);
} }
} }
} }
@ -4959,15 +4981,15 @@ char *real_getrandomob(map_t *map, char *buf, int cond, int cval, int forcedepth
pluralname = strdup(ot->name); pluralname = strdup(ot->name);
} }
// blessed or cursed? // blessed or cursed? 15% chance each way
strcpy(cursestr, ""); strcpy(cursestr, "");
if (!hasflag(ot->flags, F_NOBLESS)) { if (!hasflag(ot->flags, F_NOBLESS)) {
int num; int num;
num = rnd(1,100); num = rnd(1,100);
if (num <= 15) { if (num <= 15) {
strcpy(cursestr, "blessed ");
} else if (num <= 30) {
strcpy(cursestr, "cursed "); strcpy(cursestr, "cursed ");
} else if (num >= 85) {
strcpy(cursestr, "blessed ");
} }
} }
@ -5377,6 +5399,18 @@ object_t *hasobofclass(obpile_t *op, enum OBCLASS cid) {
return NULL; return NULL;
} }
int hasobmod(object_t *o, obmod_t *om) {
flag_t *omf;
int found = B_TRUE;
for (omf = om->flags->first ; omf ; omf = omf->next){
if (!hasflagval(o->flags, omf->id, omf->val[0], omf->val[1], omf->val[2], NULL)) {
found = B_FALSE;
break;
}
}
return found;
}
object_t *hasobmulti(obpile_t *op, enum OBTYPE *oid, int noids) { object_t *hasobmulti(obpile_t *op, enum OBTYPE *oid, int noids) {
object_t *o; object_t *o;
int n; int n;
@ -5736,6 +5770,8 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL); addflag(lastmaterial->flags, F_DTIMMUNE, DT_SLASH, NA, NA, NULL);
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_SILVER, "silver", 11);
addflag(lastmaterial->flags, F_HARDNESS, 2, NA, NA, NULL);
addmaterial(MT_METAL, "metal", 13); addmaterial(MT_METAL, "metal", 13);
addflag(lastmaterial->flags, F_HARDNESS, 5, 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);
@ -5748,8 +5784,7 @@ void initobjects(void) {
addflag(lastmaterial->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastmaterial->flags, F_DTVULN, DT_BASH, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTVULN, DT_COLD, NA, NA, NULL); addflag(lastmaterial->flags, F_DTVULN, DT_COLD, NA, NA, NULL);
addmaterial(MT_GOLD, "gold", 16); addmaterial(MT_GOLD, "gold", 16);
addflag(lastmaterial->flags, F_HARDNESS, 4, NA, NA, NULL); addflag(lastmaterial->flags, F_HARDNESS, 3, NA, NA, NULL);
//addmaterial(MT_GOLD, "gold", 16);
// object classes // object classes
addoc(OC_DFEATURE, "Dungeon Features", "Doors, etc.", '\\', C_GREY); addoc(OC_DFEATURE, "Dungeon Features", "Doors, etc.", '\\', C_GREY);
@ -6332,6 +6367,10 @@ void initobjects(void) {
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, NA, NULL);
addflag(lastot->flags, F_NUMAPPEAR, 1, 15, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 15, NA, "");
addot(OT_CACFRUIT, "cactus fruit", "The nutritous fruit from a cactus plant.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_RED, NA, NA, "%");
addflag(lastot->flags, F_EDIBLE, B_TRUE, 100, NA, "");
addflag(lastot->flags, F_RARITY, H_FOREST, 90, NA, NULL);
addot(OT_GARLIC, "clove of garlic", "A very pungent clove of raw garlic. ", MT_FOOD, 0.1, OC_FOOD, SZ_TINY); addot(OT_GARLIC, "clove of garlic", "A very pungent clove of raw garlic. ", MT_FOOD, 0.1, OC_FOOD, SZ_TINY);
addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%"); addflag(lastot->flags, F_GLYPH, C_BROWN, NA, NA, "%");
addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, ""); addflag(lastot->flags, F_EDIBLE, B_TRUE, 5, NA, "");
@ -6683,7 +6722,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
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, 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_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SMITEGOOD, "smite good", "Instantly deals 1-^bpower*2^n damage to good creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_SMITEGOOD, "smite good", "Instantly deals 1-^bpower*2^n damage to good creatures.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_DEATH, NA, NA, NULL);
@ -7049,6 +7088,12 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL); addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_NEED, NA, NULL);
// l6
addot(OT_S_ABSOLUTEZERO, "absolute zero", "Instantly freezes everything around the caster - creatures, objects, even the ground itself.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 6, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_ANYWHERE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
/////////////////// ///////////////////
// nature // nature
/////////////////// ///////////////////
@ -7331,6 +7376,13 @@ void initobjects(void) {
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
// l4 // l4
addot(OT_S_HEALINGMAJ, "major healing", "Restores 20-30 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell heals an extra 2 damage per power level.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_CUREPOISON, "cure poison", "Cures the target of all poisons.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CUREPOISON, "cure poison", "Cures the target of all poisons.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
@ -7348,7 +7400,6 @@ void initobjects(void) {
addot(OT_S_STUN, "stun", "Stuns the target, preventing them from taking action for a few seconds.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_STUN, "stun", "Stuns the target, preventing them from taking action for a few seconds.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
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_MAXPOWER, 1, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
// l2 // l2
@ -7365,6 +7416,13 @@ void initobjects(void) {
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); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL);
addot(OT_S_BAFFLE, "baffle", "Confuses the target, causing them to lose control of their movement.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The target will be confused for ^bpower^n*4 turns.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, 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_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
// l3 // l3
addot(OT_S_PSYARMOUR, "psychic armour", "Mentally block incoming attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_PSYARMOUR, "psychic armour", "Mentally block incoming attacks.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The psychic armour's Armour Rating is ^bpower*4^n."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The psychic armour's Armour Rating is ^bpower*4^n.");
@ -7387,6 +7445,11 @@ void initobjects(void) {
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); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l4 // l4
addot(OT_S_STUNMASS, "mass stun", "Stuns all creatures within sight.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addot(OT_S_SLEEP, "sleep", "Puts the target creature to sleep.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_SLEEP, "sleep", "Puts the target creature to sleep.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how long the sleep effect will last."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how long the sleep effect will last.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, NA, NA, NULL);
@ -7394,13 +7457,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL); addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_HEALINGMAJ, "major healing", "Restores 20-30 health to the caster.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "This spell heals an extra 2 damage per power level.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_LIFE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
// l5 // l5
addot(OT_S_CHARM, "charm", "Causes another lifeform to temporary become friendly.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addot(OT_S_CHARM, "charm", "Causes another lifeform to temporary become friendly.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration."); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines resistability and duration.");
@ -9018,7 +9074,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ACCURACYMOD, -10, NA, NA, NULL); addflag(lastot->flags, F_ACCURACYMOD, -10, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_POISONGAS, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_POISONGAS, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -5, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -2, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_HELM, "helmet", "A plain metal helmet.", MT_METAL, 2, OC_ARMOUR, SZ_SMALL); addot(OT_HELM, "helmet", "A plain metal helmet.", MT_METAL, 2, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_COMMON, NULL);
@ -9031,7 +9087,7 @@ void initobjects(void) {
addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACYMOD, -10, NA, NA, NULL); addflag(lastot->flags, F_ACCURACYMOD, -10, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL); addflag(lastot->flags, F_OBHP, 20, 20, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -4, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -1, NA, NULL);
addot(OT_GOLDCROWN, "golden crown", "A heavy gold crown, encrusted with jewels.", MT_GOLD, 5, OC_ARMOUR, SZ_SMALL); addot(OT_GOLDCROWN, "golden crown", "A heavy gold crown, encrusted with jewels.", MT_GOLD, 5, OC_ARMOUR, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 25, RR_RARE, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 25, RR_RARE, NULL);
addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL);
@ -9060,8 +9116,8 @@ void initobjects(void) {
addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_EYES, NA, NA, NULL);
addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 0, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL); addflag(lastot->flags, F_OBHP, 2, 2, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -2, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_VISRANGEMOD, -1, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_NIGHTVISRANGEMOD, -2, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_NIGHTVISRANGEMOD, -1, NA, NULL);
addflag(lastot->flags, F_TINTED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TINTED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL);
addot(OT_EYEPATCH, "eyepatch", "A small patch of black material which covers one eye. Scary looking.", MT_CLOTH, 0.01, OC_ARMOUR, SZ_SMALL); addot(OT_EYEPATCH, "eyepatch", "A small patch of black material which covers one eye. Scary looking.", MT_CLOTH, 0.01, OC_ARMOUR, SZ_SMALL);
@ -9303,6 +9359,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 3, NA, "");
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 15, NA, NULL);
addot(OT_NANODART, "nanodart", "A metal dart with a laser-sharpened point.", MT_METAL, 0.5, OC_MISSILE, SZ_TINY); addot(OT_NANODART, "nanodart", "A metal dart with a laser-sharpened point.", MT_METAL, 0.5, OC_MISSILE, SZ_TINY);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
@ -9340,6 +9397,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 15, NA, NULL);
addot(OT_BOLT, "bolt", "A sharp metal spike, meant for firing from a crossbow.", MT_METAL, 0.5, OC_MISSILE, SZ_SMALL); addot(OT_BOLT, "bolt", "A sharp metal spike, meant for firing from a crossbow.", MT_METAL, 0.5, OC_MISSILE, SZ_SMALL);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
@ -9347,6 +9405,7 @@ void initobjects(void) {
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL); addflag(lastot->flags, F_CANHAVEOBMOD, OM_POISONED, 17, NA, NULL);
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 20, NA, NULL);
addot(OT_BULLET, "bullet", "A regular gun bullet.", MT_METAL, 0.1, OC_MISSILE, SZ_MINI); addot(OT_BULLET, "bullet", "A regular gun bullet.", MT_METAL, 0.1, OC_MISSILE, SZ_MINI);
@ -9357,8 +9416,9 @@ void initobjects(void) {
addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL); addflag(lastot->flags, F_OBHP, 1, 1, NA, NULL);
addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 10, NA, NULL);
addot(OT_RUBBERBULLET, "rubber bullet", "A rubber gun bullet - does not do much damage.", MT_STONE, 0.05, OC_MISSILE, SZ_MINI); addot(OT_RUBBERBULLET, "rubber bullet", "A rubber gun bullet - does not do much damage.", MT_RUBBER, 0.05, OC_MISSILE, SZ_MINI);
addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, ""); addflag(lastot->flags, F_STACKABLE, B_TRUE, NA, NA, "");
addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, ""); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, "");
addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, ""); addflag(lastot->flags, F_NUMAPPEAR, 1, 10, NA, "");
@ -9427,6 +9487,7 @@ void initobjects(void) {
addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL); addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL);
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 10, NA, NULL);
addot(OT_KNIFE, "knife", "A moderately sharp stabbing tool.", MT_METAL, 0.5, OC_WEAPON, SZ_SMALL); addot(OT_KNIFE, "knife", "A moderately sharp stabbing tool.", MT_METAL, 0.5, OC_WEAPON, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL);
addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d3"); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d3");
@ -9472,6 +9533,7 @@ void initobjects(void) {
addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 6, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 6, NA, NULL);
addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL);
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 5, NA, NULL);
addot(OT_SICKLE, "sickle", "A hand-held agricultural tool with a curved blade.", MT_METAL, 1, OC_WEAPON, SZ_SMALL); addot(OT_SICKLE, "sickle", "A hand-held agricultural tool with a curved blade.", MT_METAL, 1, OC_WEAPON, SZ_SMALL);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 60, NA, NULL);
addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d6"); addflag(lastot->flags, F_DAM, DT_SLASH, NA, NA, "1d6");
@ -9511,6 +9573,7 @@ void initobjects(void) {
addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_STR, 10, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 10, NA, NULL);
addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL); addflag(lastot->flags, F_CRITCHANCE, 5, NA, NA, NULL);
addflag(lastot->flags, F_CANBEDIFFMAT, MT_SILVER, 5, NA, NULL);
addot(OT_ORNSWORD, "ornamental sword", "A gleaming (but quite blunt) blade.", MT_METAL, 6, OC_WEAPON, SZ_MEDIUM); addot(OT_ORNSWORD, "ornamental sword", "A gleaming (but quite blunt) blade.", MT_METAL, 6, OC_WEAPON, SZ_MEDIUM);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL);
addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SHINY, B_TRUE, NA, NA, NULL);
@ -10269,8 +10332,9 @@ int ismetal(enum MATERIAL mat) {
int metal = B_FALSE; int metal = B_FALSE;
switch (mat) { switch (mat) {
case MT_METAL: case MT_METAL:
case MT_WIRE:
case MT_GOLD: case MT_GOLD:
case MT_SILVER:
case MT_WIRE:
metal = B_TRUE; metal = B_TRUE;
break; break;
default: default:
@ -10469,6 +10533,12 @@ void killmaterial(material_t *m) {
void killob(object_t *o) { void killob(object_t *o) {
object_t *nextone, *lastone; object_t *nextone, *lastone;
// debugging
if (o->type->id == OT_STAIRSUP) {
msg("warning: removing an up staircase!");
dblog("warning: removing an up staircase!");
}
// remove flags conferred by this object // remove flags conferred by this object
if (o->pile->owner) { if (o->pile->owner) {
loseobflags(o->pile->owner, o, ALLCONFERRED); loseobflags(o->pile->owner, o, ALLCONFERRED);
@ -10831,7 +10901,7 @@ object_t *moveob(object_t *src, obpile_t *dst, int howmany) {
object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) { object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
object_t *o, *existob; object_t *o, *existob;
int i; int i,preburdened = B_FALSE;
int db = B_FALSE; int db = B_FALSE;
flag_t *f; flag_t *f;
@ -10861,6 +10931,8 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
dst = newcell->obpile; dst = newcell->obpile;
} }
} }
} else if (dst->owner) {
preburdened = isburdened(dst->owner);
} }
if (db) dblog("DB: moveob() - moving %d x %s",howmany, src->type->name); if (db) dblog("DB: moveob() - moving %d x %s",howmany, src->type->name);
@ -10982,6 +11054,17 @@ object_t *real_moveob(object_t *src, obpile_t *dst, int howmany, int stackok) {
} }
} }
// did this make us burdened?
if (isplayer(dst->owner)) {
if (isburdened(dst->owner) != preburdened) {
if (preburdened == BR_NONE) {
msg("^wThe weight of your possessions is burdening you!");
} else {
msg("^wThe weight of your possessions is burdening you even more!");
}
}
}
// in case you picked up money, something which changes your AR, etc // in case you picked up money, something which changes your AR, etc
if (isplayer(dst->owner)) { if (isplayer(dst->owner)) {
statdirty = B_TRUE; statdirty = B_TRUE;
@ -12031,7 +12114,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) {
if ((m->region->rtype->id == RG_FIRSTDUNGEON) && (m->depth == 1)) { if ((m->region->rtype->id == RG_FIRSTDUNGEON) && (m->depth == 1)) {
cell_t *cell[MAXCANDIDATES]; cell_t *cell[MAXCANDIDATES];
int ncells,i; int ncells,i;
getradiuscells(lf->cell, 1, DT_COMPASS, B_FALSE, B_TRUE, cell, &ncells); getradiuscells(lf->cell, 1, DT_COMPASS, B_FALSE, B_TRUE, cell, &ncells, B_FALSE);
for (i = 0; i < ncells; i++) { for (i = 0; i < ncells; i++) {
if (hasob(cell[i]->obpile, OT_STAIRSUP)) { if (hasob(cell[i]->obpile, OT_STAIRSUP)) {
object_t *o; object_t *o;
@ -13637,7 +13720,8 @@ object_t *relinkob(object_t *src, obpile_t *dst) {
if (obproduceslight(src)) { if (obproduceslight(src)) {
calclight((getoblocation(src))->map); calclight((getoblocation(src))->map);
if (gamemode == GM_GAMESTARTED) { if (gamemode == GM_GAMESTARTED) {
precalclos(player); setlosdirty(player);
//precalclos(player);
} }
drawscreen(); drawscreen();
} }
@ -14891,7 +14975,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (thrower && (thrower->cell == srcloc)) { if (thrower && (thrower->cell == srcloc)) {
whogetsxp = thrower; whogetsxp = thrower;
} }
losehp(target, dam, DT_PROJECTILE, whogetsxp, damstring); losehp_real(target, dam, DT_PROJECTILE, whogetsxp, damstring, B_TRUE, o, B_TRUE);
} }
if (reduceamt && (speed >= 3)) { if (reduceamt && (speed >= 3)) {
@ -15060,7 +15144,8 @@ void timeeffectsob(object_t *o) {
if (!o->blessknown) o->blessknown = B_TRUE; if (!o->blessknown) o->blessknown = B_TRUE;
} }
calclight(ourcell->map); calclight(ourcell->map);
precalclos(player); setlosdirty(player);
//precalclos(player);
} }
} else { // not near undead } else { // not near undead
if (glowflag) { if (glowflag) {
@ -15974,7 +16059,7 @@ int willshatter(enum MATERIAL mat) {
return B_FALSE; return B_FALSE;
} }
int getcritchance(lifeform_t *lf, object_t *o) { int getcritchance(lifeform_t *lf, object_t *o, lifeform_t *victim) {
flag_t *f; flag_t *f;
int chance = 0; int chance = 0;
if (!o) return 0; if (!o) return 0;
@ -15996,6 +16081,11 @@ int getcritchance(lifeform_t *lf, object_t *o) {
} }
} }
// double crit chance if victim is vulnerable to this weapon
if (victim && lfhasflagval(victim, F_MATVULN, o->material->id, NA, NA, NULL)) {
chance *= 2;
}
return chance; return chance;
} }
@ -16123,7 +16213,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
maxrange = getmaxthrowrange(thrower, missile); maxrange = getmaxthrowrange(thrower, missile);
} }
} else { } else {
maxrange = getvisrange(thrower); maxrange = getvisrange(thrower, B_TRUE);
} }
howfar = getcelldist(thrower->cell, where); howfar = getcelldist(thrower->cell, where);

View File

@ -59,7 +59,7 @@ void genhiddennames(void);
object_t *getbestcontainer(obpile_t *op); object_t *getbestcontainer(obpile_t *op);
int getchargeinfo(object_t *o, int *cur, int *max); int getchargeinfo(object_t *o, int *cur, int *max);
int getcharges(object_t *o); int getcharges(object_t *o);
int getcritchance(lifeform_t *lf, object_t *o); int getcritchance(lifeform_t *lf, object_t *o, lifeform_t *victim);
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);
enum COLOUR getmaterialcolour(enum MATERIAL mat ); enum COLOUR getmaterialcolour(enum MATERIAL mat );
@ -136,6 +136,7 @@ object_t *hasknownob(obpile_t *op, enum OBTYPE oid);
object_t *hasob(obpile_t *op, enum OBTYPE oid); object_t *hasob(obpile_t *op, enum OBTYPE oid);
object_t *hasobletter(obpile_t *op, char letter); object_t *hasobletter(obpile_t *op, char letter);
object_t *hasobofclass(obpile_t *op, enum OBCLASS cid); object_t *hasobofclass(obpile_t *op, enum OBCLASS cid);
int hasobmod(object_t *o, obmod_t *om);
object_t *hasobmulti(obpile_t *op, enum OBTYPE *oid, int noids); object_t *hasobmulti(obpile_t *op, enum OBTYPE *oid, int noids);
object_t *hasobwithflag(obpile_t *op, enum FLAG flagid); object_t *hasobwithflag(obpile_t *op, enum FLAG flagid);
object_t *hasobwithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int val2, char *text); object_t *hasobwithflagval(obpile_t *op, enum FLAG flagid, int val0, int val1, int val2, char *text);

2
save.c
View File

@ -217,6 +217,7 @@ lifeform_t *loadlf(FILE *f, cell_t *where) {
fscanf(f, "sorted: %d\n",&l->sorted); fscanf(f, "sorted: %d\n",&l->sorted);
fscanf(f, "polyrevert: %d\n",&l->polyrevert); fscanf(f, "polyrevert: %d\n",&l->polyrevert);
fscanf(f, "forgettimer: %f\n",&l->forgettimer); fscanf(f, "forgettimer: %f\n",&l->forgettimer);
fscanf(f, "eyeadj: %d\n",&l->eyeadjustment);
if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted); if (db) dblog("--> Got hp=%d/%d. timespend=%d. sorted=%d. Now loading flags.",l->hp,l->maxhp,l->timespent,l->sorted);
@ -797,6 +798,7 @@ int savelf(FILE *f, lifeform_t *l) {
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);
fprintf(f, "forgettimer: %f\n",l->forgettimer); fprintf(f, "forgettimer: %f\n",l->forgettimer);
fprintf(f, "eyeadj: %d\n",l->eyeadjustment);
// lf flags // lf flags
saveflagpile(f, l->flags); saveflagpile(f, l->flags);

347
spell.c
View File

@ -54,7 +54,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
char targetname[BUFLEN]; char targetname[BUFLEN];
char buf[BUFLEN]; char buf[BUFLEN];
int power = 0,needgrab = B_FALSE, range = 0; int power = 0,needgrab = B_FALSE, range = 0;
char damstr[BUFLEN]; char damstr[BUFLEN],racestr[BUFLEN];
objecttype_t *ot; objecttype_t *ot;
flag_t *f; flag_t *f;
@ -67,7 +67,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
needgrab = B_FALSE; needgrab = B_FALSE;
if (cwflag && strlen(cwflag->text)) { if (cwflag && strlen(cwflag->text)) {
texttospellopts(cwflag->text, &power, damstr, &needgrab, &range); texttospellopts(cwflag->text, "pw:", &power, "dam:", damstr, "needgrab:", &needgrab, "range:", &range, "range:", racestr, NULL);
} }
// get more options from ablity itself... // get more options from ablity itself...
@ -925,6 +925,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
int howlong; int howlong;
int slev; int slev;
flag_t *f; flag_t *f;
if (lfhasflagval(user, F_INJURY, IJ_WINDPIPECRUSHED, NA, NA, NULL)) {
if (isplayer(user)) msg("You can't sprint with a crushed windpipe.");
return B_TRUE;
}
if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) { if (isswimming(user) && !lfhasflag(user, F_AQUATIC)) {
if (isplayer(user)) msg("You can't sprint while swimming!"); if (isplayer(user)) msg("You can't sprint while swimming!");
@ -1015,7 +1019,10 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
if ((o->type->obclass->id == OC_SCROLL) && isknown(o)) { if ((o->type->obclass->id == OC_SCROLL) && isknown(o)) {
f = hasflag(o->flags, F_LINKSPELL); f = hasflag(o->flags, F_LINKSPELL);
if (f && !cancast(user, f->val[0], NULL)) { if (f && !cancast(user, f->val[0], NULL)) {
char buf2[BUFLEN];
getobname(o, buf, o->amt); getobname(o, buf, o->amt);
difficulty = 20 + (getspelllevel(f->val[0])*3);
sprintf(buf2, "%s (%d%% success chance)", buf, difficulty);
addchoice(&prompt, o->letter, buf, NULL, f); addchoice(&prompt, o->letter, buf, NULL, f);
} }
} }
@ -2059,8 +2066,52 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} }
// special case: summoning spell on a pentagram
if (caster && hasob(caster->cell->obpile, OT_PENTAGRAM) && hasflagval(sp->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL) &&
(sp->id != OT_S_SUMMONDEMON)) {
if (haslos(player, caster->cell)) {
msg("The pentagram pulses red.");
}
if (summonlfs(caster, caster->cell, RC_DEMON, SZ_ANY, AL_NONE, 1, PERMENANT, B_FALSE)) {
if (isplayer(caster) || cansee(player, caster)) {
msg("An other-worldly demon appears!");
}
}
return B_FALSE;
}
// switch based on spell effects... // switch based on spell effects...
if (spellid == OT_S_ABSORBMETAL) { if (spellid == OT_S_ABSOLUTEZERO) {
cell_t *retcell[MAXCANDIDATES];
int nretcells,i;
if (isplayer(caster)) {
msg("You unleash a freezing blast!");
} else if (cansee(player, caster)) {
msg("%s unleashes a freezing blast!", castername, getpossessive(castername));
}
// freeze lfs, obs in most cells
getradiuscells(caster->cell, 7, DT_ORTH, LOF_WALLSTOP, B_FALSE, retcell, &nretcells, 90);
for (i = 0; i < nretcells; i++) {
object_t *o, *nexto;
if (retcell[i]->lf) {
for (o = retcell[i]->lf->pack->first ; o ; o = nexto) {
nexto = o->next;
changemat(o, MT_ICE);
}
freezelf(retcell[i]->lf, caster, PERMENANT);
}
for (o = retcell[i]->obpile->first ; o ; o = nexto) {
nexto = o->next;
changemat(o, MT_ICE);
}
o = addobfast(retcell[i]->obpile, OT_ICESHEET);
if (o) killflagsofid(o->flags, F_OBHPDRAIN);
}
} else if (spellid == OT_S_ABSORBMETAL) {
int i; int i;
float totalmass = 0; float totalmass = 0;
object_t *o; object_t *o;
@ -2102,7 +2153,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
removedeadobs(targcell->obpile); removedeadobs(targcell->obpile);
if (targcell->lf && !skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { if (targcell->lf && !skillcheck(targcell->lf, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
// destroy only WORN metal objects, not CARRIED ones // destroy only WORN metal objects, not CARRIED ones
for (o = targcell->lf->pack->first ; o ; o = o->next) { for (o = targcell->lf->pack->first ; o ; o = o->next) {
if (isequipped(o) && ismetal(o->material->id)) { if (isequipped(o) && ismetal(o->material->id)) {
@ -2263,6 +2314,31 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else { } else {
fizzle(caster); fizzle(caster);
} }
} else if (spellid == OT_S_BAFFLE) {
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf;
if (lfhasflag(target, F_ASLEEP) || !ischarmable(target)) {
fizzle(caster);
return B_TRUE;
}
if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) {
msg("You shrug off a mental attack.");
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, target->cell)) {
getlfname(target, buf);
msg("%s shrugs off %s mental attack.", buf, isplayer(caster) ? "your" : "a");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
return B_FALSE;
} else {
confuse(target, power*4);
if (isplayer(target) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
} else if (spellid == OT_S_BARKSKIN) { } else if (spellid == OT_S_BARKSKIN) {
flag_t *f; flag_t *f;
// always targetted at caster // always targetted at caster
@ -2315,7 +2391,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
failed = B_TRUE; failed = B_TRUE;
} }
@ -2600,8 +2676,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
powerleft = power; powerleft = power;
for (i = 0; i < caster->nlos; i++) { for (i = 0; i < caster->nlos; i++) {
c = caster->los[i]; c = caster->los[i];
if (c->lf && (c->lf != caster) && (c->lf->race->raceclass->id == RC_ANIMAL) && (gethitdice(c->lf) <= powerleft)) { if (c->lf && (c->lf != caster) && (c->lf->race->raceclass->id == RC_ANIMAL) && lfhasflag(c->lf, F_HOSTILE)) {
if (lfhasflag(c->lf, F_HOSTILE)) { if (gethitdice(c->lf) <= powerleft) {
powerleft -= gethitdice(c->lf); powerleft -= gethitdice(c->lf);
makepeaceful(c->lf); makepeaceful(c->lf);
@ -2618,6 +2694,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
donesomething++; donesomething++;
} else {
if (isplayer(caster)) {
char lfname[BUFLEN];
getlfname(c->lf, lfname);
msg("%s is not affected.", lfname);
}
} }
} }
if (powerleft <= 0) break; if (powerleft <= 0) break;
@ -2788,7 +2870,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
if (skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(targcell->lf, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(caster) || cansee(player, target)) { if (isplayer(caster) || cansee(player, target)) {
msg("%s resists.",targetname); msg("%s resists.",targetname);
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -3007,7 +3089,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// saving throw // saving throw
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(caster) || cansee(player, target)) { if (isplayer(caster) || cansee(player, target)) {
char tname[BUFLEN]; char tname[BUFLEN];
getlfname(target, tname); getlfname(target, tname);
@ -3054,7 +3136,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// determine type of mosnter // determine type of mosnter
if ((power >= 7) && isplayer(caster)) { if (getforcedspellrace(caster, spellid, buf)) {
} else if ((power >= 7) && isplayer(caster)) {
// ask what kind of monster // ask what kind of monster
askstring("Create what kind of monster", '?', buf, BUFLEN, NULL); askstring("Create what kind of monster", '?', buf, BUFLEN, NULL);
} else { } else {
@ -3497,7 +3580,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// don't need line of fire! // don't need line of fire!
if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_OBJECT, spellid, power, frompot)) return B_TRUE;
getradiuscells(targcell, power, DT_ORTH, LOF_NEED, B_TRUE, cell, &ncells); getradiuscells(targcell, power, DT_ORTH, LOF_NEED, B_TRUE, cell, &ncells, B_FALSE);
for (i = 0; i < ncells; i++) { for (i = 0; i < ncells; i++) {
object_t *o,*nexto; object_t *o,*nexto;
for (o = cell[i]->obpile->first ; o ; o = nexto) { for (o = cell[i]->obpile->first ; o ; o = nexto) {
@ -3579,11 +3662,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
// flag. // flag.
// other people get a check anyway. // other people get a check anyway.
if (targcell->lf == caster) { if (targcell->lf == caster) {
if (getmr(targcell->lf) && skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { if (getmr(targcell->lf) && skillcheck(targcell->lf, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
resisted = B_TRUE; resisted = B_TRUE;
} }
} else { } else {
if (skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(targcell->lf, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
resisted = B_TRUE; resisted = B_TRUE;
} }
} }
@ -3750,7 +3833,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf; target = targcell->lf;
if ((getattr(target, A_IQ) <= 3) || skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if ((getattr(target, A_IQ) <= 3) || skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (cansee(player, target)) { if (cansee(player, target)) {
getlfname(target, buf); getlfname(target, buf);
msg("%s %s momentarily foolish.", buf, isplayer(target) ? "feel" : "looks"); msg("%s %s momentarily foolish.", buf, isplayer(target) ? "feel" : "looks");
@ -4317,7 +4400,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
} else if (spellid == OT_S_GASEOUSFORM) { } else if (spellid == OT_S_GASEOUSFORM) {
if (!target) target = caster; if (!target) target = caster;
if (getmr(target) && (target->race->id != R_VAMPIRE) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (getmr(target) && (target->race->id != R_VAMPIRE) && skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You feel momentarily insubstantial."); msg("You feel momentarily insubstantial.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -4444,7 +4527,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
if (getmr(target) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (getmr(target) && skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target) || haslos(player, target->cell)) { if (isplayer(target) || haslos(player, target->cell)) {
getlfname(target, buf); getlfname(target, buf);
msg("%s blur%s for a moment.",buf, isplayer(target) ? "" : "s"); msg("%s blur%s for a moment.",buf, isplayer(target) ? "" : "s");
@ -4455,7 +4538,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
addtempflag(target->flags, F_FASTACTMOVE, 10, NA, NA, NULL, howlong); addtempflag(target->flags, F_FASTACTMOVE, 10, NA, NA, NULL, howlong);
} }
} else if ((spellid == OT_S_HEALING) || (spellid == OT_S_HEALINGMIN) || (spellid == OT_S_HEALINGMAJ)) { } else if ((spellid == OT_S_HEALING) || (spellid == OT_S_HEALINGMIN) || (spellid == OT_S_HEALINGMAJ)) {
int donesomething = B_FALSE; int donesomething = B_FALSE,i;
flag_t *retflag[MAXCANDIDATES];
int nretflags;
if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_ALLY, spellid, power, frompot)) return B_TRUE;
target = targcell->lf; target = targcell->lf;
if (!target) { if (!target) {
@ -4471,6 +4556,23 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
donesomething = B_TRUE; donesomething = B_TRUE;
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
getflags(target->flags, retflag, &nretflags, F_NOBODYPART, F_NONE);
for (i = 0; i < nretflags; i++) {
if (retflag[i]->val[1] == B_FROMINJURY) {
if (isplayer(target)) {
msg("Your %s grows back!", getbodypartname(retflag[0]->val[0]));
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, target)) {
char targname[BUFLEN];
getlfname(target, targname);
msg("%s%s %s grows back!", targname, getpossessive(targname),
getbodypartname(retflag[0]->val[0]));
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
killflag(retflag[i]);
donesomething = B_TRUE;
}
}
if ((spellid == OT_S_HEALINGMIN) && donesomething) { if ((spellid == OT_S_HEALINGMIN) && donesomething) {
// minor healing will stop here // minor healing will stop here
@ -4577,20 +4679,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
fizzle(caster); fizzle(caster);
return B_FALSE; return B_FALSE;
} }
if (isplayer(target)) { if (isplayer(target)) {
// make more hungry msg("A sudden hunger comes over you!");
modhunger(target, HUNGERCONST);
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (cansee(player, target)) {
char lfname[BUFLEN];
getlfname(target, lfname);
msg("%s looks more hungry.", lfname);
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (lfhasflag(target, F_HUNGER)) {
modhunger(target, HUNGERCONST); // make more hungry
} else { } else {
if (cansee(player, target)) { addflag(target->flags, F_HUNGER, HUNGERCONST*2, NA, NA, NULL);
if (lfhasflag(target, F_HUNGER)) {
modhunger(target, HUNGERCONST); // make more hungry
} else {
// ie. "hungry"
addflag(target->flags, F_HUNGER, HUNGERCONST*2, NA, NA, NULL);
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} }
} else if (spellid == OT_S_HOLYAURA) { } else if (spellid == OT_S_HOLYAURA) {
flag_t *f; flag_t *f;
@ -4723,7 +4826,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
for (l = caster->cell->map->lf ; l ; l = l->next) { for (l = caster->cell->map->lf ; l ; l = l->next) {
if (l != caster) { if (l != caster) {
if (isimmuneto(l->flags, DT_NECROTIC) || skillcheck(l, SC_RESISTMAG, 20 + power, 0)) { if (isimmuneto(l->flags, DT_NECROTIC) || skillcheck(l, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(l)) { if (isplayer(l)) {
msg("Luckily, the evil doesn't seem to harm you."); msg("Luckily, the evil doesn't seem to harm you.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -4739,7 +4842,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// now hit the caster! // now hit the caster!
if (isimmuneto(caster->flags, DT_NECROTIC) || skillcheck(caster, SC_RESISTMAG, 20 + power, 0)) { if (isimmuneto(caster->flags, DT_NECROTIC) || skillcheck(caster, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(caster)) { if (isplayer(caster)) {
msg("Luckily, the evil doesn't seem to harm you."); msg("Luckily, the evil doesn't seem to harm you.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -4888,7 +4991,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// destroy objects right away // destroy objects right away
removedeadobs(targcell->obpile); removedeadobs(targcell->obpile);
if (targcell->lf && !skillcheck(targcell->lf, SC_RESISTMAG, 20 + power, 0)) { if (targcell->lf && !skillcheck(targcell->lf, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
// destroy only WORN metal objects, not CARRIED ones // destroy only WORN metal objects, not CARRIED ones
for (o = targcell->lf->pack->first ; o ; o = o->next) { for (o = targcell->lf->pack->first ; o ; o = o->next) {
if (isequipped(o) && ismetal(o->material->id)) { if (isequipped(o) && ismetal(o->material->id)) {
@ -4921,7 +5024,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
lifeform_t *oldplayer; lifeform_t *oldplayer;
// calc view // calc view
precalclos(targcell->lf); setlosdirty(targcell->lf);
//precalclos(targcell->lf);
// temporarily change player pointer... // temporarily change player pointer...
oldplayer = player; oldplayer = player;
@ -5027,7 +5131,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
saved = B_TRUE; saved = B_TRUE;
} else if (skillcheck(target, SC_STR, 20 + power, 0)) { } else if (skillcheck(target, SC_STR, 20 + power, 0)) {
saved = B_TRUE; saved = B_TRUE;
@ -5062,7 +5166,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// make this a constitution skill check ? // make this a constitution skill check ?
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
failed = B_TRUE; failed = B_TRUE;
} else if (skillcheck(target, SC_CON, 20 + power, 0)) { } else if (skillcheck(target, SC_CON, 20 + power, 0)) {
failed = B_TRUE; failed = B_TRUE;
@ -5102,7 +5206,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// savingthrow // savingthrow
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0) || skillcheck(target, SC_CON, 30 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0) || skillcheck(target, SC_CON, 30 + power, 0)) {
if (haslos(player, target->cell)) { if (haslos(player, target->cell)) {
char lfname[BUFLEN]; char lfname[BUFLEN];
getlfname(target, lfname); getlfname(target, lfname);
@ -5198,7 +5302,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
// saving throw.... // saving throw....
if (skillcheck(target, SC_RESISTMAG, 16 + power*2, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(caster) && cansee(player, target)) { if (isplayer(caster) && cansee(player, target)) {
msg("%s%s mind fights off your intrusion!", targname, getpossessive(targname)); msg("%s%s mind fights off your intrusion!", targname, getpossessive(targname));
} }
@ -5883,7 +5987,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
if (lfhasflag(target, F_GRAVBOOSTED) || skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (lfhasflag(target, F_GRAVBOOSTED) || skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You feel momentarily heavier."); msg("You feel momentarily heavier.");
} else if (cansee(player, target)) { } else if (cansee(player, target)) {
@ -6103,7 +6207,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
getlfname(target, targetname); getlfname(target, targetname);
if (skillcheck(targcell->lf, SC_RESISTMAG, 30 + power, 0)) { if (skillcheck(targcell->lf, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(caster) || cansee(player, target)) { if (isplayer(caster) || cansee(player, target)) {
msg("%s resists.",targetname); msg("%s resists.",targetname);
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -6145,7 +6249,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
breakgrabs(target, B_TRUE, B_TRUE); breakgrabs(target, B_TRUE, B_TRUE);
} else if (spellid == OT_S_POLYMORPH) { } else if (spellid == OT_S_POLYMORPH) {
race_t *r = NULL; race_t *r = NULL;
flag_t *f;
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf; target = targcell->lf;
@ -6155,7 +6258,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE; return B_TRUE;
} }
if ((target != caster) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if ((target != caster) && skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You feel momentarily different."); msg("You feel momentarily different.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -6167,9 +6270,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE; return B_FALSE;
} }
f = lfhasflag(target, F_FORCEPOLY); if ((caster == target) && getforcedspellrace(caster, spellid, buf)) {
if (f) { r = findracebyname(buf);
r = findrace(f->val[0]);
} else { } else {
if (lfhasflag(caster, F_CONTROL)) { if (lfhasflag(caster, F_CONTROL)) {
if (power < 5) { if (power < 5) {
@ -6550,7 +6652,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE; return B_TRUE;
} }
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You yawn."); msg("You yawn.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -6616,7 +6718,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf; target = targcell->lf;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You feel momentarily slower."); msg("You feel momentarily slower.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -6660,7 +6762,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = haslf(targcell); target = haslf(targcell);
if (target) { if (target) {
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(caster) || cansee(player, target)) { if (isplayer(caster) || cansee(player, target)) {
char tname[BUFLEN]; char tname[BUFLEN];
getlfname(target, tname); getlfname(target, tname);
@ -6857,7 +6959,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE; return B_TRUE;
} }
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You feel momentarily nauseated."); msg("You feel momentarily nauseated.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -7013,7 +7115,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_TRUE; return B_TRUE;
} }
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You shrug off a mental attack."); msg("You shrug off a mental attack.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -7024,11 +7126,49 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} }
return B_FALSE; return B_FALSE;
} else { } else {
stun(target, 2); stun(target, (power/5)+2);
if (isplayer(target) || cansee(player, target)) { if (isplayer(target) || cansee(player, target)) {
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
} }
} }
} else if (spellid == OT_S_STUNMASS) {
int i;
int donesomething = B_FALSE;
target = caster;
// stun everyone within los of caster
for (i = 0; i < target->nlos; i++) {
lifeform_t *thistarg;
targcell = target->los[i];
thistarg = targcell->lf;
if (thistarg && (thistarg != caster)) {
if (lfhasflag(thistarg, F_ASLEEP) || !ischarmable(thistarg)) {
fizzle(caster);
return B_TRUE;
}
if (skillcheck(thistarg, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
donesomething = B_TRUE;
if (isplayer(thistarg)) {
msg("You shrug off a mental attack.");
if (seenbyplayer) *seenbyplayer = B_TRUE;
} else if (haslos(player, thistarg->cell)) {
getlfname(thistarg, buf);
msg("%s shrugs off %s mental attack.", buf, isplayer(caster) ? "your" : "a");
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
} else {
donesomething = B_TRUE;
stun(thistarg, (power/5)+2);
if (isplayer(thistarg) || cansee(player, thistarg)) {
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
}
}
}
if (!donesomething) {
fizzle(caster);
}
} else if (spellid == OT_S_SUCK) { } else if (spellid == OT_S_SUCK) {
if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell,TT_MONSTER, spellid, power, frompot)) return B_TRUE;
@ -7037,7 +7177,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (target) { if (target) {
int failed = B_FALSE; int failed = B_FALSE;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
failed = B_TRUE; failed = B_TRUE;
} else { } else {
// they get pulled towards caster // they get pulled towards caster
@ -7069,7 +7209,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
target = caster; target = caster;
if (getmr(target) && skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (getmr(target) && skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (isplayer(target)) { if (isplayer(target)) {
msg("You flicker."); msg("You flicker.");
if (seenbyplayer) *seenbyplayer = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE;
@ -7420,7 +7560,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
int friendly; int friendly;
lifetime = (power * 9) + rnd(1,power*2); lifetime = (power * 9) + rnd(1,power*2);
switch (spellid) { switch (spellid) {
case OT_S_SUMMONDEMON: case OT_S_SUMMONDEMON:
wantrc = RC_DEMON; wantrc = RC_DEMON;
@ -7747,7 +7886,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE;
target = targcell->lf; target = targcell->lf;
if (skillcheck(target, SC_RESISTMAG, 20 + power, 0)) { if (skillcheck(target, SC_RESISTMAG, getmrdiff(spellid,power), 0)) {
if (cansee(player, target)) { if (cansee(player, target)) {
getlfname(target, buf); getlfname(target, buf);
msg("%s %s momentarily weaker.", buf, isplayer(target) ? "feel" : "looks"); msg("%s %s momentarily weaker.", buf, isplayer(target) ? "feel" : "looks");
@ -8132,6 +8271,56 @@ void fizzle(lifeform_t *caster) {
} }
} }
char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr) {
flag_t *f;
// forced?
f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL);
if (f) {
texttospellopts(f->text, "race:", racestr, NULL);
if (strlen(racestr)) {
return racestr;
}
}
return NULL;
}
int getmpcost(lifeform_t *lf, enum OBTYPE oid) {
flag_t *f;
objecttype_t *ot;
int cost = 0;
ot = findot(oid);
if (!ot) {
return 0;
}
if (lf) {
if (lfhasflagval(lf, F_BOOSTSPELL, oid, NA, NA, NULL)) {
return 0; // ie. deactivating it
}
if (lfhasflagval(lf, F_CANWILL, oid, NA, NA, NULL)) {
return 0; // ie. deactivating it
}
}
f = hasflag(ot->flags, F_MPCOST);
if (f) {
cost = f->val[0];
} else {
f = hasflag(ot->flags, F_SPELLLEVEL);
if (f) {
cost = f->val[0] * f->val[0];
}
}
return cost;
}
int getmrdiff(enum OBTYPE spellid, int power) {
int lev,diff;
lev = getspelllevel(spellid);
diff = 20 + (lev*2) + power;
return diff;
}
// maxlev <= 0 means 'any lev' // maxlev <= 0 means 'any lev'
enum OBTYPE getrandomspell(int maxlev) { enum OBTYPE getrandomspell(int maxlev) {
@ -8346,7 +8535,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// spellpower // spellpower
f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL); f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL);
if (f && strlen(f->text)) { if (f && strlen(f->text)) {
texttospellopts(f->text, &power, NULL, NULL, NULL); texttospellopts(f->text, "pw:", &power, NULL );
if (power > 0) { if (power > 0) {
if (db) { if (db) {
dblog("-->power = %d (from canwill)", power); dblog("-->power = %d (from canwill)", power);
@ -8367,12 +8556,11 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
// //
// this check doesn't apply for monsters. // this check doesn't apply for monsters.
if (isplayer(lf)) { if (isplayer(lf)) {
int maxspelllevel = MAXSPELLLEV;
if (hasjob(lf, J_DRUID) && (school == SS_NATURE)) { if (hasjob(lf, J_DRUID) && (school == SS_NATURE)) {
// always okay
} else if ((school == SS_ALLOMANCY) || (school == SS_MENTAL)) { } else if ((school == SS_ALLOMANCY) || (school == SS_MENTAL)) {
// dont need spellcasting skill for mental/allomancy // dont need spellcasting skill for mental/allomancy
} else { } else {
int maxspelllevel;
usesorcery = B_TRUE; usesorcery = B_TRUE;
switch (schoolskill) { switch (schoolskill) {
case PR_INEPT: maxspelllevel = 0; break; case PR_INEPT: maxspelllevel = 0; break;
@ -8383,16 +8571,13 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
case PR_EXPERT: maxspelllevel = 8; break; case PR_EXPERT: maxspelllevel = 8; break;
case PR_MASTER: maxspelllevel = 9; break; case PR_MASTER: maxspelllevel = 9; break;
} }
}
// player can only ever cast spells up to your level.
if (!hasjob(lf, J_GOD)) limit(&maxspelllevel, NA, lf->level);
// player can only ever cast spells up to your level. if (spelllev > maxspelllevel) {
if (!hasjob(lf, J_GOD)) { if (db) dblog("-->power = 0 (no skilled enough in spell school)");
limit(&maxspelllevel, NA, lf->level); return 0;
}
if (spelllev > maxspelllevel) {
if (db) dblog("-->power = 0 (no skilled enough in spell school)");
return 0;
}
} }
} }
@ -8533,7 +8718,7 @@ int getspellrange(lifeform_t *lf, enum OBTYPE spellid, int power) {
flag_t *f; flag_t *f;
f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL); f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL);
if (f && strlen(f->text)) { if (f && strlen(f->text)) {
texttospellopts(f->text, NULL, NULL, NULL, &newrange); texttospellopts(f->text, "range:", &newrange, NULL);
if (newrange > 0) { if (newrange > 0) {
return newrange; return newrange;
} }
@ -9101,34 +9286,4 @@ int getiqreq(enum OBTYPE oid) {
} }
*/ */
int getmpcost(lifeform_t *lf, enum OBTYPE oid) {
flag_t *f;
objecttype_t *ot;
int cost = 0;
ot = findot(oid);
if (!ot) {
return 0;
}
if (lf) {
if (lfhasflagval(lf, F_BOOSTSPELL, oid, NA, NA, NULL)) {
return 0; // ie. deactivating it
}
if (lfhasflagval(lf, F_CANWILL, oid, NA, NA, NULL)) {
return 0; // ie. deactivating it
}
}
f = hasflag(ot->flags, F_MPCOST);
if (f) {
cost = f->val[0];
} else {
f = hasflag(ot->flags, F_SPELLLEVEL);
if (f) {
cost = f->val[0] * f->val[0];
}
}
return cost;
}

View File

@ -7,7 +7,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
objecttype_t *findspelln(char *buf); objecttype_t *findspelln(char *buf);
void fizzle(lifeform_t *caster); void fizzle(lifeform_t *caster);
//int getiqreq(enum OBTYPE oid); //int getiqreq(enum OBTYPE oid);
char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr);
int getmpcost(lifeform_t *lf, enum OBTYPE oid); int getmpcost(lifeform_t *lf, enum OBTYPE oid);
int getmrdiff(enum OBTYPE spellid, int power);
enum OBTYPE getrandomspell(int maxlev); enum OBTYPE getrandomspell(int maxlev);
enum SKILL getschoolskill(enum SPELLSCHOOL ss); enum SKILL getschoolskill(enum SPELLSCHOOL ss);
char *getspellcosttext(lifeform_t *lf, enum OBTYPE spellid, int power, char *buf); char *getspellcosttext(lifeform_t *lf, enum OBTYPE spellid, int power, char *buf);

97
text.c
View File

@ -1,5 +1,7 @@
#include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "defs.h" #include "defs.h"
@ -402,17 +404,18 @@ char *getwaterdepthname(enum DEPTH d) {
return "?unknowndepth?"; return "?unknowndepth?";
} }
char *getweighttext(float weight, char *buf) { char *getweighttext(float weight, char *buf, int shortfmt) {
if (weight == 0) { if (weight == 0) {
snprintf(buf, BUFLEN, "nothing"); if (shortfmt) snprintf(buf, BUFLEN, "0kg");
else snprintf(buf, BUFLEN, "nothing");
} else if (weight >= 1) { } else if (weight >= 1) {
if ((int)weight == weight) { // ie. is weight an integer? if ((int)weight == weight) { // ie. is weight an integer?
snprintf(buf, BUFLEN, "%0.0f kg",weight); snprintf(buf, BUFLEN, "%0.0f%skg",weight, shortfmt ? "" : " ");
} else { } else {
snprintf(buf, BUFLEN, "%0.1f kg",weight); snprintf(buf, BUFLEN, "%0.1f%skg",weight, shortfmt ? "" : " ");
} }
} else { } else {
snprintf(buf, BUFLEN, "%0.0f grams", weight * 1000); snprintf(buf, BUFLEN, "%0.0f%s", weight * 1000, shortfmt ? "g" : " grams");
} }
return buf; return buf;
} }
@ -854,7 +857,8 @@ int texttodice(char *text, int *ndice, int *nsides, int *bonus) {
return B_FALSE; return B_FALSE;
} }
void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range) { /*
void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range, char *racestr) {
char *p; char *p;
int n; int n;
char *argname[] = { char *argname[] = {
@ -862,6 +866,7 @@ void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *r
"dam:", "dam:",
"needgrab:", "needgrab:",
"range:", "range:",
"race:",
NULL, NULL,
}; };
void *argval[] = { void *argval[] = {
@ -869,6 +874,7 @@ void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *r
damstr, damstr,
needgrab, needgrab,
range, range,
racestr,
NULL, NULL,
}; };
char argtype[] = { char argtype[] = {
@ -876,6 +882,7 @@ void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *r
's', 's',
'b', 'b',
'i', 'i',
's',
'\0', '\0',
}; };
@ -884,6 +891,7 @@ void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *r
if (damstr) strcpy(damstr, ""); if (damstr) strcpy(damstr, "");
if (needgrab) *needgrab = B_FALSE; if (needgrab) *needgrab = B_FALSE;
if (range) *range = 0; if (range) *range = 0;
if (racestr) strcpy(racestr, "");
if (!strlen(text)) { if (!strlen(text)) {
return; return;
@ -915,7 +923,84 @@ void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *r
} }
} }
} }
*/
void texttospellopts(char *text, ... ) {
char *p;
va_list args;
char *validname[] = {
"pw:",
"dam:",
"needgrab:",
"range:",
"race:",
NULL,
};
char argtype[] = {
'i',
's',
'b',
'i',
's',
'\0',
};
char *wantname = NULL;
void *writeto = NULL;
va_start(args, text);
wantname = va_arg(args, char *);
if (wantname) writeto = va_arg(args, void *);
while (wantname) {
int foundidx = -1,i;
// process this one
// validate 'wantname' - must match one of 'validname[]'
for (i = 0; validname[i]; i++) {
if (streq(validname[i], wantname)) {
foundidx = i;
break;
}
}
assert(foundidx != -1);
// look for 'wantname' within 'text'
for (p = text ; *p ; p++) {
if (!strncmp(p, wantname, strlen(wantname)) ) { // found it!
char localval[BUFLEN];
char *valfull;
// blank our dest buffer
if (argtype[foundidx] == 'i') {
*((int *)writeto) = 0;
} else if (argtype[foundidx] == 'b') {
*((int *)writeto) = B_FALSE;
} else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, "");
}
// extract value from text
// p will point to "pw:xxx;"
strcpy(localval, p + strlen(wantname)); // localval is "xxx;"
valfull = strtok(localval, ";"); // valfull is "xxx"
if (valfull) {
// if it's there, write the value into 'writeto'
if (argtype[foundidx] == 'i') {
*((int *)writeto) = atoi(valfull);
} else if (argtype[foundidx] == 'b') {
*((int *)writeto) = atoi(valfull) ? B_TRUE : B_FALSE;
} else if (argtype[foundidx] == 's') {
strcpy((char *)writeto, valfull);
}
}
}
}
// get next one
wantname = va_arg(args, char *);
if (wantname) writeto = va_arg(args, void *);
}
va_end(args);
}
char *you(lifeform_t *lf) { char *you(lifeform_t *lf) {
if (isplayer(lf)) { if (isplayer(lf)) {

5
text.h
View File

@ -19,7 +19,7 @@ char *getsizetext(enum LFSIZE sz);
char *gettimetext(char *retbuf); char *gettimetext(char *retbuf);
char *gettimetextfuzzy(char *retbuf, int wantpm); char *gettimetextfuzzy(char *retbuf, int wantpm);
char *getwaterdepthname(enum DEPTH d); char *getwaterdepthname(enum DEPTH d);
char *getweighttext(float weight, char *buf); char *getweighttext(float weight, char *buf, int shortfmt);
char *is(lifeform_t *lf); char *is(lifeform_t *lf);
int isvowel(char c); int isvowel(char c);
char *makekillertext(char *retbuf, char *lastdam, int wantextra); char *makekillertext(char *retbuf, char *lastdam, int wantextra);
@ -39,7 +39,8 @@ char *strends(char *a, char *suffix);
char *strstarts(char *a, char *prefix); char *strstarts(char *a, char *prefix);
int strpixmatch(char *haystack, char *needle); int strpixmatch(char *haystack, char *needle);
int texttodice(char *text, int *ndice, int *nsides, int *bonus); int texttodice(char *text, int *ndice, int *nsides, int *bonus);
void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range); void texttospellopts(char *text, ... );
//void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range, char *racestr);
char *you(lifeform_t *lf); char *you(lifeform_t *lf);
char *you_l(lifeform_t *lf); char *you_l(lifeform_t *lf);
char *your(lifeform_t *lf); char *your(lifeform_t *lf);

View File

@ -0,0 +1,21 @@
! filled with random monsters
@id:monsterzoo
@map
random(3,3,5,5)
@end
@legend
@end
@flags
autodoors:100
goesin:dungeon
! every cell in here has 1-3 objects and a monster
scatter(1,1,-2,-2) mon:random:100%
scatter(1,1,-2,-2) ob:random:100%
scatter(1,1,-2,-2) ob:random:100%
scatter(1,1,-2,-2) ob:random:100%:50
scatter(1,1,-2,-2) ob:random:100%:50
rarity:rare
@end

View File

@ -1,11 +1,11 @@
@id:playerstart_1 @id:playerstart_1
@map @map
########## ##########
#...c..|,# #......|,#
#...-/-### #..c...###
+......|,# +......|,#
#.-/-..### #..c...###
#...c..|,# #......|,#
########## ##########
@end @end
@legend @legend
@ -14,16 +14,11 @@
,:ob:1-4 bones:50 ,:ob:1-4 bones:50
+:ob:wooden door +:ob:wooden door
+:exit +:exit
/:ob:wooden table
-:ob:wooden footstool
@end @end
@flags @flags
goesin:dungeon goesin:dungeon
playerstart playerstart
norandom
atoneof(8,1)(8,3)(8,5) ob:playerstart atoneof(8,1)(8,3)(8,5) ob:playerstart
scatter(1,1,-2,-2) ob:wooden footstool:0-3
scatter(1,1,-2,-2) ob:random food:0-2
mayrotate mayrotate
@end @end

View File

@ -1,25 +1,26 @@
@id:playerstart_2 @id:playerstart_2
@map @map
###x### ###x###
#.|.|.# #m|.|m#
###.### ###.###
#.|.|.# #m|.-p#
###.### ###.###
#.|.|.# #m|.|m#
###.### ###.###
#.|.|.# #m|.|m#
###x### ###x###
@end @end
@legend @legend
#:cell:rock wall #:cell:rock wall
|:ob:iron gate |:ob:locked iron gate
-:ob:iron gate
p:ob:playerstart
m:mon:humanoid
x:exit x:exit
@end @end
@flags @flags
goesin:dungeon goesin:dungeon
playerstart playerstart
norandom
atoneof(1,1)(1,3)(1,5)(1,7)(5,1)(5,3)(5,5)(5,7) ob:playerstart
mayrotate mayrotate
@end @end

View File

@ -20,7 +20,6 @@ p:ob:playerstart
goesin:dungeon goesin:dungeon
autodoors:50 autodoors:50
playerstart playerstart
norandom
mayrotate mayrotate
@end @end

View File

@ -19,7 +19,6 @@ x:exit
@flags @flags
goesin:dungeon goesin:dungeon
playerstart playerstart
norandom
mayrotate mayrotate
@end @end

21
vaults/playerstart5.vlt Normal file
View File

@ -0,0 +1,21 @@
@id:playerstart_5
@map
#######
##...##
#.....#
#..p..x
#.....#
##...##
#######
@end
@legend
#:cell:rock wall
p:ob:playerstart
x:exit
@end
@flags
goesin:dungeon
playerstart
mayrotate
@end

23
vaults/playerstart6.vlt Normal file
View File

@ -0,0 +1,23 @@
@id:playerstart_6
@map
######
####.#
###..x
##...#
#..p.#
##...#
###..x
####.#
######
@end
@legend
#:cell:rock wall
p:ob:playerstart
x:exit
@end
@flags
goesin:dungeon
playerstart
mayrotate
@end

26
vaults/playerstart7.vlt Normal file
View File

@ -0,0 +1,26 @@
@id:playerstart_7
@map
##+###+##
#...#...#
+.p.|.f.+
#...#...#
##|###|##
#...#...#
+.f.|.f.+
#...#...#
##+###+##
@end
@legend
#:cell:rock wall
p:ob:playerstart
p:ob:fountain
f:ob:fountain
+:ob:wooden door
|:ob:iron gate
@end
@flags
goesin:dungeon
playerstart
mayrotate
@end