- [+] monsters should automatically attack locked doors if they're

chasing the plaeyr
- [+] if a monster tries to open a jammed door, make a noise
* [+] glyph of warding spell - monsters won't walk on it
- [+] ice crust not working? fixed.
- [+] seal entrance should close doors too
- [+] more kinds of wizard staff
* [+] replace 'freezing touch' with something more useful.
- [+] in askcoords, writing:xxx, use colours
- [+] replace poisongas damtype name with 'gas'
* [+] redo skill screen
- [+] make ash clouds (sleeping etc) not affect thrower's square?
- [+] There is a magical inscription here:  ""
* [+] rename some spells
* [+] poltergeist spell keeps missing.
- [+] reduce fire damage from burning objects in pack, or equipped
- [+] first spell in beginner spellbook should be the one we know. 
- [+] fix bug with item inspect ability
* [+] stamina food
* [+] locate object issues
- [+] still got a wrapprint bug when showing spell descriptions.
This commit is contained in:
Rob Pearce 2011-11-01 20:35:50 +00:00
parent 6bbf4d56d2
commit 965fcdd4c0
18 changed files with 666 additions and 240 deletions

2
ai.c
View File

@ -811,7 +811,7 @@ int aimovetolf(lifeform_t *lf, lifeform_t *target, int wantattack) {
if (db) dblog(".oO { i don't know my target's last known movement dir. }");
} else {
// try going in last known dir
if (db) dblog(".oO { trying my master's last known move dir (%s) }",getdirname(lastdir));
if (db) dblog(".oO { trying target's last known move dir (%s) }",getdirname(lastdir));
if (!trymove(lf, lastdir, B_TRUE, B_FALSE)) {
if (db) dblog(".oO { ...successfully }");
// we now don't know their last known dir.

View File

@ -1259,35 +1259,49 @@ int attackob(lifeform_t *lf, object_t *o, object_t *wep, flag_t *damflag) {
construct_hit_string(lf, NULL, attackername, obname, NULL, wep, damtype[i], dam[i], maxhp, i, B_FALSE, B_FALSE, B_FALSE, isunarmed, buf);
/*
if (isplayer(lf)) {
char extradambuf[BUFLEN];
if (lfhasflag(player, F_EXTRAINFO) || lfhasflag(player, F_OMNIPOTENT) ) {
snprintf(extradambuf, BUFLEN, " [%d dmg]",dam[i]);
} else {
strcpy(extradambuf, "");
}
msg("You %s %s.", getattackverb(lf, wep, damtype[i], dam[i], maxhp),
obname, extradambuf);
} else if (cansee(player, lf)) {
char withwep[BUFLEN];
if (wep && !isunarmed && !isblind(player)) { // announce weapon used
snprintf(withwep, BUFLEN, " with %s", wepname);
} else {
strcpy(withwep, "");
}
msg("%s %ss %s%s.", attackername,
getattackverb(lf, wep, damtype[i],dam[i],maxhp), obname,withwep);
} else {
noise(lf->cell, NULL, NC_OTHER, 3, "sounds of fighting.", NULL);
}
*/
if (strlen(buf)) {
msg("%s", buf);
}
if (!isplayer(lf) && !cansee(player, lf)) {
noise(lf->cell, lf, NC_OTHER, 3, "sounds of fighting.", NULL);
char noisebuf[BUFLEN];
int vol;
switch (o->material->id) {
case MT_METAL:
strcpy(noisebuf, "a metallic clanging.");
vol = 4;
break;
case MT_GLASS:
strcpy(noisebuf, "cracking glass.");
vol = 4;
break;
case MT_WOOD:
case MT_DRAGONWOOD:
strcpy(noisebuf, "splintering wood.");
vol = 4;
break;
case MT_BONE:
case MT_STONE:
strcpy(noisebuf, "a dull thumping.");
vol = 3;
break;
case MT_GOLD:
case MT_SILVER:
case MT_LEATHER:
strcpy(noisebuf, "a dull thumping.");
vol = 2;
break;
case MT_PAPER:
case MT_WETPAPER:
case MT_RUBBER:
strcpy(noisebuf, "a dull thumping.");
vol = 1;
break;
default:
strcpy(noisebuf, "something being hit.");
vol = 3;
break;
}
noise(obloc, NULL, NC_OTHER, vol, noisebuf, NULL);
}
if ((i == 0) && (wep->type->id == OT_FISTS) && hasflag(o->flags, F_HARDNESS)) {

133
data.c
View File

@ -408,6 +408,7 @@ void initjobs(void) {
// initial skills
addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL); // limit
addflag(lastjob->flags, F_STARTSKILL, SK_EVASION, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_BEGINNER, NA, NULL);
@ -419,7 +420,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_TECHUSAGE, PR_BEGINNER, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_ARMOUR, PR_NOVICE, NA, NULL); // limit
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, PR_BEGINNER, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, PR_BEGINNER, NA, NULL); // limit
addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
@ -621,7 +622,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_JOBATTRMOD, A_IQ, 4, NA, NULL);
addflag(lastjob->flags, F_JOBATTRMOD, A_CON, -3, NA, NULL);
// initial objects
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "enchanted wizard staff");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "neophyte staff");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "wizard hat");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "robe");
addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "2 potions of magic");
@ -635,6 +636,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_STARTSKILL, SK_CHANNELING, PR_NOVICE, NA, NULL);
addflag(lastjob->flags, F_STARTSKILL, SK_STAVES, PR_NOVICE, NA, NULL);
// learnable skills
addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, PR_ADEPT, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_SHORTBLADES, PR_NOVICE, NA, NULL);
@ -928,6 +930,7 @@ void initobjects(void) {
addmaterial(MT_DRAGONWOOD, "dragonwood", 3);
addflag(lastmaterial->flags, F_HARDNESS, 5, NA, NA, NULL);
addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL);
addflag(lastmaterial->flags, F_DTIMMUNE, DT_FIRE, NA, NA, NULL);
addmaterial(MT_RUBBER, "rubber", 4);
addmaterial(MT_LEATHER, "leather", 4);
addflag(lastmaterial->flags, F_CANGETWET, B_TRUE, NA, NA, NULL);
@ -2180,7 +2183,7 @@ void initobjects(void) {
// elemental - fire
///////////////////
// l1
addot(OT_S_SPARK, "spark", "Creates a tiny spark of flame, dealing 1-3 fire damage to creatures and objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_SPARK, "flambe", "Creates very hot but short lived burst of flame around the target, dealing 1-6 fire damage to creatures and objects.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_FIRE, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_NATURE, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_MONSTER, NA, NA, NULL);
@ -2264,6 +2267,7 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_NORANDOM, B_TRUE, NA, NA, NULL);
addot(OT_S_ICECRUST, "ice crust", "Enrusts your bladed weapon with a layer of ice.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how long the enchantment will remain.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
@ -2272,14 +2276,23 @@ void initobjects(void) {
addflag(lastot->flags, F_TARGETTEDSPELL, TT_ALLY, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOATTACK, ST_SELF, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_CRYSTALSHIELD, "crystalline shield", "Summons a shield of ice crystals to protect you from missiles.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how effective the shield is.");
addot(OT_S_CRYSTALARM, "crystalline armour", "Summons ice crystal armour to protect you from damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 1-3: one piece of armour is created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 4-6: two pieces of armour are created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 7-9: three pieces of armour are created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 10: four pieces of armour are created.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 2, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
// l3
addot(OT_S_CRYSTALSHIELD, "crystalline shield", "Summons a shield of ice crystals to protect you from missiles.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how effective the shield is.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 3, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 6, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_COLDRAY, "cold ray", "Shoots a blast of ice cold air, dealing 3d6 cold damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "Spell power determines how difficult the ray is to dodge.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
@ -2323,15 +2336,6 @@ void initobjects(void) {
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_AICASTTOFLEE, ST_VICTIM, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_CRYSTALARM, "crystalline armour", "Summons ice crystal armour to protect you from damage.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 1-3: one piece of armour is created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 4-6: two pieces of armour are created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 7-9: three pieces of armour are created.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "At power 10: four pieces of armour are created.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 4, NA, NA, NULL);
addflag(lastot->flags, F_ONGOING, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_FALSE, LOF_DONTNEED, NA, NULL);
addot(OT_S_SHARDSHOT, "shard shot", "Fires a scattered burst of small, fast moving ice shards. The shot will pass through multiple creatures, but damage is reduced with range.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's range is determined by its power.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_COLD, NA, NA, NULL);
@ -2782,7 +2786,7 @@ void initobjects(void) {
// modification
///////////////////
// l1
addot(OT_S_HOLDPORTAL, "seal entrance", "Prevents a door from opening.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_HOLDPORTAL, "seal entrance", "Magically closes and jams a door, preventing it from opening.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_SPELLSCHOOL, SS_MODIFICATION, NA, NA, NULL);
addflag(lastot->flags, F_SPELLSCHOOL, SS_ENCHANTMENT, NA, NA, NULL);
addflag(lastot->flags, F_TARGETTEDSPELL, TT_DOOR, NA, NA, NULL);
@ -2870,6 +2874,13 @@ void initobjects(void) {
// summoning
///////////////////
// l1
addot(OT_S_GLYPHWARDING, "glyph of warding", "Inscribes a magical glyph in the ground which wards off monsters.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The glyph will stop monsters up to ^bpower^n/2 hit dice.");
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The glyph will last for ^bpower^n*5 turns.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
addflag(lastot->flags, F_MAXPOWER, 10, NA, NA, NULL);
addflag(lastot->flags, F_LOSLOF, B_TRUE, LOF_DONTNEED, NA, NULL);
addot(OT_S_FLOATINGDISC, "floating disc", "Creates a disc of energy to carry your equipment.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power level determines how much wight the disc can carry.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_SUMMONING, NA, NA, NULL);
@ -5314,13 +5325,69 @@ void initobjects(void) {
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_CRITCHANCE, 8, NA, NA, NULL);
addot(OT_WIZARDSTAFF, "wizard staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addot(OT_WIZARDSTAFF, "neophyte staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 4, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_STAVES, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 10, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addot(OT_WIZARDSTAFF2, "enchanter staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_UNCOMMON, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 4, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 1, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 12, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addot(OT_WIZARDSTAFF3, "sorcerer staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 4, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 2, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 14, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addot(OT_WIZARDSTAFF4, "spellbinder staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 4, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 3, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 16, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addot(OT_WIZARDSTAFF5, "warlock staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_RARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 4, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 4, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 17, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
addot(OT_WIZARDSTAFF6, "archmagi staff", "A twisted branch of wood.", MT_DRAGONWOOD, 4, OC_WEAPON, SZ_HUMAN);
addflag(lastot->flags, F_RARITY, H_DUNGEON, 100, RR_VERYRARE, NULL);
addflag(lastot->flags, F_DAM, DT_BASH, 4, NA, NULL);
addflag(lastot->flags, F_OBATTACKDELAY, 100, NA, NA, NULL);
addflag(lastot->flags, F_ACCURACY, 80, NA, NA, NULL);
addflag(lastot->flags, F_USESSKILL, SK_LORE_ARCANA, NA, NA, NULL);
addflag(lastot->flags, F_RODSHAPED, B_TRUE, NA, NA, NULL);
addflag(lastot->flags, F_EQUIPCONFER, F_MAGICBOOST, 5, NA, NULL);
addflag(lastot->flags, F_ATTREQ, A_IQ, 18, NA, NULL);
addflag(lastot->flags, F_HASHIDDENNAME, B_TRUE, NA, NA, "twisted branch");
// clubs (bashing)
@ -5600,7 +5667,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+2");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d3+4");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 2, NA, NULL);
@ -5625,6 +5692,7 @@ void initrace(void) {
// penalties
addflag(lastrace->flags, F_DTVULN, DT_FIRE, NA, NA, NULL);
addflag(lastrace->flags, F_DTVULN, DT_ELECTRIC, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+3");
// other special stuff
addflag(lastrace->flags, F_NOISETEXT, N_GETANGRY, 3, NA, "screechs^a screech");
addflag(lastrace->flags, F_BODYPARTNAME, BP_HANDS, NA, NA, "talons");
@ -5634,7 +5702,6 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_UNCOMMON, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+3");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_STARTJOB, 75, J_RANDOM, NA, NULL);
@ -5695,7 +5762,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_RARE, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_MEDIUM, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+3");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d3+4");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 2, NA, NULL);
@ -5721,7 +5788,7 @@ void initrace(void) {
addflag(lastrace->flags, F_RARITY, H_FOREST, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_VARLEVEL, NA, NA, NA, NULL);
addflag(lastrace->flags, F_SIZE, SZ_HUMAN, NA, NA, NULL);
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+3");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d2+4");
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_FISTS, 2, NA, NULL);
@ -6936,7 +7003,7 @@ void initrace(void) {
addflag(lastrace->flags, F_MOVESPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_SPELLSPEED, SP_NORMAL, NA, NA, NULL);
addflag(lastrace->flags, F_ACTIONSPEED, SP_NORMAL, NA, NA, "");
addflag(lastrace->flags, F_CANCAST, OT_S_TELEKINESIS, NA, NA, NULL);
addflag(lastrace->flags, F_CANWILL, OT_S_TELEKINESIS, NA, NA, "pw:5;");
addflag(lastrace->flags, F_SPELLCASTTEXT, NA, NA, B_APPENDYOU, "gestures");
addflag(lastrace->flags, F_NOBODYPART, BP_WEAPON, NA, NA, NULL);
addflag(lastrace->flags, F_NOBODYPART, BP_SECWEAPON, NA, NA, NULL);
@ -7371,7 +7438,7 @@ void initrace(void) {
addflag(lastrace->flags, F_SIZE, SZ_SMALL, NA, NA, NULL);
addflag(lastrace->flags, F_MOVESPEED, SP_VERYFAST, NA, NA, "");
addflag(lastrace->flags, F_FLYING, B_TRUE, NA, NA, "");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "2d4+2");
addflag(lastrace->flags, F_HITDICE, NA, NA, NA, "1d4+2");
addflag(lastrace->flags, F_HASATTACK, OT_TEETH, 2, NA, NULL);
addflag(lastrace->flags, F_HASATTACK, OT_CLAWS, 3, NA, NULL);
addflag(lastrace->flags, F_MAXATTACKS, 1, 1, NA, NULL);
@ -8093,7 +8160,7 @@ void initrace(void) {
addflag(lastrace->flags, F_TREMORSENSE, 10, NA, NA, NULL);
addflag(lastrace->flags, F_DIURNAL, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_NOFLEE, B_TRUE, NA, NA, NULL);
addrace(R_SPIDER, "giant spider", 5, 'S', C_GREY, MT_FLESH, RC_ANIMAL, "An eight legged beast who is the central feature in many nightmares.");
addrace(R_SPIDER, "giant spider", 5, 'S', C_GREY, MT_FLESH, RC_ANIMAL, "An eight legged beast which features prominently in many nightmares.");
addflag(lastrace->flags, F_RARITY, H_DUNGEON, NA, RR_COMMON, NULL);
addflag(lastrace->flags, F_HOSTILE, B_TRUE, NA, NA, NULL);
addflag(lastrace->flags, F_STARTATT, A_AGI, AT_GTAVERAGE, NA, NULL);
@ -9036,13 +9103,13 @@ void initskills(void) {
addskilldesc(SK_SS_COLD, PR_SKILLED, "Allows you to cast Cold Magic spells up to level 4.", B_FALSE);
addskilldesc(SK_SS_COLD, PR_EXPERT, "Allows you to cast Cold Magic spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_COLD, PR_MASTER, "Allows you to cast Cold Magic spells up to level 6.", B_FALSE);
addskill(SK_SS_GRAVITY, "Sorcery:Gravitation Magic", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_GRAVITY, PR_NOVICE, "Allows you to cast Gravitation Magic spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_BEGINNER, "Allows you to cast Gravitation Magic spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_ADEPT, "Allows you to cast Gravitation Magic spells up to level 3.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_SKILLED, "Allows you to cast Gravitation Magic spells up to level 4.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_EXPERT, "Allows you to cast Gravitation Magic spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_MASTER, "Allows you to cast Gravitation Magic spells up to level 6.", B_FALSE);
addskill(SK_SS_GRAVITY, "Sorcery:Gravitation", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_GRAVITY, PR_NOVICE, "Allows you to cast Gravitation spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_BEGINNER, "Allows you to cast Gravitation spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_ADEPT, "Allows you to cast Gravitation spells up to level 3.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_SKILLED, "Allows you to cast Gravitation spells up to level 4.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_EXPERT, "Allows you to cast Gravitation spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_GRAVITY, PR_MASTER, "Allows you to cast Gravitation spells up to level 6.", B_FALSE);
addskill(SK_SS_LIFE, "Sorcery:Life Magic", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_LIFE, PR_NOVICE, "Allows you to cast Life Magic spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_LIFE, PR_BEGINNER, "Allows you to cast Life Magic spells up to level 2.", B_FALSE);

Binary file not shown.

19
defs.h
View File

@ -481,6 +481,8 @@ enum SKILL {
SK_UNARMED,
// spell schools
SK_SS_ALLOMANCY,
SK_SS_MENTAL,
SK_SS_NATURE,
SK_SS_AIR,
SK_SS_DEATH,
SK_SS_DIVINATION,
@ -490,8 +492,6 @@ enum SKILL {
SK_SS_GRAVITY,
SK_SS_LIFE,
SK_SS_MODIFICATION,
SK_SS_MENTAL,
SK_SS_NATURE,
SK_SS_SUMMONING,
SK_SS_TRANSLOCATION,
SK_SS_WILD,
@ -1269,6 +1269,7 @@ enum OBTYPE {
OT_S_WATERJET,
// -- summoning
OT_S_FLOATINGDISC,
OT_S_GLYPHWARDING,
OT_S_CLEARLEVEL,
OT_S_CREATEMONSTER,
OT_S_SUMMONWEAPON,
@ -1616,6 +1617,11 @@ enum OBTYPE {
OT_IRONSTAFF,
OT_BLADEDSTAFF,
OT_WIZARDSTAFF,
OT_WIZARDSTAFF2,
OT_WIZARDSTAFF3,
OT_WIZARDSTAFF4,
OT_WIZARDSTAFF5,
OT_WIZARDSTAFF6,
// clubs
OT_CLUB,
OT_FLAIL,
@ -2003,6 +2009,7 @@ enum FLAG {
// should always be singular
F_OBATTACKDELAY, // how long weapon takes to attack
F_USESSKILL, // weapon needs skill sk_v0
F_MAGICBOOST, // boost power of all spells by v0
F_CANHAVEOBMOD, // weapon can have obmod om_v0 applied
// optional: v1 is chance of randomly having it
F_ATTREQ, // requires attrib v0 to be at least v1
@ -2217,6 +2224,7 @@ enum FLAG {
F_AVOIDOBTYPE, // AI won't walk on top of obtype v0.
// if v1 == B_TRUE, then avoid lfs weilding this
// object too.
F_AVOIDCELL, // AI won't walk on top of cell x/y = v0/v1
F_STAYINHABITAT, // lf will not walk onto a cell of a different
// habitat
F_STAYINROOM, // lf will not walk out of roomid v0
@ -2318,7 +2326,7 @@ enum FLAG {
F_ACTIONSPEED, // override default action speed
F_SPELLSPEED, // override default spellcast speed (ie. movespeed)
F_RARITY, // val[0] = habitat, val[1] = rarity%
// opt. val[2] = commonality (enum RARITY RR_xxx)
// val[2] = commonality (enum RARITY RR_xxx)
// NA means rr_common
F_NUMAPPEAR, // when randomly appearing, can have > 1. val[0] = min, val[1] = max
@ -2393,6 +2401,9 @@ enum FLAG {
F_COMBOSTRIKE, // lf is performing a combination strike
F_HEAVYBLOW, // next attack is a heavy blow
F_QUIVERINGPALM, // your next strike will be a quivpalm attack
F_TKTHROW, // when you throw an object, use your
// attrib = v0 and skilltype = v1
// rather than AGI and SK_THROWING like normal
F_TRUESTRIKE, // your attacks ALWAYS hit. turnsleft=v0
F_HURRICANESTRIKE, // lf is performing a hurricane strike
// INTRINSICS
@ -2587,6 +2598,7 @@ enum FLAG {
// doorway with no door).
F_AUTOPOPULATE, // fill this vault with obs/mons/pillars like normal rooms
F_NORANDOM, // this vault does not randomly appear
// OR this spell doesn't apear in books
F_VAULTATOB, // v0/1=x/y, v2=pctchance, text=obname
F_VAULTATLF, // v0/1=x/y, v2=pctchance, text=lfname
F_VAULTATCELL, // v0/1=x/y, v2=pctchance, text=cellname
@ -3013,6 +3025,7 @@ typedef struct cell_s {
int littimer;
char *writing;
int writinglifetime;
// lifeform pile
struct lifeform_s *lf;

156
io.c
View File

@ -1,6 +1,7 @@
#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@ -939,9 +940,13 @@ cell_t *askcoords(char *prompt, char *subprompt, int targettype, lifeform_t *src
wclear(msgwin);
if (subprompt) {
mvwprintw(msgwin, 0, 0, "%s%s", subprompt, buf);
char fullline[BUFLEN];
wmove(msgwin, 0, 0);
sprintf(fullline, "%s%s", subprompt, buf);
textwithcol(msgwin, fullline);
} else {
mvwprintw(msgwin, 0, 0, "%s",buf);
wmove(msgwin, 0, 0);
textwithcol(msgwin, buf);
}
wrefresh(msgwin);
@ -1162,6 +1167,12 @@ int announceflaggain(lifeform_t *lf, flag_t *f) {
msg("%s %s forms around %s!",needan(f->text) ? "an" : "a", f->text, lfname);
donesomething = B_TRUE;
break;
case F_MAGICBOOST:
if (isplayer(lf)) {
msg("Your magical ability feels boosted!");
donesomething = B_TRUE;
}
break;
case F_ASLEEP:
if (isplayer(lf) && (f->val[2] != NA)) { // ie. resting, not forced asleep
object_t *restob;
@ -1761,6 +1772,12 @@ int announceflagloss(lifeform_t *lf, flag_t *f) {
msg("%s%s %s vanishes.",lfname,getpossessive(lfname), f->text);
donesomething = B_TRUE;
break;
case F_MAGICBOOST:
if (isplayer(lf)) {
msg("Your magical ability no longer feels boosted.");
donesomething = B_TRUE;
}
break;
case F_ATTACHEDTO:
lf2 = findlf(NULL, f->val[0]);
if (lf2 && !isdead(lf2)) {
@ -5417,7 +5434,9 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, " - %s", contentname);
if (o->type->id == OT_SPELLBOOK) {
char lbuf[BUFLEN];
sprintf(lbuf, " (Lv %d)", getspelllevel(oo->type->id));
sprintf(lbuf, " (Lv %d)%s", getspelllevel(oo->type->id),
lfhasflagval(player, F_CANCAST, oo->type->id, NA, NA, NULL) ?
" [known]" : "");
strcat(buf, lbuf);
}
strcat(buf, "\n");
@ -5549,8 +5568,8 @@ char *makedesc_spell(objecttype_t *ot, char *retbuf) {
f = hasflag(ot->flags, F_STAMCOST);
if (f) {
sprintf(buf, "It costs %d stamina to use.\n",f->val[0]);
}
strncat(retbuf, buf, HUGEBUFLEN);
}
f = hasflag(ot->flags, F_CASTINGTIME);
@ -6606,10 +6625,10 @@ int downline(int *y, int h, char *heading, char *subheading, char *bottomstring,
centre(mainwin, C_WHITE, h-1, bottomstring);
}
ch = getch();
if (cmdchars && strchr(cmdchars, ch)) {
if (ch == 27) { // ESC
if (retchar) *retchar = ch;
return B_TRUE;
} else if (ch == 27) { // ESC
} else if (cmdchars && strchr(cmdchars, ch)) {
if (retchar) *retchar = ch;
return B_TRUE;
}
@ -6758,18 +6777,20 @@ void drawlevelfor(lifeform_t *lf) {
void doheading(WINDOW *win, int *y, int x, char *what) {
int len,i;
char *buf;
char *underline;
len = strlen(what) + 1;
buf = malloc(len * sizeof(char));
underline = malloc(len * sizeof(char));
for (i = 0; i < len; i++) {
buf[i] = '-';
underline[i] = '-';
}
buf[i] = '\0';
underline[i] = '\0';
//mvwprintw(win, *y, x, what); (*y)++;
wmove(win, *y, x);
textwithcol(win, what); (*y)++;
setcol(win, C_WHITE);
mvwprintw(win, *y, x, what); (*y)++;
mvwprintw(win, *y, x, buf); (*y)++;
mvwprintw(win, *y, x, underline); (*y)++;
unsetcol(win, C_WHITE);
free(buf);
free(underline);
}
void doheadingsmall(WINDOW *win, int y, int x, char *format, char *heading) {
@ -7465,11 +7486,11 @@ enum COLOUR getskilllevelcolour(enum SKILLLEVEL slev) {
case PR_ADEPT:
return C_GREEN;
case PR_SKILLED:
return C_BOLDGREEN;
return C_BLUE;
case PR_EXPERT:
return C_BOLDCYAN;
return C_CYAN;
case PR_MASTER:
return C_BOLDMAGENTA;
return C_MAGENTA;
}
return C_GREY;
}
@ -9680,9 +9701,12 @@ void showlfstats(lifeform_t *lf, int showall) {
int numknown = 0, numavailable = 0;
int n;
enum SKILLLEVEL slev;
skill_t *sk;
int finished = B_FALSE,dounknown;
centre(mainwin, C_WHITE, 0, "SKILLS");
/*
// get available skills
for (f = lf->flags->first ; f ; f = f->next) {
if (f->id == F_CANLEARN) {
@ -9699,32 +9723,88 @@ void showlfstats(lifeform_t *lf, int showall) {
}
}
}
*/
//centre(mainwin, y, "SKILLS"); y ++;
snprintf(skilltitle, BUFLEN, "%-40s%-40s","AVAILABLE SKILLS", "KNOWN SKILLS (*=maxed)");
y = 2;
snprintf(skilltitle, BUFLEN, "%-21s"," ");
for (i = PR_NOVICE; i <= PR_MASTER; i++) {
char toadd[BUFLEN], *sn;
int prepad,postpad,n;
// construct "|xxxxxxxx"
// ie "|Beginner"
// ie "| Inept "
sn = getskilllevelname(i);
prepad = (8 - strlen(sn))/2;
postpad = 8 - strlen(sn) - prepad;
limit(&postpad, 0, NA);
sprintf(toadd, "|^%d", getskilllevelcolour(i));
for (n = 0;n < prepad; n++) strcat(toadd, " ");
strcat(toadd, sn);
for (n = 0;n < postpad; n++) strcat(toadd, " ");
strcat(toadd, "^n");
strcat(skilltitle, toadd);
}
doheading(mainwin, &y, 0, skilltitle);
for (n = 0; n < MAXOF(numknown,numavailable); n++) {
if (n < numavailable) {
setcol(mainwin, C_RED);
mvwprintw(mainwin, y, 0, "- %s",
getskillname(available[n]->val[0]) );
unsetcol(mainwin, C_RED);
// for each skill...
for (dounknown = 0; dounknown <= 1; dounknown++) {
for (sk = firstskill ; sk ; sk = sk->next) {
char thisline[BUFLEN];
int printed = B_FALSE;
slev = getskill(lf, sk->id);
if (!dounknown && (slev != PR_INEPT)) {
// known skill
sprintf(thisline, "%-21s[^%d", sk->name, getskilllevelcolour(slev));
for (i = PR_NOVICE; i <= PR_MASTER; i++) {
char toadd[BUFLEN];
if (i == slev) {
if (i == getmaxskilllevel(player, sk->id)) {
// draw bar right up to the end
sprintf(toadd, "========|");
} else {
// leave a small gap at the end of the bar
sprintf(toadd, "=======| ");
}
if (n < numknown) {
setcol(mainwin, getskilllevelcolour(known[n]->val[1]));
mvwprintw(mainwin, y, 40, "%c %s (%s)%s",
ismaxedskill(lf, known[n]->val[0]) ? '*' : '-',
getskillname(known[n]->val[0]),
getskilllevelname(known[n]->val[1]),
//ismaxedskill(lf, known[n]->val[0]) ? "/MAX" : "",
(known[n]->lifetime == FROMSPELL) ? "[spell]" : "");
unsetcol(mainwin, getskilllevelcolour(known[n]->val[1]));
} else if (i < slev) {
sprintf(toadd, "=========");
} else {
sprintf(toadd, "^n ");
}
if (downline(&y, h, "SKILLS", skilltitle, promptstr, cmdchars, &ch)) {
strcat(thisline, toadd);
if (i == getmaxskilllevel(player, sk->id)) {
break;
}
}
strcat(thisline, "]^n");
wmove(mainwin, y, 0);
textwithcol(mainwin, thisline);
printed = B_TRUE;
} else if (dounknown && !slev && lfhasflagval(lf, F_CANLEARN, sk->id, NA, NA, NULL)) {
// learnable skill
setcol(mainwin, C_RED);
mvwprintw(mainwin, y, 0, "%-21s", sk->name, " " );
unsetcol(mainwin, C_RED);
wprintw(mainwin, "[");
for (i = PR_NOVICE; i < PR_MASTER+1; i++) {
wprintw(mainwin, " ");
}
wprintw(mainwin, "]");
unsetcol(mainwin, C_RED);
printed = B_TRUE;
}
if (printed) {
if (downline(&y, h, "SKILLS", skilltitle, promptstr, cmdchars, &ch)) {
finished = B_TRUE;
break;
}
}
}
}
} else if (mode == 'm') {
char subheading[BUFLEN];
int lev;
@ -10252,6 +10332,14 @@ void showlfstats(lifeform_t *lf, int showall) {
}
y++;
}
f = lfhasknownflag(lf, F_MAGICBOOST);
if (f && (f->known)) {
int boost;
sumflags(lf->flags, F_MAGICBOOST, &boost, NULL, NULL);
mvwprintw(mainwin, y, 0, "The power of %s spells is boosted by %d.",
isplayer(lf) ? "your" : "its", boost);
y++;
}
f = lfhasflag(lf, F_OMNIPOTENT);
if (f && (f->known)) {

66
lf.c
View File

@ -2958,6 +2958,15 @@ int eat(lifeform_t *lf, object_t *o) {
}
if (fullyeaten) {
// special cases only when eaten
switch (o->type->id) {
case OT_CHOCOLATE:
setstamina(lf, getmaxstamina(lf));
break;
default:
break;
}
// remove object
removeob(o, 1);
} else {
@ -4622,6 +4631,8 @@ int getarmourrating(lifeform_t *lf, object_t **hitob, int *hitchance, int *narms
}
}
limit(&ar, 0, NA);
return ar;
}
@ -10899,11 +10910,15 @@ int losehp_real(lifeform_t *lf, int amt, enum DAMTYPE damtype, lifeform_t *froml
// elemental effects on held objects
if ((damtype == DT_FIRE) && !fromob) {
object_t *o, *nexto;
int nburnt = 0;
// up to dam/5 objects might be burnt
// fire: dam*10 chance of burning each object which is vulnerable to fire
for (o = lf->pack->first ; o ; o = nexto) {
nexto = o->next;
if (isvulnto(o->flags, DT_FIRE) && pctchance(amt*10)) {
int newdam;
nburnt++;
if (nburnt >= (amt/5)) break;
// object takes 1/4 of damage
newdam = pctof(25, amt);
limit(&newdam, 1, NA);
@ -11472,28 +11487,9 @@ int noise(cell_t *c, lifeform_t *noisemaker, enum NOISECLASS nclass, int volume,
char lfname[BUFLEN];
char distbuf[BUFLEN],distbufbad[BUFLEN];
char dirbuf[BUFLEN];
int dir;
real_getlfnamea(noisemaker, lfname, B_FALSE);
if (dist >= 20) { // 20+
strcpy(distbuf, " very far away");
strcpy(distbufbad, " far away");
} else if (dist >= 10) { // 10 - 19
strcpy(distbuf, " far away");
} else if (dist >= 5) { // 5 - 9
strcpy(distbuf, " nearby");
strcpy(distbufbad, " nearby");
} else if (dist >= 2) { // 2 - 4
strcpy(distbuf, " very nearby");
strcpy(distbufbad, " nearby");
} else { // 1
strcpy(distbuf, " right beside you");
strcpy(distbufbad, " nearby");
}
dir = getdirtowards(l->cell, c, NULL, B_FALSE, DT_COMPASS);
strcpy(dirbuf, getdirname(dir));
dirbuf[0] = tolower(dirbuf[0]);
getdisttext(l->cell, c, distbuf, distbufbad, dirbuf);
slev = getskill(l, SK_LISTEN);
//
@ -13005,6 +13001,36 @@ void setlosdirty(lifeform_t *lf) {
}
}
void setstamina(lifeform_t *lf, float howmuch) {
float orig;
orig = getstamina(lf);
lf->stamina = howmuch;
limitf(&(lf->stamina), 0, getmaxstamina(lf));
if (getstamina(lf) != orig) {
if (isplayer(lf)) {
statdirty = B_TRUE;
drawstatus();
updatestatus();
if (getstamina(lf) == 0) {
msg("^BYou are exhausted.");
} else if (orig == 0) {
msg("You feel less exhausted now.");
}
}
/*else if (cansee(player, lf)) {
if (getstamina(lf) == 0) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s looks exhausted.", lfname);
}
}*/
}
if (getstamina(lf) == 0) {
stopsprinting(lf);
}
}
int shoot(lifeform_t *lf) {
object_t *gun,*ammo;
lifeform_t *targ;

1
lf.h
View File

@ -357,6 +357,7 @@ void setlastdam(lifeform_t *lf, char *buf);
//void setlftarget(lifeform_t *lf, lifeform_t *victim);
int setlfmaterial(lifeform_t *lf, enum MATERIAL id);
void setlosdirty(lifeform_t *lf);
void setstamina(lifeform_t *lf, float howmuch);
int shoot(lifeform_t *lf);
int skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod);
int real_skillcheck(lifeform_t *lf, enum CHECKTYPE ct, int diff, int mod, int *result);

34
map.c
View File

@ -71,6 +71,7 @@ cell_t *addcell(map_t *m, int x, int y) {
cell->littimer = 0;
cell->origlittimer = 0;
cell->writing = NULL;
cell->writinglifetime = -1;
cell->known = B_FALSE;
cell->knowntime = 0;
cell->knownglyph.ch = ' ';
@ -5738,7 +5739,36 @@ int wallstoleftright(cell_t *c, int dir) {
return B_FALSE;
}
void writetextonground(lifeform_t *lf, cell_t *c, char *buf, int howlong) {
char *p;
if (lf && isblind(lf)) {
// if blind, garble text somewhat
for (p = buf ; *p; p++) {
if (*p != ' ') {
if (onein(4)) {
if (onein(2)) {
*p = rnd('a','z');
} else {
*p = rnd('A','Z');
}
}
}
}
}
if (c->writing) {
free(c->writing);
}
c->writing = strdup(buf);
c->writinglifetime = howlong;
if (haslos(player, c)) {
if (c == player->cell) {
msg("Magical writing appears around you!");
} else {
msg("Magical writing appears nearby!");
}
} else if (c == player->cell) {
msg("You feel something stirring in the air around you.");
}
}

1
map.h
View File

@ -139,3 +139,4 @@ void updateknowncells(void);
int validateregions(void);
int validateregionthing(regionthing_t *thing);
int wallstoleftright(cell_t *c, int dir);
void writetextonground(lifeform_t *lf, cell_t *c, char *buf, int howlong);

79
move.c
View File

@ -82,9 +82,11 @@ int ispossiblemove(lifeform_t *lf, int dir) {
case E_LFINWAY:
return B_TRUE;
case E_DOORINWAY:
if (canopendoors(lf)) {
// if ai lifeforms CANT open doors, they will attack them
if (canopendoors(lf) || !isplayer(lf)) {
return B_TRUE;
}
//}
break;
case E_OBINWAY:
inway = (object_t *)rdata;
@ -1609,6 +1611,12 @@ int opendoor(lifeform_t *lf, object_t *o) {
if (!canopendoors(lf)) {
if (isplayer(lf)) {
msg("You have no hands with which to open the door!");
} else {
// ai will try to break down doors
if (gettargetlf(lf)) {
attackcell(lf, doorcell, B_TRUE);
return B_FALSE;
}
}
return B_TRUE;
}
@ -1670,8 +1678,21 @@ int opendoor(lifeform_t *lf, object_t *o) {
}
// locked?
if (hasflag(o->flags, F_LOCKED)) {
if (lf && isplayer(lf)) {
if (lf) {
if (isplayer(lf)) {
msg("The %s is locked.", noprefix(obname));
} else {
if (gettargetlf(lf)) {
// ai will automatically attack locked doors to
// get at the player
attackcell(lf, doorcell, B_TRUE);
return B_FALSE;
} else {
noise(doorcell, NULL, NC_OTHER, 2, "a door handle rattling", NULL);
}
}
taketime(lf, getactspeed(lf));
touch(lf, o);
}
return B_TRUE;
} else {
@ -1682,12 +1703,33 @@ int opendoor(lifeform_t *lf, object_t *o) {
amt = getattr(lf, A_STR) - 10;
if (amt < 0) amt = 0;
if (lf && isplayer(lf)) {
if (lf) {
if (isplayer(lf)) {
if (amt > 0) {
msg("The %s moves slightly but seems jammed.", noprefix(obname));
} else {
msg("The %s is jammed.", noprefix(obname));
}
} else {
// ai chasing someone and not strong enough to unjam the door?
if ((amt == 0) && gettargetlf(lf)) {
attackcell(lf, doorcell, B_TRUE);
return B_FALSE;
} else {
// try to force it
if (cansee(player, lf)) {
char lfname[BUFLEN];
getlfname(lf, lfname);
msg("%s tries to open %s, but fails.", lfname, obname);
} else if (haslos(player, doorcell)) {
msg("Something tries to open %s.", obname);
} else {
char noisebuf[BUFLEN];
sprintf(noisebuf, "%s jiggling against its hinges.", obname);
noise(doorcell, NULL, NC_OTHER, 3, noisebuf, NULL);
}
}
}
}
// loosen a bit
if (amt) {
@ -1710,15 +1752,19 @@ int opendoor(lifeform_t *lf, object_t *o) {
if (lf) {
if (isplayer(lf)) {
msg("You open %s.",obname);
msg("You force %s open!",obname);
} else {
if (cansee(player, lf) && isadjacent(lf->cell, doorcell)) {
getlfname(lf, buf);
capitalise(buf);
msg("%s opens %s.",buf, obname);
msg("%s forces %s open!",buf, obname);
} else if (haslos(player, doorcell)) {
capitalise(obname);
msg("%s opens.",obname);
msg("%s bursts open!",obname);
} else {
char noisebuf[BUFLEN];
sprintf(noisebuf, "%s bursting open.", obname);
noise(doorcell, NULL, NC_OTHER, 4, noisebuf, NULL);
}
}
@ -2859,6 +2905,27 @@ int willmove(lifeform_t *lf, int dir, enum ERROR *error) {
return B_FALSE;
}
// glyph of warding?
if (cell->writing && strstr(cell->writing, "*WARD")) {
char buf[BUFLEN];
char *bp, *p;
int power;
// extract number
bp = buf;
for (p = cell->writing; *p; p++) {
if (isdigit(*p)) {
*bp = *p;
bp++;
}
}
*bp = '\0';
power = atoi(buf);
if ( gethitdice(lf) <= power) {
if (error) *error = E_WONT;
return B_FALSE;
}
}
// some lfs will only leave their rooms if they have a target
// ie. shopkeepers
f = lfhasflag(lf, F_STAYINROOM);

32
nexus.c
View File

@ -297,29 +297,27 @@ int main(int argc, char **argv) {
giveskilllev(player, sk->id, PR_NOVICE);
switch (sk->id) {
case SK_SS_AIR:
addflag(player->flags, F_CANCAST, OT_S_MIST, NA, NA, NULL);
addflag(player->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL);
sb1 = addob(player->pack, "spellbook of air magic");
break;
case SK_SS_COLD:
addflag(player->flags, F_CANCAST, OT_S_CHILL, NA, NA, NULL);
sb1 = addob(player->pack, "spellbook of cold magic");
break;
case SK_SS_FIRE:
addflag(player->flags, F_CANCAST, OT_S_SPARK, NA, NA, NULL);
sb1 = addob(player->pack, "spellbook of fire magic");
break;
case SK_SS_DEATH:
addflag(player->flags, F_CANCAST, OT_S_STENCH, NA, NA, NULL);
sb1 = addob(player->pack, "spellbook of necromancy");
break;
case SK_SS_WILD:
addflag(player->flags, F_CANCAST, OT_S_MANASPIKE, NA, NA, NULL);
sb1 = addob(player->pack, "spellbook of wild magic");
break;
default:
break;
}
if (sb1) {
addflag(player->flags, F_CANCAST, sb1->contents->first->type->id, NA, NA, NULL);
}
initprompt(&prompt, "Select your secondary spell school:");
addchoice(&prompt, 'd', getskillname(SK_SS_DIVINATION), NULL, findskill(SK_SS_DIVINATION), NULL);
@ -332,28 +330,26 @@ int main(int argc, char **argv) {
giveskilllev(player, sk->id, PR_NOVICE);
switch (sk->id) {
case SK_SS_DIVINATION:
addflag(player->flags, F_CANCAST, OT_S_SIXTHSENSE, NA, NA, NULL);
sb2 = addob(player->pack, "spellbook of divination magic");
break;
case SK_SS_GRAVITY:
addflag(player->flags, F_CANCAST, OT_S_TRUESTRIKE, NA, NA, NULL);
sb2 = addob(player->pack, "spellbook of gravitation magic");
break;
case SK_SS_MODIFICATION:
addflag(player->flags, F_CANCAST, OT_S_HOLDPORTAL, NA, NA, NULL);
sb2 = addob(player->pack, "spellbook of modification magic");
break;
case SK_SS_SUMMONING:
addflag(player->flags, F_CANCAST, OT_S_FLOATINGDISC, NA, NA, NULL);
sb2 = addob(player->pack, "spellbook of summoning magic");
break;
case SK_SS_TRANSLOCATION:
addflag(player->flags, F_CANCAST, OT_S_APPORTATION, NA, NA, NULL);
sb2 = addob(player->pack, "spellbook of translocation magic");
break;
default:
break;
}
if (sb2) {
addflag(player->flags, F_CANCAST, sb2->contents->first->type->id, NA, NA, NULL);
}
identify(sb1);
identify(sb2);
}
@ -1468,6 +1464,22 @@ void timeeffectsworld(map_t *map, int updategametime) {
}
}
// writing fading?
if (c->writing && (c->writinglifetime > 0)) {
c->writinglifetime--;
if (c->writinglifetime <= 0) {
free(c->writing);
c->writing = NULL;
if (haslos(player, c)) {
if (c == player->cell) {
msg("The magical inscription beneath you vanishes.");
} else {
msg("A magical inscription nearby vanishes.");
}
}
}
}
pit = hasobwithflagval(c->obpile, F_PIT, D_DOWN, NA, NA, NULL);
if (pit) {
obsfallthrough(c, pit);

View File

@ -1193,9 +1193,15 @@ object_t *addobject(obpile_t *where, char *name, int canstack, int wantlinkholes
// remember the book's school (used for description)
addflag(o->flags, F_LINKSCHOOL, bookcontents, NA, NA, NULL);
// add contents to the book
if (where->owner) { // giving to a lifeform?
nspells = 6;
firstlev = 1;
if (where->owner && isplayer(where->owner) && (gamemode == GM_CHARGEN)) {
enum OBTYPE firstspell;
// giving to player at start of game
nspells = 5;
firstlev = 2;
// fixed first spell
firstspell = getfirstwizspell(bookcontents);
assert(addobfast(o->contents, firstspell));
} else {
nspells = rnd(2,5);
firstlev = rnd(1,4);
@ -1685,30 +1691,20 @@ obpile_t *addobpile(lifeform_t *owner, cell_t *where, object_t *parentob) {
}
void addobsinradius(cell_t *centre, int radius, int dirtype, char *name, int allowdupes) {
int x,y;
cell_t *cell[MAXCANDIDATES],*c;
int ncells,i;
objecttype_t *ot;
ot = findotn(name);
if (!ot) return;
getradiuscells(centre, radius, DT_ORTH, B_FALSE, LOF_WALLSTOP, B_FALSE, cell, &ncells, B_FALSE);
for (y = centre->y - radius ; y <= centre->y + radius; y++) {
for (x = centre->x - radius ; x <= centre->x + radius; x++) {
int valid = B_FALSE;
cell_t *c;
c = getcellat(centre->map, x, y);
if (c && !c->type->solid && haslof(centre, c, LOF_WALLSTOP, NULL)) {
for (i = 0; i < ncells; i++) {
c = cell[i];
if (allowdupes || !hasob(c->obpile, ot->id)) {
if ((dirtype == DT_COMPASS) && (getcelldist(centre, c) <= radius)) {
valid = B_TRUE;
} else if ((dirtype == DT_ORTH) && (getcelldistorth(centre, c) <= radius)) {
valid = B_TRUE;
}
}
}
if (valid) {
addob(c->obpile, name);
}
}
}
}
objecttype_t *addot(enum OBTYPE id, char *name, char *description, int material, float weight, int obclassid, enum LFSIZE size) {
@ -3668,7 +3664,7 @@ char *getdamname(enum DAMTYPE damtype) {
case DT_PETRIFY: return "petrification";
case DT_PIERCE: return "piercing";
case DT_POISON: return "poison";
case DT_POISONGAS: return "poison gas";
case DT_POISONGAS: return "gas";
case DT_PROJECTILE: return "projectile";
case DT_SLASH: return "slashing";
case DT_SONIC: return "sonic";
@ -3687,7 +3683,7 @@ char *getdamnamenoun(enum DAMTYPE damtype) {
case DT_MELT: return "melting";
case DT_PETRIFY: return "petrification";
case DT_PIERCE: return "piercing damage";
case DT_POISONGAS: return "poison gas";
case DT_POISONGAS: return "gas";
case DT_POISON: return "poison";
case DT_SLASH: return "slashing damage";
case DT_ELECTRIC: return "electricity";
@ -5381,7 +5377,7 @@ int getthrowdam(object_t *o) {
break;
}
return (int)dam;
return (int)ceil(dam);
}
// get either name of top object, or cell type
@ -5417,6 +5413,10 @@ char *gettopobname(cell_t *c, char *retbuf) {
// just print the cell's name
strcat(retbuf, c->type->name);
}
if (c->writing) {
strcat(retbuf, ", writing:");
strcat(retbuf, c->writing);
}
return retbuf;
}
@ -10015,12 +10015,12 @@ int real_takedamage(object_t *o, unsigned int howmuch, int damtype, int wantanno
// no damage from equipped _weapons_
if ((f->val[0] != BP_WEAPON) || (f->val[0] != BP_SECWEAPON)) {
} else {
// equipped clothes/armour? 1.5x damage.
lfdam = pctof(150,howmuch);
// equipped clothes/armour? full damage.
lfdam = howmuch;
}
} else {
// otherwise normal.
lfdam = howmuch;
// objects in your pack? just a little bit of damage
lfdam = pctof(25,howmuch);
}
if (lfdam) {
// announce
@ -10261,7 +10261,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
int shattered = B_FALSE;
char throwverbpast[BUFLEN];
char throwverbpres[BUFLEN];
int acc;
int acc,myroll;
int youhit = B_FALSE;
int missiledam = 0;
object_t *newob = NULL;
@ -10548,13 +10548,12 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
if (willcatch) {
acc = 100;
} else {
acc = getmissileaccuracy(thrower, where, o, firearm, A_AGI);
acc = getmissileaccuracy(thrower, where, o, firearm, lfhasflag(thrower, F_TKTHROW)) ;
}
} else {
// purely based on saving throw...
acc = 100;
}
// adjust for swimming
if (isswimming(thrower)) {
switch (getskill(thrower, SK_SWIMMING)) {
@ -10569,9 +10568,13 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
break;
}
}
if (db && thrower) {
dblog("%s is throwing %s - acc = %d, speed = %d\n", realthrowername, obname, acc, speed);
}
// roll for hit
youhit = B_FALSE;
myroll = rnd(1,100);
// metal projectile versus magnetic shield?
if (target && lfhasflag(target, F_MAGSHIELD) && ismetal(o->material->id)) {
// announce
@ -10580,9 +10583,12 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
announcedmiss = B_TRUE;
}
youhit = B_FALSE;
} else if (rnd(1,100) <= acc) {
} else if (myroll <= acc) {
youhit = B_TRUE;
}
if (db && thrower) {
dblog("roll = %d, youhit = %s", myroll, youhit ? "YES" : "no");
}
if (youhit && target) {
@ -10664,6 +10670,7 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
willcatch = B_TRUE;
} else if (!lfhasflag(target, F_CASTINGSPELL) && skillcheck(target, SC_DODGE, 7*speed, dodgemod)) {
// then check if we dodge it...
if (db) dblog("target passed dodge check.");
youhit = B_FALSE;
}
}
@ -10718,13 +10725,15 @@ int fireat(lifeform_t *thrower, object_t *o, int amt, cell_t *where, int speed,
throwdam = getthrowdam(o);
dam = (int)((float)throwdam * multiplier);
if (db) dblog("fireat(): dam = throwdam(%d) * speed(%d)/2 = %d",throwdam, speed, dam);
// special case
if (o->type->id == OT_RUBBERBULLET) {
dam = 1;
}
if (db) dblog("fireat(): dam = throwdam(%d) * multi(%d)",throwdam, multiplier);
if (db) dblog("dealing %d damage", dam);
// deal extra cutting damage afterwards?
if (willshatter(o->material->id)) {
shattered = B_TRUE;
@ -11928,9 +11937,11 @@ enum MATSTATE getmaterialstate(enum MATERIAL mat) {
return MS_OTHER; // should never happen
}
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt) {
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, flag_t *tkthrow) {
int acc,maxrange,howfar;
enum SKILLLEVEL slev;
enum SKILL whichskill;
enum ATTRIB whichatt;
// figure out if you miss or not, based on distance and
// dexterity
// base:
@ -11942,6 +11953,14 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
// then modify using dexterity/int/whatever
// then penalise for throwing non-missiles
if (tkthrow) {
whichatt = tkthrow->val[0];
whichskill = tkthrow->val[1];
} else {
whichatt = A_AGI;
whichskill = SK_THROWING;
}
// base accuracy
if (firearm) {
@ -11950,8 +11969,8 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
// ie. inept = -30%, adept = 0%, master = +30%
acc += ((slev - PR_ADEPT) * 10);
} else {
slev = getskill(thrower, SK_THROWING);
acc = 40;
slev = getskill(thrower, whichskill);
acc = 60;
// ie. inept = -30%, adept = 0%, master = +30%
acc += ((slev - PR_ADEPT) * 10);
// acc will now be 10 - 70
@ -11984,7 +12003,7 @@ int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, ob
}
// penalty for throwing non-missiles
if (missile && !firearm && !isthrowmissile(missile)) {
if (missile && !firearm && !isthrowmissile(missile) && !tkthrow) {
acc -= 20;
}
// modify for prone throwers

View File

@ -69,7 +69,7 @@ int geteffecttime(int min, int max, enum BLESSTYPE isblessed);
objecttype_t *getlinkspell(object_t *o);
enum COLOUR getmaterialcolour(enum MATERIAL mat );
enum MATSTATE getmaterialstate(enum MATERIAL mat);
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, enum ATTRIB whichatt);
int getmissileaccuracy(lifeform_t *thrower, cell_t *where, object_t *missile, object_t *firearm, flag_t *tkthrow);
int getobaccuracy(object_t *wep, lifeform_t *weilder);
int getobbonus(object_t *o, int onlyknown);
int getobpoints(object_t *o);

149
spell.c
View File

@ -2642,7 +2642,7 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
} else if (abilid == OT_A_INSPECT) {
object_t *o;
int difficulty;
int rarity;
enum RARITY rarity;
int mod;
enum SKILLLEVEL slev;
flag_t *f;
@ -2704,11 +2704,11 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// skillcheck...
f = hasflag(o->flags, F_RARITY);
if (f) {
rarity = f->val[1];
rarity = f->val[2];
} else {
rarity = 0;
}
difficulty = 25 + ((100 - rarity) / 5);
difficulty = 20 + (rarity*5);
switch (o->type->obclass->id) {
case OC_SCROLL:
difficulty += 2; break;
@ -4712,6 +4712,10 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
brightflash(caster->cell, 2 + (power/4), caster);
} else if (spellid == OT_S_GLYPHWARDING) {
char buf[BUFLEN];
sprintf(buf, "^g*WARD%d*^n", power/2);
writetextonground(caster, caster->cell, buf, power*5);
} else if (spellid == OT_S_FLOATINGDISC) {
lifeform_t *newlf;
// get random adjacent cell
@ -5551,7 +5555,8 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
}
}
} else if (spellid == OT_S_HOLDPORTAL) {
object_t *o;
object_t *o,*oo;
cell_t *c;
o = hasobwithflag(targcell->obpile, F_DOOR);
if (!o) {
@ -5559,8 +5564,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE;
}
// move any objects which are in the way (but not lfs)
for (oo = targcell->obpile->first ; oo ; oo = oo->next) {
if ((oo != o) && (getmaterialstate(oo->material->id) == MS_SOLID)) {
c = getrandomadjcell(targcell, WE_NOTWALL, B_ALLOWEXPAND);
if (c) moveob(oo, c->obpile, ALL);
}
}
closedoor(NULL, o);
addflag(o->flags, F_JAMMED, 100, NA, NA, NULL);
addflag(o->flags, F_JAMMED, power*2, NA, NA, NULL);
if (haslos(player, targcell)) {
char buf[BUFLEN];
@ -5608,7 +5621,7 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
return B_FALSE;
}
// does caster have a bladed weapon?
// does caster have a weapon?
wep = getweapon(target);
if (!wep) {
fizzle(caster);
@ -5618,16 +5631,16 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
getobname(wep, obname, wep->amt);
if (isplayer(target)) {
msg("Your %s%s is covered with ice!", obname, getpossessive(obname));
msg("Your %s is covered with ice!", 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), lfname);
msg("%s%s %s is covered with ice!", lfname, getpossessive(lfname), noprefix(obname));
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
addtempflag(wep->flags, F_EXTRADAM, DT_COLD, NA, NA, "1d6", 10 + power*3);
addtempflag(wep->flags, F_FROZEN, B_TRUE, NA, NA, NULL, 10 + power*3);
} else if (spellid == OT_S_ICICLE) {
object_t *o;
@ -6425,29 +6438,11 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
if (seenbyplayer) *seenbyplayer = B_TRUE;
// ask what to inscribe
askstring("What will you inscribe here", '?', buf, BUFLEN, NULL);
if (strlen(buf) > 0) {
char *p;
if (isblind(caster)) {
// if blind, garble text somewhat
for (p = buf ; *p; p++) {
if (*p != ' ') {
if (onein(4)) {
if (onein(2)) {
*p = rnd('a','z');
} else {
*p = rnd('A','Z');
}
}
}
}
msg("You feel something stirring in the air around you.");
} else {
msg("Magical writing appears before you!");
}
if (caster->cell->writing) {
free(caster->cell->writing);
}
caster->cell->writing = strdup(buf);
if (strchr(buf, '*') || strchr(buf, '^')) {
// prevent glyphs / colours
fizzle(caster);
} else if (strlen(buf) > 0) {
writetextonground(caster, caster->cell, buf, power*50);
} else {
fizzle(caster);
}
@ -6789,43 +6784,52 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
prompt.maycancel = B_TRUE;
for (m = firstmap ; m ; m = m->next) {
int x,y;
char ch = 'b';
// on the ground?
char ch = 'a';
char mapname[BUFLEN];
getregionname(mapname, m, B_TRUE);
capitalise(mapname);
if (m->habitat->id == H_HEAVEN) continue;
for (y = 0; y < m->h; y++) {
for (x = 0; x < m->w; x++) {
cell_t *c;
c = getcellat(m, x, y);
if (c) {
// on the ground?
for (o = c->obpile->first ; o ; o = o->next) {
char obname[BUFLEN];
real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_FALSE, B_FALSE, B_FALSE);
if (strcasestr(obname, wantname)) {
addchoice(&prompt, ch++, obname, NULL, o, NULL);
}
}
}
char ptext[BUFLEN];
char distbuf[BUFLEN],dirbuf[BUFLEN];
getdisttext(caster->cell, c, distbuf, NULL, dirbuf);
sprintf(ptext, "%s: %s (%s to the %s)", mapname, obname, distbuf, dirbuf);
addchoice(&prompt, ch++, ptext, NULL, o, NULL);
}
}
// carried by someone?
for (y = 0; y < m->h; y++) {
for (x = 0; x < m->w; x++) {
cell_t *c;
c = getcellat(m, x, y);
if (c && c->lf) {
if (c->lf) {
for (o = c->lf->pack->first ; o ; o = o->next) {
char obname[BUFLEN];
real_getobname(o, obname, o->amt, B_TRUE, B_TRUE, B_FALSE, B_FALSE, B_FALSE);
if (strcasestr(obname, wantname)) {
char ptext[BUFLEN];
char distbuf[BUFLEN],dirbuf[BUFLEN];
char lfname[BUFLEN];
real_getlfnamea(c->lf, lfname, B_FALSE);
strcat(obname, " (held by ");
strcat(obname, lfname);
strcat(obname, ")");
addchoice(&prompt, ch++, obname, NULL, o, NULL);
real_getlfnamea(c->lf, lfname, B_FALSE);
getdisttext(caster->cell, c, distbuf, NULL, dirbuf);
sprintf(ptext, "%s: %s (%s to the %s, held by %s)",
mapname, obname, distbuf, dirbuf, lfname);
addchoice(&prompt, ch++, ptext, NULL, o, NULL);
}
}
}
}
}
}
}
@ -7822,15 +7826,15 @@ 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 spark of flame singes %s.", lfname);
msg("A small burst of flame singes %s.", lfname);
} else {
msg("A small spark of flame appears.");
msg("A small burst of flame appears.");
}
if (seenbyplayer) *seenbyplayer = B_TRUE;
}
if (targcell->lf) {
losehp(targcell->lf, rnd(1,3), DT_FIRE, caster, "a spark");
losehp(targcell->lf, rnd(1,6), DT_FIRE, caster, "a spark");
} else {
for (o = targcell->obpile->first ; o ; o = nexto) {
nexto = o->next;
@ -8422,7 +8426,9 @@ int dospelleffects(lifeform_t *caster, enum OBTYPE spellid, int power, lifeform_
} else {
// otherwise throw it there - but speed is based on
// caster's INTELLIGENCE, not strength like normal.
addflag(caster->flags, F_TKTHROW, A_IQ, SK_SS_MENTAL, NA, NULL);
fireat(caster, targob, targob->amt, targcell, power, NULL);
killflagsofid(caster->flags, F_TKTHROW);
// note that we use fireat() rather than throwat() to avoid
// calling taketime() twice.
}
@ -9218,6 +9224,24 @@ void fizzle(lifeform_t *caster) {
}
}
enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school) {
enum OBTYPE firstspell = OT_S_MANASPIKE;
switch (school) {
case SS_AIR: firstspell = OT_S_MIST; break;
case SS_COLD: firstspell = OT_S_CHILL; break;
case SS_FIRE: firstspell = OT_S_SPARK; break;
case SS_DEATH: firstspell = OT_S_STENCH; break;
case SS_DIVINATION: firstspell = OT_S_SIXTHSENSE; break;
case SS_GRAVITY: firstspell = OT_S_TRUESTRIKE; break;
case SS_MODIFICATION: firstspell = OT_S_HOLDPORTAL; break;
case SS_TRANSLOCATION: firstspell = OT_S_APPORTATION; break;
case SS_SUMMONING: firstspell = OT_S_GLYPHWARDING; break;
default:
case SS_WILD: firstspell = OT_S_MANASPIKE; break;
}
return firstspell;
}
char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr) {
flag_t *f;
// forced?
@ -9314,11 +9338,13 @@ enum OBTYPE getrandomspellfromschool(enum SPELLSCHOOL school, int wantlev) {
// get list of all spells of this school
for (ot = objecttype ; ot ; ot = ot->next) {
if ((ot->obclass->id == OC_SPELL) && spellisfromschool(ot->id, school)) {
if (!hasflag(ot->flags, F_NORANDOM)) {
if ((wantlev == 0) || (getspelllevel(ot->id) == wantlev)) {
poss[nposs++] = ot;
}
}
}
}
if (nposs <= 0) {
return OT_NONE;
@ -9511,18 +9537,22 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
enum SKILLLEVEL schoolskill;
enum SPELLSCHOOL school;
int db = B_FALSE;
int boost;
flag_t *f;
if (db) {
objecttype_t *ot;
ot = findot(spellid);
if (db) dblog("getspellpower for lf %s, spell %s", lf->race->name, ot->name);
}
sumflags(lf->flags, F_MAGICBOOST, &boost, NULL, NULL);
////////////////////////////////////
// CAN WE CAST THIS AT ALL
////////////////////////////////////
// If we can _will_ this to occur then we might have a set
// If we can will/cast this then we might have a set
// spellpower
f = lfhasflagval(lf, F_CANWILL, spellid, NA, NA, NULL);
if (f && strlen(f->text)) {
@ -9532,8 +9562,22 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
dblog("-->power = %d (from canwill)", power);
}
// note that this power _can_ override max spell power
power += boost;
return power;
}
} else {
f = lfhasflagval(lf, F_CANCAST, spellid, NA, NA, NULL);
if (f && strlen(f->text)) {
texttospellopts(f->text, "pw:", &power, NULL );
if (power > 0) {
if (db) {
dblog("-->power = %d (from cancast)", power);
}
// note that this power _can_ override max spell power
power += boost;
return power;
}
}
}
// get spell details
@ -9598,6 +9642,7 @@ int getspellpower(lifeform_t *lf, enum OBTYPE spellid) {
power = gethitdice(lf);
}
power += boost;
limit(&power, 0, getspellmaxpower(spellid));
return power;
}

View File

@ -8,6 +8,7 @@ objecttype_t *findspelln(char *buf);
enum SPELLSCHOOL findspellschoolbyname(char *buf);
void fizzle(lifeform_t *caster);
//int getiqreq(enum OBTYPE oid);
enum OBTYPE getfirstwizspell(enum SPELLSCHOOL school);
char *getforcedspellrace(lifeform_t *lf, enum OBTYPE spellid, char *racestr);
int getmpcost(lifeform_t *lf, enum OBTYPE oid);
int getmrdiff(enum OBTYPE spellid, int power);

43
text.c
View File

@ -8,6 +8,8 @@
#include "defs.h"
#include "flag.h"
#include "lf.h"
#include "map.h"
#include "move.h"
#include "nexus.h"
#include "objects.h"
#include "text.h"
@ -86,6 +88,9 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
int usecrittext = B_FALSE;
char wepname[BUFLEN],buf[BUFLEN];
// default
strcpy(retbuf, "");
getobname(wep, wepname, 1);
// initial hit...
@ -190,7 +195,7 @@ char *construct_hit_string(lifeform_t *lf, lifeform_t *victim, char *attackernam
} else if (fatal) { // fatal
switch (damtype) {
case DT_COLD:
snprintf(retbuf, BUFLEN, "^%c%s %s chilled to the bone", getlfcol(victim, CC_BAD), victimname, is(victim));
snprintf(retbuf, BUFLEN, "^%c%s %s chilled to the bone!", getlfcol(victim, CC_BAD), victimname, is(victim));
break;
case DT_HEAT:
case DT_FIRE:
@ -455,7 +460,13 @@ char *getattackverb(lifeform_t *lf, object_t *wep, enum DAMTYPE damtype, int dam
return "purify";
}
} else if (damtype == DT_MAGIC) {
if (pct <= 5) {
return "zap";
} else if (pct <= 15) {
return "sear";
} else if (pct <= 40) {
return "blast";
}
} else if (damtype == DT_PIERCE) {
if (pct <= 5) {
return "poke";
@ -614,6 +625,36 @@ char *getdirnameshort(int dir) {
return "?";
}
void getdisttext(cell_t *src, cell_t *dst,char *distbuf, char *distbufapprox, char *dirbuf) {
int dist;
int dir;
dist = getcelldist(src, dst);
dir = getdirtowards(src, dst, NULL, B_FALSE, DT_COMPASS);
if (dirbuf) {
strcpy(dirbuf, getdirname(dir));
dirbuf[0] = tolower(dirbuf[0]);
}
if (dist >= 20) { // 20+
if (distbuf) strcpy(distbuf, " very far away");
if (distbufapprox) strcpy(distbufapprox, " far away");
} else if (dist >= 10) { // 10 - 19
if (distbuf) strcpy(distbuf, " far away");
if (distbufapprox) strcpy(distbufapprox, " far away");
} else if (dist >= 5) { // 5 - 9
if (distbuf) strcpy(distbuf, " nearby");
if (distbufapprox) strcpy(distbufapprox, " nearby");
} else if (dist >= 2) { // 2 - 4
if (distbuf) strcpy(distbuf, " very nearby");
if (distbufapprox) strcpy(distbufapprox, " nearby");
} else { // 1
if (distbuf) strcpy(distbuf, " right beside you");
if (distbufapprox) strcpy(distbufapprox, " nearby");
}
}
int gethitconferlifetime(char *text, int *min, int *max) {
int howlong;
int localmin = -1,localmax = -1;

1
text.h
View File

@ -15,6 +15,7 @@ char *getattrabbrev(enum ATTRIB att);
char *getattrname(enum ATTRIB att);
char *getdirname(int dir);
char *getdirnameshort(int dir);
void getdisttext(cell_t *src, cell_t *dst,char *distbuf, char *distbufapprox, char *dirbuf);
int gethitconferlifetime(char *text, int *min, int *max);
char *getkillverb(lifeform_t *victim, object_t *wep, enum DAMTYPE damtype, int dam, int maxhp);
char *getpoisondamverb(enum POISONTYPE ptype);