I did this. Below is most of the code.
The defines in structs.h:
Code:
#define RESIST_UNARMED 0
#define RESIST_EXOTIC 1
#define RESIST_BLUNT 2
#define RESIST_PIERCE 3
#define RESIST_SLASH 4
#define RESIST_MAGIC 5
#define NUM_RESISTS 6
#define APPLY_RESIST_UNARMED 32
#define APPLY_RESIST_EXOTIC 33
#define APPLY_RESIST_BLUNT 34
#define APPLY_RESIST_PIERCE 35
#define APPLY_RESIST_SLASH 36
#define APPLY_RESIST_MAGIC 37
In char_point_data in structs.h
Code:
int resists[NUM_RESISTS];
In utils.h
Code:
#define GET_RESISTS(ch, i) ((ch)->points.resists[i])
In apply_types[] in const.c
Code:
"RESIST_UNARMED",
"RESIST_EXOTIC",
"RESIST_BLUNT",
"RESIST_PIERCE",
"RESIST_SLASH",
"RESIST_MAGIC",
In damage() in fight.c:
Code:
/* attacktype is passed to the damage() function by hit() or mag_damage() */
if (attacktype >= TYPE_HIT && attacktype < TYPE_HIT + NUM_ATTACK_TYPES)
{
switch (attacktype)
{
case TYPE_HIT:
case TYPE_THRASH:
case TYPE_PUNCH:
resist = RESIST_UNARMED;
break;
case TYPE_CRUSH:
case TYPE_SHIELD_SLAM:
case TYPE_BLAST:
resist = RESIST_EXOTIC;
break;
case TYPE_BLUDGEON:
case TYPE_POUND:
case TYPE_MAUL:
resist = RESIST_BLUNT;
break;
case TYPE_STING:
case TYPE_BITE:
case TYPE_PIERCE:
case TYPE_STAB:
resist = RESIST_PIERCE;
break;
case TYPE_WHIP:
case TYPE_SLASH:
case TYPE_CLAW:
resist = RESIST_SLASH;
break;
default:
resist = -1;
break;
}
}
/* All damaging spells go through this function and process them here */
if (attacktype >= 0 && attacktype < MAX_SPELLS)
{
if (spell_info[attacktype].violent)
resist = RESIST_MAGIC;
if (ROOM_FLAGGED(IN_ROOM(ch), ROOM_MAGIC_DAMPEN))
dampen = TRUE;
else if (ROOM_FLAGGED(IN_ROOM(victim), ROOM_MAGIC_DAMPEN))
dampen = TRUE;
}
/* We grab the leftover attacks here */
if (resist > -1 && dam >= 2)
{
for (int r = 0; r < NUM_RESISTS; r++)
{
if (resist == r)
{
if (GET_RESISTS(victim, r) > 0)
dam -= dam * MIN(GET_RESISTS(victim, r), 100) / 100;
if (GET_RESISTS(victim, r) < 0)
dam += dam * MIN(abs(GET_RESISTS(victim, r)), 100) / 100;
}
}
}
In medit_parse() in medit.c
Code:
case MEDIT_RESIST_0:
GET_RESISTS(OLC_MOB(d), RESIST_UNARMED) = LIMIT(i, -100, 100);
write_to_output(d, "Enter the melee resist exotic (-100 to 100): ");
OLC_MODE(d) = MEDIT_RESIST_1;
return;
case MEDIT_RESIST_1:
GET_RESISTS(OLC_MOB(d), RESIST_EXOTIC) = LIMIT(i, -100, 100);
write_to_output(d, "Enter the melee resist blunt (-100 to 100): ");
OLC_MODE(d) = MEDIT_RESIST_2;
return;
case MEDIT_RESIST_2:
GET_RESISTS(OLC_MOB(d), RESIST_BLUNT) = LIMIT(i, -100, 100);
write_to_output(d, "Enter the melee resist pierce (-100 to 100): ");
OLC_MODE(d) = MEDIT_RESIST_3;
return;
case MEDIT_RESIST_3:
GET_RESISTS(OLC_MOB(d), RESIST_PIERCE) = LIMIT(i, -100, 100);
write_to_output(d, "Enter the melee resist slash (-100 to 100): ");
OLC_MODE(d) = MEDIT_RESIST_4;
return;
case MEDIT_RESIST_4:
GET_RESISTS(OLC_MOB(d), RESIST_SLASH) = LIMIT(i, -100, 100);
write_to_output(d, "Enter the magic resist (-100 to 100): ");
OLC_MODE(d) = MEDIT_RESIST_5;
return;
case MEDIT_RESIST_5:
GET_RESISTS(OLC_MOB(d), RESIST_MAGIC) = LIMIT(i, -100, 100);
OLC_VAL(d) = TRUE;
medit_disp_stats_menu(d);
return;
In interpret_espec() in db.c
Code:
CASE("RES_0")
{
RANGE(-100, 100);
mob_proto[i].points.resists[RESIST_UNARMED] = num_arg;
}
CASE("RES_1")
{
RANGE(-100, 100);
mob_proto[i].points.resists[RESIST_EXOTIC] = num_arg;
}
CASE("RES_2")
{
RANGE(-100, 100);
mob_proto[i].points.resists[RESIST_BLUNT] = num_arg;
}
CASE("RES_3")
{
RANGE(-100, 100);
mob_proto[i].points.resists[RESIST_PIERCE] = num_arg;
}
CASE("RES_4")
{
RANGE(-100, 100);
mob_proto[i].points.resists[RESIST_SLASH] = num_arg;
}
CASE("RES_5")
{
RANGE(-100, 100);
mob_proto[i].points.resists[RESIST_MAGIC] = num_arg;
}
In write_mobile_espec() in genmob.c
Code:
if (GET_RESISTS(mob, 0) != 0)
fprintf(fd, "RES_0: %d\n", GET_RESISTS(mob,RESIST_UNARMED));
if (GET_RESISTS(mob, 1) != 0)
fprintf(fd, "RES_1: %d\n", GET_RESISTS(mob,RESIST_EXOTIC));
if (GET_RESISTS(mob, 2) != 0)
fprintf(fd, "RES_2: %d\n", GET_RESISTS(mob,RESIST_BLUNT));
if (GET_RESISTS(mob, 3) != 0)
fprintf(fd, "RES_3: %d\n", GET_RESISTS(mob,RESIST_PIERCE));
if (GET_RESISTS(mob, 4) != 0)
fprintf(fd, "RES_4: %d\n", GET_RESISTS(mob,RESIST_SLASH));
if (GET_RESISTS(mob, 5) != 0)
fprintf(fd, "RES_5: %d\n", GET_RESISTS(mob,RESIST_MAGIC));
In aff_apply_modify() in handler.c
Code:
case APPLY_RESIST_UNARMED:
GET_RESISTS(ch, RESIST_UNARMED) += mod;
break;
case APPLY_RESIST_EXOTIC:
GET_RESISTS(ch, RESIST_EXOTIC) += mod;
break;
case APPLY_RESIST_BLUNT:
GET_RESISTS(ch, RESIST_BLUNT) += mod;
break;
case APPLY_RESIST_PIERCE:
GET_RESISTS(ch, RESIST_PIERCE) += mod;
break;
case APPLY_RESIST_SLASH:
GET_RESISTS(ch, RESIST_SLASH) += mod;
break;
case APPLY_RESIST_MAGIC:
GET_RESISTS(ch, RESIST_MAGIC) += mod;
break;
In load_char() in players.c:
Code:
else if (!strcmp(tag, "RES0"))
GET_RESISTS(ch, RESIST_UNARMED) = atoi(line);
else if (!strcmp(tag, "RES1"))
GET_RESISTS(ch, RESIST_EXOTIC) = atoi(line);
else if (!strcmp(tag, "RES2"))
GET_RESISTS(ch, RESIST_BLUNT) = atoi(line);
else if (!strcmp(tag, "RES3"))
GET_RESISTS(ch, RESIST_PIERCE) = atoi(line);
else if (!strcmp(tag, "RES4"))
GET_RESISTS(ch, RESIST_SLASH) = atoi(line);
else if (!strcmp(tag, "RES5"))
GET_RESISTS(ch, RESIST_MAGIC) = atoi(line);
I added them to medit_disp_stats_menu() as well but my display has been entirely reorganized so providing the code won't be so helpful.
I added them to do_score() in act.informative.c. It's been reorganized as well.
I added them to zaffs[], set_fields[], perform_set() and do_stat_character() in act.wizard.c. This is fairly straightforward.
There are some spells in magic.c (stoneskin, steelskin, etc) than can buff the resists.
These changes shouldn't break your mob or player files as interpret_espec() and load_char() only process the value if the value exists. Once you load the player or mob and modify the values, the appropriate file will be updated and saved.
Additionally, because I added the APPLY_RESIST_(TYPE), the resistances can be added to equipment with oedit. A wooden shield could make you resistant to pierce but vulnerable to blunt. A dragonscale shield could make you resistant to exotic and magic.
All in all, this has worked flawlessly and the only change I'm pondering is reorganizing my damage spells into magical colors like MtG or classical greek elements and adding the corresponding resistances.
Note: negative values for resists are calculated as vulnerabilities.
Hope this helps.