- Allow mages to select spells from their primary school through training, by spending points.

- Rename 'weapon attraction' spell to 'guided weapon'
- When showing spells in a book, include their school
- $ key to show current money
This commit is contained in:
Rob Pearce 2016-06-07 16:52:41 +10:00
parent 267f046986
commit fd450ba0c3
10 changed files with 344 additions and 62 deletions

9
ai.c
View File

@ -1043,7 +1043,7 @@ int aigetspelltarget(lifeform_t *lf, objecttype_t *spelltype, lifeform_t *victim
}
cell_t *aigettargetcell(lifeform_t *lf, flag_t **targflag) {
flag_t *f;
flag_t *f = NULL;
if (targflag) {
*targflag = NULL;
@ -1856,7 +1856,7 @@ int ai_movement(lifeform_t *lf) {
// do we have a target cell?
c = aigettargetcell(lf, &f);
if (!f) return B_FALSE;
if (!f) return B_FALSE; // ooo is f bad here?
// is it still valid?
if (!c) {
@ -1887,6 +1887,8 @@ int ai_movement(lifeform_t *lf) {
// always ok.
} else if (f->val[2] == MR_BACKTOLAIR) {
// always ok.
} else if (f->val[2] == MR_OTHER) {
// always ok.
} else {
// weird ?
raise (SIGINT);
@ -2362,6 +2364,9 @@ int aimovetotargetcell(lifeform_t *lf, flag_t *f) {
cell_t *c = NULL,*origc,*targetc;
int db = B_FALSE;
enum ATTRBRACKET iqb;
assert(f->id <= F_LAST);
iqb = getattrbracket(getattr(lf, A_IQ), A_IQ, NULL);
checkflagpile_maplfs(lf->cell->map);

32
data.c
View File

@ -206,6 +206,7 @@ void initcommands(void) {
addcommand(CMD_NEXTTARGET, '\'', "Cycle to next firearm target.");
// Information
addcommand(CMD_HELP, '?', "Display this text.");
addcommand(CMD_COUNTMONEY, '$', "Count your funds.");
addcommand(CMD_INFOPLAYER, '@', "Display player stats.");
addcommand(CMD_INFOARMOUR, ']', "Display player armour.");
addcommand(CMD_FORCEATTACK, 'A', "Force an attack in a given direction.");
@ -1391,6 +1392,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_CANSTUDY, SS_AIR, NA, NA, NULL);
addflag(lastjob->flags, F_CANSEETHROUGHMAT, MT_GAS, NA, NA, NULL);
addflag(lastjob->flags, F_NEEDOBFORSPELLS, NA, F_WIZSTAFF, NA, "wizard staff");
addflag(lastjob->flags, F_MAXHPMOD, 80, NA, NA, NULL); // low hp
@ -1451,6 +1453,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_CANSTUDY, SS_FIRE, NA, NA, NULL);
addflag(lastjob->flags, F_NEEDOBFORSPELLS, NA, F_WIZSTAFF, NA, "wizard staff");
addflag(lastjob->flags, F_MAXHPMOD, 80, NA, NA, NULL); // low hp
addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL);
@ -1511,6 +1514,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_CANSTUDY, SS_COLD, NA, NA, NULL);
addflag(lastjob->flags, F_NEEDOBFORSPELLS, NA, F_WIZSTAFF, NA, "wizard staff");
addflag(lastjob->flags, F_MAXHPMOD, 80, NA, NA, NULL); // low hp
addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL);
@ -1571,6 +1575,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_CANSTUDY, SS_DEATH, NA, NA, NULL);
addflag(lastjob->flags, F_MAXHPMOD, 80, NA, NA, NULL); // low hp
addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL);
addflag(lastjob->flags, F_RESTHEALTIME, 6, NA, NA, NULL); // wizard heals slowly, but regenerates mp
@ -1628,6 +1633,7 @@ void initjobs(void) {
addflag(lastjob->flags, F_CANLEARN, SK_LORE_DRAGONS, NA, NA, NULL);
addflag(lastjob->flags, F_CANLEARN, SK_LORE_UNDEAD, NA, NA, NULL);
// abilities
addflag(lastjob->flags, F_CANSTUDY, SS_WILD, NA, NA, NULL);
addflag(lastjob->flags, F_NEEDOBFORSPELLS, NA, F_WIZSTAFF, NA, "wizard staff");
addflag(lastjob->flags, F_MAXHPMOD, 80, NA, NA, NULL); // low hp
addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL);
@ -4323,7 +4329,7 @@ void initobjects(void) {
// elemental - air
///////////////////
// l1
addot(OT_S_TRUESTRIKE, "weapon attraction", "Wind currents gives the target unerring accuracy, making their attacks always hit and negating strength penalties.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addot(OT_S_TRUESTRIKE, "guided weapon", "Wind currents give the target unerring accuracy, making their attacks always hit and negating strength penalties.", MT_NOTHING, 0, OC_SPELL, SZ_TINY);
addflag(lastot->flags, F_EXTRADESC, NA, NA, NA, "The spell's power determines the amount of strikes before it expires.");
addflag(lastot->flags, F_SPELLSCHOOL, SS_AIR, NA, NA, NULL);
addflag(lastot->flags, F_SPELLLEVEL, 1, NA, NA, NULL);
@ -21014,7 +21020,7 @@ void initskills(void) {
// spell schools
addskill(SK_SS_ALLOMANCY, "Allomancy", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_ALLOMANCY, PR_INEPT, "- Spell power power depends on your Level and Strength.", B_FALSE);
addskilldesc(SK_SS_ALLOMANCY, PR_INEPT, "- Spell power depends on your Level and Strength.", B_FALSE);
addskilldesc(SK_SS_ALLOMANCY, PR_INEPT, "- Each rank gives you a 20% chance to learn a new allomantic ability when levelling up.", B_FALSE);
addskilldesc(SK_SS_ALLOMANCY, PR_NOVICE, "Allows you to cast Allomancy spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_ALLOMANCY, PR_BEGINNER, "Allows you to cast Allomancy spells up to level 2.", B_FALSE);
@ -21023,7 +21029,7 @@ void initskills(void) {
addskilldesc(SK_SS_ALLOMANCY, PR_EXPERT, "Allows you to cast Allomancy spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_ALLOMANCY, PR_MASTER, "Allows you to cast Allomancy spells up to level 6.", B_FALSE);
addskill(SK_SS_MENTAL, "Psionics", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_MENTAL, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_MENTAL, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_MENTAL, PR_INEPT, "- Each rank gives you a 20% chance to learn a new psionic ability when levelling up.", B_FALSE);
addskilldesc(SK_SS_MENTAL, PR_NOVICE, "Allows you to cast Psionic spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_MENTAL, PR_BEGINNER, "Allows you to cast Psionic spells up to level 2.", B_FALSE);
@ -21032,7 +21038,7 @@ void initskills(void) {
addskilldesc(SK_SS_MENTAL, PR_EXPERT, "Allows you to cast Psionic spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_MENTAL, PR_MASTER, "Allows you to cast Psionic spells up to level 6.", B_FALSE);
addskill(SK_SS_NATURE, "Enviromancy", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_NATURE, PR_INEPT, "- Spell power power depends on your Level and Wisdom.", B_FALSE);
addskilldesc(SK_SS_NATURE, PR_INEPT, "- Spell power depends on your Level and Wisdom.", B_FALSE);
addskilldesc(SK_SS_NATURE, PR_NOVICE, "Allows you to cast Nature spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_NATURE, PR_BEGINNER, "Allows you to cast Nature spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_NATURE, PR_ADEPT, "Allows you to cast Nature spells up to level 3.", B_FALSE);
@ -21040,7 +21046,7 @@ void initskills(void) {
addskilldesc(SK_SS_NATURE, PR_EXPERT, "Allows you to cast Nature spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_NATURE, PR_MASTER, "Allows you to cast Nature spells up to level 6.", B_FALSE);
addskill(SK_SS_AIR, "Sorcery:Air Magic", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_AIR, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_AIR, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_AIR, PR_NOVICE, "Allows you to cast Air Magic spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_AIR, PR_BEGINNER, "Allows you to cast Air Magic spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_AIR, PR_ADEPT, "Allows you to cast Air Magic spells up to level 3.", B_FALSE);
@ -21048,7 +21054,7 @@ void initskills(void) {
addskilldesc(SK_SS_AIR, PR_EXPERT, "Allows you to cast Air Magic spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_AIR, PR_MASTER, "Allows you to cast Air Magic spells up to level 6.", B_FALSE);
addskill(SK_SS_DEATH, "Sorcery:Necromancy", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_DEATH, PR_INEPT, "- Spell power power depends on your Level, your Intelligence, and Hecta's pleasure.", B_FALSE);
addskilldesc(SK_SS_DEATH, PR_INEPT, "- Spell power depends on your Level, your Intelligence, and Hecta's pleasure.", B_FALSE);
addskilldesc(SK_SS_DEATH, PR_NOVICE, "Allows you to cast Necromancy spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_DEATH, PR_BEGINNER, "Allows you to cast Necromancy spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_DEATH, PR_ADEPT, "Allows you to cast Necromancy spells up to level 3.", B_FALSE);
@ -21056,7 +21062,7 @@ void initskills(void) {
addskilldesc(SK_SS_DEATH, PR_EXPERT, "Allows you to cast Necromancy spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_DEATH, PR_MASTER, "Allows you to cast Necromancy spells up to level 6.", B_FALSE);
addskill(SK_SS_DIVINATION, "Sorcery:Divination", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_DIVINATION, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_DIVINATION, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_DIVINATION, PR_NOVICE, "Allows you to cast Divination spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_DIVINATION, PR_BEGINNER, "Allows you to cast Divination spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_DIVINATION, PR_ADEPT, "Allows you to cast Divination spells up to level 3.", B_FALSE);
@ -21064,7 +21070,7 @@ void initskills(void) {
addskilldesc(SK_SS_DIVINATION, PR_EXPERT, "Allows you to cast Divination spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_DIVINATION, PR_MASTER, "Allows you to cast Divination spells up to level 6.", B_FALSE);
addskill(SK_SS_FIRE, "Sorcery:Fire Magic", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_FIRE, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_FIRE, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_FIRE, PR_NOVICE, "Allows you to cast Fire Magic spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_FIRE, PR_BEGINNER, "Allows you to cast Fire Magic spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_FIRE, PR_ADEPT, "Allows you to cast Fire Magic spells up to level 3.", B_FALSE);
@ -21072,7 +21078,7 @@ void initskills(void) {
addskilldesc(SK_SS_FIRE, PR_EXPERT, "Allows you to cast Fire Magic spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_FIRE, PR_MASTER, "Allows you to cast Fire Magic spells up to level 6.", B_FALSE);
addskill(SK_SS_COLD, "Sorcery:Cold Magic", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_COLD, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_COLD, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_COLD, PR_NOVICE, "Allows you to cast Cold Magic spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_COLD, PR_BEGINNER, "Allows you to cast Cold Magic spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_COLD, PR_ADEPT, "Allows you to cast Cold Magic spells up to level 3.", B_FALSE);
@ -21080,7 +21086,7 @@ void initskills(void) {
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_LIFE, "Sorcery:Life Magic", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_LIFE, PR_INEPT, "- Spell power power depends on your Level, your Intelligence, and Glorana's pleasure.", B_FALSE);
addskilldesc(SK_SS_LIFE, PR_INEPT, "- Spell power depends on your Level, your Intelligence, and Glorana's pleasure.", B_FALSE);
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);
addskilldesc(SK_SS_LIFE, PR_ADEPT, "Allows you to cast Life Magic spells up to level 3.", B_FALSE);
@ -21088,7 +21094,7 @@ void initskills(void) {
addskilldesc(SK_SS_LIFE, PR_EXPERT, "Allows you to cast Life Magic spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_LIFE, PR_MASTER, "Allows you to cast Life Magic spells up to level 6.", B_FALSE);
addskill(SK_SS_SUMMONING, "Sorcery:Summoning", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_SUMMONING, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_SUMMONING, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_SUMMONING, PR_NOVICE, "Allows you to cast Summoning spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_SUMMONING, PR_BEGINNER, "Allows you to cast Summoning spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_SUMMONING, PR_ADEPT, "Allows you to cast Summoning spells up to level 3.", B_FALSE);
@ -21096,7 +21102,7 @@ void initskills(void) {
addskilldesc(SK_SS_SUMMONING, PR_EXPERT, "Allows you to cast Summoning spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_SUMMONING, PR_MASTER, "Allows you to cast Summoning spells up to level 6.", B_FALSE);
addskill(SK_SS_TRANSLOCATION, "Sorcery:Translocation", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_TRANSLOCATION, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_TRANSLOCATION, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_TRANSLOCATION, PR_NOVICE, "Allows you to cast Translocation spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_TRANSLOCATION, PR_BEGINNER, "Allows you to cast Translocation spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_TRANSLOCATION, PR_ADEPT, "Allows you to cast Translocation spells up to level 3.", B_FALSE);
@ -21104,7 +21110,7 @@ void initskills(void) {
addskilldesc(SK_SS_TRANSLOCATION, PR_EXPERT, "Allows you to cast Translocation spells up to level 5.", B_FALSE);
addskilldesc(SK_SS_TRANSLOCATION, PR_MASTER, "Allows you to cast Translocation spells up to level 6.", B_FALSE);
addskill(SK_SS_WILD, "Sorcery:Wild Magic", "Boosts casting of spells from this school.", 50);
addskilldesc(SK_SS_WILD, PR_INEPT, "- Spell power power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_WILD, PR_INEPT, "- Spell power depends on your Level and Intelligence.", B_FALSE);
addskilldesc(SK_SS_WILD, PR_NOVICE, "Allows you to cast Wild Magic spells up to level 1.", B_FALSE);
addskilldesc(SK_SS_WILD, PR_BEGINNER, "Allows you to cast Wild Magic spells up to level 2.", B_FALSE);
addskilldesc(SK_SS_WILD, PR_ADEPT, "Allows you to cast Wild Magic spells up to level 3.", B_FALSE);

3
defs.h
View File

@ -38,6 +38,7 @@
#define TEXT_WARN_FLY "Warning: while airborne you will not map your surroundings."
#define TEXT_WARN_MUTABLE "(you can now gain attributes by eating corpses)"
#define TEXT_WARN_NOXP_GOODVSPEACEFUL "Warning: Only Evil players gain XP for peaceful kills."
#define TEXT_WARN_TRAIN_NOBOOK "You will not be able to study spells without a spellbook. Really train?"
// F_SCOREBONUS text args
#define SCB_DONATIONS "charitable donations"
@ -3722,6 +3723,7 @@ enum FLAG {
F_AUTOCMD, // val0 = how many times to repeat this
F_LASTCMD, // text[0] = last command performed, v0/1 = x/y of cell, v2=various
F_WILLTHROW, // this lf will treat obid v0 as a thrown missile.
F_CANSTUDY, // lf can study spells from school v0
F_CANLEARN, // lf is able to learn skill val0
// v1 = max lev
F_STAMBOOST, // lf gets v0 extra stamina
@ -4758,6 +4760,7 @@ enum COMMAND {
CMD_WEAR,
CMD_WEILD,
CMD_EXCHANGE,
CMD_COUNTMONEY,
};
typedef struct condset_s {

52
io.c
View File

@ -5420,6 +5420,53 @@ void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf) {
msg("\"I know of no %sdangers in this area.\"", (totdone) ? "other " : "");
}
void docountmoney(lifeform_t *lf) {
int goldamt = 0,gemamt = 0,credit = 0;
int unknowncredit = 0;
char goldbuf[BUFLEN], gembuf[BUFLEN],creditbuf[BUFLEN];
object_t *o;
goldamt = countmoney(lf->pack);
for (o = lf->pack->first ; o ; o = o->next) {
if (hasflag(o->flags, F_GEM)) {
gemamt += getobvalue(o);
} else if (o->type->id == OT_CREDITCARD) {
if (isidentified(o)) {
credit += getcharges(o);
} else {
unknowncredit++;
}
}
}
if (gemamt) {
snprintf(gembuf, BUFLEN, ", $%d worth of gemstones", gemamt);
} else {
strcpy(gembuf, "");
}
if (credit) {
if (unknowncredit) {
snprintf(creditbuf, BUFLEN, " and at least $%d credit", credit);
} else {
snprintf(creditbuf, BUFLEN, " and $%d credit", credit);
}
} else if (unknowncredit) {
if (unknowncredit == 1) {
snprintf(creditbuf, BUFLEN, " and a stolen credit card");
} else {
snprintf(creditbuf, BUFLEN, " and %d stolen credit cards", unknowncredit);
}
} else {
strcpy(creditbuf, "");
}
if (goldamt == 0) {
sprintf(goldbuf, "no money");
} else {
sprintf(goldbuf, "$%d", goldamt);
}
msg("You have %s%s%s.", goldbuf, gembuf, creditbuf);
}
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst) {
object_t *o;
char buf[BUFLEN];
@ -7722,7 +7769,7 @@ char *makedesc_ob(object_t *o, char *retbuf) {
sprintf(buf, " - %s", contentname);
if ((o->type->id == OT_SPELLBOOK) || (o->type->id == OT_GRIMOIRE)) {
char lbuf[BUFLEN];
sprintf(lbuf, " (Lv %d)%s", getspelllevel(oo->type->id),
sprintf(lbuf, " (Lv %d %s)%s", getspelllevel(oo->type->id), getschoolname(getspellschool(oo->type->id)),
lfhasflagval(player, F_CANCAST, oo->type->id, NA, NA, NULL) ?
" [known]" : "");
strcat(buf, lbuf);
@ -11170,6 +11217,9 @@ void handleinput(void) {
case CMD_INV: // inventory
doinventory(player->pack);
break;
case CMD_COUNTMONEY: // count money
docountmoney(player);
break;
case CMD_INFOPLAYER: // display player stats
showlfstats(player, B_FALSE);
break;

1
io.h
View File

@ -57,6 +57,7 @@ void docomms(lifeform_t *target);
void docommslf(lifeform_t *lf, char ch, lifeform_t *lf2, cell_t *targc);
void docomms_areainfo(char *who, flagpile_t *fp, lifeform_t *lf);
void docomms_areadangers(char *who, flagpile_t *fp, lifeform_t *lf);
void docountmoney(lifeform_t *lf);
void dodrop(obpile_t *op, int wantmulti, obpile_t *dst);
void doeat(obpile_t *op);
void doenter(lifeform_t *lf);

268
lf.c
View File

@ -719,6 +719,12 @@ int cancast(lifeform_t *lf, enum OBTYPE oid, int *mpcost) {
flag_t *f;
objecttype_t *ot;
int stamcost = 0;
if (mpcost) {
// default to base cost
*mpcost = getmpcost(lf, oid);
}
if (lfhasflag(lf, F_SILENCED)) {
reason = E_SILENCED;
return B_FALSE;
@ -1565,6 +1571,48 @@ int cansleep(lifeform_t *lf) {
return B_TRUE;
}
int canstudyspell(lifeform_t *lf, enum OBTYPE spellid) {
//object_t *o;
//int hasbook = B_FALSE;
enum SPELLSCHOOL school;
school = getspellschool(spellid);
switch (school) {
case SS_NATURE:
case SS_ALLOMANCY:
case SS_LIFE:
case SS_MENTAL:
return B_FALSE;
default:
break;
}
if (!lfhasflagval(lf, F_CANSTUDY, school, NA, NA, NULL)) return B_FALSE;
/*
// must have a spellbook to record the spell in.
for (o = lf->pack->first ; o ; o = o->next) {
if (o->type->id == OT_SPELLBOOK) {
if (hasflagval(o->flags, F_LINKSCHOOL, school, NA, NA, NULL)) {
hasbook = B_TRUE;
}
} else if (o->type->id == OT_GRIMOIRE) {
hasbook = B_TRUE;
}
}
if (!hasbook) return B_FALSE;
*/
if (lf->skillpoints < getspelllevel(spellid)) return B_FALSE; // too high a level
if (!spelllearnable(lf, spellid)) return B_FALSE; // too high powered ?
return B_TRUE;
}
int canthrow(lifeform_t *lf, object_t *o, enum ERROR *why) {
flag_t *f;
if (why) *why = E_OK;
@ -5766,7 +5814,10 @@ void enhanceskills(lifeform_t *lf) {
char eorl = 'e';
int skillstoenhance = 0;
int skillstolearn = 0;
int magictolearn = 0;
int done = B_FALSE;
obpile_t *spells;
objecttype_t *ot;
skillstoenhance = 0;
for (f = lf->flags->first ; f ; f = f->next) {
@ -5786,28 +5837,57 @@ void enhanceskills(lifeform_t *lf) {
}
}
// construct list of spells you can study
//
// can study a spell if:
// - it's not a nature spell.
// - player can't already cast it
// - player is skilled in at least one of the spell's schools.
// - player is a high enough level to cast the spell.
// - player has sufficient training points
magictolearn = 0;
spells = addobpile(NOOWNER, NOLOC, NULL);
while (!done && lf->skillpoints && (skillstolearn || skillstoenhance)) {
for (ot = objecttype ; ot ; ot = ot->next) {
if (ot->obclass->id != OC_SPELL) continue;
if (!canstudyspell(lf, ot->id)) continue;
// spell is learnable - add to the list
addobfast(spells, ot->id);
magictolearn++;
}
while (!done && lf->skillpoints && (skillstolearn || skillstoenhance || magictolearn)) {
char q[BUFLEN],buf2[BUFLEN],validchars[BUFLEN];
char defchar[BUFLEN];
strcpy(q, "");
strcpy(validchars, "n");
strcpy(defchar, "n");
if (skillstolearn) {
char buf[BUFLEN];
if (skillstoenhance) {
snprintf(buf, BUFLEN, "(E)nhance skills, (L)earn skills, or (N)one (%d points left)?",lf->skillpoints);
eorl = askchar(buf,"eln","e", B_TRUE, B_FALSE);
} else {
snprintf(buf, BUFLEN,"Learn a new skill (%d points left)?",lf->skillpoints);
ch = askchar(buf,"yn","y", B_TRUE, B_FALSE);
if (ch == 'y') eorl = 'l';
else eorl = 'n';
}
} else if (skillstoenhance) {
char buf[BUFLEN];
snprintf(buf, BUFLEN,"Enhance your current skills (%d points left)?",lf->skillpoints);
ch = askchar(buf,"yn","y", B_TRUE, B_FALSE);
if (ch == 'y') eorl = 'e';
else eorl = 'n';
} else {
eorl = 'n';
strcat(q, "(E)nhance");
strcat(validchars, "e");
strcpy(defchar, "e");
}
if (skillstoenhance) {
if (strlen(q)) {
strcat(q, "/");
}
strcat(q, "(L)earn");
strcat(validchars, "l");
}
strcat(q, " skills");
if (magictolearn && !lfhasflag(lf, F_NOSPELLS)) {
strcat(q, ", study (M)agic");
strcat(validchars, "m");
}
strcat(q, " or (N)one");
snprintf(buf2, BUFLEN, " [%d trn left]",lf->skillpoints); // ooo add color?
strcat(q, buf2);
eorl = askchar(q,validchars,defchar, B_TRUE, B_FALSE);
if (eorl == 'e') {
// enhance an existing skill
@ -5905,10 +5985,113 @@ void enhanceskills(lifeform_t *lf) {
msg("There is nothing more that you can learn.");
}
}
} else if (eorl == 'm') {
object_t *o = NULL;
int schoolok[SS_LAST],i;
// select a magic spell
// get a list of possible schools
for (i = 0; i < SS_LAST; i++) {
schoolok[i] = B_FALSE;
}
for (o = spells->first ; o ; o = o->next) {
enum SPELLSCHOOL school;
school = getspellschoolknown(lf, o->type->id);
schoolok[school] = B_TRUE;
}
// ask which school
initprompt(&prompt, "Learn a spell from which school?");
ch = 'a';
for (i = 0; i < SS_LAST; i++) {
if (schoolok[i]) {
addchoice(&prompt, i, getschoolname(i), NULL, NULL, NULL);
}
}
addchoice(&prompt, '\0', "(none)", NULL, NULL, NULL);
ch = getchoicestr(&prompt, B_FALSE, B_TRUE);
if (ch != '\0') {
char ques[BUFLEN];
snprintf(ques, BUFLEN, "Learn which spell (%d point%s left)?", lf->skillpoints,
(lf->skillpoints == 1) ? "" : "s");
initprompt(&prompt, ques);
// ask which spell from that school
for (o = spells->first ; o ; o = o->next) {
enum SPELLSCHOOL school;
school = getspellschoolknown(lf, o->type->id);
if (school == ch) {
char buf[BUFLEN];
snprintf(buf, BUFLEN, "%s (%s) [%d points]", o->type->name,
getschoolname(school),
getspelllevel(o->type->id) );
addchoice(&prompt, o->type->id, o->type->name, buf, o, NULL);
}
}
addchoice(&prompt, '-', "(none)", NULL, NULL, NULL);
getchoicestr(&prompt, B_FALSE, B_TRUE);
o = prompt.result;
if (o) {
if (prompt.whichq == 0) {
learnspell(lf, o->type->id, B_TRUE);
player->skillpoints -= getspelllevel(o->type->id);
done = B_TRUE;
/*
char bookname[BUFLEN];
enum SPELLSCHOOL school;
school = getspellschoolknown(lf, o->type->id);
object_t *book;
// add it to a spellbook.
snprintf(ques, BUFLEN, "Which spellbook will you record '%s' in?", o->type->name);
initprompt(&prompt, ques);
for (book = lf->pack->first ; book ; book = book->next) {
int ok = B_FALSE;
if (book->type->id == OT_SPELLBOOK) {
if (hasflagval(book->flags, F_LINKSCHOOL, school, NA, NA, NULL)) {
ok = B_TRUE;
}
} else if (book->type->id == OT_GRIMOIRE) {
ok = B_TRUE;
}
if (ok) {
addchoice(&prompt, book->letter, book->type->name, NULL, book, NULL);
}
}
// prompt for which spellbook.
if (prompt.nchoices == 1) {
book = prompt.choice[0].data;
} else {
getchoice(&prompt);
book = (object_t *)prompt.result;
}
assert(book != NULL);
addobfast(book->contents, o->type->id);
getobname(book, bookname, 1);
msg("'%s' added to %s.", o->type->name, bookname);
*/
} else {
describespell(o->type);
}
}
}
} else if (eorl == 'n') {
done = B_TRUE;
} // end enhance/learnnew
} // whiel skillstolearn || skillstoenhance
// free list of possible spells
killobpile(spells);
statdirty = B_TRUE;
} else if (lf->skillpoints) {
// monsters will just enhance a random skill, they never learn new ones.
@ -5946,8 +6129,7 @@ void enhanceskills(lifeform_t *lf) {
ff = giveskill(lf, f->val[1]);
ff->fromlev = lf->level;
} else if ((f->id == F_LEVSPELL) && !lfhasflag(lf, F_NOSPELLS)) {
ff = addtempflag(lf->flags, F_CANCAST, f->val[1], NA, NA, NULL, FROMJOB);
ff->fromlev = lf->level;
learnspell(lf, f->val[1], B_TRUE);
} else if ((f->id == F_LEVSPELLSCHOOL) && !lfhasflag(lf, F_NOSPELLS)) { // select a spell from school
if (isplayer(lf)) {
select_new_spell(f->val[1], lf->level);
@ -5959,8 +6141,7 @@ void enhanceskills(lifeform_t *lf) {
// pick one randomly
ot = (objecttype_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data;
if (ot) {
ff = addtempflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL, FROMJOB);
ff->fromlev = lf->level;
learnspell(lf, ot->id, B_TRUE);
}
}
}
@ -6031,8 +6212,7 @@ void enhanceskills(lifeform_t *lf) {
ot = prompt.result;
if (ot) {
if (prompt.whichq == 0) { // learn the spell
ff = addtempflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL, FROMJOB);
ff->fromlev = lf->level;
learnspell(lf, ot->id, B_TRUE);
done = B_TRUE;
} else {
describespell(ot);
@ -6048,8 +6228,7 @@ void enhanceskills(lifeform_t *lf) {
// pick randomly
ot = (objecttype_t *)prompt.choice[rnd(0,prompt.nchoices-1)].data;
if (ot) {
ff = addtempflag(lf->flags, F_CANCAST, ot->id, NA, NA, NULL, FROMJOB);
ff->fromlev = lf->level;
learnspell(lf, ot->id, B_TRUE);
}
}
}
@ -7154,10 +7333,6 @@ void gainxp(lifeform_t *lf, long amt) {
amtneeded = getspforpoint(lf);
if (isplayer(lf)) statdirty = B_TRUE;
}
// debug!
if (newskillpoints >= 5) {
raise(SIGINT);
}
}
// ready for next level? can only go up ONE level.
@ -11607,24 +11782,13 @@ int getteachableskills(lifeform_t *teacher, lifeform_t *student, int *info, enum
for (i = 0; i < nretflags; i++) {
objecttype_t *spell;
enum OBTYPE spellid;
enum SPELLSCHOOL knownschool;
int teachable = B_FALSE;
f = retflag[i];
spellid = f->val[0];
spell = findot(spellid);
if (spell->obclass->id != OC_SPELL) continue;
// student skilled in one of the spell's schools?
knownschool = getspellschoolknown(student, spellid);
if (getskill(student, getschoolskill(knownschool))) {
int mpneeded;
if (!cancast(student, spellid, &mpneeded) && (getspellpower(student, spellid) > 0)) {
if (getmaxmp(student) >= mpneeded) {
teachable = B_TRUE;
}
}
}
teachable = spelllearnable(student, spellid);
if (teachable) {
info[*ninfo] = spellid;
tradetype[*ninfo] = TI_SPELL;
@ -12107,7 +12271,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) {
spell = getrandomspellfromschool(SS_NATURE, 1);
}
// you can now cast it.
addtempflag(lf->flags, F_CANCAST, spell, NA, NA, NULL, FROMJOB);
learnspell(lf, spell, B_FALSE);
}
// druids always worship ekrub
if (isplayer(lf)) {
@ -16774,7 +16938,10 @@ void autolearnspellsfrombook(lifeform_t *lf, object_t *book) {
if ((getspellschoolknown(lf, o->type->id) != SS_NONE) &&
!hasflagval(lf->flags, F_CANCAST, o->type->id, NA, NA, NULL) &&
(getspellpower(lf, o->type->id) > 0)) {
addtempflag(lf->flags, F_CANCAST, o->type->id, NA, NA, NULL, FROMJOB);
//addtempflag(lf->flags, F_CANCAST, o->type->id, NA, NA, NULL, FROMJOB);
learnspell(lf, o->type->id, B_FALSE);
//if (isplayer(lf)) {
// autoshortcut(lf, o->type->id);
//}
@ -17321,6 +17488,17 @@ void killsubjob(subjob_t *sj) {
}
*/
void learnspell(lifeform_t *lf, enum OBTYPE sid, int fromlevelup) {
flag_t *ff;
// learn the spell
ff = addtempflag(lf->flags, F_CANCAST, sid, NA, NA, NULL, FROMJOB);
assert(ff);
if (fromlevelup) {
ff->fromlev = lf->level;
}
}
flag_t *levelabilityready(lifeform_t *lf) {
flag_t *f;
int i;

2
lf.h
View File

@ -71,6 +71,7 @@ int cansee(lifeform_t *viewer, lifeform_t *viewee);
int cansee_real(lifeform_t *viewer, lifeform_t *viewee, int uselos);
int canshoot(lifeform_t *lf, enum ERROR *why);
int cansleep(lifeform_t *lf);
int canstudyspell(lifeform_t *lf, enum OBTYPE spellid);
int canthrow(lifeform_t *lf, object_t *o, enum ERROR *why);
int canuseweapons(lifeform_t *lf);
int canwear(lifeform_t *lf, object_t *o, enum BODYPART where);
@ -426,6 +427,7 @@ void killlf(lifeform_t *lf);
void killpoisontype(poisontype_t *pt);
void killrace(race_t *race);
//void killsubjob(subjob_t *sj);
void learnspell(lifeform_t *lf, enum OBTYPE sid, int fromlevelup);
flag_t *levelabilityready(lifeform_t *lf);
int loadfirearm(lifeform_t *lf, object_t *gun, object_t *ammo);
int loadfirearmfast(lifeform_t *lf, int onpurpose);

View File

@ -6023,7 +6023,7 @@ char *getobextrainfo(object_t *o, char *buf) {
}
} else if (o->type->id == OT_CREDITCARD) {
if (f->val[0] > 0) {
snprintf(chargestr, BUFLEN, " ($%d balance)",f->val[0]);
snprintf(chargestr, BUFLEN, " ($%d credit)",f->val[0]);
} else {
snprintf(chargestr, BUFLEN, " (maxed out)");
}

36
spell.c
View File

@ -2866,6 +2866,23 @@ int abilityeffects(lifeform_t *user, enum OBTYPE abilid, cell_t *targcell, lifef
// safe to train?
if (check_rest_ok(user)) return B_TRUE;
// warn if we're a mage training without a spellbook
/*
f = lfhasflag(user, F_CANSTUDY);
if (f) {
if (!hasobwithflagval(user->pack, F_LINKSCHOOL, f->val[0], NA, NA, NULL) &&
!hasob(user->pack, OT_GRIMOIRE)) {
char buf[BUFLEN];
snprintf(buf, BUFLEN, "You cannot study %s without a spellbook. Continue", getschoolname(f->val[0]));
// warn
if (!real_warnabout(buf, DEF_WARNINGTIME, B_TRUE)) {
return B_TRUE;
}
}
}
*/
// start training!
if (!startresting(user, B_TRUE)) {
// do the first one right away
@ -15608,6 +15625,25 @@ int spellisfromschool(int spellid, enum SPELLSCHOOL school) {
return B_FALSE;
}
int spelllearnable(lifeform_t *lf, enum OBTYPE spellid) {
enum SPELLSCHOOL knownschool;
int ok = B_FALSE;
// skilled in one of the spell's schools?
knownschool = getspellschoolknown(lf, spellid);
if (getskill(lf, getschoolskill(knownschool))) {
int mpneeded;
if (!cancast(lf, spellid, &mpneeded)) {
if (getspellpower(lf, spellid) > 0) {
if (getmaxmp(lf) >= mpneeded) {
ok = B_TRUE;
}
}
}
}
return ok;
}
int spellokformonsters(int spellid) {
objecttype_t *sp;
sp = findot(spellid);

View File

@ -40,6 +40,7 @@ void pullobto(object_t *o, lifeform_t *lf);
int schoolappearsinbooks(enum SPELLSCHOOL ss);
void spellcloud(cell_t *srcloc, int radius, int dirtype, 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 spelllearnable(lifeform_t *lf, enum OBTYPE spellid);
int spellokformonsters(int spellid);
int spellresisted(lifeform_t *target, lifeform_t *caster, int spellid, int power, int *seenbyplayer, int announce);
int stopspell(lifeform_t *caster, enum OBTYPE spellid);