From 27f08ed7abc372c499beb97a9776a38d1d346187 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Mon, 19 Dec 2011 08:04:49 +0000 Subject: [PATCH] - [+] stomach code - [+] create 1 vault - [+] must have: - [+] ot_playerstart - [+] ot_stomachexit - [+] swallow ability moves to there - [+] when the lf dies, destroy the map - [+] TEST - [+] mover object - [+] moves you if you didn't move - [+] f_pushdir, v0 = dir - [+] invisible obejct - [+] may flip them horizontally - [+] chance to dodge the swallow - [+] rename green ooze to "sizzling slime" - [+] don't put traps on top of stairs!! - [+] remove unneeded extra redraw when changing levels. - [+] make ']' show object AR bonusss - [+] don't even call precalclos during endgame. - [+] don't say "you see footprints and footprints here" - [+] break grabs when you fall unconscious - [+] bug - ring of wounding not working. - [+] crash in free(npcnames) !!!!! pointer being freed was not allcoated - [+] grave sprite - [+] glutworm - [+] swallows you - [+] eats all objects - [+] canines/felines should die from chocolate - [+] weapons with multiple damtypes - [+] at adept skilllevel, you can change type (but only with weapons you're pr_skilled or higher in) - [+] f_altdamtype xx. must have altdam for normal dam too. - [+] fire primality Hecta effect: - [+] necrotic beam --- ai.c | 20 +-- attack.c | 14 ++- data.c | 309 +++++++++++++++++++++++++++++++++++++++++------ data/hiscores.db | Bin 13312 -> 13312 bytes defs.h | 47 ++++++- doc/glyphs.txt | 2 + doc/vaults.txt | 7 ++ flag.c | 8 +- flag.h | 1 + io.c | 45 ++++++- lf.c | 62 ++++++++-- map.c | 90 ++++++++++++-- map.h | 1 + move.c | 10 +- nexus.c | 15 ++- objects.c | 36 ++++-- spell.c | 227 +++++++++++++++++++++++++++++++--- vault.c | 72 ++++++++++- vault.h | 2 + 19 files changed, 848 insertions(+), 120 deletions(-) diff --git a/ai.c b/ai.c index 87b2b2a..41902aa 100644 --- a/ai.c +++ b/ai.c @@ -690,14 +690,13 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) { int chance = 100; // chance that we ('lf') will attack 'who' int reachpenalty; // will usually ignore targets who we can't reach - if (!canreach(lf, who, &reachpenalty)) { - if (!aigetrangedattack(lf, who, NULL, NULL)) { // no ranged attack? - // 1 size too small = 53% chance to attack - // 1 size too small = 6% chance to attack - chance = 100 - (reachpenalty*47); - if (db) dblog(".oO { target %d (%s) is %d sizes out of reach. %d%% chance to ignore }",who->id, who->race->name, - reachpenalty, reachpenalty*47); - } + if (!canreach(lf, who, &reachpenalty) && !aigetrangedattack(lf, who, NULL, NULL)) { + // 1 size too small = 53% chance to attack + // 1 size too small = 6% chance to attack + chance = 100 - (reachpenalty*47); + if (db) dblog(".oO { target %d (%s) is %d sizes out of reach. %d%% chance to ignore }", + who->id, who->race->name, + reachpenalty, reachpenalty*47); } else if (isresting(who)) { // targets sleeping in a tent will probably be ignored object_t *restob; @@ -1836,6 +1835,11 @@ void aiturn(lifeform_t *lf) { // DEFAULT - try to move in a random direction if (db) dblog(".oO { default - moving randomly }"); dorandommove(lf, B_NOBADMOVES, B_TRUE); // this function will call rest() if we cant move + + // somehow still here? + if (!lf->timespent) { + taketime(lf, getmovespeed(lf)); + } } // is the spell 'spellid' okay for AI lifeform 'lf' to cast at 'victim', for given purpose. diff --git a/attack.c b/attack.c index 77a0924..9d1b19f 100644 --- a/attack.c +++ b/attack.c @@ -234,7 +234,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { } killflagsofid(c->lf->flags, F_PRONE); // still counts as a move! - if (isplayer(lf)) addflag(lf->flags, F_MOVED, B_TRUE, NA, NA, NULL); + addflagifneeded(lf->flags, F_TOOKACTION, B_TRUE, NA, NA, NULL); taketime(lf, getmovespeed(lf)); return B_FALSE; } @@ -379,7 +379,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { } if (maxattacks) { - if (isplayer(lf)) addflag(lf->flags, F_MOVED, B_TRUE, NA, NA, NULL); + addflagifneeded(lf->flags, F_TOOKACTION, B_TRUE, NA, NA, NULL); } attacksdone = 0; @@ -628,7 +628,7 @@ int attacklf(lifeform_t *lf, lifeform_t *victim, object_t *wep, flag_t *damflag) // long weapon in an enclosed space? - if (wep && hasflag(wep->flags, F_NEEDSSPACE)) { + if (wep && hasflag(wep->flags, F_NEEDSSPACE) && (getdamtype(wep) != DT_PIERCE)) { if (countcellexits(lf->cell, DT_COMPASS) < 3) { if (pctchance(75)) { if (isplayer(lf)) { @@ -1701,17 +1701,19 @@ int getextradamlf(lifeform_t *lf, int *dam, enum DAMTYPE *damtype, int *ndam) { int doinc = B_FALSE; if ((f->val[0] == NA) || (f->val[0] == *damtype)) { + // addition to the first one damwhere = dam; damtypewhere = damtype; *(damwhere) += roll(f->text); // addition } else { + // add a new damtype damwhere = (dam + *ndam); damtypewhere = (damtype + *ndam); - *(damwhere) = roll(f->text); // set doinc = B_TRUE; + *(damwhere) = roll(f->text); // set + *(damtypewhere) = f->val[0]; } - *(damtypewhere) = f->val[0]; if ((f->lifetime == FROMOBEQUIP) || (f->lifetime == FROMOBHOLD) || @@ -2131,7 +2133,7 @@ void wepeffects(flagpile_t *fp, cell_t *where, flag_t *damflag, int dam) { addobfast(where->obpile, OT_FIRESMALL); // announce if (haslos(player, where)) { - msg("^wA column of fire erupts from the ground!"); + msg("^wA burst of fire erupts from the ground!"); f->known = B_KNOWN; } } diff --git a/data.c b/data.c index b19072f..329c85e 100644 --- a/data.c +++ b/data.c @@ -325,7 +325,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, PR_SKILLED, NA, NULL); // abilities addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); - addjob(J_DRUID, "Druid", "Druids use the power of nature to aid themselves or harm others. They start with a pet wolf, and their spells are more powerful when near plants. They are willing to eat other lifeforms when neccessary but prefer a vegetable-based diet."); + addjob(J_DRUID, "Druid", "Druids use the power of nature to aid themselves or harm others. They start with a pet wolf, and their spells are more powerful when near plants. They are willing to eat other lifeforms when neccessary but prefer a vegetable-based diet. Unlike other spellcasters, Druids gain spells automotically when levelling."); // stats addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL); addflag(lastjob->flags, F_JOBATTRMOD, A_WIS, 3, NA, NULL); @@ -1344,6 +1344,7 @@ void initobjects(void) { addot(OT_GRATINGROOF, "drain in the roof", "An open draining grate set into the roof.", MT_NOTHING, 0, OC_DFEATURE, SZ_LARGE); addflag(lastot->flags, F_GLYPH, C_BLUE, '<', NA, NULL); addflag(lastot->flags, F_CLIMBABLE, D_UP, NA, NA, NULL); + addflag(lastot->flags, F_DONTSHOWDEST, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PIT, D_UP, NA, NA, NULL); addflag(lastot->flags, F_OPPOSITESTAIRS, OT_GRATINGFLOOR, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); @@ -1354,6 +1355,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL); addflag(lastot->flags, F_GLYPH, C_BLUE, '^', NA, NULL); addflag(lastot->flags, F_CLIMBABLE, D_DOWN, NA, NA, NULL); + addflag(lastot->flags, F_DONTSHOWDEST, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PIT, D_DOWN, NA, NA, NULL); addflag(lastot->flags, F_OPPOSITESTAIRS, OT_HOLEINROOF, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); @@ -1363,6 +1365,7 @@ void initobjects(void) { addot(OT_HOLEINROOF, "hole in the roof", "A gaping hole in the roof.", MT_NOTHING, 0, OC_DFEATURE, SZ_LARGE); addflag(lastot->flags, F_GLYPH, C_BLUE, '<', NA, NULL); addflag(lastot->flags, F_CLIMBABLE, D_UP, NA, NA, NULL); + addflag(lastot->flags, F_DONTSHOWDEST, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PIT, D_UP, NA, NA, NULL); addflag(lastot->flags, F_OPPOSITESTAIRS, OT_HOLEINGROUND, NA, NA, NULL); addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); @@ -1509,6 +1512,14 @@ void initobjects(void) { addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + addot(OT_STOMACHEXIT, "gaping hole", "A gaping hole in an enormous creature.", MT_MAGIC, 0, OC_DFEATURE, SZ_LARGE); + addflag(lastot->flags, F_GLYPH, C_GREY, '^', NA, NULL); + addflag(lastot->flags, F_DONTSHOWDEST, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_CLIMBABLE, D_IN, NA, NA, NULL); + addflag(lastot->flags, F_NOPICKUP, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOBLESS, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, B_TRUE, NA, NA, NULL); + // terrain addot(OT_WATERDEEP, "water", "Deep water.", MT_WATER, 300, OC_TERRAIN, SZ_HUGE); addflag(lastot->flags, F_NO_A, B_TRUE, NA, NA, NULL); @@ -1933,6 +1944,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, NULL); addflag(lastot->flags, F_RARITY, H_FOREST, 100, RR_VERYRARE, NULL); addflag(lastot->flags, F_HOLDCONFER, F_EXTRALUCK, 1, NA, NULL); + addflag(lastot->flags, F_VALUE, 300, NA, NA, ""); killflagsofid(lastot->flags, F_STACKABLE); addot(OT_BREADSTALE, "loaf of stale bread", "A small loaf of old, stale bread.", MT_FOOD, 0.5, OC_FOOD, SZ_TINY); addflag(lastot->flags, F_GLYPH, C_BROWN, '%', NA, NULL); @@ -3211,6 +3223,7 @@ void initobjects(void) { addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_WALLSTOP, NA, NULL); addot(OT_S_LETHARGY, "lethargy", "Reduces the target's stamina by ^bpower^n*2.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_MENTAL, 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_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_VICTIM, NA, NA, NULL); @@ -3353,6 +3366,7 @@ void initobjects(void) { addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL); addot(OT_S_QUICKENSTONE, "quicken stone", "Crafts nearby stone into powerful stone primalities.", MT_NOTHING, 0, OC_SPELL, SZ_TINY); addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how many creatures will be created."); + addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power level VI, stronger creatures will be created."); addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL); addflag(lastot->flags, F_MAXPOWER, 8, NA, NA, NULL); addflag(lastot->flags, F_SPELLLEVEL, 5, NA, NA, NULL); @@ -3588,6 +3602,8 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addflag(lastot->flags, F_STAMCOST, 2, NA, NA, NULL); + addot(OT_A_ALTERATTACK, "alter attack style", "Adjust your attack style to cause a different kind of damage.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_EMPLOY, "employ", "Assigns a job to the target lifeform.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_CHARGE, "charge", "You can quickly charge into close quarters for battle.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); @@ -3705,6 +3721,11 @@ void initobjects(void) { addot(OT_A_SUCKBLOOD, "suck blood", "You can suck the blood from enemies after attaching to them.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); + addot(OT_A_SWALLOW, "swallow", "Swallow an enemy whole.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); + addflag(lastot->flags, F_STAMCOST, 2, NA, NA, NULL); + addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); + addflag(lastot->flags, F_RANGE, 1, NA, NA, NULL); + addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJVICTIM, NA, NA, NULL); addot(OT_A_SWOOP, "swoop", "You can attack an enemy while flying past them.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_STAMCOST, 2, NA, NA, NULL); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); @@ -5714,6 +5735,12 @@ void initobjects(void) { addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); + addot(OT_TOUCHBURN, "burning touch", "burning touch object", MT_BONE, 0, OC_WEAPON, SZ_TINY); + addflag(lastot->flags, F_DAM, DT_FIRE, 1, NA, NULL); + addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); + addflag(lastot->flags, F_NOSTRDAMMOD, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_USESSKILL, SK_NONE, NA, NA, NULL); + addflag(lastot->flags, F_UNARMEDWEP, B_TRUE, NA, NA, NULL); addot(OT_TOUCHCHILL, "chilling touch", "chilling touch object", MT_BONE, 0, OC_WEAPON, SZ_TINY); addflag(lastot->flags, F_DAM, DT_COLD, 1, NA, NULL); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); @@ -5857,6 +5884,7 @@ void initobjects(void) { addot(OT_AXE, "axe", "A short pole with a heavy, wedge-shaped blade for chopping.", MT_METAL, 5, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, 6, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 9, 10, NULL); @@ -5864,6 +5892,7 @@ void initobjects(void) { addot(OT_BATTLEAXE, "battleaxe", "An large axe specifically designed for combat.", MT_METAL, 8, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, 11, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 5, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, 10, NULL); @@ -5871,6 +5900,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 50, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, 18, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, NULL); addflag(lastot->flags, F_NEEDSSPACE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); @@ -5896,6 +5926,7 @@ void initobjects(void) { addot(OT_WARAXE, "war axe", "An axe made for combat.", MT_METAL, 7, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, 12, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 5, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_AXES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 11, 10, NULL); @@ -5905,6 +5936,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 65, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 75, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 5, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 3, NA, NULL); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); @@ -5916,6 +5948,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 80, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 75, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 8, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_AGI, 8, 10, NULL); @@ -5925,6 +5958,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 50, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 4, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_SLASH, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -5945,6 +5979,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 50, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 3, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 3, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_PICKLOCKS, 7, B_BLUNTONFAIL, NA, NULL); @@ -5970,6 +6005,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 50, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 4, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_SLASH, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 100, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_CRITCHANCE, 2, NA, NA, NULL); @@ -5986,6 +6022,7 @@ void initobjects(void) { addot(OT_SHORTSWORD, "gladius", "A short gladiator blade. Designed for stabbing rather than slashing.", MT_METAL, 4, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 90, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 6, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_SLASH, 6, NA, NULL); addflag(lastot->flags, F_ACCURACY, 90, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_SHORTBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 6, 5, NULL); @@ -6003,6 +6040,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 50, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 2, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 2, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_DAMAGABLE, B_TRUE, NA, NA, NULL); @@ -6015,6 +6053,7 @@ void initobjects(void) { addot(OT_BASTARDSWORD, "bastard sword", "Very large, heavy sword.", MT_METAL, 8, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 12, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 12, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); @@ -6032,6 +6071,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 55, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 180, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 15, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 15, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NEEDSSPACE, B_TRUE, NA, NA, NULL); @@ -6041,6 +6081,7 @@ void initobjects(void) { addot(OT_LONGSWORD, "longsword", "Standard issue long slashing weapon.", MT_METAL, 5, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 9, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 9, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_LONGBLADES, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 10, 3, NULL); @@ -6070,6 +6111,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 73, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 150, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 12, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NEEDSSPACE, B_TRUE, NA, NA, NULL); @@ -6083,6 +6125,7 @@ void initobjects(void) { addflag(lastot->flags, F_NEEDSSPACE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 9, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 13, 1, NULL); @@ -6093,6 +6136,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBATTACKDELAY, 130, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_TRIPLF, NA, NULL); addflag(lastot->flags, F_DAM, DT_CHOP, 13, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_SLASH, 10, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NEEDSSPACE, B_TRUE, NA, NA, NULL); @@ -6105,6 +6149,7 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 11, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); @@ -6116,6 +6161,7 @@ void initobjects(void) { addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 120, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 11, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL); addflag(lastot->flags, F_ACCURACY, 70, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); @@ -6133,6 +6179,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_OBATTACKDELAY, 140, NA, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 10, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 6, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_CANWILL, OT_A_THRUST, NA, NULL); addflag(lastot->flags, F_ACCURACY, 65, NA, NA, NULL); addflag(lastot->flags, F_THROWMISSILE, B_TRUE, NA, NA, NULL); @@ -6144,6 +6191,7 @@ void initobjects(void) { addot(OT_TRIDENT, "trident", "A three-pronged stabbing weapon.", MT_METAL, 5, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 75, NA, NULL); addflag(lastot->flags, F_DAM, DT_PIERCE, 10, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 4, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_POLEARMS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_AGI, 11, 10, NULL); @@ -6178,6 +6226,7 @@ void initobjects(void) { addot(OT_BLADEDSTAFF, "bladed staff", "A long wooden pole with blades on either end.", MT_WOOD, 5, OC_WEAPON, SZ_HUMAN); addflag(lastot->flags, F_RARITY, H_DUNGEON, 85, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 12, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 8, NA, NULL); addflag(lastot->flags, F_NEEDSSPACE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_ACCURACY, 75, NA, NA, NULL); addflag(lastot->flags, F_TWOHANDED, B_TRUE, NA, NA, NULL); @@ -6361,6 +6410,8 @@ void initobjects(void) { addot(OT_KATANA, "katana", "A long, finely balanced blade. Less raw power then a standard longsword, but its weight gives it a higher critical chance.", MT_METAL, 4, OC_WEAPON, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_DUNGEON, 70, NA, NULL); addflag(lastot->flags, F_DAM, DT_SLASH, 6, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_PIERCE, 6, NA, NULL); + addflag(lastot->flags, F_ALTDAM, DT_BASH, 3, NA, NULL); addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL); addflag(lastot->flags, F_USESSKILL, SK_EXOTICWEPS, NA, NA, NULL); addflag(lastot->flags, F_ATTREQ, A_AGI, 12, 15, NULL); @@ -6512,6 +6563,26 @@ void initobjects(void) { // special obs addot(OT_PLAYERSTART, "playerstart", "starting pos for player", MT_NOTHING, 0, OC_MISC, SZ_MINI); + addot(OT_PUSHN, "pushn", "pusher north", MT_NOTHING, 0, OC_MISC, SZ_MINI); + addflag(lastot->flags, F_INVISOB, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOGLYPH, NA, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, NA, NA, NA, NULL); + addflag(lastot->flags, F_MOVELFS, DC_N, NA, NA, NULL); + addot(OT_PUSHE, "pushe", "pusher east", MT_NOTHING, 0, OC_MISC, SZ_MINI); + addflag(lastot->flags, F_INVISOB, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOGLYPH, NA, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, NA, NA, NA, NULL); + addflag(lastot->flags, F_MOVELFS, DC_E, NA, NA, NULL); + addot(OT_PUSHS, "pushs", "pusher south", MT_NOTHING, 0, OC_MISC, SZ_MINI); + addflag(lastot->flags, F_INVISOB, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOGLYPH, NA, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, NA, NA, NA, NULL); + addflag(lastot->flags, F_MOVELFS, DC_S, NA, NA, NULL); + addot(OT_PUSHW, "pushw", "pusher west", MT_NOTHING, 0, OC_MISC, SZ_MINI); + addflag(lastot->flags, F_INVISOB, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_NOGLYPH, NA, NA, NA, NULL); + addflag(lastot->flags, F_NOFEEL, NA, NA, NA, NULL); + addflag(lastot->flags, F_MOVELFS, DC_W, NA, NA, NULL); // recipes - easy addrecipe(OT_MUSHROOMSTUFFED, @@ -7616,6 +7687,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 10, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_GNOLLHM, "gnoll hunter", 130, 'h', C_BROWN, MT_FLESH, RC_HUMANOID, "Hunters are gnolls tasked with obtaining food, but can also turn their ranged skills to combat."); setbodytype(lastrace, BT_HUMANOID); @@ -7654,6 +7726,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 12, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_GOBLIN, "goblin", 25, 'g', C_BROWN, MT_FLESH, RC_HUMANOID, "Small humanoids with flat faces, broad noses, pointed ears, and small, sharp fangs."); setbodytype(lastrace, BT_HUMANOID); @@ -7787,30 +7860,6 @@ void initrace(void) { addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); - addrace(R_GOLEMSTONE, "stone primality", 200, 'H', C_GREY, MT_STONE, RC_HUMANOID, "A living mass of stone, animated by powerful magic."); - setbodytype(lastrace, BT_HUMANOID); - addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL); - addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXHIGH, NA, NULL); - addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL); - addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL); - addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL); - addflag(lastrace->flags, F_STARTATT, A_CON, AT_EXHIGH, NA, NULL); - addflag(lastrace->flags, F_STARTATT, A_CHA, AT_EXLOW, NA, NULL); - addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "10d4"); - addflag(lastrace->flags, F_ARMOURRATING, 14, NA, NA, NULL); - addflag(lastrace->flags, F_EVASION, -50, NA, NA, NULL); - addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); - addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 16, NA, NULL); - addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL); - addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "boulder"); - addflag(lastrace->flags, F_UNSUMMONOB, NA, NA, NA, "boulder"); - addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); - addrace(R_HOBGOBLIN, "hobgoblin", 90, 'g', C_GREEN, MT_FLESH, RC_HUMANOID, "A larger, stronger, smarter and more menacing form of a goblin."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -7919,6 +7968,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_TROGLODYTE, "troglodyte", 20, 'z', C_GREY, MT_FLESH, RC_HUMANOID, "Troglodytes are smaller, stunted lizardmen who at outcast at birth. They linger on the outskirts of society, scavenging garbage and living in their own filth."); setbodytype(lastrace, BT_HUMANOID); @@ -8227,6 +8277,112 @@ void initrace(void) { addflag(lastrace->flags, F_CASTCHANCE, 60, NA, NA, NULL); addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + addrace(R_PRIMALFIRE, "fire primality", 50, 'E', C_RED, MT_FIRE, RC_HUMANOID, "A living mass of fire, animated by powerful magic."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "6d4"); + addflag(lastrace->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_WATER, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "small fire"); + addflag(lastrace->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TOUCHBURN, 4, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_PYROMANIA, NA, NA, "pw:1;"); + addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "burns brightly"); + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "large fire"); + addflag(lastrace->flags, F_UNSUMMONOB, NA, NA, NA, "large fire"); + addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); + + addrace(R_PRIMALFIREL, "lesser fire primality", 30, 'E', C_RED, MT_FIRE, RC_HUMANOID, "A living mass of fire, animated by powerful magic."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_LARGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "3d4"); + addflag(lastrace->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_DTVULN, DT_WATER, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_AUTOCREATEOB, 0, NA, NA, "small fire"); + addflag(lastrace->flags, F_FLAMESTRIKE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TOUCHBURN, 2, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL); + addflag(lastrace->flags, F_CANCAST, OT_S_PYROMANIA, NA, NA, "pw:1;"); + addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, NA, "burns brightly"); + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "medium fire"); + addflag(lastrace->flags, F_UNSUMMONOB, NA, NA, NA, "medium fire"); + addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); + + addrace(R_PRIMALSTONE, "stone primality", 200, 'E', C_GREY, MT_STONE, RC_HUMANOID, "A living mass of stone, animated by powerful magic."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "10d4"); + addflag(lastrace->flags, F_ARMOURRATING, 14, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, -50, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 16, NA, NULL); + addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL); + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "boulder"); + addflag(lastrace->flags, F_UNSUMMONOB, NA, NA, NA, "boulder"); + addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + + addrace(R_PRIMALSTONEL, "lesser stone primality", 120, 'E', C_GREY, MT_STONE, RC_HUMANOID, "A living mass of stone, animated by powerful magic."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_ALIGNMENT, AL_NONE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_AGI, AT_LTAVERAGE, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_WIS, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_EXHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CHA, AT_EXLOW, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_HUGE, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "5d4"); + addflag(lastrace->flags, F_ARMOURRATING, 12, NA, NA, NULL); + addflag(lastrace->flags, F_EVASION, -50, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_SLOW, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_VERYSLOW, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 12, NA, NULL); + addflag(lastrace->flags, F_HEAVYBLOW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL); + addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "boulder"); + addflag(lastrace->flags, F_UNSUMMONOB, NA, NA, NA, "boulder"); + addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + addrace(R_SATYR, "satyr", 80, 'h', C_GREEN, MT_FLESH, RC_HUMANOID, "A goat-like humanoid equipped with a set of magical panpipes."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); @@ -8280,8 +8436,11 @@ void initrace(void) { addflag(lastrace->flags, F_AUTOCREATEOB, 1, NA, NA, "puff of smoke"); addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_CARNIVORE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_WANTSOBFLAG, F_EDIBLE, B_COVETS, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); - addrace(R_OOZEGREY, "green ooze", 10, 'j', C_GREEN, MT_SLIME, RC_SLIME, "Exactly what it sounds like - a small lump of green ooze. Green, acidic ooze."); + addrace(R_OOZEGREY, "sizzling slime", 10, 'j', C_GREEN, MT_SLIME, RC_SLIME, "Exactly what it sounds like - a small lump of green ooze. Green, acidic ooze."); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "puddle of slime"); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); @@ -8333,7 +8492,36 @@ void initrace(void) { addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); - addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC, "A small magical creature surrounded by freezing ice."); + addrace(R_SPRITEGRAVE, "grave sprite", 5, 'n', C_BLUE, MT_FLESH, RC_MAGIC, "A small magical creature made from corpse dust."); + setbodytype(lastrace, BT_HUMANOID); + addflag(lastrace->flags, F_NOCORPSE, NA, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, AT_AVERAGE, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_UNCOMMON, NULL); + addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4"); + addflag(lastrace->flags, F_EVASION, 15, NA, NA, NULL); + addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); + addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL); + addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_SPELLSPEED, SP_SLOW, NA, NA, NULL); + addflag(lastrace->flags, F_CANWILL, OT_S_SMITEGOOD, NA, NA, "pw:2;"); + addflag(lastrace->flags, F_CANWILL, OT_S_LETHARGY, NA, NA, "pw:3;"); + addflag(lastrace->flags, F_CANWILL, OT_S_ANIMATEDEAD, NA, NA, "pw:10;"); + addflag(lastrace->flags, F_SPELLCASTTEXT, OT_NONE, NA, B_APPENDYOU, "gestures"); + addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL); + addflag(lastrace->flags, F_DTIMMUNE, DT_COLD, NA, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_SS_DEATH, PR_ADEPT, NA, NULL); + addflag(lastrace->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL); + addflag(lastrace->flags, F_HUMANOID, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); + addflag(lastrace->flags, F_CASTCHANCE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + + addrace(R_SPRITEICE, "ice sprite", 5, 'n', C_WHITE, MT_ICE, RC_MAGIC, "A small magical creature made from freezing ice."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_CORPSETYPE, NA, NA, NA, "sheet of ice"); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LOW, NA, NULL); @@ -8895,6 +9083,7 @@ void initrace(void) { addflag(lastrace->flags, F_TAMABLE, 30, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_DOGBLINK, "blink dog", 35, 'd', C_YELLOW, MT_FLESH, RC_ANIMAL, "Magical canines who can teleport small distances at will."); setbodytype(lastrace, BT_QUADRAPED); addbodypart(lastrace, BP_TAIL, NULL); @@ -8922,6 +9111,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 2, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_DOGDEATH, "death hound", 40, 'd', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Possessed evil canines who thrive on death and destruction."); setbodytype(lastrace, BT_QUADRAPED); addbodypart(lastrace, BP_TAIL, NULL); @@ -8952,6 +9142,7 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 15, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_DOGWAR, "war hound", 40, 'd', C_BROWN, MT_FLESH, RC_ANIMAL, "Canines bred for war."); setbodytype(lastrace, BT_QUADRAPED); addbodypart(lastrace, BP_TAIL, NULL); @@ -8978,6 +9169,7 @@ void initrace(void) { addflag(lastrace->flags, F_TAMABLE, 40, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_FROG, "impaler frog", 10, ';', C_BOLDGREEN, MT_FLESH, RC_ANIMAL, "As their name implies, impaler frogs are dangerous frogs whose tongues end in a very sharp point. They use this to spear their enemies from afar, often while hiding underwater."); setbodytype(lastrace, BT_QUADRAPED); @@ -9018,7 +9210,7 @@ void initrace(void) { addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, ""); addflag(lastrace->flags, F_CANWILL, OT_S_FLIGHT, NA, NA, NULL); addflag(lastrace->flags, F_SPELLCASTTEXT, OT_S_FLIGHT, NA, NA, NULL); - addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+4"); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+2"); addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 2, NA, NULL); addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); @@ -9488,6 +9680,7 @@ void initrace(void) { addflag(lastrace->flags, F_TAMABLE, 30, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); addrace(R_WOLF, "wolf", 25, 'd', C_GREY, MT_FLESH, RC_ANIMAL, "Highly intelligent members of the canine family."); setbodytype(lastrace, BT_QUADRAPED); addbodypart(lastrace, BP_TAIL, NULL); @@ -9514,6 +9707,30 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 7, NA, NA, NULL); addflag(lastrace->flags, F_CANINE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_FATALFOOD, OT_CHOCOLATE, NA, NA, NULL); + + addrace(R_WORMGLUT, "glutworm", 25, 'W', C_MAGENTA, MT_FLESH, RC_ANIMAL, "Gigantic worms who swallow their prey whole, slowly digesting their still living bodies."); + addbodypart(lastrace, BP_HEAD, NULL); + addbodypart(lastrace, BP_TAIL, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + //addflag(lastrace->flags, F_HATESALL, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_CON, AT_VHIGH, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_ENORMOUS, NA, NA, NULL); + addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); + addflag(lastrace->flags, F_ENHANCESMELL, 2, NA, NA, NULL); + addflag(lastrace->flags, F_TREMORSENSE, 2, NA, NA, NULL); + addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_VERYRARE, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "7d4"); + addflag(lastrace->flags, F_EVASION, 10, NA, NA, NULL); + //addflag(lastrace->flags, F_WANTSOBFLAG, F_RARITY, NA, NA, NULL); // ie. everything + addflag(lastrace->flags, F_CANWILL, OT_A_SWALLOW, 5, 5, NULL); + addflag(lastrace->flags, F_CASTCHANCE, 100, NA, NA, NULL); + addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, NA, NULL); + addflag(lastrace->flags, F_NOISETEXT, N_WALK, SV_ROAR, NA, "^slithering"); + addflag(lastrace->flags, F_FLEEONHPPCT, 20, NA, NA, ""); + addflag(lastrace->flags, F_MORALE, 50, NA, NA, NULL); + addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); // end animals // dragons @@ -9971,7 +10188,6 @@ void initrace(void) { addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_SILENTMOVE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_POISONGAS, NA, NA, NULL); - addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 0, NA, NA, NULL); addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_TIMID, B_TRUE, NA, NA, NULL); @@ -10445,7 +10661,7 @@ void initrace(void) { addflag(lastrace->flags, F_DTVULN, DT_BASH, NA, NA, NULL); addflag(lastrace->flags, F_DTRESIST, DT_PIERCE, NA, NA, NULL); addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); - addflag(lastrace->flags, F_TREMORSENSE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_TREMORSENSE, 5, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_XPVAL, 0, NA, NA, NULL); @@ -10485,6 +10701,26 @@ void initrace(void) { addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); addflag(lastrace->flags, F_NOSLEEP, B_TRUE, NA, NA, NULL); + addrace(R_TOOTH, "tooth", 20, '^', C_WHITE, MT_BONE, RC_OTHER, "The sharp tooth of an enormous creature."); + addbodypart(lastrace, BP_WEAPON, NULL); + addflag(lastrace->flags, F_ALIGNMENT, AL_NEUTRAL, NA, NA, NULL); + addflag(lastrace->flags, F_AWARENESS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NODEATHANNOUNCE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOCORPSE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_MINDLESS, NA, NULL); + addflag(lastrace->flags, F_BLOODOB, NA, NA, NA, NULL); + addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_SIZE, SZ_ENORMOUS, NA, NA, NULL); + addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4"); + addflag(lastrace->flags, F_DOESNTMOVE, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_NOPRINTS, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); + addflag(lastrace->flags, F_NOINJURIES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DEAF, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_TREMORSENSE, 5, NA, NA, NULL); + addflag(lastrace->flags, F_MORALE, 30, NA, NA, NULL); + addflag(lastrace->flags, F_XPVAL, 0, NA, NA, NULL); + // now do final steps in race initialisation: // - add flags based on raceclass, etc // - fill in missing alignments @@ -10552,12 +10788,12 @@ void initskills(void) { skill_t *sk; addskill(SK_ARMOUR, "Armour", "Reduces evasion and stealth penalties from wearing armour.", 100); addskilldesc(SK_ARMOUR, PR_INEPT, "- Reduces the noise you make when wearing metal armour.", B_FALSE); - addskilldesc(SK_ARMOUR, PR_NOVICE, "^gReduces armour evasion penalties by 10%.^n", B_FALSE); - addskilldesc(SK_ARMOUR, PR_BEGINNER, "^gReduces armour evasion penalties by 20%.^n", B_FALSE); - addskilldesc(SK_ARMOUR, PR_ADEPT, "^gReduces armour evasion penalties by 30%.^n", B_FALSE); - addskilldesc(SK_ARMOUR, PR_SKILLED, "^gReduces armour evasion penalties by 40%.^n", B_FALSE); - addskilldesc(SK_ARMOUR, PR_EXPERT, "^gReduces armour evasion penalties by 50%.^n", B_FALSE); - addskilldesc(SK_ARMOUR, PR_MASTER, "^gReduces armour evasion penalties by 60%.^n", B_FALSE); + addskilldesc(SK_ARMOUR, PR_NOVICE, "^gReduces armour penalties by 10%.^n", B_FALSE); + addskilldesc(SK_ARMOUR, PR_BEGINNER, "^gReduces armour penalties by 20%.^n", B_FALSE); + addskilldesc(SK_ARMOUR, PR_ADEPT, "^gReduces armour penalties by 30%.^n", B_FALSE); + addskilldesc(SK_ARMOUR, PR_SKILLED, "^gReduces armour penalties by 40%.^n", B_FALSE); + addskilldesc(SK_ARMOUR, PR_EXPERT, "^gReduces armour penalties by 50%.^n", B_FALSE); + addskilldesc(SK_ARMOUR, PR_MASTER, "^gReduces armour penalties by 60%.^n", B_FALSE); addskill(SK_ATHLETICS, "Athletics", "Grants various athletic abilities and increases Stamina.", 50); addskilldesc(SK_ATHLETICS, PR_NOVICE, "^gYou gain the 'sprint' ability.^n", B_FALSE); addskilldesc(SK_ATHLETICS, PR_ADEPT, "^gYou gain the 'tumble' ability.^n", B_FALSE); @@ -10914,6 +11150,7 @@ void initskills(void) { addskilldesc(sk->id, PR_NOVICE, "^g-2 accuracy penalty.^n", B_FALSE); addskilldesc(sk->id, PR_BEGINNER, "^g-1 accuracy penalty^n", B_FALSE); addskilldesc(sk->id, PR_ADEPT, "^g+10% damage bonus.^n", B_FALSE); + addskilldesc(sk->id, PR_ADEPT, "^gYou can now alter your attack style to deal different damage types.", B_FALSE); addskilldesc(sk->id, PR_SKILLED, "^g+2 accuracy, +20% damage bonus.^n", B_FALSE); addskilldesc(sk->id, PR_SKILLED, "^gYou can now block certain attacks with this kind of weapon.^n", B_FALSE); addskilldesc(sk->id, PR_EXPERT, "^g+4 accuracy, +30% damage bonus.^n", B_FALSE); diff --git a/data/hiscores.db b/data/hiscores.db index f71dca80034725de02696259be7a6b7bc5c5f677..cc3aa581cc0c88514bf7bb2905bb6865d59fd4a1 100644 GIT binary patch delta 641 zcmXX@TS${(7=91`^xxcE9+0JT`%S@_E@hiSlQanwM1w*|)L4@Q$qtw#<%R7h=!Br- zqvKr{fw%b~S=jNS>>}_YOzEQ9AUaxjSrUE!pWh45_wYUs?}0ZpoEn}f^E`q7FIRnd zFSN!M(RrDru4OplHhTfQD&;gg6gqkoXss^ngrjIw^B=QE5sXpT*DWTBlbHl1lK`xFc7@8@g3xVP2Ot^I6`IOm(w4% zGat&foVTfEi#@eW30uv?z+sb*Vz zkD92TQZ!3ztn+nVl7_pKHMQM%_Rpx#|6Lz{7QbhMBliZ&-1+W`QzlI z2hfN`;np)^CJ>YpfvdQ~3t50H`mh79s6L;lggR-G=IA?D@DShR*XhwmvZbz^=c-Vv z#dYvt05E{vco7#VM2Bgbmgp}xDEBRO1uOb^njfdzN@aU!7OfHEa-*h@jC|Mx*u)4P z$2+)6h15L2Xlam>i6I?vA5U|CnIhlBlA|ruo$hZ5!a$4d2usgnHu+DfiSmMiSCkIU-g)g rJUg_j$vk39&Boa2Q-fXOF<};$ixZ)|g0Pvil-j7b*H$9pOMdVl+9sD* delta 556 zcmXw0T}YE*6h1%Sw|(E&mbxfJKR!1UnmBb1r~NydC|M9!{Ip(?|C>s?gIs=!|kud6Tc7JPtf8a@~dc#;D0 z-F9Qt2==IkP31JT{bP$&(Fi5MoT##4%7B@ZZpSq@>kl~vs{&?EHK|seFnY%!h$X-h zKEMhEDM81mK(kb4i_?5dg#!(2w5NTbGBwXFL}k_g;vEmc#s$Cy{6a1b&=va1S-z<1 z-89*WVLkA+SnpYx^qSOp?;6(nXc_ngPxBaeGtu(g_+xUqiX&BFd(Qzm9Pwltext // object flags F_BADOBJECT, // this object is dangerous. ie. potion of poison, // potion of sleep, etc. @@ -1993,6 +2009,7 @@ enum FLAG { // v0 is either NA (white) or colourid (C_xxx). F_NOGLYPH, // this object doesn't appear normally F_COSMETIC, // this object is mostly cosmetic, don't say 'you see xx' + F_INVISOB, // this object cannot be seen F_NOPICKUP, // cannot pick this up F_ATTACKABLE, // can attack this with 'A' F_IMPASSABLE, // cannot walk past this if your size is between v0 and v1 @@ -2083,6 +2100,9 @@ enum FLAG { // optional v1 = how many less turns between // skillchecks. should not go more than // DEFAULTRESTHEALTIME. + F_DONTSHOWDEST, // don't show destination of this stair + // object. ie say "staircase", not "staircase + // to level 4" // technology flags F_TECHLEVEL, // v0 is a PR_xxx enum for tech usage skill F_RNDCHARGES, // ob starts with between val0 and val1 charges @@ -2232,6 +2252,12 @@ enum FLAG { //F_DAM, // v0 = damtype, text = 1d1+1 F_DAM, // v0 = damtype, // v1=DR (this takes precedence) + F_ALTDAM, // this weapon deal multiple damage types. + // v0 = damtype + // v1 = DR + // (add this flag multiple times for each damtype, + // and remember to include the one listed in its + // F_DAM) F_MISSILEDAM, // val0 = dam if it hits (without speed multiplier) F_TANGLEMISSILE, // this object will trip anyone it is thrown at // (if it hits), unless they pass a SC_SLIP @@ -2288,6 +2314,7 @@ enum FLAG { // text is the name if you don't know what it is F_IDENTIFIED, // whether this object is fully identified F_KNOWNBAD, // you know this object is somehow bad + F_MOVELFS, // v0 = dir which this object will move lfs // bad flags F_DEEPWATER, // v0 = depth. F_WALKDAM, // val0 = damtype, text = dam per sec @@ -2343,7 +2370,9 @@ enum FLAG { // text = obid of hotel F_ALIGNMENT, // v0 = al_good, al_neutral, al_evil. default neutral. F_PIETY, // for god lifeforms - tracks player's piety with them - F_MOVED, // lf purposely moved in their last turn. + F_TOOKACTION, // lf purposely took action in their last turn. + F_MOVED, // lf purposely walked/flew/swum/moved in prev turn + F_HASBEENMOVED, // an object moved this lf since their last turn. F_PRAYEDTO, // player has prayed to this god before. F_GAVEMONEY, // v0 tracks how much money we gave away this turn // used for r_godgreed anger effects. @@ -2526,6 +2555,7 @@ enum FLAG { F_RNDHOSTILE, // v0% chance of being hostile. F_HOSTILE, // lf will attack the player if in sight F_FRIENDLY, // lf will attack all non-players if in sight + F_FATALFOOD, // if lf eats food with id = v0, they die. F_WANTS, // lf will try to pick up object type val0. if // val1 = B_COVETS, will even abandon attacks // for it! @@ -2876,6 +2906,7 @@ enum FLAG { // can be repeated multiple times // if a vault doesnt have this flag, it can go anywhere F_VAULTISPLAYERSTART, // player can start in this vault + F_VAULTISSTOMACH, // this vault is a stomach F_VAULTISSHOP, // this vault is a shop, so add f_shopitem to objects // here. F_VAULTISSHRINE, // this vault is a godstone shrine @@ -2885,6 +2916,8 @@ enum FLAG { // if maxcount is PCT, mincount is a percentage // of the total space. F_VAULTMAYROTATE, // may rotate this vault in 90degree increments. + F_VAULTMAYFLIPX, // may flip this vault horizontally + F_VAULTMAYFLIPY, // may flip this vault vertically F_VAULTNOLINK, // this vault doesn't have to be connected to the // rest of the map. F_VAULTRANDOMMAP, // v0=minwidth, v1=minheight. this vault's map is @@ -3154,6 +3187,7 @@ enum REGIONTYPE { RG_HEAVEN, RG_PIT, RG_SEWER, + RG_STOMACH, }; enum HABITAT { @@ -3163,7 +3197,8 @@ enum HABITAT { H_PIT = 4, H_VILLAGE = 5, H_SEWER = 6, - H_SWAMP = 7, + H_STOMACH = 7, + H_SWAMP = 8, H_ALL = 999 }; @@ -3459,7 +3494,7 @@ typedef struct lifeform_s { // set to TRUE after lf has being created int born; - // for ai movement - don't need to save. + // for ai movement and pushers. DO save these. struct cell_s *prevcell[2]; struct cell_s *cell; diff --git a/doc/glyphs.txt b/doc/glyphs.txt index 8a93615..383bb8d 100644 --- a/doc/glyphs.txt +++ b/doc/glyphs.txt @@ -13,6 +13,7 @@ c = cockatricoe C = celestial / divine ? d = canine/dog e = eye +E = elemental ? f = feline/cat F = flora (flowers, plants, etc) g = goblin @@ -36,6 +37,7 @@ S = spider U = unearthly/horrific creature V = vampire w = worm +W = large worm ?: x = small creature/monster X = unknown thing! y/Y = air related creatures like clouds of gas, air elemental diff --git a/doc/vaults.txt b/doc/vaults.txt index 3b6a79f..46d93ee 100644 --- a/doc/vaults.txt +++ b/doc/vaults.txt @@ -67,7 +67,10 @@ Flags can be: margin:x,y // must be x/y away from edges of map + // MAY ONLY USE ONE OF THE FOLLOWING mayrotate // vault can be rotated randomly + mayflipx // vault can be flipped horz + mayflipy // vault can be flipper vert nolink // don't try to link this vault up to the rest of // the map @@ -85,6 +88,10 @@ Flags can be: // appear when specifically requested via a region's // outline. + shrine // } + shop // } this vault is a shop/shrine/etc + stomach // } + NOTES: when adding lfs/objects, "random" creates a random one. diff --git a/flag.c b/flag.c index 0d58806..3714377 100644 --- a/flag.c +++ b/flag.c @@ -46,6 +46,12 @@ void addcondition(flag_t *f, enum FLAGCONDITION fc, int chance) { flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text) { return addflag_real(fp, id, val1, val2, val3, text, PERMENANT, B_KNOWN, -1); } +flag_t *addflagifneeded(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text) { + if (!hasflag(fp, id)) { + return addflag_real(fp, id, val1, val2, val3, text, PERMENANT, B_KNOWN, -1); + } + return NULL; +} flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, char *text, int timeleft) { return addflag_real(fp, id, val1, val2, val3, text, timeleft, B_KNOWN, -1); } @@ -447,7 +453,7 @@ void checkmapflags(map_t *m) { void checkflagpile(flagpile_t *fp) { if (fpisbad(fp)) { - assert("flagpile is corrupt!" == 0); + assert("flagpile is corrupt!" == 0); } } diff --git a/flag.h b/flag.h index 8d299a1..0ec3251 100644 --- a/flag.h +++ b/flag.h @@ -5,6 +5,7 @@ altflagval_t *addaltval(flag_t *f, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text); void addcondition(flag_t *f, enum FLAGCONDITION fc, int chance); flag_t *addflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text); +flag_t *addflagifneeded(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text); flag_t *addtempflag(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text, int timeleft); flag_t *addflag_real(flagpile_t *fp, enum FLAG id, int val1, int val2, int val3, /*@null@*/ char *text, int lifetime, int known, long obfromid); flagpile_t *addflagpile(lifeform_t *owner, object_t *o); diff --git a/io.c b/io.c index 43e0698..8f3f6b3 100644 --- a/io.c +++ b/io.c @@ -1127,8 +1127,30 @@ void announcearrival(lifeform_t *lf, map_t *newmap) { } else { msg("You arrive at the surface."); } - } else if (newmap->habitat->id == H_DUNGEON) { - msg("You arrive at dungeon level %d.", newmap->depth); + } else { + flag_t *f; + switch (newmap->habitat->id) { + case H_DUNGEON: + msg("You arrive %sat dungeon level %d.", + (newmap->lastplayervisit == -1) ? "" : "back ", + newmap->depth); + break; + case H_SWAMP: + msg("You arrive %sat a swamp.", + (newmap->lastplayervisit == -1) ? "" : "back "); + break; + case H_SEWER: + msg("You find yourself in a sewer."); + break; + case H_STOMACH: + f = hasflag(newmap->flags, F_STOMACHOF); + if (f) { + msg("You find yourself inside the stomach of %s!", f->text); + } + break; + default: + break; + } } } } @@ -4393,7 +4415,11 @@ void dolook(cell_t *where, int onpurpose) { getobname(firstob, buf, firstob->amt); getobname(secondob, buf2, secondob->amt); } - msg("You %s %s and %s here.", seeverb, buf, buf2); + if (streq(buf, buf2)) { + msg("You %s %s here.", seeverb, buf); + } else { + msg("You %s %s and %s here.", seeverb, buf, buf2); + } } else if ((numobs >= 3) && (numobs <= 4)) { msg("You %s a few things here.", seeverb); } else if ((numobs >= 5) && (numobs <= 6)) { @@ -6724,7 +6750,7 @@ void doenter(lifeform_t *lf) { } } - enterob = hasob(lf->cell->obpile, OT_PORTAL); + enterob = hasobwithflagval(lf->cell->obpile, F_CLIMBABLE, D_IN, NA, NA, NULL); if (enterob) { usestairs(lf, enterob, B_TRUE, B_FALSE); return; @@ -9510,7 +9536,9 @@ void showlfarmour(lifeform_t *lf) { f = hasflag(o->flags, F_ARMOURRATING); if (f && (f->val[0])) { char numbuf[BUFLENSMALL]; - snprintf(numbuf, BUFLENSMALL, " ^g[AR:%d]^n",f->val[0]); + int thisar; + thisar = f->val[0] + getobbonus(o, B_TRUE); + snprintf(numbuf, BUFLENSMALL, " ^g[AR:%d]^n",thisar); strcat(rhs, numbuf); } f = hasflag(o->flags, F_OBHP); @@ -9724,6 +9752,7 @@ void showlfstats(lifeform_t *lf, int showall) { } } + if (showall) { char maxmpstr[BUFLEN]; if (getmaxmp(lf) == lf->maxmp) { @@ -9736,7 +9765,8 @@ void showlfstats(lifeform_t *lf, int showall) { wprintw(mainwin, "%d / %d%s ", lf->mp , lf->maxmp,maxmpstr); y++; } - if (showall) { + + if (showall || (lorelev >= PR_ADEPT)) { if (isplayer(lf)) { doheadingsmall(mainwin, y, 0, ftext, "Exp Level"); } else { @@ -9748,6 +9778,9 @@ void showlfstats(lifeform_t *lf, int showall) { } else { wprintw(mainwin, "%d", gethitdice(lf)); y++; } + } + + if (showall) { if (isplayer(lf)) { int attpoints; int pct; diff --git a/lf.c b/lf.c index aabc717..6247bd7 100644 --- a/lf.c +++ b/lf.c @@ -3183,7 +3183,6 @@ int eat(lifeform_t *lf, object_t *o) { } } - hlev = gethungerlevel(gethungerval(player)); if (alreadyeating) { if (turnstoeat <= 1) { killflag(alreadyeating); @@ -3210,8 +3209,9 @@ int eat(lifeform_t *lf, object_t *o) { } // get less hungry + hlev = gethungerlevel(gethungerval(lf)); modhunger(lf, -eateachturn); - posthlev = gethungerlevel(gethungerval(player)); + posthlev = gethungerlevel(gethungerval(lf)); if (fullyeaten) { // special cases @@ -3280,6 +3280,16 @@ int eat(lifeform_t *lf, object_t *o) { stopeating = B_TRUE; } + if (lfhasflagval(lf, F_FATALFOOD, o->type->id, NA, NA, NULL)) { + char buf[BUFLEN]; + // die. + lf->hp = 0; + sprintf(buf, "eating %s", obname); + setlastdam(lf, buf); + stopeating = B_TRUE; + } + + // stop eating if we are full if (!stopeating && !fullyeaten && (posthlev != hlev) && (posthlev <= H_FULL)) { if (isplayer(lf) && (posthlev != H_STUFFED)) { @@ -4795,7 +4805,7 @@ void getwhowillfollow(lifeform_t *lf, object_t *stairob, lifeform_t **adjally, i cell_t *c; c = getcellat(lf->cell->map, x, y); if (c && c->lf && (c->lf != lf)) { - if (!isimmobile(c->lf)) { + if (!isimmobile(c->lf) && !lfhasflag(c->lf, F_DOESNTMOVE)) { int ok = B_FALSE; if (areallies(lf, c->lf) && haslof(c->lf->cell, lf->cell, LOF_NEED, NULL)) { // ally with a clear path to you (even if they can't see you, we assume @@ -6621,7 +6631,6 @@ int getvisrange(lifeform_t *lf, int useambient) { } else { range = DEF_VISRANGE; } - if (useambient) { if ((gamemode == GM_GAMESTARTED) && (lf->cell)) { int maxrange; @@ -7037,7 +7046,7 @@ int getallshields(lifeform_t *lf, enum DAMTYPE damtype, object_t **retob, int *c hasflagval(o->flags, F_CANBLOCK, damtype, NA, NA, NULL) || hasflagval(o->flags, F_CANBLOCK, DT_ALL, NA, NA, NULL)) { retob[*nretobs] = o; - checkmod[*nretobs] = getshieldblockmod(lf, o); + if (checkmod) checkmod[*nretobs] = getshieldblockmod(lf, o); (*nretobs)++; } } @@ -8628,9 +8637,15 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) { } if (isweaponskill(id)) { - if (f->val[1] == PR_MASTER) { + if (f->val[1] == PR_ADEPT) { + if (!hasflagval(lf->flags, F_CANWILL, OT_A_ALTERATTACK, NA, NA, NULL)) { + newf = addflag(lf->flags, F_CANWILL, OT_A_ALTERATTACK, NA, NA, NULL); + newf->lifetime = FROMSKILL; + } + } else if (f->val[1] == PR_MASTER) { if (!hasflagval(lf->flags, F_CANWILL, OT_A_COMBOSTRIKE, NA, NA, NULL)) { - addflag(lf->flags, F_CANWILL, OT_A_COMBOSTRIKE, NA, NA, NULL); + newf = addflag(lf->flags, F_CANWILL, OT_A_COMBOSTRIKE, NA, NA, NULL); + newf->lifetime = FROMSKILL; } } } @@ -10156,6 +10171,14 @@ void killlf(lifeform_t *lf) { // remove references lf->cell->lf = NULL; + // stomach? + f = lfhasflag(lf, F_MAPLINK); + if (f) { + map_t *m; + m = findmap(f->val[0]); + killmap(m); // kill the stomach + killflag(f); // kill the link flag + } // shouldn't need this... lf->cell = NULL; @@ -10760,6 +10783,8 @@ lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller) { needredraw = B_TRUE; } } + // + a->losdirty = B_TRUE; return a; } @@ -12117,6 +12142,7 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml if (fromlf && isplayer(fromlf)) { pleasegodmaybe(R_GODMERCY, 5); } + breakgrabs(lf, B_TRUE, B_FALSE); } else { // you wake up if you were hit, unless you were unconscious! f = lfhasflag(lf, F_ASLEEP); @@ -13248,10 +13274,12 @@ void precalclos_new(lifeform_t *lf) { cell_t *retcell[MAXRETCELLS]; int numpixels; //int db = B_FALSE; - enum SKILLLEVEL plev; + enum SKILLLEVEL plev = PR_INEPT; flag_t *missingeye; long allocamt; + if (gamemode == GM_CLEANUP) return; + if (lf->cell->type->id == CT_FAKE) return; if (lf->los) { @@ -13366,6 +13394,7 @@ void precalclos_new(lifeform_t *lf) { los[nlos] = c; blocker[nlos] = keepgoing ? B_FALSE : B_TRUE; nlos++; + assert (nlos < allocamt); } else { // if cell WASNT lit, add it to an array of dark "visible" cells // (lf->darklos) @@ -13373,6 +13402,7 @@ void precalclos_new(lifeform_t *lf) { // when light changes. losdark[nlosdark] = c; nlosdark++; + assert (nlos < allocamt); } } } else { // ie. if !c @@ -13380,8 +13410,8 @@ void precalclos_new(lifeform_t *lf) { } } // end foreach cell and while keepgoing } - assert(nlos < (MAX_MAPW * MAX_MAPH)); - assert(nlosdark < (MAX_MAPW * MAX_MAPH)); + assert(nlos < allocamt); + assert(nlosdark < allocamt); // now fill in lifeform structure if (nlos) { @@ -13483,7 +13513,8 @@ int push(lifeform_t *lf, object_t *o, int dir) { } touch(lf, o); - if (isplayer(lf)) addflag(lf->flags, F_MOVED, B_TRUE, NA, NA, NULL); + addflagifneeded(lf->flags, F_MOVED, B_TRUE, NA, NA, NULL); + addflagifneeded(lf->flags, F_TOOKACTION, B_TRUE, NA, NA, NULL); return B_FALSE; @@ -15188,6 +15219,9 @@ void startlfturn(lifeform_t *lf) { // clear one-turn-only flags killflagsofid(lf->flags, F_DONELISTEN); killflagsofid(lf->flags, F_NOSWAP); + killflagsofid(lf->flags, F_HASBEENMOVED); + killflagsofid(lf->flags, F_MOVED); + // update where player knows // (but without a map you will then slowly forget it) @@ -15347,8 +15381,8 @@ void startlfturn(lifeform_t *lf) { } if (lossamt) modstamina(lf, -lossamt); } else { - // if we didn't move last turn, regenerate stamina. - if (!killflagsofid(lf->flags, F_MOVED)) { + // if we didn't take action last turn, regenerate stamina. + if (!killflagsofid(lf->flags, F_TOOKACTION)) { if (getstamina(lf) < getmaxstamina(lf)) { modstamina(lf, getstamregen(lf)); } @@ -17216,6 +17250,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) { } } + /* if (isplayer(lf)) { statdirty = B_TRUE; needredraw = B_TRUE; @@ -17224,6 +17259,7 @@ int usestairs(lifeform_t *lf, object_t *o, int onpurpose, int climb) { //precalclos(lf); drawscreen(); } + */ return B_FALSE; } diff --git a/map.c b/map.c index 3b282c0..761eb67 100644 --- a/map.c +++ b/map.c @@ -63,6 +63,7 @@ cell_t *addcell(map_t *m, int x, int y) { cell->y = y; cell->habitat = m->habitat; cell->obpile = addobpile(NOOWNER, cell, NOOB); + cell->type = NULL; setcelltype(cell, cell->habitat->solidcelltype); cell->lf = NULL; cell->room = NULL; @@ -1523,6 +1524,7 @@ object_t *gettopobject(cell_t *where, int forglyph) { flag_t *f; // ignore hidden traps, but not secret doors if (hasflag(o->flags, F_SECRET) && !isdoor(o, NULL)) { + } else if (hasflag(o->flags, F_INVISOB)) { } else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) { } else if (forglyph && hasflag(o->flags, F_NOGLYPH)) { } else { @@ -1546,6 +1548,7 @@ object_t *gettopobject(cell_t *where, int forglyph) { for (o = where->obpile->last ; o ; o = o->prev) { if (o->type->obclass->id == sortorder[c]) { if (hasflag(o->flags, F_SECRET)) { + } else if (hasflag(o->flags, F_INVISOB)) { } else if (hasflag(o->flags, F_TRAIL) && !canseeob(player, o)) { } else if (forglyph && hasflag(o->flags, F_NOGLYPH)) { } else { @@ -1650,7 +1653,7 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int int nposs = 0; cell_t *cell; int sel; - int db = B_FALSE; + int db = B_TRUE; int foundvalid = B_FALSE; // init coords list @@ -1738,6 +1741,8 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int } else { score = 9999; } + } else { + if (db) dblog("cell %d,%d - a %dx%d room would not fit here",x,y,score,w,h); } coordscore[i] = score; if (db) dblog("cell %d,%d - score %d",x,y,score); @@ -1756,6 +1761,7 @@ int calcroompos(map_t *map, int w, int h, int xmargin, int ymargin, int *bx, int } if (nposs == 0) { + if (db) dblog("calcroompos - zero possibilities!"); *bx = -1; *by = -1; return B_TRUE; @@ -2413,9 +2419,6 @@ void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir, object_ case H_FOREST: createforest(map, depth, parentmap, exitdir, entryob, rnd(0,5)); break; - case H_SWAMP: - createswamp(map, depth, parentmap, exitdir, entryob); - break; case H_VILLAGE: createforest(map, depth, parentmap, exitdir, entryob, 0); break; @@ -2428,6 +2431,12 @@ void createhabitat(map_t *map, int depth, map_t *parentmap, int exitdir, object_ case H_SEWER: createsewer(map, depth, parentmap, exitdir, entryob); break; + case H_STOMACH: + createstomach(map, depth, parentmap, exitdir, entryob); + break; + case H_SWAMP: + createswamp(map, depth, parentmap, exitdir, entryob); + break; case H_ALL: dblog("ERROR - createhabitat with invalid habitat!"); msg("ERROR - createhabitat with invalid habitat!"); @@ -2929,7 +2938,7 @@ void createmap(map_t *map, int depth, region_t *region, map_t *parentmap, int ex object_t *o; c = getcellat(map, x, y); o = hasobwithflag(c->obpile, F_CLIMBABLE); - if (o && (o->type->id != OT_PORTAL) && !getstairdestination(o, NULL)) { + if (o && (o->type->id != OT_PORTAL) && !getstairdestination(o, NULL) && !hasflag(o->flags, F_MAPLINK)) { // this will join these stairs to existing ones on // existing adjacent maps if (!linkstairs(o, NULL)) { @@ -3251,6 +3260,45 @@ void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t } +void createstomach(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) { + vault_t *v; + int x,y; + + // fill entire maze with walls + for (y = 0; y < map->h; y++) { + for (x = 0; x < map->w; x++) { + addcell(map, x, y); + } + } + // add a random worm vault + v = findvaultwithflag(F_VAULTISSTOMACH); + assert(v); + if (createvault(map, map->nrooms, v, NULL, NULL, NULL, NULL)) { + dblog("ERROR - couldn't create stomach vault '%s' on map %s", v->id, map->name); + msg("ERROR - couldn't create stomach vault '%s' on map %s", v->id, map->name); + } + + // add an empty maplink to the exits - this will be filled in by OT_A_SWALLOW code in spell.c + // also stop acid from disappearing + for (y = 0; y < map->h; y++) { + for (x = 0; x < map->w; x++) { + cell_t *c; + object_t *o; + c = getcellat(map, x, y); + o = hasob(c->obpile, OT_STOMACHEXIT); + for (o = c->obpile->first ; o ; o = o->next) { + if (o->material->id == MT_ACID) { + killflagsofid(o->flags, F_OBHPDRAIN); + } + if (o->type->id == OT_STOMACHEXIT) { + killflagsofid(o->flags, F_MAPLINK); + addflag(o->flags, F_MAPLINK, parentmap->id, NA, NA, NULL); + } + } + } + } +} + void createswamp(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob) { int x,y; cell_t *c; @@ -4811,6 +4859,9 @@ char *getregionname(char *buf, map_t *m, int withlevel) { case RG_SEWER: snprintf(buf, BUFLEN, "a sewer L%d", m->depth); break; + case RG_STOMACH: + snprintf(buf, BUFLEN, "a stomach"); + break; } } else { switch (r->rtype->id) { @@ -4829,6 +4880,9 @@ char *getregionname(char *buf, map_t *m, int withlevel) { case RG_SEWER: snprintf(buf, BUFLEN, "a sewer"); break; + case RG_STOMACH: + snprintf(buf, BUFLEN, "a stomach"); + break; } } return buf; @@ -5219,12 +5273,14 @@ void initmap(void) { addhabitat(H_PIT, "pit", CT_CORRIDOR, CT_WALL, 0, 0, 0, 5); addhabitat(H_VILLAGE, "village", CT_GRASS, CT_WALL, 3, 70, 0, MAXVISRANGE); addhabitat(H_SEWER, "sewer", CT_CORRIDOR, CT_WALL, 5, 50, 0, MAXVISRANGE); + addhabitat(H_STOMACH, "stomach", CT_FLOORFLESH, CT_WALLFLESH, 5, 80, 0, MAXVISRANGE); addhabitat(H_SWAMP, "swamp", CT_CORRIDOR, CT_WALL, 3, 50, 0, MAXVISRANGE); // cell types - solid addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 100); addcelltype(CT_ROOMWALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 100); addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0, 50); + addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, B_SOLID, B_OPAQUE, MT_FLESH, 0, 50); addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0, 150); addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0, 200); // cell types - non-solid @@ -5232,6 +5288,7 @@ void initmap(void) { addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0, -1); addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0, -1); addcelltype(CT_FLOORWOOD, "wood floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0, -1); + addcelltype(CT_FLOORFLESH, "flesh floor", '.', C_RED, B_EMPTY, B_TRANS, MT_FLESH, 0, -1); addcelltype(CT_FLOORSHOP, "shop floor", '.', C_BROWN, B_EMPTY, B_TRANS, MT_WOOD, 0, -1); addcelltype(CT_ROOM, "rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, 0, -1); addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 0, -1); @@ -5245,6 +5302,7 @@ void initmap(void) { addregiontype(RG_HEAVEN, "Realm of Gods", H_HEAVEN, 1, 0, D_NONE, B_FALSE); addregiontype(RG_PIT, "Pit", H_PIT, 1, 1, D_DOWN, B_FALSE); addregiontype(RG_SEWER, "Sewer", H_SEWER, 1, 0, D_NONE, B_FALSE); + addregiontype(RG_STOMACH, "Stomach", H_STOMACH, 1, 0, D_NONE, B_FALSE); // MAPMAPMAPMAP // region definitions (outlines) @@ -6097,8 +6155,26 @@ void setcelltype(cell_t *cell, enum CELLTYPE id) { if (cell->type->solid) { assert(!cell->obpile->first); } - if ((gamemode == GM_GAMESTARTED) && haslos(player, cell)) { - needredraw = B_TRUE; + if (gamemode == GM_GAMESTARTED) { + + // digging out of a stomach + if (cell->map && + !cell->map->beingcreated && + !cell->type->solid && + (cell->map->habitat->id == H_STOMACH)) { + object_t *o,*exit; + cell_t *exitcell; + // find an existing exit to copy + exitcell = findobinmap(cell->map, OT_STOMACHEXIT); + exit = hasob(exitcell->obpile, OT_STOMACHEXIT); + assert(exit); + // add a new exit + o = addobfast(cell->obpile, OT_STOMACHEXIT); + copyflag(o->flags, exit->flags, F_MAPLINK); + } + if (haslos(player, cell)) { + needredraw = B_TRUE; + } } } diff --git a/map.h b/map.h index 1a5f98c..8e3d245 100644 --- a/map.h +++ b/map.h @@ -59,6 +59,7 @@ void createriver(map_t *m); void createroom(map_t *map, int roomid, int x1, int y1, int x2, int y2, int forcewalls); int calcposandmakeroom(map_t *map, int roomid, int overrideminw, int overrideminh, int xmargin, int ymargin, int *retx, int *rety, int *retw, int *reth, int doorpct, int forcewalls); void createsewer(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); +void createstomach(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); void createswamp(map_t *map, int depth, map_t *parentmap, int exitdir, object_t *entryob); int createvault(map_t *map, int roomid, vault_t *v, int *retw, int *reth, int *retx, int *rety); int dirtox(int dt, int dir); diff --git a/move.c b/move.c index 9c03ed3..0d4e6c3 100644 --- a/move.c +++ b/move.c @@ -1473,7 +1473,7 @@ int movelf(lifeform_t *lf, cell_t *newcell) { } } - if (preseenbyplayer && !cansee(player, lf)) { + if (preseenbyplayer && !cansee(player, lf) && !changedlev) { if (areenemies(player, lf)) { real_getlfnamea(lf, lfname, B_FALSE); msg("%s moves out of view.", lfname); @@ -1517,9 +1517,8 @@ int moveto(lifeform_t *lf, cell_t *newcell, int onpurpose, int dontclearmsg) { // this is the equivilant of losing the same amount of stamina which we // would regenerate, only it avoids constantly redrawing the status // bar every single move. - if (isplayer(lf)) { - addflag(lf->flags, F_MOVED, B_TRUE, NA, NA, NULL); - } + addflagifneeded(lf->flags, F_TOOKACTION, B_TRUE, NA, NA, NULL); + addflagifneeded(lf->flags, F_MOVED, B_TRUE, NA, NA, NULL); if (!onpurpose || !isplayer(lf)) { dontclearmsg = B_TRUE; @@ -2429,7 +2428,8 @@ void swapplaces(lifeform_t *lf1, lifeform_t *lf2, int changedir, int onpurpose) // remember that we just swapped, and this counts as a move if (!isplayer(lf1)) { if (!hasflag(lf1->flags, F_NOSWAP)) addflag(lf1->flags, F_NOSWAP, B_TRUE, NA, NA, NULL); - if (isplayer(lf1)) addflag(lf1->flags, F_MOVED, B_TRUE, NA, NA, NULL); + addflagifneeded(lf1->flags, F_MOVED, B_TRUE, NA, NA, NULL); + addflagifneeded(lf1->flags, F_TOOKACTION, B_TRUE, NA, NA, NULL); } } diff --git a/nexus.c b/nexus.c index a7d7bb5..5463639 100644 --- a/nexus.c +++ b/nexus.c @@ -242,6 +242,7 @@ int main(int argc, char **argv) { // make the initial level newworld = B_TRUE; + // create world map. wregion = addregion(RG_WORLDMAP, NULL, -1); assert(wregion); @@ -646,7 +647,7 @@ void checkendgame(void) { } void cleanup(void) { - + int i; gamemode = GM_CLEANUP; free(xpposs); @@ -675,8 +676,11 @@ void cleanup(void) { while (firstrace) killrace(firstrace); // free celltypes while (firstcelltype) killcelltype(firstcelltype); - // free npcnames - free(npcname); + for (i = 0; i < numnpcnames; i++) { + // free npcnames + free(npcname[i].name); + free(&npcname[i]); + } // free hidden names while (firsthiddenname) killhiddenname(firsthiddenname); //WriteMemLeak(); @@ -775,7 +779,6 @@ void donextturn(map_t *map) { sid = f->val[0]; power = f->val[1]; - // finished! p = f->text; p = readuntil(buf, p, ';'); @@ -927,8 +930,8 @@ void donextturn(map_t *map) { } } - // moved into a new map? stop turn. - if (who->cell->map != map) { + // us or the player moved into a new map? stop turn. + if ((who->cell->map != map) || (player->cell->map != map)) { break; } } diff --git a/objects.c b/objects.c index 2ea6de3..301bd59 100644 --- a/objects.c +++ b/objects.c @@ -520,7 +520,6 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes } } - // parse name string nsp = numstringmin; for (p = localname ; isdigit(*p) ; p++) { @@ -905,6 +904,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes // we now have the objecttype! //////////////////////////////////// + // don't put traps on top of stairs + if (hasflag(ot->flags, F_TRAP)) { + if (hasobwithflag(where, F_CLIMBABLE) || hasobwithflag(where, F_SHOP)) { + ot = findot(OT_BLOODSTAIN); + } + } if (gamemode != GM_LOADING) { if (hasflag(ot->flags, F_ONEPERCELL)) { @@ -2378,6 +2383,8 @@ int canseeob(lifeform_t *lf, object_t *o) { return B_TRUE; } + if (hasflag(o->flags, F_INVISOB)) return B_FALSE; + obloc = getoblocation(o); if (hasflag(o->flags, F_SECRET) && isplayer(lf)) { @@ -4946,7 +4953,7 @@ char *real_getobname(object_t *o, char *buf, int count, int wantpremods, int wan // show portal/stair destination f = hasflag(o->flags, F_MAPLINK); - if (f && f->known && !hasflag(o->flags, F_PIT)) { + if (f && f->known && !hasflag(o->flags, F_DONTSHOWDEST)) { cell_t *thiscell; map_t *thismap; map_t *newmap; @@ -6884,11 +6891,10 @@ void killmaterial(material_t *m) { void killob(object_t *o) { object_t *nextone, *lastone; - - dblog("killing object id %ld (%d x %s)", o->id, o->amt, o->type->name); - if (o->pile->where) { - dblog(" from cell %d,%d", o->pile->where->x, o->pile->where->y); - } + //dblog("killing object id %ld (%d x %s)", o->id, o->amt, o->type->name); + //if (o->pile->where) { + // dblog(" from cell %d,%d", o->pile->where->x, o->pile->where->y); + //} // debugging /* @@ -12012,6 +12018,18 @@ void timeeffectsob(object_t *o) { } } + if (location && !owner) { + lifeform_t *who; + who = location->lf; + if (who && !lfhasflag(who, F_HASBEENMOVED) && !lfhasflag(who, F_MOVED)) { + f = hasflag(o->flags, F_MOVELFS); + if (f) { + // move them + trymove(who, f->val[0], B_FALSE, B_TRUE); + addflag(who->flags, F_HASBEENMOVED, B_TRUE, NA, NA, NULL); + } + } + } if (location) { // object makes noise? @@ -12796,6 +12814,10 @@ int validateobs(void) { } f = hasflag(ot->flags, F_DAM); if (f) { + // automatically add in the missing altdam flags. + if (hasflag(ot->flags, F_ALTDAM) && !hasflagval(ot->flags, F_ALTDAM, f->val[0], NA, NA, NULL)) { + addflag(ot->flags, F_ALTDAM, f->val[0], f->val[1], f->val[2], f->text ); + } if (f->val[0] < 0) { printf("ERROR in object '%s' - F_DAM does not specify damage type.\n", ot->name); goterror = B_TRUE; diff --git a/spell.c b/spell.c index 0d8a560..6e85cae 100644 --- a/spell.c +++ b/spell.c @@ -1947,6 +1947,137 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef } } } + } else if (abilid == OT_A_SWALLOW) { + object_t *o = NULL,*nexto; + int nswallowed = 0,dodged = B_FALSE; + + if (!targcell) { + int dirch; + // ask which dir + dirch = askchar("Swallow in which direction (- to cancel)", "yuhjklbn-","-", B_FALSE, B_TRUE); + if ((dirch == '-') || !dirch) { + if (isplayer(user)) msg("Cancelled."); + return B_TRUE; + } else { + int dir; + dir = chartodir(dirch); + if (dir == D_NONE) { + if (isplayer(user)) msg("Cancelled."); + return B_TRUE; + } else { + targcell = getcellindir(user->cell, dir); + } + } + } + + // take some time + taketime(user, getactspeed(user)); + + for (o = targcell->obpile->first ; o ; o = nexto) { + nexto = o->next; + if (!hasflag(o->flags, F_NOPICKUP)) { + // TODO: move to new map instead? + killob(o); + nswallowed++; + } + } + + target = targcell->lf; + + if (target) { + if (skillcheck(target, SC_DODGE, 20, 0)) { + dodged = B_TRUE; + } + } + + + if (target) { + char targname[BUFLEN]; + getlfname(target, targname); + if (dodged) { + if (isplayer(user)) { + msg("^WYou try to swallow %s, but miss.", targname); + } else if (cansee(player, user) || isplayer(target)) { + msg("^W%s tries to swallow %s, but misses!", username, targname); + } + } else { + if (isplayer(user)) { + msg("^WYou swallow %s!", targname); + } else if (cansee(player, user) || isplayer(target)) { + msg("^W%s swallows %s!", username, targname); + } + } + } else { + if (isplayer(user)) { + msg("You swallow some %s!", (nswallowed || target) ? "objects" : "air"); + } else if (cansee(player, user)) { + msg("%s swallows some %s!", username, (nswallowed || target) ? "objects" : "air"); + } + } + + if (target) { + if (isplayer(user)) { + // just kill the target + killlf(target); + } else { + // move the target into the swallower's stomach + map_t *newmap; + cell_t *c,*entry; + flag_t *lflinkflag; + int x,y; + + + lflinkflag = hasflag(user->flags, F_MAPLINK); + if (lflinkflag) { + newmap = findmap(lflinkflag->val[0]); + } else { + region_t *r; + // create and move to new "worm" map. + // this map will be destroyed when you leave it. + r = findregionbytype(RG_STOMACH); + if (!r) { + r = addregion(RG_STOMACH, NULL, -1); + } + // create stomach map + newmap = addmap(); + createmap(newmap, 1, r, targcell->map, D_NONE, NULL); + addflag(newmap->flags, F_STOMACHOF, NA, NA, NA, username); + } + + // find a random empty cell here + entry = getrandomroomcell(newmap, ANYROOM); + while (!cellwalkable(target, entry, NULL)) { + entry = getrandomroomcell(newmap, ANYROOM); + } + + // link the map to this lf + if (!lflinkflag) { + addflag(user->flags, F_MAPLINK, newmap->id, NA, NA, NULL); + } + + // udpate the map's exits to go to where we were swallowed + for (y = 0; y < newmap->h; y++) { + for (x = 0; x < newmap->w; x++) { + c = getcellat(newmap, x, y); + o = hasob(c->obpile, OT_STOMACHEXIT); + if (o) { + killflagsofid(o->flags, F_MAPLINK); + addflag(o->flags, F_MAPLINK, targcell->map->id, targcell->x, targcell->y, NULL); + } + } + } + + if (isplayer(target)) { + // pause before moving... + more(); + } + + // move target close to entrypoint + movelf(target, entry); + // announce + announcearrival(target, target->cell->map); + } + } } else if (abilid == OT_A_SWOOP) { cell_t *adjcell = NULL,*origcell; char targetname[BUFLEN]; @@ -2505,6 +2636,58 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef f = addflag(user->flags, F_AIMEDSTRIKE, B_TRUE, NA, NA, NULL); attackcell(user, targcell, B_TRUE); killflag(f); + } else if (abilid == OT_A_ALTERATTACK) { + object_t *wep; + enum SKILLLEVEL slev = PR_INEPT; + char obname[BUFLEN],buf[BUFLEN]; + flag_t *retflag[MAXCANDIDATES],*damflag; + int nretflags,i; + char ch = 'a'; + enum DAMTYPE curdt = DT_NONE; + wep = getweapon(user); + if (wep) { + slev = getweaponskill(user, wep); + curdt = getdamtype(wep); + } else { + msg("You need to weild a weapon first!"); + return B_TRUE; + } + if (slev < PR_SKILLED) { + msg("You are not skilled enough with your weapon to do this!"); + return B_TRUE; + } + damflag = hasflag(wep->flags, F_DAM); + if (damflag) { + getflags(wep->flags, retflag, &nretflags, F_ALTDAM, F_NONE); + } else { + nretflags = 0; + } + if (!nretflags) { + msg("Your weapon is not capable of dealing any other damage type."); + return B_TRUE; + } + getobname(wep, obname, 1); + sprintf(buf, "Deal what kind of damage with your %s?", noprefix(obname)); + initprompt(&prompt, buf); + + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + sprintf(buf, "%s, DR %d", getdamname(f->val[0]), f->val[1]); + if (f->val[0] == curdt) { + strcat(buf, " (current)"); + } + addchoice(&prompt, ch++, buf, NULL, f, NULL); + } + ch = getchoice(&prompt); + f = (flag_t *)prompt.result; + if (f->val[0] == curdt) { + msg("Cancelled."); + } else { + // change dam type and amt + damflag->val[0] = f->val[0]; + damflag->val[1] = f->val[1]; + msg("Your %s will now deal %s damage.", noprefix(obname), getdamname(damflag->val[0])); + } } else if (abilid == OT_A_COMBOSTRIKE) { object_t *wep; skill_t *wepsk = NULL; @@ -3311,8 +3494,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ lifeform_t *newlf; newlf = makezombie(o); if (newlf) { - if (isplayer(target) && skillcheck(target, A_IQ, 20, power)) { - makefriendly(newlf, PERMENANT); + if (isplayer(target)){ + if (skillcheck(target, A_IQ, 20, power)) { + makefriendly(newlf, PERMENANT); + } else if (cansee(target, newlf)) { + msg("Uh oh, you have a bad feeling about this..."); + } } donesomething = B_TRUE; } @@ -3567,6 +3754,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ fizzle(caster); } } else if (spellid == OT_S_BLINK) { + cell_t *poss[MAXCANDIDATES]; + int nposs = 0,x,y; + if (lfhasflag(caster, F_CONTROL) && (power < 6)) { power = 6; } @@ -3575,12 +3765,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // must be within line of sight. if (!validatespellcell(caster, &targcell, TT_MONSTER, spellid, power, frompot)) return B_TRUE; if (!targcell || !cellwalkable(caster, targcell, NULL)) { - fizzle(caster); - return B_TRUE; + char ch; + ch = askchar("Teleport randomly?", "yn","n", B_TRUE, B_FALSE); + if (ch != 'y') { + fizzle(caster); + return B_TRUE; + } } - } else { - cell_t *poss[MAXCANDIDATES]; - int nposs = 0,x,y; + } + if (!targcell) { // pick a random location // only needs to be in line-of-FIRE, not neccesarily sight. for (y = 0 ; y <= caster->cell->map->h; y++) { @@ -3604,6 +3797,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } targcell = poss[rnd(0,nposs-1)]; } + teleportto(caster, targcell, B_TRUE); } else if (spellid == OT_S_BLINKASS) { target = targcell->lf; @@ -4627,7 +4821,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ ndigs = 0; - // get rid of rock in the cells... + // get rid of rock/flesh in the cells... c = getcellindir(caster->cell, dir); while (c && (ndigs <= power)) { int seenthiscell = B_FALSE; @@ -4635,8 +4829,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (haslos(player, c)) seenthiscell = B_TRUE; if (c->type->solid) { - // can dig through stone, but nothing else. - if (c->type->material->id == MT_STONE) { + if ((c->type->material->id == MT_STONE) || (c->type->material->id == MT_FLESH)) { setcelltype(c, c->map->habitat->emptycelltype); ndigs++; if (seenthiscell) { @@ -4844,7 +5037,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ object_t *o,*nexto; for (o = cell[i]->obpile->first ; o ; o = nexto) { nexto = o->next; - if (o->material->id == MT_WATER) { + if (getmaterialstate(o->material->id) == MS_LIQUID) { int cellseen = B_FALSE; if (haslos(player, cell[i])) { cellseen = B_TRUE; @@ -4866,7 +5059,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (nsteamseen) { msg("A huge cloud of steam appears!"); } else if (nseen) { - msg("Some nearby water evaporates!"); + msg("Some nearby liquid evaporates!"); } else { fizzle(caster); } @@ -7078,6 +7271,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("%s flicker%s then vanishes!",targname, isplayer(target) ? "" : "s"); if (seenbyplayer) *seenbyplayer = B_TRUE; } + breakaitargets(target, B_TRUE); } else if (spellid == OT_S_JOLT) { target = haslf(targcell); if (target) { @@ -7601,7 +7795,6 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // hack - make all monsters who can see you stop targetting you. // otherwise they will just try to go to your last known location. breakaitargets(caster, B_TRUE); - } else if (spellid == OT_S_MENDING) { object_t *o; int donesomething = B_FALSE; @@ -8003,12 +8196,18 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // now change them for (i = 0; i < howmany; i++) { lifeform_t *lf; + enum RACE rid; // pick a random one sel = rnd(0,nposs-1); c = poss[sel]; // turn it into a golem setcelltype(c, c->map->habitat->emptycelltype); - lf = summonmonster(caster, c, R_GOLEMSTONE, NULL, 30, B_TRUE); + if (power < 6) { + rid = R_PRIMALSTONEL; + } else { + rid = R_PRIMALSTONE; + } + lf = summonmonster(caster, c, R_PRIMALSTONE, NULL, 30, B_TRUE); if (haslos(player, c)) { if (seenbyplayer) *seenbyplayer = B_TRUE; nseen++; diff --git a/vault.c b/vault.c index bcdc8f1..e3ff838 100644 --- a/vault.c +++ b/vault.c @@ -521,14 +521,49 @@ vault_t *findvaultwithflag(enum FLAG fid) { return v; } +// generate vault map 1 as x-flipped map0. +// remember offsets into map[0] +void generatevaultflipsx(vault_t *v) { + int x,y; + v->map[1].mlen = 0; + for (y = 0 ; y < v->map[0].h; y++) { + for (x = v->map[0].w-1; x >= 0; x--) { + int offset; + getvaultchar(v, x, y, 0, &offset); + v->map[1].data[v->map[1].mlen] = offset; + v->map[1].mlen++; + } + } + + v->map[1].w = v->map[0].w; + v->map[1].h = v->map[0].h; + v->nmaps = 2; +} + +// generate vault map 1 as y-flipped map0. +// remember offsets into map[0] +void generatevaultflipsy(vault_t *v) { + int x,y; + v->map[1].mlen = 0; + for (y = v->map[0].h-1; y >= 0; y--) { + for (x = 0 ; x < v->map[0].w; x++) { + int offset; + getvaultchar(v, x, y, 0, &offset); + v->map[1].data[v->map[1].mlen] = offset; + v->map[1].mlen++; + } + } + + + v->map[1].w = v->map[0].w; + v->map[1].h = v->map[0].h; + v->nmaps = 2; +} + // generate vault maps 1-3 with offsets into map[0] void generatevaultrotations(vault_t *v) { int i; int x,y; - int db = B_FALSE; - if (streq(v->id, "jimbos_lair")) { - db = B_TRUE; - } for (i = 1; i <= 3; i++) { // rotate 90degrees from previous v->map[i].mlen = 0; @@ -1294,7 +1329,9 @@ int handleline(vault_t *v, char *line) { dblog("invalid margin flag: '%s'", line); } } else if (streq(line, "mayrotate")) { - if (v->nmaps == 1) { + if (hasflag(v->flags, F_VAULTMAYFLIPX) || hasflag(v->flags, F_VAULTMAYFLIPY)) { + dblog("vault can only have one of mayrotate / mayflipx / mayflipy."); + } else if (v->nmaps == 1) { addflag(v->flags, F_VAULTMAYROTATE, B_TRUE, NA, NA, NULL); // now generate rotated versions generatevaultrotations(v); @@ -1302,6 +1339,28 @@ int handleline(vault_t *v, char *line) { } else { dblog("vault flag mayrotate isnt valid for vaults with random maps."); } + } else if (streq(line, "mayflipx")) { + if (hasflag(v->flags, F_VAULTMAYROTATE) || hasflag(v->flags, F_VAULTMAYFLIPY)) { + dblog("vault can only have one of mayrotate / mayflipx / mayflipy."); + } else if (v->nmaps == 1) { + addflag(v->flags, F_VAULTMAYFLIPX, B_TRUE, NA, NA, NULL); + // now generate rotated versions + generatevaultflipsx(v); + ok = B_TRUE; + } else { + dblog("vault flag mayflipx isnt valid for vaults with random maps."); + } + } else if (streq(line, "mayflipy")) { + if (hasflag(v->flags, F_VAULTMAYROTATE) || hasflag(v->flags, F_VAULTMAYFLIPX)) { + dblog("vault can only have one of mayrotate / mayflipx / mayflipy."); + } else if (v->nmaps == 1) { + addflag(v->flags, F_VAULTMAYFLIPY, B_TRUE, NA, NA, NULL); + // now generate rotated versions + generatevaultflipsy(v); + ok = B_TRUE; + } else { + dblog("vault flag mayflipy isnt valid for vaults with random maps."); + } } else if (streq(line, "nolink")) { addflag(v->flags, F_VAULTNOLINK, B_TRUE, NA, NA, NULL); ok = B_TRUE; @@ -1349,6 +1408,9 @@ int handleline(vault_t *v, char *line) { } else if (streq(line, "shrine")) { // a godstone shrine addflag(v->flags, F_VAULTISSHRINE, B_TRUE, NA, NA, NULL); ok = B_TRUE; + } else if (streq(line, "stomach")) { + addflag(v->flags, F_VAULTISSTOMACH, B_TRUE, NA, NA, NULL); + ok = B_TRUE; } } } diff --git a/vault.h b/vault.h index 4700178..6941101 100644 --- a/vault.h +++ b/vault.h @@ -9,6 +9,8 @@ void dumpvault(char *name, int rotation); vault_t *findvault(char *id); vault_t *findvaultbyid(int id); vault_t *findvaultwithflag(enum FLAG fid); +void generatevaultflipsx(vault_t *v); +void generatevaultflipsy(vault_t *v); void generatevaultrotations(vault_t *v); void getadjustedcoords(vault_t *v, int origx, int origy, int minx, int miny, int maxx, int maxy, int rotation, int *retx, int *rety); void getboundingbox(int x1, int y1, int x2, int y2, int *retleft, int *rettop, int *retright, int *retbottom);