Welcome to the Builder Academy

Question Adding Luck, Statistics

More
11 Jun 2012 01:12 - 11 Jun 2012 01:14 #14 by Rumble
By Tink, 2010

Introduction

I wrote this guide to help people add in another basic stat, like Str, Dex, Cha, etc. This code is written, tested, and works on stock tbaMUD 3.61. It may or may not work if your game is heavily modified or from an older version of CWG.

Note

In most cases Luck (LCK) is added after Charisma (CHA). Following these directions to the letter will cause your player files to "break" so if you want to avoid that you may want to re-arrange where some things go.

The Code
Code:
// In class.c find the void roll_real_abils and change some numbers so that a new table is created. *** /* Roll the 6 stats for a character... each stat is made of the sum of the best * 3 out of 4 rolls of a 6-sided die. Each class then decides which priority * will be given for the best to worst stats. */ void roll_real_abils(struct char_data *ch) { int i, j, k, temp; - ubyte table[6] + ubyte table[7] ubyte rolls[4]; - for (i = 0; i < 6; i++) + for (i = 0; i < 7; i++) table[i] = 0; - for (i = 0; i < 6; i++) { + for (i = 0; i < 7; i++) { for (j = 0; j < 4; j++) - rolls[j] = rand_number(1, 6); + rolls[j] = rand_number(1, 7); temp = rolls[0] + rolls[1] + rolls[2] + rolls[3] - MIN(rolls[0], MIN(rolls[1], MIN(rolls[2], rolls[3]))); - for (k = 0; k < 6; k++) + for (k = 0; k < 7; k++) if (table[k] < temp) { temp ^= table[k]; // Scroll down a little, and find the rea_abils sets. *** ch->real_abils.wis = table[0]; ch->real_abils.intel = table[1]; ch->real_abils.str = table[2]; ch->real_abils.dex = table[3]; ch->real_abils.con = table[4]; ch->real_abils.cha = table[5]; + ch->real_abils.lck = table[6]; // In act.wizard.c, find the first instance of GET_CON, or the part that looks similar to the following. *** send_to_char(ch, "Str: [%s%d/%d%s] Int: [%s%d%s] Wis: [%s%d%s] " - "Dex: [%s%d%s] Con: [%s%d%s] Cha: [%s%d%s]\r\n", + "Dex: [%s%d%s] Con: [%s%d%s] Cha: [%s%d%s] Lck: [%s%d%s]\r\n", CCCYN(ch, C_NRM), GET_STR(k), GET_ADD(k), CCNRM(ch, C_NRM), CCCYN(ch, C_NRM), GET_INT(k), CCNRM(ch, C_NRM), CCCYN(ch, C_NRM), GET_WIS(k), CCNRM(ch, C_NRM), CCCYN(ch, C_NRM), GET_DEX(k), CCNRM(ch, C_NRM), CCCYN(ch, C_NRM), GET_CON(k), CCNRM(ch, C_NRM), - CCCYN(ch, C_NRM), GET_CHA(k), CCNRM(ch, C_NRM)); + CCCYN(ch, C_NRM), GET_CHA(k), CCNRM(ch, C_NRM), + CCCYN(ch, C_NRM), GET_LCK(k), CCNRM(ch, C_NRM)); // Further down, find the section that looks similar and change, after real_abils.cha. *** if (!IS_NPC(vict) && GET_LEVEL(ch) >= LVL_GRGOD) { if (GET_LEVEL(vict) >= LVL_IMMORT) for (i = 1; i <= MAX_SKILLS; i++) SET_SKILL(vict, i, 100); if (GET_LEVEL(vict) >= LVL_GRGOD) { vict->real_abils.str_add = 100; vict->real_abils.intel = 25; vict->real_abils.wis = 25; vict->real_abils.dex = 25; vict->real_abils.str = 18; vict->real_abils.con = 25; vict->real_abils.cha = 25; + vict->real_abils.lck = 25; // In do_wizutil, add it into SCMD_REROLL. *** case SCMD_REROLL: send_to_char(ch, "Rerolled...\r\n"); roll_real_abils(vict); log("(GC) %s has rerolled %s.", GET_NAME(ch), GET_NAME(vict)); send_to_char(ch, "New stats: Str %d/%d, Int %d, Wis %d, Dex %d, Con %d, Cha %d, Lck %d\r\n", GET_STR(vict), GET_ADD(vict), GET_INT(vict), GET_WIS(vict), - GET_DEX(vict), GET_CON(vict), GET_CHA(vict)); + GET_DEX(vict), GET_CON(vict), GET_CHA(vict), GET_LCK(vict)); break; // In set_fields, add it to the large list at the bottom. Don't forget the comma at the end. *** { "weight", LVL_BUILDER, BOTH, NUMBER }, { "wis", LVL_BUILDER, BOTH, NUMBER }, /* 55 */ { "questpoints", LVL_GOD, PC, NUMBER }, { "questhistory", LVL_GOD, PC, NUMBER }, + { "lck", LVL_BUILDER, BOTH, NUMBER }, { "\n", 0, BOTH, MISC } }; // Shortly after that, add it to the bottom of the values list. It should be the next number available. *** case 56: /* questpoints */ GET_QUESTPOINTS(vict) = RANGE(0, 100000000); break; case 57: /* questhistory */ qvnum = atoi(val_arg); if (real_quest(qvnum) == NOTHING) { send_to_char(ch, "That quest doesn't exist.\r\n"); return FALSE; } else { if (is_complete(vict, qvnum)) { remove_completed_quest(vict, qvnum); send_to_char(ch, "Quest %d removed from history for player %s.\r\n", qvnum, GET_NAME(vict)); } else { add_completed_quest(vict, qvnum); send_to_char(ch, "Quest %d added to history for player %s.\r\n", qvnum, GET_NAME(vict)); } break; } + case 58: /* lck */ + if (IS_NPC(vict) || GET_LEVEL(vict) >= LVL_GRGOD) + RANGE(3, 25); + else + RANGE(3, 18); + vict->real_abils.lck = value; + affect_total(vict); + break; default: send_to_char(ch, "Can't set that!\r\n"); return (0); } // Finally, in zaffs[] where they have the applies, add it in after CHA *** {APPLY_WIS, -5, 3, "wisdom"}, {APPLY_CON, -5, 3, "constitution"}, {APPLY_CHA, -5, 3, "charisma"}, + {APPLY_LCK, -5, 3, "luck"}, {APPLY_CLASS, 0, 0, "class"}, {APPLY_LEVEL, 0, 0, "level"}, {APPLY_AGE, -10, 10, "age"}, // In utils.h find the #defines and add it to the bottom, after CHA. *** #define GET_STR(ch) ((ch)->aff_abils.str) #define GET_ADD(ch) ((ch)->aff_abils.str_add) #define GET_DEX(ch) ((ch)->aff_abils.dex) #define GET_INT(ch) ((ch)->aff_abils.intel) #define GET_WIS(ch) ((ch)->aff_abils.wis) #define GET_CON(ch) ((ch)->aff_abils.con) #define GET_CHA(ch) ((ch)->aff_abils.cha) + #define GET_LCK(ch) ((ch)->aff_abils.lck) // In handler.c make sure it's in the applies at the bottom, after CHA. *** case APPLY_CON: GET_CON(ch) += mod; break; case APPLY_CHA: GET_CHA(ch) += mod; break; + case APPLY_LCK: + GET_LCK(ch) += mod; + break; // Make sure it has the MIN and MAX as well, a little further down, after CHA. *** GET_DEX(ch) = MAX(0, MIN(GET_DEX(ch), i)); GET_INT(ch) = MAX(0, MIN(GET_INT(ch), i)); GET_WIS(ch) = MAX(0, MIN(GET_WIS(ch), i)); GET_CON(ch) = MAX(0, MIN(GET_CON(ch), i)); GET_CHA(ch) = MAX(0, MIN(GET_CHA(ch), i)); + GET_LCK(ch) = MAX(0, MIN(GET_LCK(ch), i)); GET_STR(ch) = MAX(0, GET_STR(ch)); // In players.c in character initializations, add it after CHA. *** ch->real_abils.dex = PFDEF_DEX; ch->real_abils.intel = PFDEF_INT; ch->real_abils.wis = PFDEF_WIS; ch->real_abils.con = PFDEF_CON; ch->real_abils.cha = PFDEF_CHA; + ch->real_abils.lck = PFDEF_LCK; GET_HIT(ch) = PFDEF_HIT; GET_MAX_HIT(ch) = PFDEF_MAXHIT; // A little further down there are all the cases. Add it where it makes sense alphabetically. *** case 'L': if (!strcmp(tag, "Last")) ch->player.time.logon = atol(line); else if (!strcmp(tag, "Lern")) GET_PRACTICES(ch) = atoi(line); else if (!strcmp(tag, "Levl")) GET_LEVEL(ch) = atoi(line); else if (!strcmp(tag, "Lmot")) GET_LAST_MOTD(ch) = atoi(line); else if (!strcmp(tag, "Lnew")) GET_LAST_NEWS(ch) = atoi(line); + else if (!strcmp(tag, "Lck ")) ch->real_abils.lck = atoi(line); break; // Even further down, look for GET_CHA with the fprint and add it right after. *** if (GET_CON(ch) != PFDEF_CON) fprintf(fl, "Con : %d\n", GET_CON(ch)); if (GET_CHA(ch) != PFDEF_CHA) fprintf(fl, "Cha : %d\n", GET_CHA(ch)); + if (GET_LCK(ch) != PFDEF_LCK) fprintf(fl, "Lck : %d\n", GET_LCK(ch)); if (GET_AC(ch) != PFDEF_AC) fprintf(fl, "Ac : %d\n", GET_AC(ch)); if (GET_GOLD(ch) != PFDEF_GOLD) fprintf(fl, "Gold: %d\n", GET_GOLD(ch)); // In db.c in parse_simple_mob, add it after real_abils.cha. *** mob_proto[i].real_abils.con = 11; mob_proto[i].real_abils.cha = 11; + mob_proto[i].real_abils.lck = 11; if (!get_line(mob_f, line)) { log("SYSERR: Format error in mob #%d, file ended after S flag!", nr); exit(1); // Further down, where it defines the ranges, add it after CHA. *** CASE("Con") { RANGE(3, 25); mob_proto[i].real_abils.con = num_arg; } CASE("Cha") { RANGE(3, 25); mob_proto[i].real_abils.cha = num_arg; } + CASE("Lck") { + RANGE(3, 25); + mob_proto[i].real_abils.lck = num_arg; + } CASE("SavingPara") { RANGE(0, 100); mob_proto[i].char_specials.saved.apply_saving_throw[SAVING_PARA] = num_arg; } Even further down, add it again after real_abils.cha. *** for (i = 0; i < 5; i++) GET_SAVE(ch, i) = 0; ch->real_abils.intel = 25; ch->real_abils.wis = 25; ch->real_abils.dex = 25; ch->real_abils.str = 25; ch->real_abils.str_add = 100; ch->real_abils.con = 25; ch->real_abils.cha = 25; + ch->real_abils.lck = 25; for (i = 0; i < 3; i++) GET_COND(ch, i) = (GET_LEVEL(ch) == LVL_IMPL ? -1 : 24); // In medit.c, in init_mob, add after real_abils.cha = 11; *** GET_WEIGHT(mob) = 200; GET_HEIGHT(mob) = 198; mob->real_abils.str = mob->real_abils.intel = mob->real_abils.wis = 11; mob->real_abils.dex = mob->real_abils.con = mob->real_abils.cha = 11; + mob->real_abils.lck = 11; mob->aff_abils = mob->real_abils; GET_SAVE(mob, SAVING_PARA) = 0; GET_SAVE(mob, SAVING_ROD) = 0; // In CONFIG_MEDIT_ADVANCED, make the following changes. *** if (CONFIG_MEDIT_ADVANCED) { /* Bottom section - non-standard stats, togglable in cedit */ write_to_output(d, "(%sF%s) Str: %s[%s%2d/%3d%s]%s Saving Throws\r\n" "(%sG%s) Int: %s[%s%3d%s]%s (%sL%s) Paralysis %s[%s%3d%s]%s\r\n" "(%sH%s) Wis: %s[%s%3d%s]%s (%sM%s) Rods/Staves %s[%s%3d%s]%s\r\n" "(%sI%s) Dex: %s[%s%3d%s]%s (%sN%s) Petrification %s[%s%3d%s]%s\r\n" "(%sJ%s) Con: %s[%s%3d%s]%s (%sO%s) Breath %s[%s%3d%s]%s\r\n" - "(%sK%s) Cha: %s[%s%3d%s]%s (%sP%s) Spells %s[%s%3d%s]%s\r\n\r\n", + "(%sK%s) Cha: %s[%s%3d%s]%s (%sP%s) Spells %s[%s%3d%s]%s\r\n" + "(%sT%s) Lck: %s[%s%3d%s]%s\r\n", cyn, nrm, cyn, yel, GET_STR(mob), GET_ADD(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_INT(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_PARA), cyn, nrm, cyn, nrm, cyn, yel, GET_WIS(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_ROD), cyn, nrm, cyn, nrm, cyn, yel, GET_DEX(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_PETRI), cyn, nrm, cyn, nrm, cyn, yel, GET_CON(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_BREATH), cyn, nrm, - cyn, nrm, cyn, yel, GET_CHA(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_SPELL), cyn, nrm + cyn, nrm, cyn, yel, GET_CHA(mob), cyn, nrm, cyn, nrm, cyn, yel, GET_SAVE(mob, SAVING_SPELL), cyn, nrm, + cyn, nrm, cyn, yel, GET_LCK(mob), cyn, nrm ); } // Further down, in the cases, add in a new one for T. *** case 'k': case 'K': if (!CONFIG_MEDIT_ADVANCED) { write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); return; } OLC_MODE(d) = MEDIT_CHA; i++; break; + case 't': + case 'T': + if (!CONFIG_MEDIT_ADVANCED) { + write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); + return; + } + OLC_MODE(d) = MEDIT_LCK; + i++; + break; case 'l': case 'L': if (!CONFIG_MEDIT_ADVANCED) { write_to_output(d, "Invalid Choice!\r\nEnter Choice : "); return; } OLC_MODE(d) = MEDIT_PARA; i++; break; // A little down from that, find MEDIT_CHA and add below. *** case MEDIT_CHA: GET_CHA(OLC_MOB(d)) = LIMIT(i, 11, 25); OLC_VAL(d) = TRUE; medit_disp_stats_menu(d); return; + case MEDIT_LCK: + GET_LCK(OLC_MOB(d)) = LIMIT(i, 11, 25); + OLC_VAL(d) = TRUE; + medit_disp_stats_menu(d); + return; // Near the very bottom, add it as well. *** GET_DEX(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); GET_CON(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); GET_CHA(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); + GET_LCK(OLC_MOB(d)) = LIMIT((mob_lev*2)/3, 11, 18); // In genmob.c in write_mobile_espec, add it after CHA. *** if (GET_WIS(mob) != 11) fprintf(fd, "Wis: %d\n", GET_WIS(mob)); if (GET_CON(mob) != 11) fprintf(fd, "Con: %d\n", GET_CON(mob)); if (GET_CHA(mob) != 11) fprintf(fd, "Cha: %d\n", GET_CHA(mob)); + if (GET_LCK(mob) != 11) + fprintf(fd, "Lck: %d\n", GET_LCK(mob)); if (GET_CLASS(mob) != 1) fprintf(fd, "Class: %d\n", GET_CLASS(mob)); // In oasis.h add it into the #defines. I added it right below MEDIT_CHA. *** // Note: Make sure your numbers are in proper order! *** #define MEDIT_DEX 32 #define MEDIT_CON 33 #define MEDIT_CHA 34 + #define MEDIT_LCK 35 // In pfdefaults.h, make sure it's defined after PFDEF_CHA. *** #define PFDEF_WIS 0 #define PFDEF_CON 0 + #define PFDEF_CHA 0 #define PFDEF_LCK 0 #define PFDEF_HIT 0 #define PFDEF_MAXHIT 0 // In structs.h, add it after CHA and reorder the numbers. *** // Note: You can change this if you don't want to reorder player files. *** #define APPLY_WIS 4 /**< Apply to wisdom */ #define APPLY_CON 5 /**< Apply to constitution */ #define APPLY_CHA 6 /**< Apply to charisma */ + #define APPLY_LCK 7 /**< Apply to luck */ #define APPLY_CLASS 8 /**< Reserved */ #define APPLY_LEVEL 9 /* // In char_ability_data, after cha. *** struct char_ability_data { sbyte str; /**< Strength. */ sbyte str_add; /**< Strength multiplier if str = 18. Usually from 0 to 100 */ sbyte intel; /**< Intelligence */ sbyte wis; /**< Wisdom */ sbyte dex; /**< Dexterity */ sbyte con; /**< Constitution */ sbyte cha; /**< Charisma */ + sbyte lck; /**< Luck */ }; // In constants.c in apply_types, add it after CHA. *** "INT", "WIS", "CON", "CHA", + "LCK", "CLASS", "LEVEL", "AGE", // In utils/plrtoascii.c in char_ability_data_plrtoascii, add it after cha. *** sbyte wis; sbyte dex; sbyte con; sbyte cha; + sbyte lck; }; // A little further down, add it to the char ability data, or cad. *** if (cad->con != PFDEF_CON) fprintf(outfile, "Con : %d\n", cad->con); if (cad->cha != PFDEF_CHA) fprintf(outfile, "Cha : %d\n", cad->cha); + if (cad->lck != PFDEF_LCK) + fprintf(outfile, "Lck : %d\n", cad->lck); /* char_point_data */ cpd = &(player.points);
Conclusion

Hopefully this goes smoothly for anybody looking to use this guide. Please don't hesitate to post comments or questions. I'll try my best to answer them. :)

Rumble
The Builder Academy
tbamud.com 9091
rumble@tbamud.com
Last edit: 11 Jun 2012 01:14 by Rumble.

Please Log in or Create an account to join the conversation.

More
05 Oct 2012 21:45 - 06 Oct 2012 12:04 #863 by Rumble
Replied by Rumble on topic Re: Adding Luck, Statistics
From Liko:
Works perfect except they need to add this to dg_variables.c
1. Open dg_variables.c and search case 'L' and add the following
Code:
else if (!str_cmp(field, "Luck")) { if (subfield && *subfield) { int addition = atoi(subfield); int max = (IS_NPC(c) || GET_LEVEL(c) >= LVL_GRGOD) ? 25 : 18; GET_LCK(c) += addition; if(GET_LCK(c) > max) GET_LCK(c) = max; if(GET_LCK(c) < 1) GET_LCK(c) = 1; } snprintf(str, slen, "%d", GET_LCK(c)); }

Rumble
The Builder Academy
tbamud.com 9091
rumble@tbamud.com
Last edit: 06 Oct 2012 12:04 by Rumble.

Please Log in or Create an account to join the conversation.

More
06 Oct 2012 01:41 #864 by Liko
Replied by Liko on topic Re: Adding Luck, Statistics
change mine from GET_LUCK to GET_LCK

Randian(0.0.0)
Owner/Developer

Please Log in or Create an account to join the conversation.

More
12 Apr 2013 17:43 #1908 by JTP
Replied by JTP on topic Re: Adding Luck, Statistics
isnt 25 : 18
25 for mobs and 18 for characters ?
then it cant be that part

Please Log in or Create an account to join the conversation.

More
12 Apr 2013 18:59 #1909 by Rumble
Replied by Rumble on topic Re: Adding Luck, Statistics
Did you test it on a mortal? GrGod and above get 25 stats.

Rumble
The Builder Academy
tbamud.com 9091
rumble@tbamud.com

Please Log in or Create an account to join the conversation.

More
12 Apr 2013 19:37 #1910 by JTP
Replied by JTP on topic Re: Adding Luck, Statistics
yes i mase a lvl 1 to test thats how i noticed it

Please Log in or Create an account to join the conversation.

Time to create page: 0.471 seconds