From 8b6f5a13a824fc395f2ef6ea792bbb222f82fec7 Mon Sep 17 00:00:00 2001 From: Rob Pearce Date: Wed, 18 Jul 2012 10:12:32 +0000 Subject: [PATCH] - [+] new skill: advanced combat - [+] each level: 10% increase chance of not using stamina to attack - [+] nov: improvised weapons - [+] beg: nausea, being prone don't affect your accuracy - [+] adept: - [+] blind fighting ability. - [+] skilled: DISARM skill - [+] expert: regain stamina once you kill someone - [+] FLIP skill - [+] master: attacking uses no stamina - [+] assign to jobs - [+] Ninja starts with ADEPT level. - [+] Warrior too? - [+] genericise plural code: - [+] plural_t - [+] singular - [+] plural - [+] change object.c addobject() - [+] chnage text.c makeplural() - [+] move flak jacket to go over shoudlers. - [+] fix: don't give player skill in their race --- attack.c | 10 +- data.c | 68 +++++++++++++- data.h | 1 + defs.h | 10 +- lf.c | 43 +++++++-- nexus.c | 2 + objects.c | 42 +++------ text.c | 268 ++++++++++++++++++++++++++++-------------------------- text.h | 2 + 9 files changed, 272 insertions(+), 174 deletions(-) diff --git a/attack.c b/attack.c index d1eaba5..fbd6108 100644 --- a/attack.c +++ b/attack.c @@ -713,8 +713,14 @@ int attackcell(lifeform_t *lf, cell_t *c, int force) { } if (isplayer(lf)) { - // lose a bit of stamina - modstamina(lf, -getattackstamloss(lf)); + enum SKILLLEVEL slev; + slev = getskill(lf, SK_COMBAT); + if (slev != PR_MASTER) { + if (!pctchance(slev * 10)) { + // lose a bit of stamina + modstamina(lf, -getattackstamloss(lf)); + } + } } // stop sprinting diff --git a/data.c b/data.c index bc85454..eba5cbb 100644 --- a/data.c +++ b/data.c @@ -9,6 +9,7 @@ #include "nexus.h" #include "objects.h" #include "spell.h" +#include "text.h" extern behaviour_t *firstbehaviour,*lastbehaviour; extern command_t *firstcommand,*lastcommand; @@ -26,6 +27,7 @@ extern brand_t *firstbrand,*lastbrand; extern obmod_t *firstobmod,*lastobmod; extern material_t *material,*lastmaterial; extern lifeform_t *player; +extern plural_t *firstplural,*lastplural; extern hiddennamewithcol_t colour[]; extern char *bookadjective[]; @@ -405,6 +407,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "combat knife"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "revolver"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "helmet"); + addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather armour"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "flak jacket"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "combat pants"); addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "leather boots"); @@ -416,6 +419,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10 bullets"); // initial skills addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_COMBAT, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_COOKING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_FIRSTAID, PR_NOVICE, NA, NULL); @@ -460,6 +464,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_SPEECH, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SS_NATURE, PR_NOVICE, NA, NULL); // learnable skills + addflag(lastjob->flags, F_CANLEARN, SK_COMBAT, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_EXOTICWEPS, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_FIRSTAID, NA, NA, NULL); @@ -501,6 +506,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTSKILL, SK_LORE_HUMANOID, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_COMBAT, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_COOKING, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_EVASION, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL); @@ -664,7 +670,8 @@ void initjobs(void) { // initial skills addflag(lastjob->flags, F_STARTSKILL, SK_ARMOUR, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_ATHLETICS, PR_BEGINNER, NA, NULL); - addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL); // limit + addflag(lastjob->flags, F_STARTSKILL, SK_CARTOGRAPHY, PR_NOVICE, NA, NULL); // limited + addflag(lastjob->flags, F_STARTSKILL, SK_COMBAT, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_EVASION, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_PERCEPTION, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_UNARMED, PR_BEGINNER, NA, NULL); @@ -694,7 +701,6 @@ void initjobs(void) { // abilities addflag(lastjob->flags, F_MPDICE, 1, NA, NA, NULL); // gained abilities - addflag(lastjob->flags, F_LEVABIL, 2, OT_A_DISARMLF, NA, NULL); addflag(lastjob->flags, F_LEVABIL, 4, OT_A_TRIPLF, NA, NULL); addflag(lastjob->flags, F_LEVABIL, 6, OT_A_FLIP, NA, NULL); addflag(lastjob->flags, F_HIRABLE, B_TRUE, NA, NA, NULL); @@ -730,6 +736,7 @@ void initjobs(void) { addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, PR_ADEPT, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CARTOGRAPHY, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CLIMBING, NA, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_COMBAT, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_COOKING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, PR_EXPERT, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_METALWORK, NA, NA, NULL); @@ -771,6 +778,7 @@ void initjobs(void) { // learnable skills addflag(lastjob->flags, F_CANLEARN, SK_ATHLETICS, PR_EXPERT, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_BACKSTAB, PR_ADEPT, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_COMBAT, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_LISTEN, PR_EXPERT, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, PR_SKILLED, NA, NULL); @@ -823,6 +831,7 @@ void initjobs(void) { // learnable skills addflag(lastjob->flags, F_CANLEARN, SK_ARMOUR, PR_NOVICE, NA, NULL); // limit addflag(lastjob->flags, F_CANLEARN, SK_CHANNELING, PR_SKILLED, NA, NULL); + addflag(lastjob->flags, F_CANLEARN, SK_COMBAT, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_COOKING, NA, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_PERCEPTION, PR_SKILLED, NA, NULL); addflag(lastjob->flags, F_CANLEARN, SK_SEWING, NA, NA, NULL); // @@ -857,6 +866,7 @@ void initjobs(void) { addflag(lastjob->flags, F_STARTOB, 100, NA, NA, "10-20 gold dollars"); // initial skills addflag(lastjob->flags, F_STARTSKILL, SK_AXES, PR_NOVICE, NA, NULL); + addflag(lastjob->flags, F_STARTSKILL, SK_COMBAT, PR_BEGINNER, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_COOKING, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_CLUBS, PR_NOVICE, NA, NULL); addflag(lastjob->flags, F_STARTSKILL, SK_SHORTBLADES, PR_NOVICE, NA, NULL); @@ -6746,10 +6756,10 @@ void initobjects(void) { addflag(lastot->flags, F_OBHP, 120, 120, NA, NULL); addflag(lastot->flags, F_CRITPROTECTION, 100, NA, NA, NULL); - addot(OT_FLAKJACKET, "flak jacket", "Heavy metal body armour. Designed to stop a bullet, but ineffective against melee attacks.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM); + addot(OT_FLAKJACKET, "flak jacket", "Heavy metal vest, worn over the shoulders. Designed to stop a bullet, but ineffective against melee attacks.", MT_METAL, 30, OC_ARMOUR, SZ_MEDIUM); addflag(lastot->flags, F_RARITY, H_ALL, 100, RR_RARE, NULL); addflag(lastot->flags, F_MULTISIZE, B_TRUE, NA, NA, NULL); - addflag(lastot->flags, F_GOESON, BP_BODY, NA, NA, NULL); + addflag(lastot->flags, F_GOESON, BP_SHOULDERS, NA, NA, NULL); addflag(lastot->flags, F_ARMOURRATING, 2, NA, NA, NULL); addflag(lastot->flags, F_EQUIPCONFER, F_ARMOURPENALTY, 10, 10, NULL); addflag(lastot->flags, F_ATTREQ, A_STR, 50, NA, NULL); @@ -17723,6 +17733,7 @@ void initskills(void) { addskill(SK_ARMOUR, "Armour", "Reduces evasion and stealth penalties from wearing armour.", 100); addskilldesc(SK_ARMOUR, PR_INEPT, "- Reduces the noise you make when wearing metal armour.", B_FALSE); addskilldesc(SK_ARMOUR, PR_NOVICE, "^gReduces armour penalties by 10%.^n", B_FALSE); + addskilldesc(SK_ARMOUR, PR_NOVICE, "^gYou can now recognise the quality of armour.^n", B_FALSE); addskilldesc(SK_ARMOUR, PR_BEGINNER, "^gReduces armour penalties by 20%.^n", B_FALSE); addskilldesc(SK_ARMOUR, PR_ADEPT, "^gReduces armour penalties by 30%.^n", B_FALSE); addskilldesc(SK_ARMOUR, PR_SKILLED, "^gReduces armour penalties by 40%.^n", B_FALSE); @@ -17768,6 +17779,15 @@ void initskills(void) { addskilldesc(SK_CLIMBING, PR_SKILLED, "-5 accuracy penalty while climbing.", B_FALSE); addskilldesc(SK_CLIMBING, PR_EXPERT, "-2 accuracy penalty while climbing.", B_FALSE); addskilldesc(SK_CLIMBING, PR_MASTER, "No accuracy penalty or stamina cost to remain climbing.", B_FALSE); + addskill(SK_COMBAT, "Advanced Combat", "Affects your ability to fight in adverse situations or unorthodox styles.", 0); + addskilldesc(SK_COMBAT, PR_INEPT, " - Each skill level grants a 10% chance to bypass stamina drain when attacking.", B_FALSE); + addskilldesc(SK_COMBAT, PR_NOVICE, "Unskilled weapon penalties are greatly reduced.", B_FALSE); + addskilldesc(SK_COMBAT, PR_BEGINNER, "Eliminates penalties for being prone or nauseated.", B_FALSE); + addskilldesc(SK_COMBAT, PR_ADEPT, "Eliminates penalties when fighting unseen enemies.", B_FALSE); + addskilldesc(SK_COMBAT, PR_ADEPT, "You gain the 'disarm' ability.", B_FALSE); + addskilldesc(SK_COMBAT, PR_SKILLED, "You gain the 'trip' ability.", B_FALSE); + addskilldesc(SK_COMBAT, PR_EXPERT, "^gSecond wind restores stamina after defeating enemies.^n", B_TRUE); + addskilldesc(SK_COMBAT, PR_MASTER, "^gAttacking will no longer drain your stamina.^n", B_TRUE); addskill(SK_COOKING, "Cooking", "Your ability to combine foods into nutritious meals.", 50); addskilldesc(SK_COOKING, PR_INEPT, " - Note: when cooking, all ingredients must already be recognised.", B_FALSE); addskilldesc(SK_COOKING, PR_NOVICE, "^gYou can now cook corpses before consumption.", B_TRUE); @@ -17841,6 +17861,7 @@ void initskills(void) { addskill(SK_SHIELDS, "Shields", "Reduces shield accuracy penalty, and raises chance to block attacks.", 50); addskilldesc(SK_SHIELDS, PR_INEPT, "- Without this skill, shield accuracy penalties are tripled.", B_FALSE); addskilldesc(SK_SHIELDS, PR_NOVICE, "^gShield accuracy penalties are reduced by 1.^n", B_FALSE); + addskilldesc(SK_SHIELDS, PR_NOVICE, "^gYou can now recognise the quality of shields.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gShield accuracy penalties are reduced by 2.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_BEGINNER, "^gYou gain the 'shield bash' ability.^n", B_FALSE); addskilldesc(SK_SHIELDS, PR_ADEPT, "^gShield accuracy penalties are reduced by 3.^n", B_FALSE); @@ -18070,6 +18091,8 @@ void initskills(void) { if (isweaponskill(sk->id) || (sk->id == SK_UNARMED)) { addskilldesc(sk->id, PR_INEPT, "This skill increases your accuracy and damage when using matching weapons.", B_FALSE); if (sk->id == SK_CLUBS) addskilldesc(sk->id, PR_NOVICE, "^gYou gain the 'merciful fighting' ability.^n", B_FALSE); + addskilldesc(sk->id, PR_NOVICE, "^gYou can now recognise the quality of matching weapons.^n", B_FALSE); + addskilldesc(sk->id, PR_NOVICE, "^gYou no longer suffer accuracy penalties with matching weapons.^n", B_FALSE); addskilldesc(sk->id, PR_BEGINNER, "^g+1 accuracy.^n", B_FALSE); addskilldesc(sk->id, PR_BEGINNER, "^gYou gain the 'wild strike' ability.^n", B_FALSE); addskilldesc(sk->id, PR_ADEPT, "^g+10% damage bonus.^n", B_FALSE); @@ -18083,6 +18106,43 @@ void initskills(void) { } } +void inittext(void) { + // scrolls + addplural("bag","bags", B_TRUE); + addplural("berry","berries", B_TRUE); + addplural("block","blocks", B_TRUE); + addplural("can","cans", B_TRUE); + addplural("chunk","chunks", B_TRUE); + addplural("cloud","clouds", B_TRUE); + addplural("clove","cloves", B_TRUE); + addplural("flask","flasks", B_TRUE); + addplural("gem","gems", B_TRUE); + addplural("knife","knives", B_TRUE); + addplural("leaf","leaves", B_TRUE); + addplural("loaf","loaves", B_TRUE); + addplural("lump","lumps", B_TRUE); + addplural("piece","pieces", B_TRUE); + addplural("pile","piles", B_TRUE); + addplural("pinch","pinches", B_TRUE); + addplural("plank","planks", B_TRUE); + addplural("pool","pools", B_TRUE); + addplural("potion","potions", B_TRUE); + addplural("puddle","puddles", B_TRUE); + addplural("puff","puffs", B_TRUE); + addplural("ring","rings", B_TRUE); + addplural("ruby","rubies", B_TRUE); + addplural("scroll","scrolls", B_TRUE); + addplural("splash","splashes", B_TRUE); + addplural("set","sets", B_TRUE); + addplural("sheet","sheets", B_TRUE); + addplural("sprig","sprigs", B_TRUE); + addplural("suit","suits", B_TRUE); + addplural("vial","vials", B_TRUE); + + // don't return after finding this one + addplural("pair", "pairs", B_FALSE); +} + void killoption(option_t *w) { option_t *nextone, *lastone; diff --git a/data.h b/data.h index ab71b4a..f2b719e 100644 --- a/data.h +++ b/data.h @@ -11,6 +11,7 @@ void initoptions(void); void initrace(void); void initraceclasses(void); void initskills(void); +void inittext(void); void killbehaviour(behaviour_t *b); void killcommand(command_t *cmd); void killoption(option_t *o); diff --git a/defs.h b/defs.h index 27a49c8..80a25b1 100644 --- a/defs.h +++ b/defs.h @@ -652,6 +652,7 @@ enum SKILL { SK_CARTOGRAPHY, SK_CHANNELING, SK_CLIMBING, + SK_COMBAT, SK_COOKING, SK_EVASION, SK_FIRSTAID, @@ -702,7 +703,7 @@ enum SKILL { SK_SS_TRANSLOCATION, SK_SS_WILD, }; -#define MAXSKILLS 53 +#define MAXSKILLS 54 // proficiency levels enum SKILLLEVEL { @@ -4161,6 +4162,13 @@ typedef struct option_s { struct option_s *next, *prev; } option_t; +typedef struct plural_s { + char *singular; + char *plural; + int stopafter; // stop parsing strings after finding this? + struct plural_s *next, *prev; +} plural_t; + enum BRANCH { BH_CAVE, BH_WORLDMAP, diff --git a/lf.c b/lf.c index d368292..0af84d4 100644 --- a/lf.c +++ b/lf.c @@ -3284,6 +3284,13 @@ void die(lifeform_t *lf) { } } } + + // player might get stamina back... + if (isplayer(killer)) { + if (getskill(player, SK_COMBAT) >= PR_EXPERT) { + modstamina(lf, rnd(1,getmaxstamina(lf))); + } + } } // determine where to drop objects @@ -8019,11 +8026,15 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) { // modify for blindness if (isblind(lf)) { - acc -= 50; + if (getskill(lf, SK_COMBAT) < PR_ADEPT) { + acc -= 50; + } } // modify for being on the ground if (isprone(lf)) { - acc -= 40; + if (getskill(lf, SK_COMBAT) < PR_BEGINNER) { + acc -= 40; + } } // day/night boosts @@ -8080,7 +8091,9 @@ int getlfaccuracy(lifeform_t *lf, object_t *wep) { // modify for nausea if (lfhasflag(lf, F_NAUSEATED)) { - acc -= 25; + if (getskill(lf, SK_COMBAT) < PR_BEGINNER) { + acc -= 25; + } } // modify for stickiness @@ -8700,7 +8713,7 @@ enum MATERIAL getlfmaterial(lifeform_t *lf) { enum SKILLLEVEL getlorelevel(lifeform_t *lf, enum RACECLASS rcid) { enum SKILLLEVEL slev = PR_INEPT; raceclass_t *rc; - if (gamemode < GM_GAMESTARTED) { + if (gamemode <= GM_LOADING) { return PR_INEPT; } rc = findraceclass(rcid); @@ -10650,7 +10663,7 @@ void givejob(lifeform_t *lf, enum JOB jobid) { } - // now give start obs/skills from it + // now give start obs/skills from the job givestartskills(lf, lf->flags); if (!lfhasflag(lf, F_PHANTASM)) { givestartobs(lf, NULL, lf->flags); @@ -10965,6 +10978,9 @@ void givesubjob(lifeform_t *lf, enum SUBJOB sj) { case SJ_SCOURGE: // remove warrior's level abilities killflagsofid(lf->flags, F_LEVABIL); + // scourges don't get advanced combat + f = lfhasflagval(lf, F_HASSKILL, SK_COMBAT, NA, NA, NULL); + if (f) killflag(f); // magic resistance at level 5 addtempflag(lf->flags, F_RESISTMAG, 5, NA, NA, NULL, FROMJOB); // no mp or other magic. @@ -11352,6 +11368,16 @@ flag_t *giveskill(lifeform_t *lf, enum SKILL id) { newf = addtempflag(lf->flags, F_CANWILL, OT_S_MAPPING, 50, 50, "pw:1;", FROMSKILL); } } + } else if (id == SK_COMBAT) { + if (f->val[1] == PR_SKILLED) { + if (!hasflagval(lf->flags, F_CANWILL, OT_A_DISARM, NA, NA, NULL)) { + newf = addtempflag(lf->flags, F_CANWILL, OT_A_DISARMLF, NA, NA, NULL, FROMSKILL); + } + } else if (f->val[1] == PR_EXPERT) { + if (!hasflagval(lf->flags, F_CANWILL, OT_A_FLIP, NA, NA, NULL)) { + newf = addtempflag(lf->flags, F_CANWILL, OT_A_FLIP, NA, NA, NULL, FROMSKILL); + } + } } else if (id == SK_COOKING) { if (f->val[1] == PR_ADEPT) { if (isplayer(lf)) { @@ -11860,9 +11886,12 @@ void givestartskills(lifeform_t *lf, flagpile_t *fp) { killflagsofid(fp, F_STARTSKILL); // all races know about their own race - if (getlorelevel(lf, lf->race->raceclass->id) < PR_NOVICE) { - giveskilllev(lf, lf->race->raceclass->skill, PR_NOVICE); + if (!isplayer(lf)) { + if (getlorelevel(lf, lf->race->raceclass->id) < PR_NOVICE) { + giveskilllev(lf, lf->race->raceclass->skill, PR_NOVICE); + } } + } int gotosleep(lifeform_t *lf, int onpurpose) { diff --git a/nexus.c b/nexus.c index fbe8f41..8297e38 100644 --- a/nexus.c +++ b/nexus.c @@ -60,6 +60,7 @@ int nbuildingusage = 0; warning_t *firstwarning = NULL,*lastwarning = NULL; option_t *firstoption = NULL,*lastoption = NULL; +plural_t *firstplural = NULL,*lastplural = NULL; int maxmonhitdice = 0; // highest number of hitdice for any monster @@ -1261,6 +1262,7 @@ int init(void) { // load npc names loadnpcnames(); + inittext(); initoptions(); initcommands(); initobjects(); diff --git a/objects.c b/objects.c index 1bcbf97..0650215 100644 --- a/objects.c +++ b/objects.c @@ -31,6 +31,7 @@ extern race_t *firstrace, *lastrace; extern recipe_t *firstrecipe,*lastrecipe; extern skill_t *firstskill, *lastskill; extern region_t *firstregion; +extern plural_t *firstplural; extern buildingusage_t buildingusage[]; extern int nbuildingusage; @@ -3614,6 +3615,7 @@ objecttype_t *findot(enum OBTYPE id) { objecttype_t *findotn(char *name) { objecttype_t *ot; + plural_t *pl; knowledge_t *k; char *modname; char *p; @@ -3628,36 +3630,9 @@ objecttype_t *findotn(char *name) { // make some replacements //replace scrolls with scroll etc - modname = strrep(modname, "bags ", "bag ", NULL); - modname = strrep(modname, "berries ", "berry ", NULL); - modname = strrep(modname, "blocks ", "block ", NULL); - modname = strrep(modname, "cans ", "can ", NULL); - modname = strrep(modname, "chunks ", "chunk ", NULL); - modname = strrep(modname, "clouds ", "cloud ", NULL); - modname = strrep(modname, "cloves ", "clove ", NULL); - modname = strrep(modname, "flasks ", "flask ", NULL); - modname = strrep(modname, "gems ", "gem ", NULL); - modname = strrep(modname, "knives", "knife", NULL); - modname = strrep(modname, "leaves", "leaf", NULL); - modname = strrep(modname, "loaves ", "loaf ", NULL); - modname = strrep(modname, "lumps ", "lump ", NULL); - modname = strrep(modname, "pieces ", "piece ", NULL); - modname = strrep(modname, "piles ", "pile ", NULL); - modname = strrep(modname, "pinches ", "pinch ", NULL); - modname = strrep(modname, "planks ", "plank ", NULL); - modname = strrep(modname, "pools ", "pool ", NULL); - modname = strrep(modname, "potions ", "potion ", NULL); - modname = strrep(modname, "puddles ", "puddle ", NULL); - modname = strrep(modname, "puffs ", "puff ", NULL); - modname = strrep(modname, "rings ", "ring ", NULL); - modname = strrep(modname, "rubies", "ruby", NULL); - modname = strrep(modname, "scrolls ", "scroll ", NULL); - modname = strrep(modname, "sets ", "set ", NULL); - modname = strrep(modname, "sheets ", "sheet ", NULL); - modname = strrep(modname, "splashes ", "splash ", NULL); - modname = strrep(modname, "sprigs ", "sprig ", NULL); - modname = strrep(modname, "suits ", "suit ", NULL); - modname = strrep(modname, "vials ", "vial ", NULL); + for (pl = firstplural ; pl ; pl = pl->next) { + modname = strrep(modname, pl->plural, pl->singular, NULL); + } // only at start... if (strstr(modname, "the ") == modname) modname = strrep(modname, "the ", "", NULL); @@ -4096,6 +4071,13 @@ int getobaccuracy(object_t *wep, lifeform_t *weilder, int forthrow) { // adjust for weapon skill weplev = getweaponskill(weilder, wep); switch (weplev) { + case PR_INEPT: + if (getskill(weilder, SK_COMBAT)) { + acc -= 5; break; + } else { + acc -= 15; break; + } + case PR_NOVICE: break; // no change case PR_BEGINNER: acc += 5; break; case PR_ADEPT: acc += 10; break; case PR_SKILLED: acc += 15; break; diff --git a/text.c b/text.c index 2ed0ffb..e89541a 100644 --- a/text.c +++ b/text.c @@ -23,6 +23,36 @@ extern enum GAMEMODE gamemode; extern enum WINGAMETYPE wintype; extern material_t *material,*lastmaterial; +extern plural_t *firstplural,*lastplural; + +plural_t *addplural(char *singulartext, char *pluraltext, int stopafter) { + plural_t *a; + char buf[BUFLEN]; + + // add to the end of the list + if (firstplural == NULL) { + firstplural = malloc(sizeof(celltype_t)); + a = firstplural; + a->prev = NULL; + } else { + // go to end of list + a = lastplural; + a->next = malloc(sizeof(plural_t)); + a->next->prev = a; + a = a->next; + } + lastplural = a; + a->next = NULL; + + // set props - add spaces at the end of words + sprintf(buf, "%s ",singulartext); + a->singular = strdup(buf); + sprintf(buf, "%s ",pluraltext); + a->plural = strdup(buf); + a->stopafter = stopafter; + + return a; +} int needan(char *text) { if (isvowel(tolower(text[0]))) { @@ -1300,22 +1330,30 @@ char *getinjurydesc(enum BODYPART where, enum DAMTYPE dt) { // all strings returned here must also be defined as an obmod altprefix! // char *getobmodprefix(object_t *o, obmod_t *om) { + int enoughperception = B_TRUE; + int enoughwepskill = B_TRUE; + + if (gamemode == GM_GAMESTARTED) { + if ( (getskill(player, SK_PERCEPTION) < PR_BEGINNER)) { + enoughperception = B_FALSE; + } + if (!getweaponskill(player, o)) { + enoughwepskill = B_FALSE; + } + } + // masterwork/shoddy doors have names based on material. if (isdoor(o, NULL)) { // player perceptive enough to notice? if (om->id == OM_MASTERWORK) { - if ((gamemode == GM_GAMESTARTED) && (getskill(player, SK_PERCEPTION) < PR_BEGINNER)) { - return NULL; - } + if (!enoughperception) return NULL; switch (o->material->id) { case MT_STONE: return "reinforced "; case MT_METAL: return "reinforced "; default: return "sturdy "; } } else if (om->id == OM_SHODDY) { - if ((gamemode == GM_GAMESTARTED) && (getskill(player, SK_PERCEPTION) < PR_BEGINNER)) { - return NULL; - } + if (!enoughperception) return NULL; switch (o->material->id) { case MT_STONE: return "crumbling "; case MT_METAL: return "rusted "; @@ -1326,7 +1364,7 @@ char *getobmodprefix(object_t *o, obmod_t *om) { skill_t *sk; sk = getobskill(o->flags); if (sk) { - if (!player || (getskill(player, sk->id) >= PR_BEGINNER) || (getskill(player, SK_PERCEPTION) >= PR_BEGINNER)) { + if (!player || enoughwepskill || enoughperception) { if (om->id == OM_MASTERWORK) { switch (sk->id) { case SK_CLUBS: @@ -1352,66 +1390,70 @@ char *getobmodprefix(object_t *o, obmod_t *om) { } } } else if (isshield(o)) { - if (om->id == OM_MASTERWORK) { - switch (o->material->id) { - case MT_LEATHER: - return "studded "; - case MT_METAL: - case MT_WOOD: - case MT_DRAGONWOOD: - return "reinforced "; - default: break; - } - } else if (om->id == OM_SHODDY) { - switch (o->material->id) { - case MT_LEATHER: - case MT_RUBBER: - case MT_PAPER: - return "torn "; - case MT_CLOTH: - case MT_SILK: - return "frayed "; - case MT_GLASS: - case MT_STONE: - case MT_BONE: - return "chipped "; - case MT_METAL: - return "dented "; - case MT_WOOD: - case MT_DRAGONWOOD: - return "splintered "; - default: break; + if (!player || enoughperception || getskill(player, SK_SHIELDS)) { + if (om->id == OM_MASTERWORK) { + switch (o->material->id) { + case MT_LEATHER: + return "studded "; + case MT_METAL: + case MT_WOOD: + case MT_DRAGONWOOD: + return "reinforced "; + default: break; + } + } else if (om->id == OM_SHODDY) { + switch (o->material->id) { + case MT_LEATHER: + case MT_RUBBER: + case MT_PAPER: + return "torn "; + case MT_CLOTH: + case MT_SILK: + return "frayed "; + case MT_GLASS: + case MT_STONE: + case MT_BONE: + return "chipped "; + case MT_METAL: + return "dented "; + case MT_WOOD: + case MT_DRAGONWOOD: + return "splintered "; + default: break; + } } } } else if (isarmour(o)) { - if (om->id == OM_MASTERWORK) { - switch (o->material->id) { - case MT_LEATHER: - return "studded "; - case MT_CLOTH: - case MT_SILK: - return "tailored "; - default: break; - } - } else if (om->id == OM_SHODDY) { - switch (o->material->id) { - case MT_LEATHER: - case MT_RUBBER: - case MT_PAPER: - return "torn "; - case MT_CLOTH: - case MT_SILK: - return "frayed "; - case MT_GLASS: - case MT_STONE: - case MT_BONE: - return "chipped "; - case MT_METAL: - return "dented "; - case MT_WOOD: - case MT_DRAGONWOOD: - return "splintered "; - default: break; + if (!player || enoughperception || getskill(player, SK_ARMOUR)) { + if (om->id == OM_MASTERWORK) { + switch (o->material->id) { + case MT_LEATHER: + return "studded "; + case MT_CLOTH: + case MT_SILK: + return "tailored "; + default: break; + } + } else if (om->id == OM_SHODDY) { + switch (o->material->id) { + case MT_LEATHER: + case MT_RUBBER: + case MT_PAPER: + return "torn "; + case MT_CLOTH: + case MT_SILK: + return "frayed "; + case MT_GLASS: + case MT_STONE: + case MT_BONE: + return "chipped "; + case MT_METAL: + return "dented "; + case MT_WOOD: + case MT_DRAGONWOOD: + return "splintered "; + default: break; + } } } } @@ -1849,6 +1891,33 @@ int isvowel (char c) { return B_FALSE; } +void killplural(plural_t *w) { + plural_t *nextone, *lastone; + + // free mem + if (w->singular) free(w->singular); + if (w->plural) free(w->plural); + + // remove from list + nextone = w->next; + if (nextone != NULL) { + nextone->prev = w->prev; + } else { /* last */ + lastplural = w->prev; + } + + if (w->prev == NULL) { + /* first */ + nextone = w->next; + free(firstplural); + firstplural = nextone; + } else { + lastone = w->prev; + free (lastone->next ); + lastone->next = nextone; + } +} + // return text for player's F_GUNTARGET flag eg. "goblin [acc:50%]" void makegunaimstring(lifeform_t *lf, int lfid, char *retbuf) { char accbuf[BUFLEN]; @@ -1932,75 +2001,14 @@ char *makeplural(char *text) { char lastlet; char *newtext; int rv; + plural_t *pl; newtext = strdup(text); - // scrolls - newtext = strrep(newtext, "bag ", "bags ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "berry ", "berries ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "block ", "blocks ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "can ", "cans ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "chunk ", "chunks ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "cloud ", "clouds ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "clove ", "cloves ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "flask ", "flasks ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "gem ", "gems ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "knife", "knives", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "leaf", "leaves", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "loaf ", "loaves ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "lump ", "lumps ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "piece ", "pieces ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "pile ", "piles ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "pinch ", "pinches ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "plank ", "planks ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "pool ", "pools ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "potion ", "potions ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "puddle ", "puddles ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "puff ", "puffs ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "ring ", "rings ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "ruby", "rubies", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "scroll ", "scrolls ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "splash ", "splashes ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "set ", "sets ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "sheet ", "sheets ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "sprig ", "sprigs ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "suit ", "suits ", &rv); - if (rv) return newtext; - newtext = strrep(newtext, "vial ", "vials ", &rv); - if (rv) return newtext; - - - // - newtext = strrep(newtext, "pair ", "pairs ", &rv); - // don't return + for (pl = firstplural ; pl ; pl = pl->next) { + newtext = strrep(newtext, pl->singular, pl->plural, &rv); + if (rv && pl->stopafter) return newtext; + } // default lastlet = text[strlen(text)-1]; diff --git a/text.h b/text.h index 29260a7..f5b8d8f 100644 --- a/text.h +++ b/text.h @@ -1,5 +1,6 @@ #include "defs.h" +plural_t *addplural(char *singulartext, char *pluraltext, int stopafter); int needan(char *text); char *capitalise(char *text); char *capitaliseall(char *text); @@ -49,6 +50,7 @@ char *getweighttext(float weight, char *buf, int shortfmt); char *is(lifeform_t *lf); char *it(lifeform_t *lf); int isvowel(char c); +void killplural(plural_t *w); void makegunaimstring(lifeform_t *lf, int lfid, char *retbuf); char *makekillertext(char *retbuf, char *killverb, char *lastdam, map_t *where, int wantextra, int wantlocation); char *makelowercase(char *text);