Who: JasonYarber@hotmail.com What: tables-to-formula.txt When: May 17, 2002 Where: Class.c, Structs.h Why: This patch changes all the tables in class.c to formulas to make it easier for adding new levels and stuff like that. How: ----------------------------------------------------------------------------------------- @@ Open structs.h and search for: #define LVL_IMPL @@ Change all the level defines to: #define LVL_MAX 100 #define LVL_IMPL (LVL_MAX + 4) #define LVL_GRGOD (LVL_MAX + 3) #define LVL_GOD (LVL_MAX + 2) #define LVL_IMMORT (LVL_MAX + 1) @@ Save and close structs.h ----------------------------------------------------------------------------------------- @@ Open class.c and search under /* local functions */ for: byte saving_throws(int class_num, int type, int level); int thaco(int class_num, int level); @@ Change it to: byte saving_throws(int class_num, int type, int level, int race_num); int thaco(int class_num, int level, int race_num); @@ In the same area look for: int level_exp(int chclass, int level); @@ Change it to: int level_exp(int chclass, int level, int chrace); @@ Under all the local fuctions prototypse add: // Class and Race modifiers for formulas ********************* // Class modifiers for formulas ****************************** // Mag, Cle, Thi, War * int cmod_para[NUM_CLASSES] = { 48, 42, 38, 31 }; // * int cmod_rods[NUM_CLASSES] = { 49, 45, 39, 33 }; // * int cmod_petr[NUM_CLASSES] = { 46, 43, 37, 35 }; // * int cmod_brea[NUM_CLASSES] = { 47, 41, 40, 34 }; // * int cmod_spel[NUM_CLASSES] = { 50, 44, 36, 32 }; // * int cmod_thac[NUM_CLASSES] = { 40, 35, 50, 45 }; // * int cmod_expe[NUM_CLASSES] = { 400, 350, 250, 300 }; // * // Race modifiers for formulas ******************************* // Hum, Elf, Gno, Dwa * int rmod_para[NUM_RACES] = { 50, 47, 42, 39 }; // * int rmod_rods[NUM_RACES] = { 50, 42, 44, 37 }; // * int rmod_petr[NUM_RACES] = { 50, 46, 41, 40 }; // * int rmod_brea[NUM_RACES] = { 50, 48, 45, 36 }; // * int rmod_spel[NUM_RACES] = { 50, 50, 43, 38 }; // * int rmod_thac[NUM_RACES] = { 50, 50, 35, 40 }; // * int rmod_expe[NUM_RACES] = { 250, 400, 350, 300 }; // * //************************************************************ #define BASE_XP_MOD 500 // Base experience modifier * //************************************************************ @@ Look for the fuction: byte saving_throws(int class_num, int type, int level) { @@ Change the whole function to: byte saving_throws(int class_num, int type, int level, int race_num) { if (level > LVL_IMPL || level < 0) { log("SYSERR: Requesting saving throws for invalid level %d!", level); return 0; } if (class_num > NUM_CLASSES){ log ("SYSERR: Requesting saving throws for invalid class %d!", class_num); return 0; } if (race_num > NUM_RACES){ log("SYSERR: Requesting saving throws for invalid race %d!", race_num); return 0; } if (class_num < 0) // Sanity check class_num = CLASS_THIEF; if (race_num < 0) // Sanity check race_num = RACE_HUMAN; switch (type) { case SAVING_PARA: if (level > LVL_MAX) return 0; return (100 - (((rmod_para[race_num] + cmod_para[class_num]) * level) / LVL_MAX)); case SAVING_ROD: if (level > LVL_MAX) return 0; return (100 - (((rmod_rods[race_num] + cmod_rods[class_num]) * level) / LVL_MAX)); case SAVING_PETRI: if (level > LVL_MAX) return 0; return (100 - (((rmod_petr[race_num] + cmod_petr[class_num]) * level) / LVL_MAX)); case SAVING_BREATH: if (level > LVL_MAX) return 0; return (100 - (((rmod_brea[race_num] + cmod_brea[class_num]) * level) / LVL_MAX)); case SAVING_SPELL: if (level > LVL_MAX) return 0; return (100 - (((rmod_spel[race_num] + cmod_spel[class_num]) * level) / LVL_MAX)); default: log("SYSERR: Invalid saving throw type."); break; } /* Should not get here unless something is wrong. */ return 100; } @@ Look for the function: int thaco(int class_num, int level) { @@ Change the whole function to: int thaco(int class_num, int level, int race_num) { if (level > LVL_IMPL || level < 0) { log("SYSERR: Requesting thaco for invalid level %d!", level); return 0; } if (class_num > NUM_CLASSES){ log ("SYSERR: Requesting thaco for invalid class %d!", class_num); return 0; } if (race_num > NUM_RACES){ log("SYSERR: Requesting thaco for invalid race %d!", race_num); return 0; } if (class_num < 0) // Sanity check class_num = CLASS_THIEF; if (race_num < 0) // Sanity check race_num = RACE_HUMAN; if (level > LVL_MAX) return 0; return (20 - (((level * (rmod_thac[race_num] + cmod_thac[class_num])) / LVL_MAX) / 5)); } @@ Look for: #define EXP_MAX @@ Change it to: #define EXP_MAX 110000000 @@ Look for the function: int level_exp(int chclass, int level) { @@ Change the whole function to: // Doesn't this system make more sense? - Jason Yarber int level_exp(int chclass, int level, int chrace) { if (level > LVL_IMPL || level < 0) { log("SYSERR: Requesting exp for invalid level %d!", level); return 0; } if (chclass > NUM_CLASSES){ log ("SYSERR: Requesting exp for invalid class %d!", chclass); return 0; } if (chrace > NUM_RACES){ log("SYSERR: Requesting exp for invalid race %d!", chrace); return 0; } if (chclass < 0) // Sanity check chclass = CLASS_THIEF; if (chrace < 0) // Sanity check chrace = RACE_HUMAN; // Gods have exp close to EXP_MAX. This statement should never have to // changed, regardless of how many mortal or immortal levels exist. if (level > LVL_MAX) { return EXP_MAX - ((LVL_IMPL - level) * 1000); } // Exp required for normal mortals is below return ((level * (rmod_expe[chrace] + cmod_expe[chclass] + BASE_XP_MOD))-(rmod_expe[chrace] + cmod_expe[chclass] + BASE_XP_MOD)); } @@ Look for the function: const char *title_male(int chclass, int level) { @@ Change the whole function to: const char *title_male(int chclass, int level) { int temp_num; temp_num = (((level * 100) / LVL_MAX) / 5); if (level <= 0 || level > LVL_IMPL) return "the Man"; if (level == LVL_IMPL) return "the Implementor"; switch (chclass) { case CLASS_MAGIC_USER: switch (temp_num) { case 0: return "the Newbie Mage"; case 1: return "the Apprentice of Magic"; case 2: return "the Spell Student"; case 3: return "the Scholar of Magic"; case 4: return "the Delver in Spells"; case 5: return "the Medium of Magic"; case 6: return "the Scribe of Magic"; case 7: return "the Seer"; case 8: return "the Sage"; case 9: return "the Illusionist"; case 10: return "the Abjurer"; case 11: return "the Invoker"; case 12: return "the Enchanter"; case 13: return "the Conjurer"; case 14: return "the Magician"; case 15: return "the Creator"; case 16: return "the Savant"; case 17: return "the Magus"; case 18: return "the Wizard"; case 19: return "the Warlock"; case 20: return "the Sorcerer"; default: return "the Mage"; } break; case CLASS_CLERIC: switch (temp_num) { case 0: return "the Newbie Cleric"; case 1: return "the Believer"; case 2: return "the Attendant"; case 3: return "the Acolyte"; case 4: return "the Novice"; case 5: return "the Missionary"; case 6: return "the Adept"; case 7: return "the Deacon"; case 8: return "the Vicar"; case 9: return "the Priest"; case 10: return "the Minister"; case 11: return "the Canon"; case 12: return "the Levite"; case 13: return "the Curate"; case 14: return "the Monk"; case 15: return "the Healer"; case 16: return "the Chaplain"; case 17: return "the Expositor"; case 18: return "the Bishop"; case 19: return "the Arch Bishop"; case 20: return "the Patriarch"; default: return "the Cleric"; } break; case CLASS_THIEF: switch (temp_num) { case 0: return "the Newbie Thief"; case 1: return "the Pilferer"; case 2: return "the Footpad"; case 3: return "the Filcher"; case 4: return "the Pick-Pocket"; case 5: return "the Sneak"; case 6: return "the Pincher"; case 7: return "the Cut-Purse"; case 8: return "the Snatcher"; case 9: return "the Sharper"; case 10: return "the Rogue"; case 11: return "the Robber"; case 12: return "the Magsman"; case 13: return "the Highwayman"; case 14: return "the Burglar"; case 15: return "the Thief"; case 16: return "the Knifer"; case 17: return "the Quick-Blade"; case 18: return "the Killer"; case 19: return "the Brigand"; case 20: return "the Cut-Throat"; default: return "the Thief"; } break; case CLASS_WARRIOR: switch(temp_num) { case 0: return "the Newbie Warrior"; case 1: return "the Swordpupil"; case 2: return "the Recruit"; case 3: return "the Sentry"; case 4: return "the Fighter"; case 5: return "the Soldier"; case 6: return "the Warrior"; case 7: return "the Veteran"; case 8: return "the Swordsman"; case 9: return "the Fencer"; case 10: return "the Combatant"; case 11: return "the Hero"; case 12: return "the Myrmidon"; case 13: return "the Swashbuckler"; case 14: return "the Mercenary"; case 15: return "the Swordmaster"; case 16: return "the Lieutenant"; case 17: return "the Champion"; case 18: return "the Dragoon"; case 19: return "the Cavalier"; case 20: return "the Knight"; default: return "the Warrior"; } break; } /* Default title for classes which do not have titles defined */ return "the Classless"; } @@ Look for the function: const char *title_female(int chclass, int level) { @@ Change the whole function to: const char *title_female(int chclass, int level) { int temp_num; temp_num = (((level * 100) / LVL_MAX) / 5); if (level <= 0 || level > LVL_IMPL) return "the Woman"; if (level == LVL_IMPL) return "the Implementress"; switch (chclass) { case CLASS_MAGIC_USER: switch (temp_num) { case 0: return "the Newbie Mage"; case 1: return "the Apprentice of Magic"; case 2: return "the Spell Student"; case 3: return "the Scholar of Magic"; case 4: return "the Delveress in Spells"; case 5: return "the Medium of Magic"; case 6: return "the Scribess of Magic"; case 7: return "the Seeress"; case 8: return "the Sage"; case 9: return "the Illusionist"; case 10: return "the Abjuress"; case 11: return "the Invoker"; case 12: return "the Enchantress"; case 13: return "the Conjuress"; case 14: return "the Witch"; case 15: return "the Creator"; case 16: return "the Savant"; case 17: return "the Craftess"; case 18: return "the Wizard"; case 19: return "the War Witch"; case 20: return "the Sorceress"; default: return "the Witch"; } break; case CLASS_CLERIC: switch (temp_num) { case 0: return "the Newbie Cleric"; case 1: return "the Believer"; case 2: return "the Attendant"; case 3: return "the Acolyte"; case 4: return "the Novice"; case 5: return "the Missionary"; case 6: return "the Adept"; case 7: return "the Deaconess"; case 8: return "the Vicaress"; case 9: return "the Priestess"; case 10: return "the Lady Minister"; case 11: return "the Canon"; case 12: return "the Levitess"; case 13: return "the Curess"; case 14: return "the Nunne"; case 15: return "the Healess"; case 16: return "the Chaplain"; case 17: return "the Expositress"; case 18: return "the Bishop"; case 19: return "the Arch Lady of the Church"; case 20: return "the Matriarch"; default: return "the Cleric"; } break; case CLASS_THIEF: switch (temp_num) { case 0: return "the Newbie Thief"; case 1: return "the Pilferess"; case 2: return "the Footpad"; case 3: return "the Filcheress"; case 4: return "the Pick-Pocket"; case 5: return "the Sneak"; case 6: return "the Pincheress"; case 7: return "the Cut-Purse"; case 8: return "the Snatcheress"; case 9: return "the Sharpress"; case 10: return "the Rogue"; case 11: return "the Robber"; case 12: return "the Magswoman"; case 13: return "the Highwaywoman"; case 14: return "the Burglaress"; case 15: return "the Thief"; case 16: return "the Knifer"; case 17: return "the Quick-Blade"; case 18: return "the Murderess"; case 19: return "the Brigand"; case 20: return "the Cut-Throat"; default: return "the Thief"; } break; case CLASS_WARRIOR: switch(temp_num) { case 0: return "the Newbie Warrior"; case 1: return "the Swordpupil"; case 2: return "the Recruit"; case 3: return "the Sentress"; case 4: return "the Fighter"; case 5: return "the Soldier"; case 6: return "the Warrior"; case 7: return "the Veteran"; case 8: return "the Swordswoman"; case 9: return "the Fenceress"; case 10: return "the Combatess"; case 11: return "the Heroine"; case 12: return "the Myrmidon"; case 13: return "the Swashbuckleress"; case 14: return "the Mercenaress"; case 15: return "the Swordmistress"; case 16: return "the Lieutenant"; case 17: return "the Lady Champion"; case 18: return "the Lady Dragoon"; case 19: return "the Cavalier"; case 20: return "the Lady Knight"; default: return "the Warrior"; } break; } /* Default title for classes which do not have titles defined */ return "the Classless"; } @@ Save and close class.c ----------------------------------------------------------------------------------------- @@ Look through the rest of your code for any calls to: byte saving_throws(int class_num, int type, int level); int thaco(int class_num, int level); int level_exp(int chclass, int level); @@ Change them to include the character's race Once all that's done, recompile and run your mud. You will also need to edit the experience values of all the mobs in the mud, and set them to a low number between 0 and 1000. I usually set mine around 50 or so.