diff --git a/data.c b/data.c index e85821b..487cbd6 100644 --- a/data.c +++ b/data.c @@ -451,7 +451,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_UNARMED, PR_SKILLED, NA, NULL); // abilities addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); - addjob(J_DRUID, "Druid", "Druids use the power of nature to aid themselves or harm others. They start with a pet wolf, and their spells are more powerful when near plants. They are willing to eat other lifeforms when neccessary but prefer a vegetable-based diet. Unlike other spellcasters, Druids gain spells automotically when levelling.", JC_FIGHTERMAGE); + addjob(J_DRUID, "Druid", "Druids use the power of nature to aid themselves or harm others. They start with a pet wolf, and their spells are more powerful when near plants. They are willing to eat other lifeforms when neccessary but prefer a vegetable-based diet. Unlike other spellcasters, Druids gain spells automatically when levelling.", JC_FIGHTERMAGE); // stats addflag(lastjob->flags, F_MPDICE, 1, 1, NA, NULL); addflag(lastjob->flags, F_JOBATTRMOD, A_WIS, 15, NA, NULL); @@ -10793,6 +10793,7 @@ void initrace(void) { addflag(lastrace->flags, F_STARTSKILL, SK_METALWORK, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_ENGINEERING, PR_BEGINNER, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_SS_ALLOMANCY, PR_NOVICE, NA, NULL); + addflag(lastrace->flags, F_RESISTMAG, 5, NA, NA, NULL); // penalties addflag(lastrace->flags, F_MPMOD, -3, NA, NA, NULL); addflag(lastrace->flags, F_DTVULN, DT_LIGHT, NA, NA, "1d6"); @@ -10951,6 +10952,7 @@ void initrace(void) { // bonuses addflag(lastrace->flags, F_SEEINDARK, 6, B_BLINDABLE, NA, NULL); addflag(lastrace->flags, F_MEDITATES, B_TRUE, NA, NA, NULL); + addflag(lastrace->flags, F_DTRESIST, DT_NECROTIC, NA, NA, NULL); addflag(lastrace->flags, F_MPMOD, 3, NA, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_SS_DEATH, PR_NOVICE, NA, NULL); addflag(lastrace->flags, F_STARTSKILL, SK_STEALTH, PR_NOVICE, NA, NULL); diff --git a/defs.h b/defs.h index 2d8d2f3..ee513be 100644 --- a/defs.h +++ b/defs.h @@ -1130,6 +1130,12 @@ enum ATTRBRACKET { AT_EXHIGH = 4, }; +enum RECOMMENDATION { + R_VRECOMMENDED = 2, + R_RECOMMENDED = 1, + R_NOTRECOMMENDED = 0, +}; + #define IQ_MINDLESS AT_EXLOW #define IQ_ANIMAL AT_VLOW diff --git a/lf.c b/lf.c index 836185b..d656095 100644 --- a/lf.c +++ b/lf.c @@ -3062,6 +3062,15 @@ int countlegs(lifeform_t *lf) { return legs; } +int countmonsters(void) { + int count = 0; + race_t *r; + for (r = firstrace ; r ; r = r->next) { + count++; + } + return count; +} + int countnearbyallies(lifeform_t *lf) { lifeform_t *l; int count = 0; @@ -8780,6 +8789,132 @@ char *getjobname(lifeform_t *lf) { return ""; } +int getjobrecommendation(race_t *r, job_t *j) { + int rec = 0; + flag_t *retflag[MAXCANDIDATES],*jobflag,*f; + int nretflags,i; + + getflags(r->flags, retflag, &nretflags, F_STARTATT, F_STARTSKILL, F_NOSPELLS, F_NOSKILL, F_MPMOD, F_DTIMMUNE, F_DTRESIST, F_RESISTMAG, F_MPDICE, F_ARMOURRATING, F_NONE); + for (i = 0; i < nretflags; i++) { + f = retflag[i]; + if ((f->id == F_STARTATT) && (f->val[1] != AT_RANDOM)) { + flag_t *jobflag; + jobflag = hasflagval(j->flags, F_JOBATTRMOD, f->val[0], NA, NA, NULL); + if (jobflag && (jobflag->val[1] != AT_RANDOM)) { + if ((f->val[1] >= AT_HIGH) && (jobflag->val[1] <= -10)) { // race high, job low = -- + rec -= 1; + } else if ((f->val[1] >= AT_GTAVERAGE) && (jobflag->val[1] > 0)) { // race high, job high = ++ + rec += 2; + } else if ((f->val[1] <= AT_LTAVERAGE) && (jobflag->val[1] > 0)) { // race low, job high = -- + rec -= 2; + //} else if ((f->val[1] < 0) && (jobflag->val[1] < 0)) { // race low, job low = ---- + // rec -= 2; + } + } + } else if (f->id == F_STARTSKILL) { + if (!isloreskill(f->val[0])) { + jobflag = hasflagval(j->flags, f->id, f->val[0], NA, NA, NULL); + if (jobflag) { // both race and job start with the same skill + rec++; + } + jobflag = hasflagval(j->flags, F_NOSKILL, f->val[0], NA, NA, NULL); + if (jobflag) { // race has a skill, job can't have that skill + rec -= 4; + } + // magic skill, and job has nomagic? + if (isspellskill(f->val[0]) && hasflag(j->flags, F_NOSPELLS)) { + rec -= 6; + } + } + } else if (f->id == F_ARMOURRATING) { + for (jobflag = j->flags->first ; jobflag ; jobflag = jobflag->next) { + if ((jobflag->id == F_STARTSKILL) && isweaponskill(jobflag->val[0])) { + rec += 1; + } + } + } else if ((f->id == F_DTIMMUNE) || (f->id == F_DTRESIST)) { + if (hasflag(j->flags, f->id)) { + rec += 2; + } + if ((f->val[0] == DT_FIRE) || (f->val[0] == DT_HEAT)) { + if (hasflagval(j->flags, F_STARTSKILL, SK_SS_FIRE, NA, NA, NULL)) { + rec += 4; + } + } else if (f->val[0] == DT_COLD) { + if (hasflagval(j->flags, F_STARTSKILL, SK_SS_COLD, NA, NA, NULL)) { + rec += 4; + } + } else if (f->val[0] == DT_NECROTIC) { + if (hasflagval(j->flags, F_STARTSKILL, SK_SS_DEATH, NA, NA, NULL)) { + rec += 4; + } + } + } else if (f->id == F_NOSPELLS) { + // both race and job can't us spells + if (hasflag(j->flags, f->id)) { + rec += 4; + } + // race can't have spells, and job has a magic skill? + // (SLOW search) + for (jobflag = j->flags->first ; jobflag ; jobflag = jobflag->next) { + if ((jobflag->id == F_STARTSKILL) && isspellskill(jobflag->val[0])) { + rec -= 2; + } + } + // job uses mp? + if (hasflag(j->flags, F_MPDICE)) { + rec -= 4; + } + + } else if (f->id == F_MPMOD) { + jobflag = hasflag(j->flags, f->id); + if (f->val[0] < 0) { // mp penalty + if (jobflag && (jobflag->val[0] < 0)) { + rec += 4; + } + if (hasflag(j->flags, F_NOSPELLS)) { + rec += 6; + } else if (hasflag(j->flags, F_MPDICE)) { + rec -= 2; + } + } else if (f->val[0] > 0) { // mp bonus + if (jobflag && (jobflag->val[0] > 0)) { + rec += 4; + } else if (jobflag && (jobflag->val[0] < 0)) { + rec -= 4; + } + if (hasflag(j->flags, F_NOSPELLS)) { + rec -= 6; + } else if (hasflag(j->flags, F_MPDICE)) { + rec += 4; + } + } + } else if (f->id == F_RESISTMAG) { + if (hasflag(j->flags, f->id)) { + rec += 6; + } + } else if (f->id == F_MPDICE) { + if (hasflag(j->flags, F_NOSPELLS)) { + rec -= 4; + } + } else if (f->id == F_NOSKILL) { + jobflag = hasflagval(j->flags, F_STARTSKILL, f->val[0], NA, NA, NULL); + if (jobflag) { // race can't have a skill, job starts with it + rec -= 4; + } + jobflag = hasflagval(j->flags, F_CANLEARN, f->val[0], NA, NA, NULL); + if (jobflag) { // race can't have a skill, job can learn it + rec--; + } + jobflag = hasflagval(j->flags, F_NOSKILL, f->val[0], NA, NA, NULL); + if (jobflag) { // race can't have a skill, job can't have that skill + rec += 2; + } + } + } + return rec; +} + int getlastdir(lifeform_t *lf) { flag_t *f; f = lfhasflag(lf, F_LASTDIR); diff --git a/lf.h b/lf.h index b498588..3028935 100644 --- a/lf.h +++ b/lf.h @@ -94,6 +94,7 @@ int continuedigging(lifeform_t *lf); int continuerepairing(lifeform_t *lf, flag_t *repairflag); int countinnateattacks(lifeform_t *lf); int countlegs(lifeform_t *lf); +int countmonsters(void); int countnearbyallies(lifeform_t *lf); int countnearbyhurtallies(lifeform_t *lf); int countplantsinsight(lifeform_t *lf); @@ -208,6 +209,7 @@ job_t *getjob(lifeform_t *lf); enum JOBCATEGORY getjobcat(lifeform_t *lf); //enum SUBJOB getsubjob(lifeform_t *lf); char *getjobname(lifeform_t *lf); +int getjobrecommendation(race_t *r, job_t *j); int getlastdir(lifeform_t *lf); int getleftrightwalls(lifeform_t *lf); int getlfaccuracy(lifeform_t *lf, object_t *wep); diff --git a/nexus.c b/nexus.c index 5acdd41..a79008e 100644 --- a/nexus.c +++ b/nexus.c @@ -269,27 +269,58 @@ int main(int argc, char **argv) { if (!j) { enum JOBCATEGORY jcid; + int recommended; // ask for job initprompt(&prompt, "Select your base job:"); ch = 'a'; - for (jcid = JC_FIRST ; jcid <= JC_LAST; jcid++) { - for (j = firstjob ; j ; j = j->next) { - if ((j->category == jcid) && jobpossible(startrace->flags, j->id)) { - char *longdesc,buf[BUFLEN]; - longdesc = malloc(HUGEBUFLEN * sizeof(char)); - makedesc_job(j, longdesc); - if (!hasflag(j->flags, F_NOPLAYER)) { - // letter isn't used - if (j->id == J_GOD) { - sprintf(buf, "%-20s(%s)", "Diety", "for debugging"); - } else { - sprintf(buf, "%-20s(%s)", j->name, getjobcatname(j->category)); - } - addchoice(&prompt, '-', buf, NULL, j, longdesc); - } - free(longdesc); - } + // sort by recommendaion, then by category + for (recommended = R_VRECOMMENDED ; recommended >= R_NOTRECOMMENDED; recommended--) { + switch (recommended) { + case R_VRECOMMENDED: + addheading(&prompt, "Highly Recommended"); + break; + case R_RECOMMENDED: + addheading(&prompt, "Recommended"); + break; + case R_NOTRECOMMENDED: + addheading(&prompt, "Not Recommended"); + break; + default: + break; } + for (jcid = JC_FIRST ; jcid <= JC_LAST; jcid++) { + for (j = firstjob ; j ; j = j->next) { + int rec,recok = B_FALSE; + if (j->id == J_GOD) { + rec = -50; + } else { + rec = getjobrecommendation(startrace, j); + } + if ((recommended == R_VRECOMMENDED) && (rec >= 3)) { + recok = B_TRUE; + } else if ((recommended == R_RECOMMENDED) && (rec >= 0) && (rec < 3)) { + recok = B_TRUE; + } else if ((recommended == R_NOTRECOMMENDED) && (rec < 0)) { + recok = B_TRUE; + } + + if ((j->category == jcid) && recok && jobpossible(startrace->flags, j->id)) { + char *longdesc,buf[BUFLEN]; + longdesc = malloc(HUGEBUFLEN * sizeof(char)); + makedesc_job(j, longdesc); + if (!hasflag(j->flags, F_NOPLAYER)) { + // letter isn't used + if (j->id == J_GOD) { + sprintf(buf, "%-20s(%s)", "Diety", "for debugging"); + } else { + sprintf(buf, "%-20s(%s)", j->name, getjobcatname(j->category)); + } + addchoice(&prompt, '-', buf, NULL, j, longdesc); + } + free(longdesc); + } + } + } // end for jobcat } j = NULL; while (!j) {