- [+] 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, <racename>" 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
This commit is contained in:
Rob Pearce 2012-07-15 05:01:58 +00:00
parent af3116f6d4
commit c421529221
25 changed files with 839 additions and 483 deletions

35
ai.c
View File

@ -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,14 +1008,13 @@ 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) {
@ -1038,17 +1041,20 @@ int ai_bored(lifeform_t *lf, lifeform_t *master, int icanattack) {
return B_TRUE;
}
}
}
///////////////////////////////////////////////
// resting / healing
///////////////////////////////////////////////
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,7 +1167,6 @@ 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)) {
@ -1201,7 +1207,6 @@ int ai_healing(lifeform_t *lf) {
}
}
}
}
return B_FALSE;
}
@ -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

View File

@ -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)) {

88
data.c
View File

@ -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");
}

2
data.h
View File

@ -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);

Binary file not shown.

View File

@ -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

View File

@ -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

22
defs.h
View File

@ -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?

View File

@ -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)

31
god.c
View File

@ -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,25 +1991,12 @@ 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;
}
if (n == OT_S_HECTASSERVANT) {
if (c) {
castspell(god, n, player, NULL, c, NULL, NULL);
n = OT_NONE;
} else {
n = OT_S_DRAINLIFE;
}
case 1: n = OT_S_HECTASSERVANT; break;
}
if (n != OT_NONE) {
// kill first lifeform in sight.
for (i = 1; i < lf->nlos; i++) {
lifeform_t *who;
who = lf->los[i]->lf;
@ -2021,11 +2008,17 @@ int prayto(lifeform_t *lf, lifeform_t *god) {
who->lastdamtype = DT_NECROTIC;
setlastdam(who, "Hecta's finger of death.");
who->hp = 0;
} 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;
} 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 {
dospelleffects(god, n, 20, who, NULL, who->cell, B_UNCURSED, NULL, B_FALSE, NULL);
}
break;
}
}
}

68
io.c
View File

@ -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;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
// chance of calming hostile intelligen, monsters
if ((getallegiance(lf) == AL_HOSTILE) && (iqb >= IQ_ANIMAL) && cansee(lf, player)) {
int mod = 0;
int wanted = B_FALSE, covetted = B_FALSE;
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
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)) {
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 {
}
} 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));

169
lf.c
View File

@ -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);
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:
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:
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) {
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;
}
}

5
lf.h
View File

@ -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);

149
map.c
View File

@ -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,6 +5168,8 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
int n;
cell_t *c2;
startdist++;
// 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;
@ -5184,6 +5222,7 @@ int linkexit(cell_t *startcell, int wantfilled, int *ncellsadded) {
}
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);

5
map.h
View File

@ -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);

24
nexus.c
View File

@ -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();

View File

@ -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);

View File

@ -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,6 +13649,8 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
catchmod = -6;
dodgemod = 2;
}
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) &&
@ -13636,8 +13658,9 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
!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 if (hasfreeaction(target) && skillcheck(target, SC_DODGE, 27+(speed*2), dodgemod)) {
} else {
// then check if we dodge it...
if (db) dblog("target passed dodge check.");
@ -13655,6 +13678,7 @@ int real_fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int sp
}
}
}
}
// doesn't matter wheter you hit or not...
if (isundead(target) && isblessed(o)) {

View File

@ -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);

211
spell.c
View File

@ -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;
}

View File

@ -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);

14
text.c
View File

@ -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;

1
text.h
View File

@ -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);

101
vault.c
View File

@ -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 {
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;

View File

@ -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);