From c4215292217ad548ccb449639eed15e7844e43b2 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Sun, 15 Jul 2012 05:01:58 +0000 Subject: [PATCH] - [+] glorana doesn't like you attacking during Glorana's Peace - [+] make more shops let you donate - [+] bookstore - [+] jewellery store - [+] rename blood hawk to hunting hawk - [+] offering a bribe to creatures should make them move likely to helkp you, AND reset the "auto don't help' flag - [+] change "get lost " message to "get lost, " if your race is different. - [+] sayphrase() needs a new arg: lifeform_t *talkingto - [+] colours for spell effect. - [+] eg. "the flame dart hits xxx" should use CC_BAD - [+] muddy room - mud should be immutable. - [+] maybe change rage - you lose control totally and just attack anything in sight? - [+] do it. - [+] don't train when enraged - [+] don't hear sounds when enraged - [+] RAGE effects: strength bonus, accuracy bonus, infinite stamina, never flee, - [+] fix bug in skill point calculation - [+] CRASH - someone got their turn BEFORE the player! - [+] new poisontype field - contracttext - [+] hecta's pray effect not working. - [+] adjust food poisioning check difficulty based on food age - [+] check OBHP percentage of max. - [+] >= 80% obhp means -30% difficulty check - [+] ring of unholiness should confer dtvuln holy. - [+] fix colour on spellclouds - [+] fix bug with spellclouds not affecting centre cell. - [+] if you are frozen, heat does extra damage and cold does none. - [+] when frozen, lessen chance of melting. - [+] reduce bite damage of snakes - [+] balaclava should protect from gas - [+] make some floor types (like carpet) be multicoloured - [+] celltype->altcolour - [+] if altcolour is not C_NONE then use it where (x + y) % 2 is true. - [+] don't regain stamina while training - [+] random text in shops - sayphrase needs to cope with lf == null - [+] done - [+] fixed - hecta gifted me with a bamboo staff, but i'm inept with staves! - [+] BUG: in vault.vlt. - [+] "30% chance of door" really means "otherwise empty cell" - [+] need to be able to say "else put a wall here" - [+] so change: - [+] c:type:what[:pct] - [+] to this: - [+] c:type:what[:pct][:alttype:altwhat] - [+] vlegend_t needs - [+] enum VAULTTHING tt2 - [+] char *what2 - [+] they default to VT_NONE, NULL - [+] secret doors should take their fake wall type from the vault spec - [+] vaults need f_celltypeempty/solid flags - [+] add via: solid:xxx in vault def - [+] recycler - [+] donate anything --- ai.c | 153 ++++++++++++++------------ attack.c | 2 +- data.c | 88 +++++++++------ data.h | 2 +- data/hiscores.db | Bin 15360 -> 16384 bytes data/vaults/mudroom.vlt | 2 +- data/vaults/vault.vlt | 5 +- defs.h | 22 +++- doc/vaults.txt | 11 +- god.c | 49 ++++----- io.c | 84 +++++++++----- lf.c | 185 ++++++++++++++++++++++--------- lf.h | 5 +- map.c | 235 +++++++++++++++++++++++++--------------- map.h | 5 +- nexus.c | 24 +++- nexus.h | 2 +- objects.c | 110 +++++++++++-------- shops.c | 3 +- spell.c | 211 +++++++++++++++++++----------------- spell.h | 2 +- text.c | 14 +++ text.h | 1 + vault.c | 105 ++++++++++++++---- vault.h | 2 +- 25 files changed, 839 insertions(+), 483 deletions(-) diff --git a/ai.c b/ai.c index a7b2095..947a2c4 100644 --- a/ai.c +++ b/ai.c @@ -18,6 +18,7 @@ extern lifeform_t *player; extern enum ERROR reason; +extern int playerhasmoved; int wantdb = B_TRUE; @@ -113,9 +114,9 @@ int aiattack(lifeform_t *lf, lifeform_t *victim, int timelimit) { strcpy(text, "something"); } if (cansee(player, victim)) { - sayphrase(lf, SP_ALLY_ATTACK, SV_SHOUT, NA, text); + sayphrase(lf, SP_ALLY_ATTACK, SV_SHOUT, NA, text, victim); } else { - sayphrase(lf, SP_ALLY_ATTACKUNSEEN, SV_SHOUT, NA, text); + sayphrase(lf, SP_ALLY_ATTACKUNSEEN, SV_SHOUT, NA, text, victim); } } else { makenoise(lf, N_GETANGRY); @@ -804,7 +805,7 @@ int ai_attack_existing_target(lifeform_t *lf) { if (areallies(lf, player) && cantalk(lf)) { char text[BUFLEN]; real_getlfname(target, text, NULL, B_NOSHOWALL, B_CURRACE); - sayphrase(lf, SP_ALLY_TARGETKILL, SV_SHOUT, NA, text); + sayphrase(lf, SP_ALLY_TARGETKILL, SV_SHOUT, NA, text, target); } } else { // aquatic grabbers will try to drag their prey into the water @@ -832,7 +833,10 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) { lifeform_t *newtarget = NULL; flag_t *retflag[MAXCANDIDATES]; int nretflags = 0; - flag_t *f; + flag_t *f,*enraged; + + enraged = lfhasflag(lf, F_RAGE); + if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; // not attacking anyone in particular @@ -914,7 +918,7 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) { who->id, who->race->name); hateposs[nhateposs++] = who; } - } else if (lfhasflag(lf, F_HATESALL) || lfhasflag(lf, F_RAGE)) { + } else if (lfhasflag(lf, F_HATESALL) || enraged) { if (nhateposs < MAXCANDIDATES) { if (db) dblog(".oO { hate everything - found lfid %d (%s) ! }",who->id, who->race->name); hateposs[nhateposs++] = who; @@ -1004,50 +1008,52 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) { /////////////////////////////////////////////// // need to train skills? - if (readytotrain(lf)) { - if (safetorest(lf)) { + if (!enraged) { + if (readytotrain(lf) && safetorest(lf)) { // special case - monsters don't need to actually rest to gain // skills, although they DO still need to wait until the player // is out of sight. enhanceskills(lf); } - } - // do we have armour which needs repairing? - if (getskill(lf, SK_ARMOUR) >= PR_SKILLED) { - if (db) dblog(".oO { do i have any armour to repair? }"); - // just try to use the ability - it'll fail if we have nothing - // which we can repair. - if (!useability(lf, OT_A_REPAIR, NULL, NULL)) { - if (db) dblog(".oO { yes - done. }"); - // success - return B_TRUE; - } else { - if (db) dblog(".oO { no armour to repair. }"); + // do we have armour which needs repairing? + if (getskill(lf, SK_ARMOUR) >= PR_SKILLED) { + if (db) dblog(".oO { do i have any armour to repair? }"); + // just try to use the ability - it'll fail if we have nothing + // which we can repair. + if (!useability(lf, OT_A_REPAIR, NULL, NULL)) { + if (db) dblog(".oO { yes - done. }"); + // success + return B_TRUE; + } else { + if (db) dblog(".oO { no armour to repair. }"); + } } - } - // pet movement - note that pets will only rest if their - // master is resting. the normal rest code underneath this section - // will never be called. - if (master) { - //lifeform_t *master; - //master = findlf(lf->cell->map, mf->val[0]); - if (!aimovetolf(lf, master, B_FALSE)) { - // success - return B_TRUE; - } - } + // pet movement - note that pets will only rest if their + // master is resting. the normal rest code underneath this section + // will never be called. + if (master) { + //lifeform_t *master; + //master = findlf(lf->cell->map, mf->val[0]); + if (!aimovetolf(lf, master, B_FALSE)) { + // success + return B_TRUE; + } + } + } /////////////////////////////////////////////// // resting / healing /////////////////////////////////////////////// - // need to heal? - if (needstorest(lf, NULL) && safetorest(lf) && !hasflag(lf->flags, F_RAGE)) { - if (db) dblog(".oO { resting to heal }"); - rest(lf, B_TRUE); - return B_TRUE; + if (!enraged) { + // need to heal? + if (needstorest(lf, NULL) && safetorest(lf) && !hasflag(lf->flags, F_RAGE)) { + if (db) dblog(".oO { resting to heal }"); + rest(lf, B_TRUE); + return B_TRUE; + } } return B_FALSE; @@ -1141,6 +1147,7 @@ int ai_handle_emergencies(lifeform_t *lf, enum ATTRBRACKET iqb) { int ai_healing(lifeform_t *lf) { int db = B_FALSE; if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; + if (lfhasflag(lf, F_RAGE)) return B_FALSE; // special cases if ((lf->race->id == R_STIRGE) || (lf->race->id == R_LEECH)) { @@ -1160,43 +1167,41 @@ int ai_healing(lifeform_t *lf) { } } - if (!lfhasflag(lf, F_RAGE)) { - // feigning death with enemies in sight, and hurt? - if (lfhasflag(lf, F_FEIGNINGDEATH) && !safetorest(lf)) { - if (islowhp(lf)) { - if (db) dblog(".oO { i am feigning death and bleeding (hp=%d/%d), skipping turn. }",lf->hp,lf->maxhp); - // just wait... - rest(lf, B_TRUE); + // feigning death with enemies in sight, and hurt? + if (lfhasflag(lf, F_FEIGNINGDEATH) && !safetorest(lf)) { + if (islowhp(lf)) { + if (db) dblog(".oO { i am feigning death and bleeding (hp=%d/%d), skipping turn. }",lf->hp,lf->maxhp); + // just wait... + rest(lf, B_TRUE); + return B_TRUE; + } + } + + // hurt gods planeshift away + if (lf->race->raceclass->id == RC_GOD) { + if (gethppct(lf) <= 10) { + if (!castspell(lf, OT_S_PLANESHIFT, lf, NULL, lf->cell, NULL, NULL)) { return B_TRUE; } } + } - // hurt gods planeshift away - if (lf->race->raceclass->id == RC_GOD) { - if (gethppct(lf) <= 10) { - if (!castspell(lf, OT_S_PLANESHIFT, lf, NULL, lf->cell, NULL, NULL)) { - return B_TRUE; - } - } - } - - // need to heal? - if (lf->hp < (lf->maxhp/2)) { - if (!useitemwithflag(lf, F_AIHEALITEM)) { - return B_TRUE; - } else if (cansleep(lf)) { - // don't have or can't use our healing items - // no enemies in sight? - if (safetorest(lf)) { - // gods will only sleep/meditate if they are in the realm of gods - if (isgod(lf) && (lf->cell->habitat->id != H_HEAVEN)) { - } else { - // if it's "night time" for us, sleep forever. - // otehrwise just sleep until we're healed - if (!gotosleep(lf, issleepingtimefor(lf) ? B_TRUE : B_FALSE)) { - taketime(lf, getactspeed(lf)); // to make sure our turn ends - return B_TRUE; // success - } + // need to heal? + if (lf->hp < (lf->maxhp/2)) { + if (!useitemwithflag(lf, F_AIHEALITEM)) { + return B_TRUE; + } else if (cansleep(lf)) { + // don't have or can't use our healing items + // no enemies in sight? + if (safetorest(lf)) { + // gods will only sleep/meditate if they are in the realm of gods + if (isgod(lf) && (lf->cell->habitat->id != H_HEAVEN)) { + } else { + // if it's "night time" for us, sleep forever. + // otehrwise just sleep until we're healed + if (!gotosleep(lf, issleepingtimefor(lf) ? B_TRUE : B_FALSE)) { + taketime(lf, getactspeed(lf)); // to make sure our turn ends + return B_TRUE; // success } } } @@ -1283,7 +1288,7 @@ int ai_housekeeping(lifeform_t *lf, lifeform_t *master) { if (strlen(f->text)) { say(lf, f->text, vol); } else { - sayphrase(lf, f->val[0], vol, NA, NULL); + sayphrase(lf, f->val[0], vol, NA, NULL, NULL); } } } @@ -1473,6 +1478,7 @@ int ai_premovement(lifeform_t *lf) { int db = B_FALSE; int i; if (lfhasflag(lf, F_DEBUG)) db = B_TRUE; + if (lfhasflag(lf, F_RAGE)) return B_FALSE; // need light? if (!haslos(lf, lf->cell)) { @@ -2085,6 +2091,13 @@ void aiturn(lifeform_t *lf) { taketime(lf, SPEED_DEAD); return; } + // if game has just started and player hasn't had their turn yet, + // skip turn + if (!playerhasmoved) { + if (db) dblog(".oO { player hasn't had their initial turn yet, skipping turn. }"); + taketime(lf, SPEED_DEAD); + return; + } /////////////////////////////////////////// // info gathering diff --git a/attack.c b/attack.c index 6cd0af5..84f48e9 100644 --- a/attack.c +++ b/attack.c @@ -640,7 +640,7 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { killflagsofid(lf->flags, F_HIDING); if (saysorry && attacktarget) { - sayphrase(lf, SP_SORRY, -1, NA, NULL); + sayphrase(lf, SP_SORRY, -1, NA, NULL, attacktarget); } if (hasbleedinginjury(lf, BP_HANDS)) { diff --git a/data.c b/data.c index c1ccd92..b1a6c51 100644 --- a/data.c +++ b/data.c @@ -640,7 +640,7 @@ void initjobs(void) { // abilities addflag(lastjob->flags, F_OBESE, B_TRUE, NA, NA, NULL); addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); - addjob(J_NINJA, "Ninja", "A dark warrior dedicated to the art of ninjutsu. Ninjas are skilled with exotic weapons, and gain special martial arts abilities at higher levels."); + addjob(J_NINJA, "Ninja", "A dark warrior-assassin dedicated to the art of ninjutsu. Ninjas are skilled with exotic weapons, and gain special martial arts abilities at higher levels."); // stats addflag(lastjob->flags, F_JOBATTRMOD, A_STR, 5, NA, NULL); addflag(lastjob->flags, F_JOBATTRMOD, A_AGI, 5, NA, NULL); @@ -655,7 +655,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "balaclava"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "cloth trousers"); - addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "5 shurikens"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 shurikens"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "manriki"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "3 smoke grenades"); // shuriken @@ -1024,16 +1024,16 @@ void initobjects(void) { // init poison types - addpoisontype(P_MIGRAINE, "a migraine", "Sick", "", OT_NONE, 0, 0, PS_DISEASE,20); - addpoisontype(P_COLD, "hypothermia", "Sick", "^bYOU cough#S violently.", OT_NONE, 1, 25, PS_DISEASE, 30); - addpoisontype(P_FOOD, "gastroenteritis", "Poisoned", "^bYOU vomit#S violently.", OT_VOMITPOOL, 1, 25, PS_POISON,20); - addpoisontype(P_FOODBAD, "salmonella poisoning", "Poisoned", "^bYOU vomit#S violently.", OT_VOMITPOOL, 2, 33, PS_POISON, 30); - addpoisontype(P_GAS, "gas inhalation", "Poisoned", "^bYOU cough#S.", OT_NONE, 1, 25, PS_POISON,0); - addpoisontype(P_LYCANTHROPY, "lycanthropy", "Cursed", "", OT_NONE, 0, 0, PS_CURSE, -1); - addpoisontype(P_ROT, "the mummy's curse", "Cursed", "", OT_NONE, 0, 0, PS_CURSE, 0); - addpoisontype(P_TETANUS, "tetanus", "Sick", "^bYOUR muscles spasm violently!", OT_NONE, 0, 3, PS_DISEASE, 15); - addpoisontype(P_VENOM, "venom poisoning", "Poisoned", "^bYOU cough#S up blood.", OT_BLOODSPLASH, 1, 25, PS_POISON, 0); - addpoisontype(P_WEAKNESS, "weakening poison", "Poisoned", "cough", B_FALSE, 0, 0, PS_POISON, 0); + addpoisontype(P_MIGRAINE, "a migraine", "Sick", "have developed", "", OT_NONE, 0, 0, PS_DISEASE,20); + addpoisontype(P_COLD, "hypothermia", "Sick", "are sick with", "^bYOU cough#S violently.", OT_NONE, 1, 25, PS_DISEASE, 30); + addpoisontype(P_FOOD, "gastroenteritis", "Poisoned", "have contracted", "^bYOU vomit#S violently.", OT_VOMITPOOL, 1, 25, PS_POISON,30); + addpoisontype(P_FOODBAD, "salmonella poisoning", "Poisoned", "have contracted", "^bYOU vomit#S violently.", OT_VOMITPOOL, 2, 33, PS_POISON, 40); + addpoisontype(P_GAS, "gas inhalation", "Poisoned", "are sick with", "^bYOU cough#S.", OT_NONE, 1, 25, PS_POISON,0); + addpoisontype(P_LYCANTHROPY, "lycanthropy", "Cursed", "have been afflicted with", "", OT_NONE, 0, 0, PS_CURSE, -1); + addpoisontype(P_ROT, "the mummy's curse", "Cursed", "have been afflicated with", "", OT_NONE, 0, 0, PS_CURSE, 0); + addpoisontype(P_TETANUS, "tetanus", "Sick", "have contracted", "^bYOUR muscles spasm violently!", OT_NONE, 0, 3, PS_DISEASE, 15); + addpoisontype(P_VENOM, "venom poisoning", "Poisoned", "have been infected with", "^bYOU cough#S up blood.", OT_BLOODSPLASH, 1, 25, PS_POISON, 5); + addpoisontype(P_WEAKNESS, "weakening poison", "Poisoned", "have been infected with", "cough", B_FALSE, 0, 0, PS_POISON, 0); // generate hidden name text for (n = 0; strlen(colour[n].name); n++) { @@ -1823,7 +1823,7 @@ void initobjects(void) { addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_HASHIDDENNAME, NA, OC_SCROLL, NULL); addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_HASHIDDENNAME, NA, OC_BOOK, NULL); - make_basic_shop(lastot->flags, B_ALLOWID); + make_basic_shop(lastot->flags, B_ALLOWID, B_ALLOWDONATE); for (i = 0; i < 10; i++) { f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_BOOK, RANDOM, NULL); addcondition(f, FC_NOCONDITION, 33); @@ -1833,7 +1833,7 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); - make_basic_shop(lastot->flags, B_NOID); + make_basic_shop(lastot->flags, B_NOID, B_NODONATE); for (i = 0; i < 10; i++) { addflag(lastot->flags, F_STARTOBCLASS, 100, OC_FOOD, RANDOM, NULL); } @@ -1841,15 +1841,17 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); - make_basic_shop(lastot->flags, B_NOID); + make_basic_shop(lastot->flags, B_NOID, B_NODONATE); for (i = 0; i < 10; i++) { addflag(lastot->flags, F_STARTOBRND, 100, RANDOM, NA, NULL); } addot(OT_SHOPHARDWARE, "hardware store", "A small kiosk which sells tools and technology.", MT_METAL, 500, OC_BUILDING, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_UNCOMMON, NULL); + addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_HASHIDDENNAME, NA, OC_TOOLS, NULL); + addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_HASHIDDENNAME, NA, OC_TECH, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); - make_basic_shop(lastot->flags, B_NOID); + make_basic_shop(lastot->flags, B_NOID, B_ALLOWDONATE); for (i = 0; i < 10; i++) { f = addflag(lastot->flags, F_STARTOBCLASS, 100, OC_TOOLS, RANDOM, NULL); addcondition(f, FC_NOCONDITION, 50); @@ -1860,10 +1862,19 @@ void initobjects(void) { addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_DRINKABLE, NA, OC_POTION, NULL); addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); - make_basic_shop(lastot->flags, B_ALLOWID); + make_basic_shop(lastot->flags, B_ALLOWID, B_ALLOWDONATE); for (i = 0; i < 10; i++) { addflag(lastot->flags, F_STARTOBCLASS, 100, OC_POTION, RANDOM, NULL); } + addot(OT_SHOPRECYCLE, "recycling bay", "A small kiosk which accepts used goods.", MT_METAL, 500, OC_BUILDING, SZ_LARGE); + addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); + addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_COMMON, NULL); + addflag(lastot->flags, F_CONTAINER, B_TRUE, NA, NA, NULL); + addflag(lastot->flags, F_SHOPACCEPTSFLAG, F_RARITY, NA, NA, NULL); // ie. basically anything + addflag(lastot->flags, F_SHOPMENU, 0, MA_GOTOMENU, SM_DONATE, "d:donate something"); + addflag(lastot->flags, F_SHOPMENU, 1, MA_QUIT, NA, "q:leave"); + addflag(lastot->flags, F_MAKESNOISE, 33, 3, NA, "the clanking of metal."); + addot(OT_SHOPRING, "jewellery store", "A small kiosk dealing in rings and amulets.", MT_METAL, 500, OC_BUILDING, SZ_LARGE); addflag(lastot->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, ""); addflag(lastot->flags, F_RARITY, H_CAVE, NA, RR_VERYRARE, NULL); @@ -4804,7 +4815,7 @@ void initobjects(void) { addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addot(OT_A_REFLEXDODGE, "reflexive dodging", "Automatically use all remaining stamina to dodge fatal attacks.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); - addot(OT_A_RAGE, "rage", "Enter a state of berzerker rage, gaining attack and defence bonuses.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); + addot(OT_A_RAGE, "rage", "Enter a state of berzerker rage, losing conscious control but gaining attack and defence bonuses.", MT_NOTHING, 0, OC_ABILITY, SZ_TINY); addflag(lastot->flags, F_SPELLSCHOOL, SS_ABILITY, NA, NA, NULL); addflag(lastot->flags, F_AICASTTOATTACK, ST_ADJSELF, NA, NA, NULL); addflag(lastot->flags, F_STAMCOST, 5, NA, NA, NULL); @@ -5448,7 +5459,7 @@ void initobjects(void) { addflag(lastot->flags, F_RECHARGEWHENOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_DIECONVERT, 1, NA, NA, "cloud of smoke"); + addflag(lastot->flags, F_DIECONVERT, 1, DT_COMPASS, NA, "cloud of smoke"); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "explodes"); addflag(lastot->flags, F_DIECONVERTTEXTPL, NA, NA, NA, "explode"); addflag(lastot->flags, F_GRENADE, B_TRUE, NA, NA, NULL); @@ -5466,8 +5477,9 @@ void initobjects(void) { addflag(lastot->flags, F_RECHARGEWHENOFF, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_NOOBDIETEXT, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_SPELLCLOUDONDEATH, OT_S_SNAPFREEZE, 2, B_IFACTIVATED, "OB explodes in a cloud of freezing air!^Something explodes in a cloud of freezing air!^8"); - addflag(lastot->flags, F_SPELLCLOUDONDAM, OT_S_SNAPFREEZE, 2, B_IFACTIVATED, "8"); + addflag(lastot->flags, F_SPELLCLOUDONDEATH, OT_S_SNAPFREEZE, 1, B_IFACTIVATED, "OB explodes in a cloud of freezing air!^Something explodes in a cloud of freezing air!^8"); + addflag(lastot->flags, F_SPELLCLOUDONDAM, OT_S_SNAPFREEZE, 1, B_IFACTIVATED, "8"); + addflag(lastot->flags, F_SPELLCLOUDGLYPH, C_CYAN, UNI_SHADELIGHT, NA, NULL); addflag(lastot->flags, F_GRENADE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_TECHLEVEL, PR_BEGINNER, NA, NA, NULL); addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, NULL); @@ -6323,7 +6335,7 @@ void initobjects(void) { addot(OT_STEAMCLOUD, "cloud of steam", "A thick cloud of scalding steam.", MT_GAS, 0, OC_EFFECT, SZ_HUMAN); addflag(lastot->flags, F_GLYPH, C_WHITE, UNI_SHADEMED, NA, NULL); addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL); - addflag(lastot->flags, F_DIECONVERT, 1, NA, NA, "puff of steam"); + addflag(lastot->flags, F_DIECONVERT, 1, DT_ORTH, NA, "puff of steam"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); @@ -6376,7 +6388,7 @@ void initobjects(void) { addot(OT_SMOKECLOUD, "cloud of smoke", "A thick cloud of black smoke.", MT_GAS, 0, OC_EFFECT, SZ_LARGE); addflag(lastot->flags, F_GLYPH, C_GREY, UNI_SHADEMED, NA, NULL); addflag(lastot->flags, F_NODIECONVERTTEXT, NA, NA, NA, NULL); - addflag(lastot->flags, F_DIECONVERT, 1, NA, NA, "puff of smoke"); + addflag(lastot->flags, F_DIECONVERT, 1, DT_COMPASS, NA, "puff of smoke"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); @@ -6399,7 +6411,7 @@ void initobjects(void) { addot(OT_POISONCLOUD, "cloud of poison gas", "A thick cloud of poisonous gas.", MT_GAS, 0, OC_EFFECT, SZ_LARGE); addflag(lastot->flags, F_GLYPH, C_GREEN, UNI_SHADEMED, NA, NULL); addflag(lastot->flags, F_DIECONVERTTEXT, NA, NA, NA, "thins out a little"); - addflag(lastot->flags, F_DIECONVERT, 1, NA, NA, "puff of gas"); + addflag(lastot->flags, F_DIECONVERT, 1, DT_COMPASS, NA, "puff of gas"); addflag(lastot->flags, F_OBHP, 3, 3, NA, NULL); addflag(lastot->flags, F_OBHPDRAIN, 1, NA, NA, NULL); addflag(lastot->flags, F_NOOBDAMTEXT, B_TRUE, NA, NA, NULL); @@ -6874,7 +6886,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_SCARY, 2, NA, NA, NULL); addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); - addot(OT_BALACLAVA, "balaclava", "A form of cloth headgear that covers the whole head, exposing only the eyes.", MT_CLOTH, 1, OC_ARMOUR, SZ_SMALL); + addot(OT_BALACLAVA, "balaclava", "A form of cloth headgear that covers the whole head, exposing only the eyes. While it does not give much protection, its cloth will filter out poisonous particles.", MT_CLOTH, 1, OC_ARMOUR, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_UNCOMMON, NULL); addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL); @@ -6882,6 +6894,7 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 10, 10, NA, NULL); addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_ANONYMOUS, NA, NA, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_POISONGAS, NA, NULL); addflag(lastot->flags, F_STARTSPLAIN, B_TRUE, NA, NA, NULL); addot(OT_CAP, "cap", "Close-fitting headwear with a short shade visor at the front.", MT_CLOTH, 1, OC_ARMOUR, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_COMMON, NULL); @@ -6900,10 +6913,10 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 5, 5, NA, NULL); addflag(lastot->flags, F_NOQUALITY, B_TRUE, NA, NA, NULL); addflag(lastot->flags, F_STARTSPLAIN, B_TRUE, NA, NA, NULL); - addot(OT_GASMASK, "gas mask", "A full face mask which protects the wearer from toxic gasses.", MT_RUBBER, 3.5, OC_ARMOUR, SZ_SMALL); + addot(OT_GASMASK, "gas mask", "A full face and neck mask which protects the wearer from both head damage and toxic gasses.", MT_RUBBER, 3.5, OC_ARMOUR, SZ_SMALL); addflag(lastot->flags, F_RARITY, H_ALL, 75, RR_UNCOMMON, NULL); addflag(lastot->flags, F_GOESON, BP_HEAD, NA, NA, NULL); - addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); + addflag(lastot->flags, F_ARMOURRATING, 3, NA, NA, NULL); addflag(lastot->flags, F_ACCURACYMOD, -10, NA, NA, NULL); addflag(lastot->flags, F_OBHP, 30, 30, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_POISONGAS, NA, NULL); @@ -7277,6 +7290,7 @@ void initobjects(void) { addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_POISONGAS, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_DECAY, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DTIMMUNE, DT_NECROTIC, NA, NULL); + addflag(lastot->flags, F_EQUIPCONFER, F_DTVULN, DT_HOLY, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_BREATHWATER, B_TRUE, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_NIGHTBOOST, 15, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_DAYBOOST, -15, NA, NULL); @@ -12039,7 +12053,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTJOB, 20, J_DEMONOLOGIST, NA, NULL); addflag(lastrace->flags, F_STARTJOB, 20, J_SHAMAN, NA, NULL); - addrace(R_ORCN, "norc", 90, 'o', C_BLUE, MT_FLESH, RC_HUMANOID, "While all orcs prefer the darkness, night orcs (or 'norcs') can actually _create_ it, spewing darkness from their bodies and blotting out all that is good and holy."); + addrace(R_ORCN, "night orc", 90, 'o', C_BLUE, MT_FLESH, RC_HUMANOID, "While all orcs prefer the darkness, night orcs (or 'norcs') can actually _create_ it, spewing darkness from their bodies and blotting out all that is good and holy."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -12107,7 +12121,7 @@ void initrace(void) { addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 5, NA, NA, NULL); - addrace(R_ORCB, "borc", 90, 'o', C_RED, MT_FLESH, RC_HUMANOID, "Blood orcs (or 'borcs') are larger and more muscled than standard orcs. When they enter a state of blood rage, they are feared even by their own kind."); + addrace(R_ORCB, "blood orc", 90, 'o', C_RED, MT_FLESH, RC_HUMANOID, "Blood orcs (or 'borcs') are larger and more muscled than standard orcs. When they enter a state of blood rage, they are feared even by their own kind."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -12136,7 +12150,7 @@ void initrace(void) { addflag(lastrace->flags, F_NOCTURNAL, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_MORALE, 9, NA, NA, NULL); - addrace(R_ORCGRAND, "grorc", 120, 'o', C_MAGENTA, MT_FLESH, RC_HUMANOID, "Even more powerful than blood orcs, grand orcs (or 'grorcs') are both extremely rare and extremely powerful."); + addrace(R_ORCGRAND, "grand orc", 120, 'o', C_MAGENTA, MT_FLESH, RC_HUMANOID, "Even more powerful than blood orcs, grand orcs (or 'grorcs') are both extremely rare and extremely powerful."); setbodytype(lastrace, BT_HUMANOID); addflag(lastrace->flags, F_ALIGNMENT, AL_EVIL, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); @@ -14453,7 +14467,7 @@ void initrace(void) { addflag(lastrace->flags, F_AVIAN, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_CANEATRAW, B_TRUE, NA, NA, NULL); - addrace(R_HAWKBLOOD, "blood hawk", 1, 'A', C_RED, MT_FLESH, RC_ANIMAL, "A stronger version of a hawk."); // 'A' for Avian + addrace(R_HAWKBLOOD, "trained hawk", 1, 'A', C_RED, MT_FLESH, RC_ANIMAL, "Once ordinary hawk, these creatures have been battle-hardened through regular combat."); // 'A' for Avian setbodytype(lastrace, BT_BIRD); lastrace->baseid = R_HAWK; addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL); @@ -14960,7 +14974,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 2, NA, NA, NULL); addflag(lastrace->flags, F_TR, 3, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL); addflag(lastrace->flags, F_HITCONFER, F_POISONED, SC_POISON, 20, "5-10"); addflag(lastrace->flags, F_HITCONFERVALS, P_VENOM, 1, NA, NULL); addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); @@ -14992,7 +15006,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 1, NA, NA, NULL); addflag(lastrace->flags, F_TR, 1, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 4, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 1, NA, NULL); addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); @@ -15020,7 +15034,7 @@ void initrace(void) { addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, ""); addflag(lastrace->flags, F_HITDICE, 3, NA, NA, NULL); addflag(lastrace->flags, F_TR, 3, NA, NA, NULL); - addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 5, NA, NULL); + addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 3, NA, NULL); addflag(lastrace->flags, F_NOPACK, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_NOSPELLS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_COLD, NA, NA, NULL); @@ -16252,6 +16266,7 @@ void initrace(void) { addflag(lastrace->flags, F_RARITY, H_SWAMP, NA, RR_COMMON, NULL); addflag(lastrace->flags, F_RARITY, H_ANTNEST, NA, RR_UNCOMMON, NULL); addflag(lastrace->flags, F_INSECT, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_LOTSOFLEGS, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_STR, AT_LTAVERAGE, NA, NULL); addflag(lastrace->flags, F_STARTATT, A_IQ, IQ_ANIMAL, NA, NULL); @@ -18061,9 +18076,12 @@ void killcommand(command_t *cmd) { } } -void make_basic_shop(flagpile_t *fp, int includeid) { +void make_basic_shop(flagpile_t *fp, int includeid, int includedonate) { int idx = 0; addflag(fp, F_SHOPMENU, idx++, MA_GOTOMENU, SM_PURCHASEITEMS, "a:buy something"); + if (includedonate) { + addflag(fp, F_SHOPMENU, idx++, MA_GOTOMENU, SM_DONATE, "d:donate equipment"); + } if (includeid) { addflag(fp, F_SHOPMENU, idx++, MA_GOTOMENU, SM_ID, "i:inspect items"); } diff --git a/data.h b/data.h index a799525..ab71b4a 100644 --- a/data.h +++ b/data.h @@ -14,5 +14,5 @@ void initskills(void); void killbehaviour(behaviour_t *b); void killcommand(command_t *cmd); void killoption(option_t *o); -void make_basic_shop(flagpile_t *fp, int includeid); +void make_basic_shop(flagpile_t *fp, int includeid, int includedonate); void sortcommands(void); diff --git a/data/hiscores.db b/data/hiscores.db index ed6cdccfb4e7bd1a9eecb5e199152aefed0a00c6..df1b0b29625cd37957f43bddfbf70f8dbc81fbb6 100644 GIT binary patch delta 682 zcmZ`!T}YEr7(VBH=l;I=JIS>bE}5{Oi)PI+O{u%==VAp)jG(sVmh|oWbknelbbU#5 z5!HI32o&okq|lU4jHD>Yf-D-A-AP^4O?BmMdC}Pn?>Yyb_wc;W`<(a559jmzrmHf} zHcyQxe9rqD0oQbo;TcA?jG(Htgg}#aLZGA_5@^x(3$$JuvBCyB!>?QL56PkZ9OhvJdtebyf)T&L1}+u`=IN?M z1Fn$GI%BLr23)3>)(#_HV@BRjAf4hFN=R3@NqyDavT}*%HZ?ib8Y>BZYAy;@28b!)ixD%83n0ADw^mywe zP)+;9t&rh>#Kssaat|Nlt3s&4TWmxb7X%#=c8nd@l12u0-{?UtBOZc@GHwqHRcF=2 z(eo|z)!tC0xOlY&hanr`o= z=)PHc-FAe$ZBhCViP3PRM>?#@rK#4WD^0=126}3jDh9KvEYq>Dt9Ek>drRD8`{#Kv z>@+B9Hc6eWrM6Q3GHqHdxA)MP&r6TOwYG8?0l0wixq;76$X~APE+rZDZzXZm^$(>| VZZ+lZSNn3R;!ekNTWS7l{TEGbx|RR{ delta 594 zcmYk2Pe@d85Xa}w`rLp1$yM_ow1tB1Mj2YU5_KrDP{aP2nV`FGmrW9%KCM(jci$m8 zM5PniK{2C)1j@#f0x|4Tp;2Llr=UYYR2RKghkkWx20nb5VZOsmB7up4Tg4fT@LxPC z|H*`R?NY}gpGvaoWLh1H=~j!P$2zL$vJNP^lf!OWfGFN@@h?vC1ov|d7ctRq`c7Zy z9lfAAnxQ*nQWtelD^*esX;SIbu}#LDfgJvfEBuirXr6|-S>?iL@4Q@dSp@6ib$XYPGk8Uw*&Ax}HjNyKv%qw>vDoa=%qfGLdQJ^Vp8xr)#8q+Q@m5dp|b=6lEX zqKFD2D8 z(o=XlPrd6HkS}PQv(Ba~u{+6|UQ4)av;DRD3h5a*0B#rn%BD7&W#T4I;d3m9H>x-S zJJdM92}{@1XvK)q$CcP+V8S#a4VS9?2L~gD8TX&mjf-YHcGxtAV%`48pg-*I)MNh3 zX1KForYrJfxwcu1+E&?8+vHO&jeqS7B@O}lD%z{$LUjp8jksXYCrbgRdernH#>)hx(5A`SlE>HykaR0rTze;51tPI diff --git a/data/vaults/mudroom.vlt b/data/vaults/mudroom.vlt index 8c66b4c..bdd8a42 100644 --- a/data/vaults/mudroom.vlt +++ b/data/vaults/mudroom.vlt @@ -13,7 +13,7 @@ autopop entertext:It seems very muddy here! goesin:dungeon ! add mud to 50% of room cells -scatter(1,1,-2,-2) ob:pool of mud:50% +scatter(1,1,-2,-2) ob:immutable pool of mud:50% rarity:uncommon @end diff --git a/data/vaults/vault.vlt b/data/vaults/vault.vlt index f6b1ee5..8b8b503 100644 --- a/data/vaults/vault.vlt +++ b/data/vaults/vault.vlt @@ -11,15 +11,16 @@ #:cell:duranite wall $:ob:25-200 gold ! 30% chance of a door on each side -+:ob:secret locked iron door:30 ++:ob:secret locked iron door:30:cell:duranite wall @end @flags +cellsolid:duranite wall goesin:dungeon mayrotate rarity:vrare ! don't link to rest of map. ie this can be in the middle of nowhere. -nolink +! nolink maintainedge @end diff --git a/defs.h b/defs.h index f51032a..546cb49 100644 --- a/defs.h +++ b/defs.h @@ -84,10 +84,16 @@ #define B_ALLOWID (-1) #define B_NOID (0) +#define B_ALLOWDONATE (-1) +#define B_NODONATE (0) + #define B_ONLYIFARMED (-1) #define B_INCLUDEDISTANT (-1) #define B_NODISTANT (0) +#define B_INCLUDECENTRE (-1) +#define B_NOCENTRE (0) + #define B_MAYCHASE (-1) #define B_NOCHASE (0) #define B_ONLYEXTERNAL (-1) @@ -1413,6 +1419,7 @@ enum OBTYPE { OT_SHOPGENERAL, OT_SHOPHARDWARE, OT_SHOPPOTION, + OT_SHOPRECYCLE, OT_SHOPRING, OT_SHOPWEAPON, OT_TEMPLE, @@ -2464,6 +2471,7 @@ enum FLAG { F_NEWWATERDEPTH, // temp flag for the spread of f_deepwater obs. // v0+1 are x/y, v2 is new depth. F_STOMACHOF, // this map is the stomach of lf id V0, name = f->text + // map or vault flags F_CELLTYPESOLID, // use celltype v0 for solid cells (walls) F_CELLTYPEEMPTY, // use celltype v0 for empty cells (corridors/rooms) // object flags @@ -2590,8 +2598,9 @@ enum FLAG { F_DIECONVERTTEXT, // text when the object converts. eg. "melts" F_DIECONVERTTEXTPL, // text when the object converts, if there are more than 1. eg. "melt" F_DIECONVERT, // text = what this turns into when dying - // v0 = radius to scatter new object in (0 or NA means - // just convert the object) + // v0 = radius to scatter new object in + // (0 or NA means just convert the object) + // v1 = dirtype for radius F_NOBLESS, // can't be blessed or cursed F_NOQUALITY, // can't be masterwork / shoddy F_NOSTEAL, // this object can't be stolen, blown away, etc. @@ -2661,6 +2670,8 @@ enum FLAG { F_SPELLCLOUDONDAM, // cast spell v0 in radius v1 upon damage. // v2 = ifactivated // text = "seebuf^noseebuf^spell_power" + F_SPELLCLOUDGLYPH, // v0 = enum COLOUR of the cloud + // v1 = glyph char F_LASTDAMTYPE, // object equivilant of lf->lastdamtype F_SCROLLNEEDSOB, // this scroll targets an object // v0 = B_ALWAYS (always targets an ob) @@ -3473,6 +3484,7 @@ enum FLAG { // -1 means always change on full moon. F_UNDEAD, // this race is classed as undead F_COLDBLOOD, // this race is coldblooded + F_LOTSOFLEGS, // this race is centipede-like - heaps of legs F_NOBODYPART, // this race doesn't have bodypart val0 // if v0 is true or b_frominjury, you can regrow it // via a healing potion. @@ -4235,6 +4247,7 @@ typedef struct poisontype_s { enum POISONTYPE id; char *name; char *desc; + char *contracttext; char *damverb; // can use macros: YOU YOUR and #S enum OBTYPE vomitob; int dam; @@ -4320,7 +4333,9 @@ enum VAULTTHING { typedef struct vlegend_s { char ch; enum VAULTTHING tt; + enum VAULTTHING tt2; char *what; + char *what2; int pct; struct vault_s *vault; struct vlegend_s *next, *prev; @@ -4389,6 +4404,8 @@ typedef struct cell_s { int littimer; int hp; + char *reason; + char *writing; int writinglifetime; @@ -4414,6 +4431,7 @@ typedef struct celltype_s { char glyph; // how to display it int colour; // which colour? */ + int altcol; char *name; // name of cell type int solid; // can you walk through it? int transparent; // can you see through it? diff --git a/doc/vaults.txt b/doc/vaults.txt index d179581..16eee9b 100644 --- a/doc/vaults.txt +++ b/doc/vaults.txt @@ -18,15 +18,19 @@ General format: @end Legend is: - c:type:what[:pct] + c:type:what[:pct][:alttype:altwhat] OR c:exit (denotes an exit, for use by linkexits) - + + if pct chance fails, use alttype & altwhat to determine + what to place. c = any letter type = ob, mon or cell pct = optional pct chance of appearing what = text of what this letter represents + alttype = optional ob/mon/cell if pct chance fails + altwhat = optional text of what it represents if pct chance fails Flags can be: at(x,y) type:what[:pct] // put what at position x,y @@ -42,6 +46,9 @@ Flags can be: fill(x,y,x2,y2) type:what[:pct] // filled box with what coords can be negative ("count back from right/bottom") + cellempty:xxx // set empty cell type. eg. "dirt" + cellsolid:xxx // set solid cell type. eg. "brick wall" + scatter(x,y,x2,y2) type:what:howmany[:pct] // scatter what within region howmany can be: - a number (x) diff --git a/god.c b/god.c index 4f129c2..56351d7 100644 --- a/god.c +++ b/god.c @@ -953,7 +953,7 @@ int godgiftmaybe(enum RACE rid, int fromtemple) { break; */ case 2: - snprintf(obtogive, BUFLEN, "cursed branded weapon"); + snprintf(obtogive, BUFLEN, "cursed appropriate branded weapon"); break; case 3: // poison your weapon wep = getweapon(player); @@ -1991,41 +1991,34 @@ int prayto(lifeform_t *lf, lifeform_t *god) { break; case R_GODDEATH: msg("\"Behold, the power of death!\""); - c = NULL; n = OT_NONE; switch (rnd(0,1)) { case 0: n = OT_S_FLAYFLESH; break; - case 1: n = OT_S_HECTASSERVANT; - c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); - break; + case 1: n = OT_S_HECTASSERVANT; break; } - if (n == OT_S_HECTASSERVANT) { - if (c) { - castspell(god, n, player, NULL, c, NULL, NULL); - n = OT_NONE; - } else { - n = OT_S_DRAINLIFE; - } - } - if (n != OT_NONE) { - // kill first lifeform in sight. - for (i = 1; i < lf->nlos; i++) { - lifeform_t *who; - who = lf->los[i]->lf; - if (who && !areallies(lf, who)) { - if (isundead(who)) { - makepeaceful(who, god); - } else if (gettr(who) <= 5) { - // instakill - who->lastdamtype = DT_NECROTIC; - setlastdam(who, "Hecta's finger of death."); - who->hp = 0; + for (i = 1; i < lf->nlos; i++) { + lifeform_t *who; + who = lf->los[i]->lf; + if (who && !areallies(lf, who)) { + if (isundead(who)) { + makepeaceful(who, god); + } else if (gettr(who) <= 5) { + // instakill + who->lastdamtype = DT_NECROTIC; + setlastdam(who, "Hecta's finger of death."); + who->hp = 0; + } else if (n != OT_NONE) { + if (n == OT_S_HECTASSERVANT) { + c = getrandomadjcell(player->cell, WE_WALKABLE, B_ALLOWEXPAND); + if (c) { + castspell(god, n, player, NULL, c, NULL, NULL); + } + n = OT_S_DRAINLIFE; } else { - //castspell(god, n, who, NULL, who->cell, NULL, NULL); dospelleffects(god, n, 20, who, NULL, who->cell, B_UNCURSED, NULL, B_FALSE, NULL); - break; } + break; } } } diff --git a/io.c b/io.c index d963a62..662174d 100644 --- a/io.c +++ b/io.c @@ -1318,7 +1318,7 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { switch (f->id) { case F_AICONTROLLED: if (isplayer(lf)) { - msg("^%cYou lose control of your body!", getlfcol(lf, CC_VBAD)); + msg("^%cYou lose control of your body!", getlfcol(lf, CC_VBAD)); more(); donesomething = B_TRUE; } break; @@ -1698,11 +1698,14 @@ int announceflaggain(lifeform_t *lf, flag_t *f) { case F_POISONED: pt = findpoisontype(f->val[0]); if (isplayer(lf)) { - if (streq(pt->desc, "Sick") || (pt->id == P_FOOD) || (pt->id == P_FOODBAD)) { + /* + if ((pt->id == P_FOOD) || (pt->id == P_FOODBAD)) { msg("^%cYou are sick with %s.", getlfcol(lf, CC_VBAD), pt->name); } else { - msg("^%cYou have contracted %s.", getlfcol(lf, CC_VBAD), pt->name); + msg("^%cYou %s %s.", getlfcol(lf, CC_VBAD), pt->contracttext, pt->name); } + */ + msg("^%cYou %s %s.", getlfcol(lf, CC_VBAD), pt->contracttext, pt->name); more(); } else { msg("^%c%s looks very sick.", getlfcol(lf, CC_VBAD), lfname); @@ -4451,7 +4454,7 @@ void docomms(lifeform_t *lf) { if (!countmoney(lf->pack)) { i = rnd(1,100); if (i <= 5) { // attack you - sayphrase(lf, SP_BEGATTACK, SV_SHOUT, NA, NULL); + sayphrase(lf, SP_BEGATTACK, SV_SHOUT, NA, NULL, player); fightback(lf, player); } else if (i <= 10) { // limited wish // change to a god. @@ -4466,7 +4469,7 @@ void docomms(lifeform_t *lf) { } else if (i <= 20) { // identify object_t *poss[MAXPILEOBS],*o; int nposs = 0; - sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL); + sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL, player); // get random unknown item from player's pack for (o = player->pack->first ; o ; o = o->next){ if (!isknown(o)) { @@ -4486,11 +4489,11 @@ void docomms(lifeform_t *lf) { msg("%s %s.", OB1(o, "It's", "They're"), newobname); } } else { // nothing - sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL); + sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL, player); } } else { // they already had some money - sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL); + sayphrase(lf, SP_BEGTHANKS, SV_TALK, NA, NULL, player); } pleasegodmaybe(R_GODPURITY, 10); pleasegodmaybe(R_GODMERCY, 20); @@ -4508,21 +4511,22 @@ void docomms(lifeform_t *lf) { } else { // not giving money to a begger enum ATTRBRACKET iqb; + int mod = 0; + int wanted = B_FALSE, covetted = B_FALSE; iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL); - // chance of calming hostile intelligen, monsters + mod = getoboffermod(givenob,lf, NULL); + wanted = aiwants(lf, givenob, &covetted); + // only get speech bonus if humanoid (ie they can understand you) + if (!cantalk(lf)) { + // this will counteract the bonus given in skillcheck() + mod -= (getskill(player, SK_SPEECH)*2); + } + + // chance of calming hostile intelligent, monsters if ((getallegiance(lf) == AL_HOSTILE) && (iqb >= IQ_ANIMAL) && cansee(lf, player)) { - int mod = 0; - mod = getoboffermod(givenob,lf, NULL); - - // only get speech bonus if humanoid (ie they can understand you) - if (!cantalk(lf)) { - // this will counteract the bonus given in skillcheck() - mod -= (getskill(player, SK_SPEECH)*2); - } - if (skillcheckvs(player, SC_SPEECH, mod, lf, SC_SPEECH, 0)) { // if humanoid+intelligent, say thanks. - if (cantalk(lf)) sayphrase(lf, SP_THANKS, SV_TALK, NA, NULL); + if (cantalk(lf)) sayphrase(lf, SP_THANKS, SV_TALK, NA, NULL, player); // calm down makepeaceful(lf, player); // chance of becoming a pet if you gave something other than @@ -4536,20 +4540,48 @@ void docomms(lifeform_t *lf) { if (lf->race->raceclass->id == RC_HUMANOID) { p = assignnpcname(lf->flags); } - sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p); + sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p, player); } } pleasegodmaybe(R_GODTHIEVES, 10); } - } else { - // yumi always likes giving things away, as long as - // don't keep any for yourself. - if (count == givenob->amt) { - pleasegodmaybe(R_GODMERCY, 2); - } + } + } else if (wanted) { // if they WEREN'T hostile and liked the offer + int min = 70,max = 90; + if (covetted) { + min = 50; + max = 70; } + // reset rejected information offers + killflagsofid(lf->flags, F_NOINFO); + killflagsofid(lf->flags, F_NOHIRE); + f = lfhasflag(lf, F_INFOPRICE); + if (f) { + int newval; + // reduce asking price + newval = pctof(rnd(min,max),f->val[0]); + limit(&newval, 1, NA); + f->val[0] = newval; + } + f = lfhasflag(lf, F_HIREPRICE); + if (f) { + int newval; + // reduce asking price + newval = pctof(rnd(min,max),f->val[0]); + limit(&newval, 1, NA); + f->val[0] = newval; + } + // if humanoid+intelligent, say thanks. + if (cantalk(lf)) sayphrase(lf, SP_THANKS, SV_TALK, NA, NULL, player); } } + + // yumi always likes giving things away, as long as + // don't keep any for yourself. + if (count == givenob->amt) { + pleasegodmaybe(R_GODMERCY, 2); + } + } // end if givenob break; @@ -4620,7 +4652,7 @@ void docomms(lifeform_t *lf) { !isundead(lf)) { if (skillcheck(player, SC_SPEECH, 30, alignmod)) { // passed! - sayphrase(lf, SP_MERCYACCEPT, SV_TALK, NA, player->race->name); + sayphrase(lf, SP_MERCYACCEPT, SV_TALK, NA, player->race->name, player); // they knock you out msg("^%d*WHACK*^n", C_YELLOW); fallasleep(player, ST_KO, rnd(50,100)); diff --git a/lf.c b/lf.c index 1b2ff02..23a56ec 100644 --- a/lf.c +++ b/lf.c @@ -28,6 +28,7 @@ extern FILE *logfile; extern int noredraw; extern int enteringmap; +extern int playerorigalignment; extern map_t *firstmap; extern race_t *firstrace, *lastrace; @@ -902,7 +903,8 @@ int canhear(lifeform_t *lf, cell_t *dest, int volume, int *numwalls) { if (!hasbp(lf, BP_EARS)) return B_FALSE; if (isdeaf(lf)) return B_FALSE; - // can't hear when training + // can't hear when training or enraged + if (lfhasflag(lf, F_RAGE)) return B_FALSE; if (lfhasflag(lf, F_TRAINING)) return B_FALSE; // can't hear noises from other maps @@ -2718,6 +2720,7 @@ int countlegs(lifeform_t *lf) { } } } + if (lfhasflag(lf, F_LOTSOFLEGS)) legs += 20; return legs; } @@ -3212,7 +3215,7 @@ void die(lifeform_t *lf) { if (!hasflag(lf->flags, F_NODEATHSPEECH) && !lfhasflag(lf, F_SUMMONEDBY)) { if (ispetof(lf, player)) { if (cantalk(lf) && canhear(player, lf->cell, 4, NULL)) { - sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL); + sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL, player); } else if (!cansee(player, lf)) { warn("You feel a profound sense of loss."); // redraw since you can "see" the pet even if it's out of sight @@ -3223,7 +3226,7 @@ void die(lifeform_t *lf) { } } else if (cantalk(lf)) { if (pctchance(33)) { - sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL); + sayphrase(lf, SP_DIE, SV_SHOUT, NA, NULL, killer); } } } @@ -4610,6 +4613,11 @@ int eat(lifeform_t *lf, object_t *o) { timemax = 40; } + // fresh food makes the check easier + if (getobhppct(o) >= 80) { + checkdiff = pctof(70, checkdiff); + } + // cannibulism ? if (corpserace->id == lf->race->baseid) { ppower = 3; @@ -4909,7 +4917,7 @@ void endlfturn(lifeform_t *lf) { real_getlfname(lf, realname, NULL, B_NOSHOWALL, B_REALRACE); warn("You feel worried about %s%s.", lfhasflag(lf, F_NAME) ? "" : "your ", noprefix(realname)); } else if (cantalk(lf)) { - sayphrase(lf, SP_ALLY_INPAIN, SV_SHOUT, NA, NULL); + sayphrase(lf, SP_ALLY_INPAIN, SV_SHOUT, NA, NULL, player); } else { makenoise(lf, N_LOWHP); } @@ -5477,6 +5485,20 @@ void enhanceskills(lifeform_t *lf) { } // end if gainedxplev } +int enrage(lifeform_t *lf, int howlong) { + if (lfhasflag(lf, F_RAGE)) return B_TRUE; + + addtempflag(lf->flags, F_RAGE, NA, NA, NA, NULL, howlong); + + if (isplayer(lf)) { + addtempflag(lf->flags, F_AICONTROLLED, B_TRUE, NA, NA, NULL, howlong); + } else { + loseaitargets(lf); + } + + return B_FALSE; +} + int exchangeweapon(lifeform_t *lf) { object_t *wep,*sec = NULL,*newsec = NULL; // get secondary (if available) @@ -6400,11 +6422,16 @@ void gainxp(lifeform_t *lf, long amt) { assert(lf->skillxp >= 0); while (lf->skillxp >= amtneeded) { newskillpoints++; + lf->skillpoints++; + lf->totskillpoints++; + lf->skillxp -= amtneeded; + // recalculate + amtneeded = getspforpoint(lf); if (isplayer(lf)) statdirty = B_TRUE; } // debug! - if (newskillpoints >= 3) { + if (newskillpoints >= 5) { raise(SIGINT); } } @@ -6414,9 +6441,7 @@ void gainxp(lifeform_t *lf, long amt) { gainlevel(lf, B_FALSE); // this will increment 'newlevel' } if (newskillpoints) { - lf->skillpoints += newskillpoints; msg("^GYou feel ready to learn a new skill!"); - lf->totskillpoints += newskillpoints; } } } @@ -7046,7 +7071,7 @@ int real_getattr(lifeform_t *lf, enum ATTRIB attr, int ignoreattrset) { } } if ((f->id == F_RAGE) && (attr == A_STR)) { - val += 25; + val += 50; } } @@ -13743,7 +13768,7 @@ object_t *isstuck(lifeform_t *lf) { } -poisontype_t *addpoisontype(enum POISONTYPE id, char *name, char *desc, char *damverb, enum OBTYPE vomitob, int dam, int dampct, enum POISONSEVERITY severity, int incubationtime) { +poisontype_t *addpoisontype(enum POISONTYPE id, char *name, char *desc, char *contracttext, char *damverb, enum OBTYPE vomitob, int dam, int dampct, enum POISONSEVERITY severity, int incubationtime) { poisontype_t *a; // add to the end of the list @@ -13765,6 +13790,7 @@ poisontype_t *addpoisontype(enum POISONTYPE id, char *name, char *desc, char *da a->id = id; a->name = strdup(name); a->desc = strdup(desc); + a->contracttext = strdup(contracttext); a->damverb = strdup(damverb); a->vomitob = vomitob; a->dam = dam; @@ -14261,6 +14287,16 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) { *amt = 0; } + if (lfhasflag(lf, F_FROZEN)) { + if (basedamagetype(damtype) == DT_FIRE) { + // extra damage + (*amt) = pctof(150,*amt); + } else if (basedamagetype(damtype) == DT_COLD) { + *amt = 0; + } + } + + if (isresistantto(lf->flags, damtype, B_FALSE)) { (*amt) /= 2; } @@ -14275,7 +14311,6 @@ void adjustdamlf(lifeform_t *lf, int *amt, enum DAMTYPE damtype) { } } - // don't adjust for lifeform material - we inherit all the material's flags. //adjustdammaterial((unsigned int *)amt, damtype, getlfmaterial(lf)); adjustdamhardness(amt, damtype, getlfmaterial(lf)); @@ -14610,7 +14645,7 @@ int askforinfo(lifeform_t *lf, int diffmod) { if (lfhasflag(lf, F_NOINFO)) { // refusing to give info - sayphrase(lf, SP_INFO_REFUSE_AGAIN, SV_TALK, NA, NULL); + sayphrase(lf, SP_INFO_REFUSE_AGAIN, SV_TALK, NA, NULL, player); return B_FALSE; } else { int doinfo = B_FALSE; @@ -14657,7 +14692,7 @@ int askforinfo(lifeform_t *lf, int diffmod) { if (askingprice == -1) { addflag(lf->flags, F_NOINFO, B_TRUE, NA, NA, NULL); - sayphrase(lf, SP_INFO_REFUSE, SV_TALK, NA, NULL); + sayphrase(lf, SP_INFO_REFUSE, SV_TALK, NA, NULL, player); return B_FALSE; } else { addflag(lf->flags, F_INFOPRICE, askingprice, NA, NA, NULL); @@ -14679,7 +14714,7 @@ int askforinfo(lifeform_t *lf, int diffmod) { if (askingprice > 0) { char ch; - sayphrase(lf, SP_INFO_ASKPRICE, SV_TALK, askingprice, NULL); + sayphrase(lf, SP_INFO_ASKPRICE, SV_TALK, askingprice, NULL, player); more(); if (askingprice > countmoney(player->pack)) { @@ -14697,10 +14732,10 @@ int askforinfo(lifeform_t *lf, int diffmod) { } if (doinfo) { - sayphrase(lf, SP_INFO_ACCEPT, SV_TALK, NA, NULL); + sayphrase(lf, SP_INFO_ACCEPT, SV_TALK, NA, NULL, player); return B_TRUE; } else { - sayphrase(lf, SP_INFO_DECLINE_WONTPAY, SV_TALK, askingprice, NULL); + sayphrase(lf, SP_INFO_DECLINE_WONTPAY, SV_TALK, askingprice, NULL, player); } } // end if !nohire return B_FALSE; @@ -15150,6 +15185,7 @@ void killpoisontype(poisontype_t *pt) { // free mem free(pt->name); free(pt->desc); + free(pt->contracttext); free(pt->damverb); // remove from list @@ -15778,17 +15814,17 @@ void losehpeffects(lifeform_t *lf, int dam, enum DAMTYPE damtype, lifeform_t *fr char buf2[BUFLEN]; sprintf(buf, "^w%s releases a cloud of purple spores!", lfname); sprintf(buf2, "^wSomething releases a cloud of purple spores!"); - spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, 8, B_TRUE, buf, buf2, B_FALSE, NULL); + spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, 8, B_TRUE, buf, buf2, B_FALSE, NULL, B_NOCENTRE); } else if (lf->race->id == R_FUNGUSRAGE) { char buf2[BUFLEN]; sprintf(buf, "^w%s releases a cloud of red spores!", lfname); sprintf(buf2, "^wSomething releases a cloud of red spores!"); - spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_RED, OT_A_RAGE, 8, B_TRUE, buf, buf2, B_FALSE, NULL); + spellcloud(lf->cell, 3, UNI_SHADELIGHT, C_RED, OT_A_RAGE, 8, B_TRUE, buf, buf2, B_FALSE, NULL, B_NOCENTRE); } else if ((lf->race->id == R_UNYON) && ((damtype == DT_SLASH) || (damtype == DT_PIERCE))) { char buf2[BUFLEN]; sprintf(buf, "^w%s releases a cloud of fumes!", lfname); sprintf(buf2, "^wSomething releases a cloud of fumes!"); - spellcloud(lf->cell, 1, UNI_SHADELIGHT, C_GREY, OT_S_BLINDNESS, 8, B_TRUE, buf, buf2, B_TRUE, NULL); + spellcloud(lf->cell, 1, UNI_SHADELIGHT, C_GREY, OT_S_BLINDNESS, 8, B_TRUE, buf, buf2, B_TRUE, NULL, B_NOCENTRE); } @@ -17630,11 +17666,11 @@ int recruit(lifeform_t *lf) { if (lfhasflag(lf, F_NOHIRE)) { // refusing to join at all. - sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL); + sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL, player); rv = B_TRUE; } else if ( ((pa == AL_GOOD) && (lfa == AL_EVIL)) || ((pa == AL_EVIL) && (lfa == AL_GOOD)) ) { - sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL); + sayphrase(lf, SP_RECRUIT_DECLINE, SV_TALK, NA, NULL, player); rv = B_TRUE; } else { int dohire = B_FALSE; @@ -17688,7 +17724,7 @@ int recruit(lifeform_t *lf) { } if (askingprice > 0) { - sayphrase(lf, SP_RECRUIT_ASKPRICE, SV_TALK, askingprice, NULL); + sayphrase(lf, SP_RECRUIT_ASKPRICE, SV_TALK, askingprice, NULL, player); more(); if (askingprice > countmoney(player->pack)) { @@ -17713,12 +17749,12 @@ int recruit(lifeform_t *lf) { if (lf->race->raceclass->id == RC_HUMANOID) { p = assignnpcname(lf->flags); } - sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p); + sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p, player); } else { if (askingprice > countmoney(player->pack)) { - sayphrase(lf, SP_RECRUIT_DECLINE_CANTPAY, SV_TALK, askingprice, NULL); + sayphrase(lf, SP_RECRUIT_DECLINE_CANTPAY, SV_TALK, askingprice, NULL, player); } else { - sayphrase(lf, SP_RECRUIT_DECLINE_WONTPAY, SV_TALK, askingprice, NULL); + sayphrase(lf, SP_RECRUIT_DECLINE_WONTPAY, SV_TALK, askingprice, NULL, player); } } } // end if !nohire @@ -18076,6 +18112,9 @@ int safetorest(lifeform_t *lf) { return B_TRUE; } +// if lf is null, the player will just get a message \"blah blah blah\" +// this is used (for example) when shopkeepers are talking from the +// in-shop menu. int say(lifeform_t *lf, char *text, int volume) { char seebuf[BUFLEN]; char hearbuf[BUFLEN]; @@ -18139,13 +18178,17 @@ int say(lifeform_t *lf, char *text, int volume) { snprintf(seebuf, BUFLEN, "%s \"%s\"", verb, localtext); snprintf(hearbuf, BUFLEN, "%s \"%s\"", noun, localtext); - rv = noise(lf->cell, lf, NC_SPEECH, volume, hearbuf, seebuf); + if (lf) { + rv = noise(lf->cell, lf, NC_SPEECH, volume, hearbuf, seebuf); + } else { + msg("\"%s\"", localtext); + } free(localtext); return rv; } // volume = -1 means "auto" -int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *text) { +int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *text, lifeform_t *talkingto) { int i,rv = B_FALSE; char buf[BUFLEN]; char buf2[BUFLEN]; @@ -18185,7 +18228,7 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t case SP_ALLY_TARGETKILL: switch (rnd(1,4)) { case 1: snprintf(buf, BUFLEN, "Got it!"); break; - case 2: snprintf(buf, BUFLEN, "%s one, %s zero!", lf->race->name, noprefix(text)); + case 2: snprintf(buf, BUFLEN, "%s one, %s zero!", lf ? lf->race->name : "Me", noprefix(text)); buf[0] = toupper(buf[0]); break; case 3: snprintf(buf, BUFLEN, "Pow!"); break; @@ -18220,7 +18263,7 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t case SP_DIE: switch (rnd(1,4)) { case 1: - if (ispetof(lf, player)) { + if (lf && ispetof(lf, player)) { getplayername(buf2); snprintf(buf, BUFLEN, "Avenge me, %s!", buf2); } else { @@ -18276,7 +18319,12 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t case SP_INFO_ACCEPT: switch (rnd(1,2)) { case 1: snprintf(buf, BUFLEN, "Okay, here's what I know..."); break; - case 2: snprintf(buf, BUFLEN, "Listen carefully..."); break; + case 2: + if (lf && talkingto && (talkingto->race->id != lf->race->id)) { + snprintf(buf, BUFLEN, "Listen carefully, %s...", talkingto->race->name); break; + } else { + snprintf(buf, BUFLEN, "Listen carefully..."); break; + } } rv = say(lf, buf, volume); break; @@ -18303,16 +18351,24 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t snprintf(buf, BUFLEN, "Can't help, sorry."); break; case 3: - snprintf(buf, BUFLEN, "Get lost!"); + if (lf && talkingto && (talkingto->race->id != lf->race->id)) { + snprintf(buf, BUFLEN, "Get lost, %s!", talkingto->race->name); + } else { + snprintf(buf, BUFLEN, "Get lost!"); + } break; case 4: - snprintf(buf, BUFLEN, "No time to talk!"); + if (lf && talkingto && (talkingto->race->id != lf->race->id)) { + snprintf(buf, BUFLEN, "No time to talk, %s!", talkingto->race->name); + } else { + snprintf(buf, BUFLEN, "No time to talk!"); + } break; } rv = say(lf, buf, volume); break; case SP_INFO_REFUSE_AGAIN: - switch (rnd(1,3)) { + switch (rnd(1,4)) { case 1: snprintf(buf, BUFLEN, "Asking twice isn't going to change the answer!"); break; @@ -18406,7 +18462,7 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t } break; case SP_SORRY: - if (getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_HIGH) { + if (lf && getattrbracket(getattr(lf, A_IQ), A_IQ, NULL) >= AT_HIGH) { switch (rnd(0,1)) { case 0: rv = say(lf, "My sincerest condolences!", volume); break; case 1: rv = say(lf, "My mistake, I apologise.", volume); break; @@ -18426,10 +18482,12 @@ int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *t rv = say(lf, buf, volume); break; case SP_THANKS: - switch (rnd(1,3)) { + switch (rnd(1,5)) { case 1: snprintf(buf, BUFLEN, "Why, thank you!"); break; case 2: snprintf(buf, BUFLEN, "You have my gratitude!"); break; case 3: snprintf(buf, BUFLEN, "Thanks!"); break; + case 4: snprintf(buf, BUFLEN, "Thank you, that is very generous of you!"); break; + case 5: snprintf(buf, BUFLEN, "How kind of you!"); break; } rv = say(lf, buf, volume); break; @@ -18585,6 +18643,11 @@ int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus) { void setalignment(lifeform_t *lf, enum ALIGNMENT al) { flag_t *f; + if (isplayer(lf)) { + dblog("warning - changing player alignment"); + msg("warning - changing player alignment"); + more(); + } f = lfhasflag(lf, F_ALIGNMENT); if (f) { f->val[0] = al; @@ -19821,9 +19884,19 @@ void startlfturn(lifeform_t *lf) { if (db) dblog("startlfturn for lf id %d %s", lf->id, lf->race->name); + // debugging lf->redraws = 0; + // more debug + if (isplayer(lf)) { + if ((gamemode == GM_GAMESTARTED) && (getalignment(lf) != playerorigalignment)) { + dblog("WARNING: player alignment has changed!!!"); + msg("WARNING: player alignment has changed!!!"); + more(); + } + } + // MOVE OUT OF STOMACHS WHICH DONT EXIST ANYMORE sf = hasflag(map->flags, F_STOMACHOF); if (sf) { @@ -19876,7 +19949,7 @@ void startlfturn(lifeform_t *lf) { msg("^wAll of your items are missing!^n"); more(); } } else { - sayphrase(lf, SP_ROBBED, SV_SHOUT, NA, NULL); + sayphrase(lf, SP_ROBBED, SV_SHOUT, NA, NULL, NULL); } killflagsofid(lf->flags, F_WASROBBED); } @@ -20077,7 +20150,7 @@ void startlfturn(lifeform_t *lf) { if (lossamt) modstamina(lf, -lossamt); } else { // if we didn't take action last turn, regenerate stamina. - if (!killflagsofid(lf->flags, F_TOOKACTION)) { + if (!killflagsofid(lf->flags, F_TOOKACTION) && !lfhasflag(lf, F_TRAINING)) { if (getstamina(lf) < getmaxstamina(lf)) { modstamina(lf, getstamregen(lf)); } @@ -20313,7 +20386,7 @@ void startlfturn(lifeform_t *lf) { getlfname(otherlf, lfname); msg("The sight of %s makes your blood boil!", lfname); } - addtempflag(lf->flags, F_RAGE, B_TRUE, NA, NA, NULL, DEF_RAGETIME/2); + enrage(lf, DEF_RAGETIME/2); if (getstamina(lf) < 1) setstamina(lf, 1); forceredraw(); if (isplayer(lf)) more(); @@ -20454,7 +20527,7 @@ void startlfturn(lifeform_t *lf) { int bonus = 0; int dist; if (!lfhasflag(l, F_SILENTMOVE) && !isdeaf(lf)) { - bonus += getskill(lf, SK_LISTEN); + bonus += (getskill(lf, SK_LISTEN)/2); } dist = getcelldist(lf->cell, l->cell); @@ -20842,8 +20915,14 @@ void startlfturn(lifeform_t *lf) { } if (lfhasflag(lf, F_FROZEN)) { + int willmelt = B_FALSE; + if (hasobofmaterial(lf->cell->obpile, MT_FIRE)) { + willmelt = B_TRUE; + } else if (onein(4) && !hasobofmaterial(lf->cell->obpile, MT_ICE)) { + willmelt = B_TRUE; + } // melt... - if (rnd(1,2)) { + if (willmelt) { losehp(lf, 1, DT_MELT, NULL, "melting"); addob(lf->cell->obpile, "small puddle of water"); if (isplayer(lf)) { @@ -21828,7 +21907,7 @@ int tradeknowledge(lifeform_t *lf) { // already traded? if (lfhasflag(lf, F_DONEKNOWLEDGETRADE)) { - sayphrase(lf, SP_TRADEINFO_DECLINE_ALREADYDONE, SV_TALK, NA, NULL); + sayphrase(lf, SP_TRADEINFO_DECLINE_ALREADYDONE, SV_TALK, NA, NULL, player); return B_TRUE; } @@ -21839,7 +21918,7 @@ int tradeknowledge(lifeform_t *lf) { fromplayer = poss[sel]; fromplayertype = tradetype[sel]; } else { - sayphrase(lf, SP_TRADEINFO_DECLINE_PLAYERBAD, SV_TALK, NA, NULL); + sayphrase(lf, SP_TRADEINFO_DECLINE_PLAYERBAD, SV_TALK, NA, NULL, player); return B_TRUE; } // does lf have a skill which the player needs? @@ -21858,7 +21937,7 @@ int tradeknowledge(lifeform_t *lf) { addchoice(&prompt, '-', "(nothing)", NULL, NULL, NULL); ch = getchoice(&prompt); if (ch == '-') { - sayphrase(lf, SP_TRADEINFO_CANCEL, SV_TALK, NA, NULL); + sayphrase(lf, SP_TRADEINFO_CANCEL, SV_TALK, NA, NULL, player); return B_TRUE; } else { sel = ch - 'a'; @@ -21869,7 +21948,7 @@ int tradeknowledge(lifeform_t *lf) { toplayer = poss[sel]; toplayertype = tradetype[sel]; } else { - sayphrase(lf, SP_TRADEINFO_DECLINE_OTHERBAD, SV_TALK, NA, NULL); + sayphrase(lf, SP_TRADEINFO_DECLINE_OTHERBAD, SV_TALK, NA, NULL, player); return B_TRUE; } @@ -21880,7 +21959,7 @@ int tradeknowledge(lifeform_t *lf) { gettradeinfoname(toplayer, toplayertype, toplayertext); sprintf(tradetext, "%s^%s",fromplayertext,toplayertext); - sayphrase(lf, SP_TRADEINFO_ACCEPT, SV_TALK, NA, tradetext); + sayphrase(lf, SP_TRADEINFO_ACCEPT, SV_TALK, NA, tradetext, player); more(); // confirm. sprintf(buf, "Learn %s from %s", toplayertext, lfname); @@ -23828,12 +23907,18 @@ int wear(lifeform_t *lf, object_t *o) { // special cases: if (isplayer(lf)) { - if (o->type->id == OT_RING_INVIS) { - // make ring of invis fully known - the HPDRAIN flag - // won't be announced, so since we don't know all the flags we would - // otherwise get "you turn invisible!" but still have the ring known - // as "a blue ring" (or whatever) - makeknown(o->type->id); + switch (o->type->id) { + case OT_RING_INVIS: + // make ring of invis fully known - the HPDRAIN flag + // won't be announced, so since we don't know all the flags we would + // otherwise get "you turn invisible!" but still have the ring known + // as "a blue ring" (or whatever) + case OT_RING_UNHOLINESS: + makeknown(o->type->id); + break; + default: + break; + } } diff --git a/lf.h b/lf.h index d8cda92..93d5943 100644 --- a/lf.h +++ b/lf.h @@ -3,7 +3,7 @@ void addbodypart(race_t *r, enum BODYPART bp, char *name); lifeform_t *addlf(cell_t *cell, enum RACE rid, int level); lifeform_t *real_addlf(cell_t *cell, enum RACE rid, int level, int controller); -poisontype_t *addpoisontype(enum POISONTYPE id, char *name, char *desc, char *damverb, enum OBTYPE vomitob, int dam, int dampct, enum POISONSEVERITY severity, int incubationtime); +poisontype_t *addpoisontype(enum POISONTYPE id, char *name, char *desc, char *contracttext, char *damverb, enum OBTYPE vomitob, int dam, int dampct, enum POISONSEVERITY severity, int incubationtime); job_t *addjob(enum JOB id, char *name, char *desc); race_t *addrace(enum RACE id, char *name, float weight, char glyph, int glyphcolour, enum MATERIAL mat, enum RACECLASS raceclass, char *desc); raceclass_t *addraceclass(enum RACECLASS id, char *name, char *pluralname, enum SKILL skill); @@ -100,6 +100,7 @@ int eat(lifeform_t *lf, object_t *o); void endlfturn(lifeform_t *lf); void enhancerandomskill(lifeform_t *lf); void enhanceskills(lifeform_t *lf); +int enrage(lifeform_t *lf, int howlong); int exchangeweapon(lifeform_t *lf); void extinguishlf(lifeform_t *lf); object_t *eyesshaded(lifeform_t *lf); @@ -439,7 +440,7 @@ int rollattr(enum ATTRBRACKET bracket); int rollstat(lifeform_t *lf, enum ATTRIB attr); int safetorest(lifeform_t *lf); int say(lifeform_t *lf, char *text, int volume); -int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *text); +int sayphrase(lifeform_t *lf, enum SAYPHRASE what, int volume, int val0, char *text, lifeform_t *talkingto); int scare(lifeform_t *lf, lifeform_t *scarer, int howlong, int scarerbonus); //int setammo(lifeform_t *lf, object_t *o); void setalignment(lifeform_t *lf, enum ALIGNMENT al); diff --git a/map.c b/map.c index a663f02..7e3abdb 100644 --- a/map.c +++ b/map.c @@ -88,6 +88,7 @@ cell_t *addcell(map_t *m, int x, int y) { cell->visited = B_FALSE; cell->filled = B_FALSE; cell->isroomwall = D_NONE; + cell->reason = NULL; return cell; } @@ -947,20 +948,28 @@ branch_t *addbranch(enum BRANCH id, char *name, int pluralname, enum HABITAT def return a; } -void adjustcellglyphforlight(cell_t *c, glyph_t *g) { +void adjustcellglyph(cell_t *c, glyph_t *g) { if (g->ch == ' ') return; + + if (c->type->altcol != C_NONE) { + if ((c->x + c->y) % 2) g->colour = c->type->altcol; + } + switch (c->lit) { case L_PERMDARK: case L_NOTLIT: g->colour = C_BLUE; break; + /* case L_TEMP: // lit by a light source if (g->colour < 8) { g->colour = g->colour + 8; // ie. make bold if (g->colour >= C_GREY) g->colour = C_WHITE; } break; + */ case L_PERMLIGHT: + default: break; } } @@ -1085,12 +1094,24 @@ int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, in // change a wall into an empty cell, and add some rubble -void breakwall(cell_t *c) { +void breakwall(cell_t *c, char *why, ...) { celltype_t *origtype; int roomwall; + char buf[BUFLEN]; + va_list args; + + if (why) { + va_start(args, why); + vsnprintf( buf, BUFLEN, why, args ); + va_end(args); + } + origtype = c->type; roomwall = isroom(c); setcelltype(c, getcellempty(c)); + if (why) { + setcellreason(c, "%s", buf); + } if (origtype->solid && roomwall && onein(2)) { switch (origtype->material->id) { case MT_STONE: addob(c->obpile, "1-30 stones"); break; @@ -2009,7 +2030,7 @@ int fix_reachability(map_t *m) { floodfill(c); // any remaining non-filled empty cells? for (i = 0; i < m->w * m->h; i++) { - if (!m->cell[i]->type->solid && !m->cell[i]->filled) { + if (!m->cell[i]->type->solid && !m->cell[i]->filled && !m->cell[i]->locked) { vault_t *v; v = getcellvault(m->cell[i]); if (v && hasflag(v->flags, F_VAULTNOLINK)) { @@ -2203,6 +2224,7 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) { // scanned lf here? if (isinscanrange(c, &thing, NULL, &tempgl) == TT_MONSTER) { *g = tempgl; + adjustcellglyph(c, g); //mvwprintw(gamewin, y-viewy, x-viewx, "%c", glyph); //drawglyph(&glyph, x, y); return; @@ -2222,13 +2244,13 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) { } else { // objects here, but we can't see them. draw the cell. *g = c->type->glyph; - adjustcellglyphforlight(c, g); + adjustcellglyph(c, g); } } else { // draw cell normally //drawcell(cell, x, y); *g = c->type->glyph; - adjustcellglyphforlight(c, g); + adjustcellglyph(c, g); } } else { // can't see the cell void *thing; @@ -2259,6 +2281,12 @@ void getcellglyph(glyph_t *g, cell_t *c, lifeform_t *viewer) { enum CELLTYPE getcellempty(cell_t *c) { flag_t *f; + vault_t *v; + v = getcellvault(c); + if (v) { + f = hasflag(v->flags, F_CELLTYPEEMPTY); + if (f) return f->val[0]; + } if (c->habitat == c->map->habitat) { f = hasflag(c->map->flags, F_CELLTYPEEMPTY); if (f) return f->val[0]; @@ -2268,6 +2296,14 @@ enum CELLTYPE getcellempty(cell_t *c) { enum CELLTYPE getcellsolid(cell_t *c) { flag_t *f; + vault_t *v; + + v = getcellvault(c); + if (v) { + f = hasflag(v->flags, F_CELLTYPESOLID); + if (f) return f->val[0]; + } + if (c->habitat == c->map->habitat) { f = hasflag(c->map->flags, F_CELLTYPESOLID); if (f) return f->val[0]; @@ -5132,57 +5168,60 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) { int n; cell_t *c2; startdist++; - // check left/right from this cell for rooms - for (n = 0; n <= 1; n++) { - int turndist = 0; - c2 = getcellindir(c, perpdir[n]); + // don't bother checking left/right if this cell isn't okay to be cleared. + if (cellokforreachability(startcell, c, roomid, d, wantfilled, NULL)) { + // check left/right from this cell for rooms + for (n = 0; n <= 1; n++) { + int turndist = 0; + c2 = getcellindir(c, perpdir[n]); - while (c2) { - int gotsolution = B_FALSE; - int rv; - turndist++; + while (c2) { + int gotsolution = B_FALSE; + int rv; + turndist++; - perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns - perpturncell1[nperpcells] = c; - perpturndir1[nperpcells] = perpdir[n]; - nperpcells++; + perpcell[nperpcells] = c2; // this will be used if we need to make 2 turns + perpturncell1[nperpcells] = c; + perpturndir1[nperpcells] = perpdir[n]; + nperpcells++; - rv = cellokforreachability(startcell, c2, roomid, perpdir[n], wantfilled, NULL); + rv = cellokforreachability(startcell, c2, roomid, perpdir[n], wantfilled, NULL); - if (rv == B_FALSE) { - break; - } else if (rv == B_TRUE) { - gotsolution = B_TRUE; - } else if (turndist > 1) { - // check l/r too - int perpdir2[2],nn; - cell_t *pcell = NULL; - perpdir2[0] = perpdir[n] - 1; if (perpdir2[0] < D_N) perpdir2[0] = D_W; - perpdir2[1] = perpdir[n] + 1; if (perpdir2[1] > D_W) perpdir2[1] = D_N; - for (nn = 0; nn <= 1; nn++) { - pcell = getcellindir(c2, perpdir2[nn]); - if (pcell && adjcellokforreachability(pcell, roomid, perpdir2[nn], wantfilled)) { - // finished. - if (db) dblog(" Got to an empty cell next to us."); - gotsolution = B_TRUE; - break; + if (rv == B_FALSE) { + break; + } else if (rv == B_TRUE) { + gotsolution = B_TRUE; + } else if (turndist > 1) { + // check l/r too + int perpdir2[2],nn; + cell_t *pcell = NULL; + perpdir2[0] = perpdir[n] - 1; if (perpdir2[0] < D_N) perpdir2[0] = D_W; + perpdir2[1] = perpdir[n] + 1; if (perpdir2[1] > D_W) perpdir2[1] = D_N; + for (nn = 0; nn <= 1; nn++) { + pcell = getcellindir(c2, perpdir2[nn]); + if (pcell && adjcellokforreachability(pcell, roomid, perpdir2[nn], wantfilled)) { + // finished. + if (db) dblog(" Got to an empty cell next to us."); + gotsolution = B_TRUE; + break; + } } } + if (gotsolution) { + if (db) dblog(" Solution found: Walk %d %s, then %d %s.", + startdist, getdirname(startdir), + turndist, getdirname(perpdir[n])); + // walkable and not in this roomid. ok! + turncell = c; + endcell = c2; + turndir = perpdir[n]; + break; + } + // check next cell + c2 = getcellindir(c2, perpdir[n]); } - if (gotsolution) { - if (db) dblog(" Solution found: Walk %d %s, then %d %s.", - startdist, getdirname(startdir), - turndist, getdirname(perpdir[n])); - // walkable and not in this roomid. ok! - turncell = c; - endcell = c2; - turndir = perpdir[n]; - break; - } - // check next cell - c2 = getcellindir(c2, perpdir[n]); + if (turncell) break; } - if (turncell) break; } // now keep going in main direction. c = getcellindir(c, startdir); @@ -5193,17 +5232,17 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) { if (db) dblog(" Making path from vault to corner, initdir=%s", getdirname(startdir)); c = getcellindir(startcell, startdir); while (c != turncell) { - breakwall(c); + breakwall(c, "turnset=1, making path from vault %d to corner", getroomid(startcell)); if (ncellsadded) (*ncellsadded)++; c = getcellindir(c, startdir); } // clear the corner cell - breakwall(c); + breakwall(c, "turncell=1, this is the corner (from vault %d)",getroomid(startcell)); if (db) dblog(" Making path from corner to rest of map, turndir=%s", getdirname(turndir)); // now turn and clear up to the next room/empty cell c = getcellindir(c, turndir); while (c != endcell) { - breakwall(c); + breakwall(c, "turncell=1, clearing from corner to end (from vault %d)", getroomid(startcell)); if (ncellsadded) (*ncellsadded)++; c = getcellindir(c, turndir); } @@ -5282,17 +5321,17 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) { if (db) dblog(" Making path from vault to first corner, initdir=%s", getdirname(startdir)); c = getcellindir(startcell, startdir); while (c != turncell) { - breakwall(c); + breakwall(c, "twoturn: path from vault %d to first corner 1", getroomid(startcell)); if (ncellsadded) (*ncellsadded)++; c = getcellindir(c, startdir); } // clear the corner cell - breakwall(c); + breakwall(c, "twoturn: corner 1 (from vault %d)", getroomid(startcell)); // now turn and clear up to the next turn if (db) dblog(" Making path from 1st corner to 2nd corner, turndir=%s", getdirname(turndir)); c = getcellindir(c, turndir); while (c != turncell2) { - breakwall(c); + breakwall(c, "twoturn: path from 1st corner to 2nd corner (from vault %d)", getroomid(startcell)); if (ncellsadded) (*ncellsadded)++; c = getcellindir(c, turndir); } @@ -5301,7 +5340,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) { if (db) dblog(" Making path from 2nd corner to rest of map, turndir=%s", getdirname(turndir2)); c = getcellindir(c, turndir2); while (c != endcell) { - breakwall(c); + breakwall(c, "twoturn: path from 2nd corner to end (from vault %d)", getroomid(startcell)); if (ncellsadded) (*ncellsadded)++; c = getcellindir(c, turndir2); } @@ -5341,15 +5380,15 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) { c = getcellindir(startcell, whichway); //while (c && !cellwalkable(NULL, c, NULL)) { while (c && c != directendcell[whichway]) { - breakwall(c); + breakwall(c, "direct link (from vault %d)",getroomid(startcell)); if (ncellsadded) (*ncellsadded)++; c = getcellindir(c, whichway); } } // now make sure the START cell is empty too! - if (startcell->type->solid) { - breakwall(startcell); + if (startcell->type->solid && !startcell->locked && !cellisfixedvaultwall(startcell)) { + breakwall(startcell, "making sure start cell is empty (from vault %d)",getroomid(startcell)); } return B_FALSE; @@ -5364,6 +5403,7 @@ int linkexits(map_t *m, int roomid) { int nadded = 0; int minx = -1, miny = -1, maxx = -1, maxy = -1; int roomidx = -1; + vault_t *v; // figure out room coords for (i = 0; i < m->nrooms; i++) { @@ -5382,11 +5422,16 @@ int linkexits(map_t *m, int roomid) { c = getrandomroomcell(m, roomid, WE_NONE); if (!c) return B_FALSE; + v = getcellvault(c); + if (v) { + if (hasflag(v->flags, F_VAULTNOLINK)) { + return B_FALSE; + } + } + if (db) { char buf[BUFLEN]; - vault_t *v; - c = getrandomroomcell(m, roomid, WE_NONE); - v = getcellvault(c); + //c = getrandomroomcell(m, roomid, WE_NONE); snprintf(buf, BUFLEN, "*** linkexits for roomid %d (%s) [%d,%d-%d,%d]", roomid, v ? v->id : "novault", minx,miny,maxx,maxy); @@ -7265,31 +7310,31 @@ void initmap(void) { // cell types - solid // floorheight, hp - addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, B_SOLID, B_OPAQUE, MT_STONE, 0, 50); - addcelltype(CT_WALLBRICK, "brick wall", UNI_SHADEDARK, C_ORANGE, B_SOLID, B_OPAQUE, MT_STONE, 0, 40); - addcelltype(CT_WALLDIRT, "dirt wall", UNI_SHADEMED, C_BROWN, B_SOLID, B_OPAQUE, MT_STONE, 0, 20); - addcelltype(CT_WALLDURANITE, "duranite wall", UNI_SHADEDARK, C_MAGENTA, B_SOLID, B_OPAQUE, MT_DURANITE, 0, 20000); - addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_WOOD, 0, 30); - addcelltype(CT_WALLDWOOD, "wyrmwood wall", UNI_SOLID, C_BROWN, B_SOLID, B_OPAQUE, MT_DRAGONWOOD, 0, 100); - addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, B_SOLID, B_OPAQUE, MT_FLESH, 0, 25); - addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, B_SOLID, B_TRANS, MT_GLASS, 0, 20); + addcelltype(CT_WALL, "rock wall", UNI_SHADEDARK, C_GREY, NA, B_SOLID, B_OPAQUE, MT_STONE, 0, 50); + addcelltype(CT_WALLBRICK, "brick wall", UNI_SHADEDARK, C_ORANGE, NA, B_SOLID, B_OPAQUE, MT_STONE, 0, 40); + addcelltype(CT_WALLDIRT, "dirt wall", UNI_SHADEMED, C_BROWN, NA, B_SOLID, B_OPAQUE, MT_STONE, 0, 20); + addcelltype(CT_WALLDURANITE, "duranite wall", UNI_SHADEDARK, C_MAGENTA, NA, B_SOLID, B_OPAQUE, MT_DURANITE, 0, 20000); + addcelltype(CT_WALLWOOD, "wooden wall", UNI_SOLID, C_BROWN, NA, B_SOLID, B_OPAQUE, MT_WOOD, 0, 30); + addcelltype(CT_WALLDWOOD, "wyrmwood wall", UNI_SOLID, C_BROWN, NA, B_SOLID, B_OPAQUE, MT_DRAGONWOOD, 0, 100); + addcelltype(CT_WALLFLESH, "flesh wall", UNI_SOLID, C_RED, NA, B_SOLID, B_OPAQUE, MT_FLESH, 0, 25); + addcelltype(CT_WALLGLASS, "glass wall", UNI_SOLID, C_CYAN, NA, B_SOLID, B_TRANS, MT_GLASS, 0, 20); //addcelltype(CT_WALLTREE, "dense bushland", UNI_SHADEDARK, C_GREEN, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100); - addcelltype(CT_WALLTREE, "dense bushland", UNI_TREELOTS, C_GREEN, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100); - addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, B_SOLID, B_OPAQUE, MT_METAL, 0, 75); + addcelltype(CT_WALLTREE, "dense bushland", UNI_TREELOTS, C_GREEN, NA, B_SOLID, B_OPAQUE, MT_PLANT, 0, 100); + addcelltype(CT_WALLMETAL, "metal wall", UNI_SOLID, C_WHITE, NA, B_SOLID, B_OPAQUE, MT_METAL, 0, 75); // cell types - non-solid - addcelltype(CT_FAKE, "fake cell", '.', C_GREEN, B_EMPTY, B_TRANS, MT_STONE, 0, -1); - 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_FLOORCARPET, "carpetted floor", '.', C_RED, B_EMPTY, B_TRANS, MT_CLOTH, 0, -1); - addcelltype(CT_FLOORDURANITE, "duranite floor", '.', C_MAGENTA, B_EMPTY, B_TRANS, MT_DURANITE, 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_FLOORTILE, "tiled floor", '.', C_CYAN, B_EMPTY, B_TRANS, MT_METAL, 0, -1); - addcelltype(CT_GRASS, "grass", '.', C_GREEN, B_EMPTY, B_TRANS, MT_PLANT, 0, -1); - addcelltype(CT_DIRT, "dirt", '.', C_BROWN, B_EMPTY, B_TRANS, MT_STONE, 0, -1); - addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -1, -1); - addcelltype(CT_VLOWFLOOR, "very low rock floor", '.', C_GREY, B_EMPTY, B_TRANS, MT_STONE, -2, -1); + addcelltype(CT_FAKE, "fake cell", '.', C_GREEN, NA, B_EMPTY, B_TRANS, MT_STONE, 0, -1); + addcelltype(CT_CORRIDOR, "rock floor", '.', C_GREY, NA, B_EMPTY, B_TRANS, MT_STONE, 0, -1); + addcelltype(CT_LOOPCORRIDOR, "rock floor", 'L', C_GREY, NA, B_EMPTY, B_TRANS, MT_STONE, 0, -1); + addcelltype(CT_FLOORCARPET, "carpetted floor", '.', C_RED, C_ORANGE, B_EMPTY, B_TRANS, MT_CLOTH, 0, -1); + addcelltype(CT_FLOORDURANITE, "duranite floor", '.', C_MAGENTA, NA, B_EMPTY, B_TRANS, MT_DURANITE, 0, -1); + addcelltype(CT_FLOORWOOD, "wood floor", '.', C_BROWN, NA, B_EMPTY, B_TRANS, MT_WOOD, 0, -1); + addcelltype(CT_FLOORFLESH, "flesh floor", '.', C_RED, NA, B_EMPTY, B_TRANS, MT_FLESH, 0, -1); + addcelltype(CT_FLOORSHOP, "shop floor", '.', C_BROWN, NA, B_EMPTY, B_TRANS, MT_WOOD, 0, -1); + addcelltype(CT_FLOORTILE, "tiled floor", '.', C_CYAN, C_WHITE, B_EMPTY, B_TRANS, MT_METAL, 0, -1); + addcelltype(CT_GRASS, "grass", '.', C_GREEN, NA, B_EMPTY, B_TRANS, MT_PLANT, 0, -1); + addcelltype(CT_DIRT, "dirt", '.', C_BROWN, C_YELLOW, B_EMPTY, B_TRANS, MT_STONE, 0, -1); + addcelltype(CT_LOWFLOOR, "low rock floor", '.', C_GREY, NA, B_EMPTY, B_TRANS, MT_STONE, -1, -1); + addcelltype(CT_VLOWFLOOR, "very low rock floor", '.', C_GREY, NA, B_EMPTY, B_TRANS, MT_STONE, -2, -1); // region types // name, pluralname?, defaulthab, maxdepth stairs stair major? depthmod inherit_parent_depth? @@ -8444,7 +8489,7 @@ void selectcelltypes(map_t *map) { } // random chance of different floor type if (onein(6)) { - switch (rnd(1,3)) { + switch (rnd(1,4)) { case 1: addflag(map->flags, F_CELLTYPEEMPTY, CT_FLOORCARPET, NA, NA, NULL); break; @@ -8454,6 +8499,9 @@ void selectcelltypes(map_t *map) { case 3: addflag(map->flags, F_CELLTYPEEMPTY, CT_FLOORWOOD, NA, NA, NULL); break; + case 4: + addflag(map->flags, F_CELLTYPEEMPTY, CT_DIRT, NA, NA, NULL); + break; } } } @@ -8496,8 +8544,8 @@ void setcellknown(cell_t *cell, int forcelev) { o = hassecretdoor(cell->obpile); if (o) { celltype_t *ct; - //ct = findcelltype(getcellsolid(cell)); - ct = findcelltype(getmapsolid(cell->map)); + ct = findcelltype(getcellsolid(cell)); + //ct = findcelltype(getmapsolid(cell->map)); cell->knownglyph = ct->glyph; } else { cell->knownglyph = cell->type->glyph; @@ -8547,6 +8595,19 @@ void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype) { } } +void setcellreason(cell_t *c, char *why, ...) { + char buf[BUFLEN]; + va_list args; + + if (c->reason) free(c->reason); + + va_start(args, why); + vsnprintf( buf, BUFLEN, why, args ); + va_end(args); + + c->reason = strdup(buf); +} + void setcelltype(cell_t *cell, enum CELLTYPE id) { assert(cell); cell->type = findcelltype(id); diff --git a/map.h b/map.h index 44bffe3..0ad886a 100644 --- a/map.h +++ b/map.h @@ -11,9 +11,9 @@ region_t *addregion(enum BRANCH rtype, region_t *parent, int outlineid, int dept regionoutline_t *addregionoutline(enum BRANCH rtype); regionthing_t *addregionthing(regionoutline_t *ro, int depth, int x, int y, enum REGIONTHING whatkind, int value, char *what); branch_t *addbranch(enum BRANCH id, char *name, int pluralname, enum HABITAT defaulthabitat, int maxdepth, int stairsperlev, int deeperdir, int major, int depthmod, int addparentdepth); -void adjustcellglyphforlight(cell_t *c, glyph_t *col); +void adjustcellglyph(cell_t *c, glyph_t *col); int autodoors(map_t *map, int roomid, int minx, int miny, int maxx, int maxy, int doorpct, int dooropenchance); -void breakwall(cell_t *c); +void breakwall(cell_t *c, char *why, ...); int cellhaslos(cell_t *c1, cell_t *dest); int cellisfixedvaultwall(cell_t *c); int cellmatchescondition(cell_t *c, int wecond); @@ -188,6 +188,7 @@ void selectcelltypes(map_t *map); void set_scanned_glyph(int targettype, void *what, char *descappend, char *desc, glyph_t *glyph); void setcellknown(cell_t *cell, int forcelev); void setcellknownradius(cell_t *centre, int forcelev, int radius, int dirtype); +void setcellreason(cell_t *c, char *why, ...); void setcelltype(cell_t *cell, enum CELLTYPE id); int shattercell(cell_t *c, lifeform_t *fromlf, char *damstring); int unlinkstairsto(map_t *unlinkmap); diff --git a/nexus.c b/nexus.c index a792fd9..fbe8f41 100644 --- a/nexus.c +++ b/nexus.c @@ -53,6 +53,8 @@ extern int ngodlfs; int nextregionthingid = 0; +int playerorigalignment = AL_NONE; + buildingusage_t buildingusage[MAXBUILDINGTYPES]; int nbuildingusage = 0; @@ -61,6 +63,8 @@ option_t *firstoption = NULL,*lastoption = NULL; int maxmonhitdice = 0; // highest number of hitdice for any monster +int playerhasmoved = B_FALSE; + double presin[360]; double precos[360]; @@ -501,6 +505,7 @@ int main(int argc, char **argv) { clearmsg(); msg("%s",welcomemsg); more(); + playerorigalignment = getalignment(player); // MAIN LOOP @@ -553,7 +558,7 @@ int main(int argc, char **argv) { return B_FALSE; } -celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp) { +celltype_t *addcelltype(int id, char *name, int glyph, int colour, int altcol, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp) { celltype_t *a; // add to the end of the list @@ -576,6 +581,11 @@ celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, in a->name = strdup(name); a->glyph.ch = glyph; a->glyph.colour = colour; + if (altcol == NA) { + a->altcol = C_NONE; + } else { + a->altcol = altcol; + } a->solid = solid; a->transparent = transparent; a->material = findmaterial(mat); @@ -804,10 +814,6 @@ void donextturn(map_t *map) { completeincubation(who, incflag); willchange = B_TRUE; free(localtext); - addflag(who->flags, F_AICONTROLLED, B_TRUE, NA, NA, NULL); - if (isplayer(who)) { - addflag(who->flags, F_HATESALL, B_TRUE, NA, NA, NULL); - } willrage = B_TRUE; } } @@ -822,7 +828,7 @@ void donextturn(map_t *map) { polymorphto(who, r->id, PERMENANT); donormalmove = B_FALSE; if (willrage) { - addflag(who->flags, F_RAGE, B_TRUE, NA, NA, NULL); + enrage(who, PERMENANT); } } } else if (ispolymorphed(who)) { @@ -1088,6 +1094,12 @@ void donextturn(map_t *map) { if (!isdead(who)) endlfturn(who); } // end 'if (who)' + if (isplayer(who)) { + // in order to force the player's turn to be first, + // monsters will not take any actions until + // playerhasmoved is set + playerhasmoved = B_TRUE; + } // check for death etc checkdeath(); diff --git a/nexus.h b/nexus.h index e679b2f..8112cd9 100644 --- a/nexus.h +++ b/nexus.h @@ -1,6 +1,6 @@ #include "defs.h" -celltype_t *addcelltype(int id, char *name, int glyph, int colour, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp); +celltype_t *addcelltype(int id, char *name, int glyph, int colour, int altcol, int solid, int transparent, enum MATERIAL mat, int floorheight, int hp); warning_t *addwarning(char *text, int lifetime); void checkdeath(void); void checkendgame(void); diff --git a/objects.c b/objects.c index 8ca4925..93ef88e 100644 --- a/objects.c +++ b/objects.c @@ -811,6 +811,12 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int dolinks, enum p += strlen(mat->name); p++; // go past the space donesomething = B_TRUE; + // special flags + } else if (strstarts(p, "immutable ")) { + f = addflag(wantflags, F_IMMUTABLE, B_TRUE, NA, NA, NULL); + f->known = B_FALSE; + p += strlen("immutable "); + donesomething = B_TRUE; // rarity } else if (strstarts(p, "frequent ")) { wantrarity = RR_FREQUENT; @@ -3425,7 +3431,7 @@ int doobdieconvert(object_t *o, int wantannounce) { if (centre) { cell_t *cell[MAXCANDIDATES]; int ncells,i; - getradiuscells(centre, f->val[0], DT_COMPASS, B_FALSE, LOF_WALLSTOP, B_FALSE, cell, &ncells, B_FALSE); + getradiuscells(centre, f->val[0], f->val[1], B_FALSE, LOF_WALLSTOP, B_FALSE, cell, &ncells, B_FALSE); for (i = 0; i < ncells; i++) { newob = addob(cell[i]->obpile, f->text); if (newob && !strchr(f->text, '-')) { @@ -3766,7 +3772,8 @@ glyph_t *getglyph(object_t *o) { if (isdoor(o, &isopen)) { if (issecretdoor(o)) { - return &(findcelltype(getmapsolid(obloc->map))->glyph); + //return &(findcelltype(getmapsolid(obloc->map))->glyph); + return &(findcelltype(getcellsolid(obloc))->glyph); } else { if (isopen) { g = '-'; @@ -7593,21 +7600,12 @@ int isreadable(object_t *o) { } int isrotting(object_t *o) { - flag_t *f; - float pct; - if (hasflag(o->flags, F_TAINTED)) { return B_TRUE; } if (!iscorpse(o)) return B_FALSE; - f = hasflag(o->flags, F_OBHP); - if (f) { - pct = ((float) f->val[0] / (float) f->val[1]) * 100.0; - } else { - pct = 100; - } - if (pct < 25) { + if (getobhppct(o) < 25) { return B_TRUE; } return B_FALSE; @@ -8742,6 +8740,8 @@ void obdie(object_t *o) { int power; char obname[BUFLEN],seebuf[BUFLEN],noseebuf[BUFLEN]; char buf[BUFLEN],*p; + flag_t *glyphflag; + glyph_t cloudglyph; where = getoblocation(o); getobname(o, obname, 1); p = readuntil(seebuf, f->text, '^'); @@ -8749,14 +8749,25 @@ void obdie(object_t *o) { p = readuntil(buf, p, '^'); power = atoi(buf); + glyphflag = hasflag(o->flags, F_SPELLCLOUDGLYPH); + if (glyphflag) { + cloudglyph.colour = glyphflag->val[0]; + cloudglyph.ch = glyphflag->val[1]; + } else { + cloudglyph.colour = C_RANDOM; + cloudglyph.ch = UNI_SHADELIGHT; + } + if (f->val[2] == B_IFACTIVATED) { if (isactivated(o)) { - spellcloud(where, f->val[1], UNI_SHADELIGHT, C_RANDOM, f->val[0], power, B_TRUE, seebuf, noseebuf, B_FALSE, o); + spellcloud(where, f->val[1], cloudglyph.ch, cloudglyph.colour, f->val[0], power, B_TRUE, + seebuf, noseebuf, B_FALSE, o, B_INCLUDECENTRE); removeob(o, o->amt); return; } } else { - spellcloud(where, f->val[1], UNI_SHADELIGHT, C_RANDOM, f->val[0], power, B_TRUE, seebuf, noseebuf, B_FALSE, o); + spellcloud(where, f->val[1], cloudglyph.ch, cloudglyph.colour, f->val[0], power, B_TRUE, + seebuf, noseebuf, B_FALSE, o, B_INCLUDECENTRE); removeob(o, o->amt); return; } @@ -8808,7 +8819,7 @@ void obdie(object_t *o) { lifeform_t *l; l = findlf(loc->map, retflag[i]->val[0]); if (l) { - sayphrase(l, SP_LIFEOB_DESTROYED, SV_CAR, NA, NULL); + sayphrase(l, SP_LIFEOB_DESTROYED, SV_CAR, NA, NULL, NULL); } } } @@ -9903,11 +9914,7 @@ int operate(lifeform_t *lf, object_t *o, cell_t *where) { // create fire addobfast(c->obpile, OT_FIRELARGE); // enrage - addtempflag(c->lf->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong); - if (!isplayer(c->lf)) { - addtempflag(c->lf->flags, F_HATESALL, B_TRUE, NA, NA, NULL, howlong); - loseaitargets(c->lf); - } + enrage(c->lf, howlong); } } break; @@ -12876,7 +12883,9 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) { int power; char obname[BUFLEN],seebuf[BUFLEN],noseebuf[BUFLEN]; char buf[BUFLEN],*p; + flag_t *glyphflag; cell_t *where; + glyph_t cloudglyph; where = getoblocation(o); getobname(o, obname, 1); p = readuntil(seebuf, f->text, '^'); @@ -12884,16 +12893,27 @@ int real_takedamage(object_t *o, int howmuch, int damtype, int wantannounce) { p = readuntil(buf, p, '^'); power = atoi(buf); + glyphflag = hasflag(o->flags, F_SPELLCLOUDGLYPH); + if (glyphflag) { + cloudglyph.colour = glyphflag->val[0]; + cloudglyph.ch = glyphflag->val[1]; + } else { + cloudglyph.colour = C_RANDOM; + cloudglyph.ch = UNI_SHADELIGHT; + } + if (f->val[2] == B_IFACTIVATED) { if (isactivated(o)) { if (!hasflag(o->flags, F_SPELLCLOUDONDEATH)) { - spellcloud(where, f->val[1], UNI_SHADELIGHT, C_RANDOM, f->val[0], power, B_TRUE, seebuf, noseebuf, B_FALSE, o); + spellcloud(where, f->val[1], cloudglyph.ch, cloudglyph.colour, f->val[0], power, B_TRUE, + seebuf, noseebuf, B_FALSE, o, B_INCLUDECENTRE); } addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL); } } else { if (!hasflag(o->flags, F_SPELLCLOUDONDEATH)) { - spellcloud(where, f->val[1], UNI_SHADELIGHT, C_RANDOM, f->val[0], power, B_TRUE, seebuf, noseebuf, B_FALSE, o); + spellcloud(where, f->val[1], cloudglyph.ch, cloudglyph.colour, f->val[0], power, B_TRUE, + seebuf, noseebuf, B_FALSE, o, B_INCLUDECENTRE); } addflag(o->flags, F_DEAD, B_TRUE, NA, NA, NULL); } @@ -13344,7 +13364,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp radius = o->amt * 2; if (radius > 10) radius = 10; - spellcloud(srcloc, radius, UNI_SHADELIGHT, C_RANDOM, OT_S_INVISIBILITY, radius, B_TRUE, buf, "A cloud of twinkling lights appear!", B_FALSE, NULL); + spellcloud(srcloc, radius, UNI_SHADELIGHT, C_RANDOM, OT_S_INVISIBILITY, radius, B_TRUE, buf, "A cloud of twinkling lights appear!", B_FALSE, NULL, B_INCLUDECENTRE); } else if (o->type->id == OT_ASHSLEEP) { int radius; char buf[BUFLEN]; @@ -13357,7 +13377,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp radius = o->amt * 2; if (radius > 10) radius = 10; - spellcloud(srcloc, radius, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, radius, B_TRUE, buf, "A wispy mist appears!", B_FALSE, NULL); + spellcloud(srcloc, radius, UNI_SHADELIGHT, C_MAGENTA, OT_S_SLEEP, radius, B_TRUE, buf, "A wispy mist appears!", B_FALSE, NULL, B_INCLUDECENTRE); } else if (o->type->id == OT_SALT) { int dist; dist = getcelldist(srcloc, where); @@ -13629,28 +13649,32 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp catchmod = -6; dodgemod = 2; } - // first check to see if you can catch it. this should be very hard! - if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) && - lfhasflag(target, F_HUMANOID) && - canpickup(target, o, o->amt) && - !willburden(target, o, o->amt) && - !isimmobile(target) && - skillcheck(target, SC_DEX, 27 + (speed*5), catchmod)) { - willcatch = B_TRUE; - } else if (hasfreeaction(target) && skillcheck(target, SC_DODGE, 27+(speed*2), dodgemod)) { - // then check if we dodge it... - if (db) dblog("target passed dodge check."); + if (hasfreeaction(target) && skillcheck(target, SC_DODGE, 27+(speed*2), dodgemod)) { + // if we passed the dodge check, now see if we caught it... + // first check to see if you can catch it. this should be very hard! + if (!lfhasflag(target, F_NOPACK) && hasbp(target, BP_HANDS) && + lfhasflag(target, F_HUMANOID) && + canpickup(target, o, o->amt) && + !willburden(target, o, o->amt) && + !isimmobile(target) && + skillcheck(target, SC_DEX, 27 + (speed*5), catchmod)) { + if (db) dblog("target passed catch check."); + willcatch = B_TRUE; + } else { + // then check if we dodge it... + if (db) dblog("target passed dodge check."); - youhit = B_FALSE; - if (seen) { - if (isplayer(target)) { - msg("You dodge %s.", obname); - } else if (cansee(player, target)) { - msg("%s dodges %s.", targetname, obname); + youhit = B_FALSE; + if (seen) { + if (isplayer(target)) { + msg("You dodge %s.", obname); + } else if (cansee(player, target)) { + msg("%s dodges %s.", targetname, obname); + } + announcedmiss = B_TRUE; } - announcedmiss = B_TRUE; + practice(target, SK_EVASION, 1); } - practice(target, SK_EVASION, 1); } } } diff --git a/shops.c b/shops.c index bc79847..96fb2c5 100644 --- a/shops.c +++ b/shops.c @@ -503,7 +503,8 @@ enum SHOPRETURN shopdonate(lifeform_t *lf, object_t *vm, int starty, char *topte msg("\"We appreciate your kind donation.\""); } } else { - msg("\"Thanks!\""); more(); + sayphrase(NULL, SP_THANKS, SV_TALK, NA, NULL, player); + more(); } f = hasflag(vm->flags, F_SHOPDONATED); diff --git a/spell.c b/spell.c index bc52472..30c3add 100644 --- a/spell.c +++ b/spell.c @@ -1443,7 +1443,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef return B_TRUE; } howlong = DEF_RAGETIME; - addtempflag(user->flags, F_RAGE, B_TRUE, NA, NA, NULL, howlong); + enrage(user, howlong); } else if (abilid == OT_A_REPAIR) { object_t *o; enum MATERIAL repairablemats[MAXCANDIDATES]; @@ -2395,7 +2395,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef wep = getweapon(user); - // try to disarm them... + // try to trip them... taketime(user, getactspeed(user)); if (wep) { @@ -4251,7 +4251,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (target && cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); - msg("A green miasma surrounds %s%s %s.", lfname, + msg("^%cA green miasma surrounds %s%s %s.", getlfcol(target, CC_BAD), lfname, getpossessive(lfname), obname); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (targcell && haslos(player, targcell)) { @@ -4274,7 +4274,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (cansee(player, targcell->lf)) { char lfname[BUFLEN]; getlfname(targcell->lf, lfname); - msg("A green miasma surrounds %s.", lfname); + msg("^%cA green miasma surrounds %s.", getlfcol(targcell->lf, CC_BAD), lfname); if (seenbyplayer) *seenbyplayer = B_TRUE; } if (isliving(targcell->lf)) { @@ -4290,7 +4290,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } losehp(targcell->lf, dam, DT_DECAY, caster, damstr); if (isplayer(targcell->lf)) { - msg("A blight courses through your veins!"); + msg("^%cA blight courses through your veins!", getlfcol(targcell->lf, CC_BAD)); } else if (cansee(player, targcell->lf)) { char tname[BUFLEN]; getlfname(targcell->lf, tname); @@ -4516,7 +4516,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ char realcname[BUFLEN]; getlfname(c->lf,buf); if (!isimmuneto(c->lf->flags, DT_FIRE, B_FALSE)) { - msg("%s burn%s!",buf,isplayer(c->lf) ? "" : "s"); + msg("^%c%s burn%s!",getlfcol(c->lf, CC_BAD), buf,isplayer(c->lf) ? "" : "s"); } real_getlfname(caster, realcname, NULL, B_SHOWALL, B_REALRACE); snprintf(damstring, BUFLEN, "%s%s wave of fire", realcname, getpossessive(realcname)); @@ -4615,7 +4615,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (haslos(player, targcell)) { animsky(targcell, '}', C_WHITE); - msg("%s %s struck by a bolt of lightning!",targname,is(target)); + msg("^%c%s %s struck by a bolt of lightning!",getlfcol(target, CC_BAD), targname,is(target)); if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -4878,11 +4878,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ limit(&pct, 0, 100); if (pct) { if (isplayer(target)) { - msg("Your wounds are healed!"); + msg("^%cYour wounds are healed!", getlfcol(target, CC_GOOD)); } else if (cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); - msg("%s%s wounds are healed!", lfname, getpossessive(lfname)); + msg("^%c%s%s wounds are healed!", getlfcol(target, CC_GOOD), lfname, getpossessive(lfname)); } gainhp(target, pctof(pct, target->maxhp)); } else { @@ -5104,21 +5104,21 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ dam = rnd(1,exposedlimbs); if (isplayer(target)) { - msg("The air around you feels icy cold!"); + msg("^%cThe air around you feels icy cold!", getlfcol(target, CC_BAD)); } if (isplayer(target)) { if (isimmuneto(target->flags, DT_COLD, B_FALSE)) { msg("You feel mildly chilly."); } else { - msg("You feel cold!"); + msg("^%cYou feel very cold!", getlfcol(target, CC_BAD)); } if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { if (isimmuneto(target->flags, DT_COLD, B_FALSE)) { msg("%s doesn't seem to mind the cold.", lfname); } else { - msg("%s looks cold!", lfname); + msg("^%c%s looks very cold!", getlfcol(target, CC_BAD), lfname); } if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -5154,7 +5154,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // automatic hit getlfname(targcell->lf, lfname); if (haslos(player, targcell)) { - msg("%s %s chilled!",lfname,is(targcell->lf)); + msg("^%c%s %s chilled!",getlfcol(targcell->lf, CC_BAD), + lfname,is(targcell->lf)); } losehp(targcell->lf, rolldie(1,8)+3, DT_COLD, caster, "a burst of coldness"); } @@ -5193,7 +5194,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int dam; // hit if (cansee(player, target)) { - msg("A blast of icy air hits %s.",lfname); + msg("^%cA blast of icy air assails %s.",getlfcol(target, CC_BAD), lfname); } dam = roll("3d6"); if (power > 1) { // overcast for dragons @@ -5398,9 +5399,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // announce getobname(o, obname, 1); if (isplayer(target)) { - msg("%s forms %s your %s!", obname, getbodypartequipname(bp[i]), getbodypartname(target, bp[i])); + msg("^%c%s forms %s your %s!", getlfcol(target, CC_VGOOD), obname, getbodypartequipname(bp[i]), getbodypartname(target, bp[i])); } else if (cansee(player, target)) { - msg("%s forms %s %s%s %s!", obname, getbodypartequipname(bp[i]), + msg("^%c%s forms %s %s%s %s!", getlfcol(target, CC_VGOOD),obname, getbodypartequipname(bp[i]), castername, getpossessive(castername), getbodypartname(target, bp[i])); } // don't use "wear" because we don't want it being announced. @@ -5449,9 +5450,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // announce if (isplayer(target)) { - msg("A %s shield of shimmering ice forms in your hand!", getsizetext(sz)); + msg("^%cA %s shield of shimmering ice forms in your hand!", getlfcol(target, CC_GOOD), + getsizetext(sz)); } else if (cansee(player, target)) { - msg("A %s shield of shimmering ice forms in %s%s hand!", getsizetext(sz), castername, + msg("^%cA %s shield of shimmering ice forms in %s%s hand!",getlfcol(target, CC_GOOD), + getsizetext(sz), castername, getpossessive(castername)); } // don't use "wear" because we don't want it being announced. @@ -5807,7 +5810,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } if (isplayer(target)) { - msg("You feel your body's essence unraveling!"); + msg("^%cYou feel your body's essence unraveling!", getlfcol(target, CC_BAD)); } else if (cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); @@ -5981,7 +5984,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else if (spellid == OT_S_DETONATEDELAY) { addobfast(targcell->obpile, OT_VIBCLOUD); if (haslos(player, targcell)) { - msg("The air nearby begins to vibrate violently..."); more(); + msg("^%cThe air nearby begins to vibrate violently...", getlfcol(player, CC_VBAD)); more(); if (seenbyplayer) *seenbyplayer = B_TRUE; } } else if (spellid == OT_S_EQANDOP) { @@ -5994,10 +5997,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ howlong = power*5; addtempflag(caster->flags, F_AUTOCREATEOB, 0, NA, NA, "whirlwind", howlong); if (isplayer(caster)) { - msg("A spinning whirlwind lifts you off the ground!"); + msg("^%cA spinning whirlwind lifts you off the ground!", getlfcol(caster, CC_GOOD)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, caster)) { - msg("A spinning whirlwind lifts %s off the ground!", castername); + msg("^%cA spinning whirlwind lifts %s off the ground!", getlfcol(caster, CC_GOOD), castername); if (seenbyplayer) *seenbyplayer = B_TRUE; } addtempflag(caster->flags, F_LEVITATING, B_TRUE, NA, NA, NULL, howlong); @@ -6193,13 +6196,15 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (isplayer(caster) || cansee(player, caster)) { if (isimmuneto(target->flags, DT_NECROTIC, B_FALSE)) { - msg("%s suck%s death from %s!",castername,isplayer(caster) ? "" : "s", lfname); + msg("^%c%s suck%s death from %s!",getlfcol(target, CC_BAD), + castername,isplayer(caster) ? "" : "s", lfname); } else { - msg("%s suck%s life from %s!",castername,isplayer(caster) ? "" : "s", lfname); + msg("^%c%s suck%s life from %s!",getlfcol(target, CC_BAD), + castername,isplayer(caster) ? "" : "s", lfname); } if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (isplayer(target)) { - msg("You feel your life force draining away!"); + msg("^%cYou feel your life force draining away!", getlfcol(target, CC_BAD)); if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -6240,11 +6245,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (c->lf && (c->lf != caster) && haslof(targcell, c, B_FALSE, NULL)) { // automatic hit if (isplayer(c->lf)) { - msg("A blast of energy hits you!"); + msg("^%cA blast of energy hits you!", getlfcol(c->lf, CC_BAD)); } else if (cansee(player, c->lf)) { char lfname[BUFLEN]; getlfname(c->lf, lfname); - msg("A blast of energy hits %s.",lfname); + msg("^%cA blast of energy hits %s.", getlfcol(c->lf, CC_BAD), lfname); } losehp(c->lf, roll("2d6"), DT_MAGIC, caster, "an energy blast"); } @@ -6271,10 +6276,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (lfhasflag(target, F_ASLEEP)) { if (isplayer(target)) { - msg("You suffer terrifying nightmares!"); + msg("^%cYou suffer terrifying nightmares!", getlfcol(target, CC_BAD)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, caster)) { - msg("%s thrashes about in its sleep!",targname); + msg("^%c%s thrashes about in its sleep!",getlfcol(target, CC_BAD), targname); if (seenbyplayer) *seenbyplayer = B_TRUE; } losehp(target, roll("2d6"), DT_DIRECT, caster, "terrifying nightmares"); @@ -6364,11 +6369,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (isplayer(target)) { if (seenbyplayer) *seenbyplayer = B_TRUE; - msg("Unseen forces rip into your flesh!"); + msg("^%cUnseen forces rip into your flesh!", getlfcol(target, CC_VBAD)); } else if (cansee(player, target)) { if (seenbyplayer) *seenbyplayer = B_TRUE; getlfname(target, targetname); - msg("Unseen forces rip into %s%s flesh!", targetname, getpossessive(targetname)); + msg("^%cUnseen forces rip into %s%s flesh!", getlfcol(target, CC_VBAD), targetname, getpossessive(targetname)); } criticalhit(caster, target, getrandomcorebp(target, NULL), NULL, rnd(1,6), DT_SLASH); } else if (spellid == OT_S_GLYPHWARDING) { @@ -6504,9 +6509,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // ALWAYS hits. if (cansee(player, target)) { if (power == 1) { - msg("A bolt of energy hits %s.",lfname); + msg("^%cA bolt of energy hits %s.",getlfcol(target, CC_BAD), lfname); } else { - msg("%s bolts of energy hit %s.",numbuf, lfname); + msg("^%c%s bolts of energy hit %s.",getlfcol(target, CC_BAD), numbuf, lfname); } } losehp(target, rolldie(power*2,4), DT_MAGIC, caster, "an energy bolt"); @@ -6656,7 +6661,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { // hit if (isplayer(target) || cansee(player, target)) { - msg("A dart of flame hits %s.",lfname); + msg("^%cA dart of flame hits %s.",getlfcol(target, CC_BAD), lfname); } losehp(target, rnd(1,6) + power, DT_FIRE, caster, "a dart of flame"); } @@ -6690,7 +6695,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // automatic hit getlfname(targcell->lf, lfname); if (haslos(caster, targcell)) { - msg("%s burn%s!",lfname,isplayer(targcell->lf) ? "" : "s"); + msg("^%c%s burn%s!",getlfcol(targcell->lf, CC_BAD), + lfname,isplayer(targcell->lf) ? "" : "s"); } losehp(targcell->lf, rolldie(2,6), DT_FIRE, caster, "a burst of fire"); } @@ -6860,7 +6866,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } getlfname(target, targname); if (cansee(player, target)) { - msg("Entangling vines rise up and grasp %s!",targname); + msg("^%cEntangling vines rise up and grasp %s!",getlfcol(target, CC_BAD), targname); if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -7057,14 +7063,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isimmuneto(target->flags, DT_COLD, B_FALSE)) { msg("You feel mildly chilly."); } else { - msg("You feel extremely cold!"); + msg("^%cYou feel extremely cold!", getlfcol(target, CC_BAD) ); } if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { if (isimmuneto(target->flags, DT_COLD, B_FALSE)) { msg("%s looks mildly chilly.", lfname); } else { - msg("%s looks extremely cold!", lfname); + msg("^%c%s looks extremely cold!", getlfcol(target, CC_BAD), lfname); } if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -7109,11 +7115,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ sprintf(buf, "being sucked into %s", castername); losehp(c->lf, c->lf->maxhp, DT_DIRECT, target, buf); if (isplayer(c->lf)) { - msg("Your essence is sucked into %s!", castername); + msg("^%cYour essence is sucked into %s!", getlfcol(c->lf, CC_VBAD), castername); } else if (cansee(player, c->lf)) { char lfname[BUFLEN]; getlfname(c->lf, lfname); - msg("%s%s essence is sucked into %s!", lfname, getpossessive(lfname), castername); + msg("^%c%s%s essence is sucked into %s!",getlfcol(c->lf, CC_VBAD), lfname, getpossessive(lfname), castername); } amt++; } @@ -7310,12 +7316,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (bpgone != BP_NONE) { if (isplayer(target)) { - msg("Your %s grows back!", getbodypartname(target, bpgone)); + msg("^%cYour %s grows back!", getlfcol(target, CC_GOOD), getbodypartname(target, bpgone)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { char targname[BUFLEN]; getlfname(target, targname); - msg("%s%s %s grows back!", targname, getpossessive(targname), + msg("^%c%s%s %s grows back!", getlfcol(target, CC_GOOD), targname, getpossessive(targname), getbodypartname(target, bpgone)); if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -7351,7 +7357,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ losehp(target, amt, DT_HOLY, caster, "the power of healing"); if (isplayer(target) || cansee(player, target)) { getlfname(target, buf); - msg("%s writhe%s in agony!", buf, isplayer(target) ? "" : "s"); + msg("^%c%s writhe%s in agony!", getlfcol(target, CC_BAD), buf, isplayer(target) ? "" : "s"); } } else if (target->hp < target->maxhp) { if (!undead && lfhasflagval(target, F_POISONED, P_ROT, NA, NA, NULL)) { @@ -7363,34 +7369,34 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (target->hp >= target->maxhp) { switch (spellid) { case OT_S_HEALINGMIN: - msg("All of your scrapes and bruises are healed!"); + msg("^%cAll of your scrapes and bruises are healed!", getlfcol(target, CC_GOOD)); break; case OT_S_HEALING: default: - msg("Your wounds close themselves!"); + msg("^%cYour wounds close themselves!", getlfcol(target, CC_GOOD)); break; case OT_S_HEALINGMAJ: - msg("Your injuries are healed!"); + msg("^%cYour injuries are healed!", getlfcol(target, CC_GOOD)); break; } } else { switch (spellid) { case OT_S_HEALINGMIN: - msg("Some of your scrapes and bruises are healed!"); + msg("^%cSome of your scrapes and bruises are healed!", getlfcol(target, CC_GOOD)); break; case OT_S_HEALING: default: - msg("Some of your wounds close themselves!"); + msg("^%cSome of your wounds close themselves!", getlfcol(target, CC_GOOD)); break; case OT_S_HEALINGMAJ: - msg("Your injuries are partially healed!"); + msg("^%cYour injuries are partially healed!", getlfcol(target, CC_GOOD)); break; } } if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (haslos(player, target->cell)) { getlfname(target, buf); - msg("%s looks healthier!", buf); + msg("^%c%s looks healthier!", getlfcol(target, CC_GOOD), buf); if (seenbyplayer) *seenbyplayer = B_TRUE; } donesomething = B_TRUE; @@ -7425,11 +7431,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (ismetal(target->race->material->id)) { if (!isimmuneto(target->flags, DT_HEAT, B_FALSE)) { if (isplayer(target)) { - msg("Your suffer massive burns!"); + msg("^%cYou suffer massive burns!", getlfcol(target, CC_BAD) ); } else if (cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); - msg("%s glows red hot!", lfname); + msg("^%c%s glows red hot!", getlfcol(target, CC_BAD), lfname); } losehp(target, roll("6d4"), DT_HEAT, caster, "massive burns"); donesomething = B_TRUE; @@ -7552,12 +7558,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } if (isplayer(target)) { - msg("A sudden hunger comes over you!"); + msg("^%cA sudden hunger comes over you!", getlfcol(target, CC_BAD)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); - msg("%s looks more hungry.", lfname); + msg("^%c%s looks ravenous!", getlfcol(target, CC_BAD), lfname); if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -7594,12 +7600,12 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ getobname(wep, obname, wep->amt); if (isplayer(target)) { - msg("Your %s is covered with ice!", noprefix(obname)); + msg("^%cYour %s is covered with ice!", getlfcol(target, CC_GOOD), noprefix(obname)); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); - msg("%s%s %s is covered with ice!", lfname, getpossessive(lfname), noprefix(obname)); + msg("^%c%s%s %s is covered with ice!", getlfcol(target, CC_GOOD), lfname, getpossessive(lfname), noprefix(obname)); if (seenbyplayer) *seenbyplayer = B_TRUE; } @@ -7625,11 +7631,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ knockback(targcell->lf, getdirtowards(targcell, c, NULL, B_FALSE, DT_COMPASS), 1, NULL, 25+power, B_TRUE); } else { if (isplayer(targcell->lf)) { - msg("You are impaled by an icicle!"); + msg("^%cYou are impaled by an icicle!", getlfcol(targcell->lf, CC_BAD) ); } else if (cansee(player, targcell->lf)) { char lfname[BUFLEN]; getlfname(targcell->lf, lfname); - msg("%s is impaled by an icicle!", lfname); + msg("^%c%s is impaled by an icicle!", getlfcol(targcell->lf, CC_BAD), lfname); } losehp(targcell->lf, rolldie(3,power), DT_PIERCE, caster, "impalement on an icicle"); } @@ -7714,7 +7720,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ 0, B_FALSE, B_FALSE, B_FALSE, B_TRUE, buf); msg("%s", buf); if (seenbyplayer) *seenbyplayer = B_TRUE; - msg("%s is engulfed in roaring flames!", targname); + msg("^%c%s is engulfed in roaring flames!", getlfcol(target, CC_BAD), targname); addobfast(target->cell->obpile, OT_FIREMED); } } else { @@ -7734,7 +7740,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ msg("A wave of incalculable evil blasts outwards from %s!", buf); if (seenbyplayer) *seenbyplayer = B_TRUE; } else if (player->cell->map == caster->cell->map) { // should always be true - msg("Oh no! A wave of incalculable evil washes over you!"); + msg("^%cOh no! A wave of incalculable evil washes over you!", getlfcol(player, CC_VBAD)); } for (l = caster->cell->map->lf ; l ; l = l->next) { if (l != caster) { @@ -7793,9 +7799,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // always hit if (cansee(player, target)) { if (power == 1) { - msg("A spike of mana hits %s.",lfname); + msg("^%cA spike of mana hits %s.",getlfcol(target, CC_BAD), lfname); } else { - msg("%s spikes of mana hit %s.",numbuf, lfname); + msg("^%c%s spikes of mana hit %s.",getlfcol(target, CC_BAD), numbuf, lfname); } } losehp(target, rolldie(power,4), DT_MAGIC, caster, "a mana spike"); @@ -7874,10 +7880,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // works on all metal in sight if (isplayer(caster)) { if (seenbyplayer) *seenbyplayer = B_FALSE; - msg("You draw health from nearby metal!"); + msg("^%cYou draw health from nearby metal!", getlfcol(caster, CC_GOOD)); } else if (cansee(player, caster)) { if (seenbyplayer) *seenbyplayer = B_FALSE; - msg("%s draws health from nearby metal!",castername); + msg("^%c%s draws health from nearby metal!", getlfcol(caster, CC_GOOD),castername); } totalmass = 0; @@ -8767,7 +8773,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { // hit if (cansee(player, target)) { - msg("A glob of venom hits %s.",lfname); + msg("^%cA glob of venom hits %s.",getlfcol(target, CC_BAD), lfname); } if (!isimmuneto(target->flags, DT_POISON, B_FALSE)) { poison(target, power*3, P_VENOM, (power/4)+1, "a glob of venom", caster ? caster->race->id : R_NONE); @@ -8909,9 +8915,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ losehp(target, dam, DT_DIRECT, caster, "a psionic blast"); getlfname(target, targetname); if (isplayer(target)) { - msg("Your brain is blasted!"); + msg("^%cYour brain is blasted!",getlfcol(target, CC_BAD) ); } else if (cansee(player, target)) { - msg("%s%s brain is blasted!",targetname, getpossessive(targetname)); + msg("^%c%s%s brain is blasted!",getlfcol(target, CC_BAD), targetname, getpossessive(targetname)); } } else if (spellid == OT_S_PSYARMOUR) { flag_t *f; @@ -9127,9 +9133,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isplayer(target)) { getobname(o, obname, o->amt); if (haslos(player, newcell)) { - msg("Your %s suddenly appears next to you!", noprefix(obname)); + msg("^%cYour %s suddenly appears next to you!", getlfcol(target, CC_BAD), noprefix(obname)); } else { - msg("Your %s suddenly vanishes!", noprefix(obname)); + msg("^%cYour %s suddenly vanishes!", getlfcol(target, CC_BAD), noprefix(obname)); announcethump = B_TRUE; } @@ -9138,10 +9144,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ getlfname(target, lfname); getobname(o, obname, o->amt); if (haslos(player, newcell)) { - msg("%s%s %s suddenly appears next to it!", lfname, getpossessive(lfname), + msg("^%c%s%s %s suddenly appears next to it!", getlfcol(target, CC_BAD), lfname, getpossessive(lfname), noprefix(obname)); } else { - msg("%s%s %s suddenly vanishes!", lfname, getpossessive(lfname), + msg("^%c%s%s %s suddenly vanishes!", getlfcol(target, CC_BAD), lfname, getpossessive(lfname), noprefix(obname)); } } @@ -9197,11 +9203,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ int dam; // hit if (isplayer(target)) { - msg("A pulse of electricity shocks you!"); + msg("^%cA pulse of electricity shocks you!",getlfcol(target, CC_BAD)); } else if (cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); - msg("A pulse of electricity shocks %s!",lfname); + msg("^%cA pulse of electricity shocks %s!",getlfcol(target, CC_BAD),lfname); } dam = power*2; losehp(target, dam, DT_ELECTRIC, caster, "a jolt of electricity"); @@ -9364,7 +9370,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // the bolt firing, announce it hitting people (since we've already said // "the javelin turns into lightning"). if (!fromob) { - msg("%s shoot%s a bolt of electricity!",castername, isplayer(caster) ? "" : "s"); + msg("%s shoot%s a bolt of lightning!",castername, isplayer(caster) ? "" : "s"); } } @@ -9379,14 +9385,14 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (power > 1) { dam += power; // maxpower is 1, but blue dragons can exceed this } - losehp(c->lf, dam, DT_ELECTRIC, caster, "an electricity bolt"); + losehp(c->lf, dam, DT_ELECTRIC, caster, "a lightning bolt"); nhits--; } if (haslos(player, c)) { if (fromob) { char lfname[BUFLEN]; getlfname(c->lf, lfname); - msg("The bolt of lightning strikes %s!", lfname); + msg("^%cThe bolt of lightning strikes %s!", getlfcol(c->lf, CC_BAD), lfname); } needredraw = B_TRUE; if (seenbyplayer) *seenbyplayer = B_TRUE; @@ -9438,7 +9444,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ for (i = 0; i < ntarg; i++) { if (cansee(player, targ[i])) { getlfname(targ[i],targname); - msg("%s %s struck by a bolt of lightning!",targname, is(targ[i])); + msg("^%c%s %s struck by a bolt of lightning!",getlfcol(targ[i], CC_BAD), + targname, is(targ[i])); } if (caster && (targ[i]->cell->map->habitat->id == H_FOREST)) { losehp(targ[i], rolldie(4,6), DT_ELECTRIC, caster, "a bolt of lightning"); @@ -9737,9 +9744,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (targcell->lf) { char lfname[BUFLEN]; getlfname(targcell->lf, lfname); - msg("A thick veil of mist surrounds %s!", lfname); + msg("^%cA thick veil of mist surrounds %s!", getlfcol(targcell->lf, CC_GOOD), lfname); } else { - msg("A thick veil of mist appears!"); + msg("^%cA thick veil of mist appears!", getlfcol(targcell->lf, CC_GOOD)); } } o = addob(targcell->obpile, "thick mist"); @@ -10391,7 +10398,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // cut power in half f->val[1] /= 2; if (f->val[1] < 1) f->val[1] = 1; if (isplayer(target)) { - msg("Your %s seems less intense.",pt->name); + msg("^%cYour %s seems less intense.",getlfcol(target, CC_GOOD),pt->name); } ndone++; } @@ -10417,11 +10424,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } amttolose = power*2; if (isplayer(target)) { - msg("You suddenly feel very lethargic!"); + msg("^%cYou suddenly feel very lethargic!", getlfcol(target, CC_BAD)); } else if (cansee(player, target)) { char targname[BUFLEN]; getlfname(target, targname); - msg("%s looks very lethargic!", targname); + msg("%s looks very lethargic!", getlfcol(target, CC_BAD), targname); } modstamina(target, -amttolose); } else if (spellid == OT_S_REFRACTION) { @@ -10429,9 +10436,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ f = addtempflag(caster->flags, F_EVASION, 15+(power*5), NA, NA, NULL, FROMSPELL); f->obfrom = spellid; if (isplayer(caster)) { - msg("Your body seems to shimmer and bend!"); + msg("^%cYour body seems to shimmer and bend!", getlfcol(caster, CC_GOOD)); } else if (cansee(player, caster)) { - msg("%s%s body seems to shimmer and bend!", castername, getpossessive(castername)); + msg("^%c%s%s body seems to shimmer and bend!", getlfcol(caster, CC_GOOD), + castername, getpossessive(castername)); } } else if (spellid == OT_S_REPELINSECTS) { // just announce @@ -10545,7 +10553,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isundead(target)) { if (seen) { - msg("%s writhe%s in agony!", lfname, isplayer(target) ? "" : "s"); + msg("^%c%s writhe%s in agony!",getlfcol(target, CC_BAD), lfname, isplayer(target) ? "" : "s"); } losehp(target, power*10, DT_HOLY, caster, "the power of restoration"); return B_FALSE; @@ -10589,7 +10597,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ gainhp(target, hpheal - target->hp); failed = B_FALSE; if (!isplayer(target) && cansee(player, target)) { - msg("%s%s health has been restored!", lfname, getpossessive(lfname)); + msg("^%c%s%s health has been restored!", getlfcol(target, CC_GOOD),lfname, getpossessive(lfname)); } } if (target->mp < mpheal) { @@ -10831,10 +10839,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ // 2nd one failed - lose all stamina instead modstamina(target, -(getstamina(target))); if (isplayer(target)) { - msg("You suddenly feel very lethargic!"); + msg("^%cYou suddenly feel very lethargic!",getlfcol(target, CC_BAD)); } else if (cansee(player, target)) { getlfname(target, buf); - msg("%s looks very lethargic!", buf); + msg("^%c%s looks very lethargic!", getlfcol(target, CC_BAD),buf); } } return B_FALSE; @@ -10922,11 +10930,13 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ return B_TRUE; } if (isplayer(target)) { - msg("The power of %s smites you!", (spellid == OT_S_SMITEEVIL) ? "good" : "evil"); + msg("^%cThe power of %s smites you!",getlfcol(target, CC_BAD), + (spellid == OT_S_SMITEEVIL) ? "good" : "evil"); } else if (cansee(player, target)) { char lfname[BUFLEN]; getlfname(target, lfname); - msg("The power of %s smites %s!", (spellid == OT_S_SMITEEVIL) ? "good" : "evil", lfname); + msg("^%cThe power of %s smites %s!", getlfcol(target, CC_BAD), + (spellid == OT_S_SMITEEVIL) ? "good" : "evil", lfname); } // use direct damage rather than holy, because otherwise it might be increased // due to vulnerabilities @@ -11057,7 +11067,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (targcell->lf && cansee(player, targcell->lf)) { char lfname[BUFLEN]; getlfname(targcell->lf, lfname); - msg("A small burst of flame singes %s.", lfname); + msg("^%cA small burst of flame singes %s.", getlfcol(targcell->lf, CC_BAD),lfname); } else { msg("A small burst of flame appears."); } @@ -12038,16 +12048,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } // announce if (isplayer(target)) { - msg("A blade of pure energy forms in your hands!"); + msg("^%cA blade of pure energy forms in your hands!", getlfcol(target, CC_GOOD)); } else if (cansee(player, target)) { - msg("A blade of pure energy forms in %s%s hands!",castername, + msg("^%cA blade of pure energy forms in %s%s hands!", getlfcol(target, CC_GOOD),castername, getpossessive(castername)); } weild(target, o); // set its damage value f = hasflag(o->flags, F_DAM); if (f) { - f->val[1] = 2+power; + f->val[1] = 3+power; } addflag(o->flags, F_CREATEDBYSPELL, spellid, NA, NA, NULL); } else { @@ -12475,11 +12485,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ } else { addob(c->obpile, "web"); if (isplayer(c->lf)) { - msg("You are stuck in a web!"); + msg("^%cYou are stuck in a web!", getlfcol(c->lf, CC_BAD)); } else if (cansee(player, c->lf)) { char lfname[BUFLEN]; getlfname(c->lf, lfname); - msg("%s is stuck in a web!", lfname); + msg("^%c%s is stuck in a web!", getlfcol(c->lf, CC_BAD), lfname); } } } @@ -12732,7 +12742,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_ if (isplayer(target)) { p = assignnpcname(lf->flags); - sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p); + sayphrase(lf, SP_RECRUIT_ACCEPT, SV_TALK, NA, p, lf); } strcpy(buf, ""); @@ -13941,7 +13951,7 @@ int schoolappearsinbooks(enum SPELLSCHOOL ss) { return B_TRUE; } -void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes, object_t *fromob) { +void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes, object_t *fromob, int includecentre) { int x,y; char *see = NULL, *nosee = NULL; objecttype_t *ot; @@ -13980,9 +13990,12 @@ void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE for (x = srcloc->x - radius ; x <= srcloc->x + radius; x++) { cell_t *c; c = getcellat(srcloc->map, x, y); - if (c && c->lf && (c != srcloc) && !c->type->solid && + if (c && c->lf && !c->type->solid && haslof(srcloc, c, LOF_WALLSTOP, NULL)) { int safe = B_FALSE; + if (!includecentre && (c == srcloc)) { + safe = B_TRUE; + } if (aimedateyes && (!hasbp(c->lf, BP_EYES) || getarmour(c->lf, BP_EYES))) { safe = B_TRUE; } diff --git a/spell.h b/spell.h index feecc03..5c92eb7 100644 --- a/spell.h +++ b/spell.h @@ -36,7 +36,7 @@ int getworkablematerials(lifeform_t *lf, enum SKILL skid , enum MATERIAL *repair object_t *getworkhelpob(obpile_t *op, enum MATERIAL mat); void pullobto(object_t *o, lifeform_t *lf); int schoolappearsinbooks(enum SPELLSCHOOL ss); -void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes, object_t *fromob); +void spellcloud(cell_t *srcloc, int radius, int ch, enum COLOUR col, enum OBTYPE sid, int power, int frompot, char *seetext, char *noseetext, int aimedateyes, object_t *fromob, int includecentre); int spellisfromschool(int spellid, enum SPELLSCHOOL school); int spellokformonsters(int spellid); int spellresisted(lifeform_t *target, lifeform_t *caster, int spellid, int power, int *seenbyplayer, int announce); diff --git a/text.c b/text.c index d44e76f..2ea8658 100644 --- a/text.c +++ b/text.c @@ -2428,6 +2428,20 @@ int strpixmatch(char *haystack, char *needle) { return matched; } +enum VAULTTHING strtovt(char *text) { + enum VAULTTHING tt; + if (streq(text, "ob")) { + tt = VT_OB; + } else if (streq(text, "mon")) { + tt = VT_LF; + } else if (streq(text, "cell")) { + tt = VT_CELL; + } else { + tt = VT_NONE; + } + return tt; +} + int texttodice(char *text, int *ndice, int *nsides, int *bonus) { char *dummy; char *localtext; diff --git a/text.h b/text.h index cb805ef..3afd234 100644 --- a/text.h +++ b/text.h @@ -73,6 +73,7 @@ char *strstarts(char *a, char *prefix); char *strstartswitha(char *text, char *retprefix); int strlen_without_colours(char *buf); int strpixmatch(char *haystack, char *needle); +enum VAULTTHING strtovt(char *text); int texttodice(char *text, int *ndice, int *nsides, int *bonus); int texttospellopts(char *text, ... ); //void texttospellopts(char *text, int *power, char *damstr, int *needgrab, int *range, char *racestr); diff --git a/vault.c b/vault.c index fe4d84b..485c87c 100644 --- a/vault.c +++ b/vault.c @@ -22,7 +22,7 @@ extern lifeform_t *player; extern enum GAMEMODE gamemode; -vlegend_t *addlegend(vault_t *v, int ch, enum VAULTTHING tt, int pct, char *what) { +vlegend_t *addlegend(vault_t *v, int ch, enum VAULTTHING tt, int pct, char *what, enum VAULTTHING tt2, char *what2) { vlegend_t *l; // add to the end of the list @@ -46,6 +46,13 @@ vlegend_t *addlegend(vault_t *v, int ch, enum VAULTTHING tt, int pct, char *what l->tt = tt; l->pct = pct; l->what = strdup(what); + // alternatives... + l->tt2 = tt2; + if (what2) { + l->what2 = strdup(what2); + } else { + l->what2 = strdup(""); + } return l; } @@ -102,12 +109,15 @@ void addvaultcellcontents(cell_t *c, vault_t *v, int x, int y, int rotation) { if (l->ch == ch) { if (rnd(1,100) <= l->pct) { addvaultthing(c, v, l->tt, l->what); + } else if (l->tt2 != VT_NONE) { + addvaultthing(c, v, l->tt2, l->what2); } } } } +// add vault contents based on flags void addvaultcontents(map_t *m, vault_t *v, int minx, int miny, int maxx, int maxy, int rotation) { flag_t *f; char buf[BUFLEN]; @@ -917,39 +927,51 @@ int handleline(vault_t *v, char *line) { // legend definition if (nargs >= 2) { int pct; - enum VAULTTHING tt; - char what[BUFLEN]; - if (streq(arg[0], "ob")) { - tt = VT_OB; - } else if (streq(arg[0], "mon")) { - tt = VT_LF; - } else if (streq(arg[0], "cell")) { - tt = VT_CELL; - } else { - tt = VT_NONE; - } - + enum VAULTTHING tt,tt2; + char what[BUFLEN],what2[BUFLEN]; + + // default is no alternative + tt2 = VT_NONE; + strcpy(what2, ""); + + // get ob specification + tt = strtovt(arg[0]); strcpy(what, arg[1]); - - if (nargs == 3) { // ie have a percentage + if (nargs >= 3) { // ie have a percentage pct = atoi(arg[2]); } else { pct = 100; } - if (tt == VT_NONE) { + if (nargs == 5) { // have alternative value if percentage fails + tt2 = strtovt(arg[3]); + strcpy(what2, arg[4]); + } + + if (nargs == 4) { + dblog("alternative obtype given but no alternative ob text"); + } else if (tt == VT_NONE) { dblog("invalid type in legend definition"); - } else if (vaultthingok(tt, what)) { - // validated ok. - addlegend(v, command[0], tt, pct, what); - ok = B_TRUE; } else { - dblog("invalid legend definition: '%s'", line); + int error = B_FALSE; + if (!vaultthingok(tt, what)) { + dblog("invalid legend definition: '%s'", line); + error = B_TRUE; + } + if ((tt2 != VT_NONE) && !vaultthingok(tt2,what2)) { + dblog("invalid legend alternative definition: '%s'", line); + error = B_TRUE; + } + if (!error) { + // validated ok. + addlegend(v, command[0], tt, pct, what, tt2, what2); + ok = B_TRUE; + } } } else { // special legend... if (streq(arg[0], "exit")) { - addlegend(v, command[0], VT_EXIT, 100, ""); + addlegend(v, command[0], VT_EXIT, 100, "", VT_NONE, NULL); ok = B_TRUE; } else { dblog("invalid syntax for legend value"); @@ -1283,6 +1305,44 @@ int handleline(vault_t *v, char *line) { } else if (streq(line, "autopop")) { addflag(v->flags, F_AUTOPOPULATE, B_TRUE, NA, NA, NULL); ok = B_TRUE; + } else if (strstarts(line, "cellempty")) { + char *p; + p = line + strlen("cellempty"); + if (*p == ':') { + char buf[BUFLEN]; + celltype_t *ct; + p++; + p = readuntil(buf, p, ','); // eol + // validate celltype name + ct = findcelltypebyname(buf); + if (ct) { + addflag(v->flags, F_CELLTYPEEMPTY, ct->id, NA, NA, NULL); + ok = B_TRUE; + } else { + dblog("invalid celltype specified in cellempty definition: '%s'", line); + } + } else { + dblog("syntax error in cellempty definition: '%s'", line); + } + } else if (strstarts(line, "cellsolid")) { + char *p; + p = line + strlen("cellsolid"); + if (*p == ':') { + char buf[BUFLEN]; + celltype_t *ct; + p++; + p = readuntil(buf, p, ','); // eol + // validate celltype name + ct = findcelltypebyname(buf); + if (ct) { + addflag(v->flags, F_CELLTYPESOLID, ct->id, NA, NA, NULL); + ok = B_TRUE; + } else { + dblog("invalid celltype specified in cellsolid definition: '%s'", line); + } + } else { + dblog("syntax error in cellsolid definition: '%s'", line); + } } else if (strstarts(line, "dlevmax")) { // dlevmax:max char *p; @@ -1483,6 +1543,7 @@ int handleline(vault_t *v, char *line) { void killlegend(vlegend_t *l) { vlegend_t *nextone,*lastone; if (l->what) free(l->what); + if (l->what2) free(l->what2); // deallocate nextone = l->next; diff --git a/vault.h b/vault.h index ac202bf..f9d477c 100644 --- a/vault.h +++ b/vault.h @@ -1,6 +1,6 @@ #include "defs.h" -vlegend_t *addlegend(vault_t *v, int ch, enum VAULTTHING tt, int pct, char *what); +vlegend_t *addlegend(vault_t *v, int ch, enum VAULTTHING tt, int pct, char *what, enum VAULTTHING tt2, char *what2); vault_t *addvault(void); void addvaultcellcontents(cell_t *c, vault_t *v, int x, int y, int rotation); void addvaultcontents(map_t *m, vault_t *v, int minx, int miny, int maxx, int maxy, int rotationmapnum);