Welcome to the Builder Academy

Question Adding onto Damaging Items

More
23 Oct 2017 19:07 #7030 by Papaya Pete
I was starting to add dialog to some of my NPCs in my starter town, but when I think about some of the code I still wanted to add... I couldn't help but go back to it and try to finish things up.
Just for the fun of it, I wanted to try and add onto the complexity of damaging an item. Before, there was just a flat 10% chance to damage an item and the damage was always 1d6. However, after adding on different materials, I thought it would be neat to have different materials wear down faster. Some attack types will wear away light, medium, and heavy armors down at a different rate. Blades and jabbing weapons will do more damage to leather, cloths, etc. than to thick metal armor, but a big blunt hammer will do more damage to that metal than to some leather. Different kinds of breath weapons also have a different effect on different kinds of armor; if you're wearing leather, for example, acid will damage that a lot more than metal armor. Against cold, that leather might actually shield you from it a little as opposed to metal armor, which will actually absorb that cold and result in more harm done.

Here's part of a snippet that will go into probably far too much detail into item damage than anyone will ever care about. The first part: breath weapons, which damage every piece of equipment worn.
Code:
int damage_item(struct char_data *ch, int attack_type, int item_type_damaged) { int wearslot = 0; // Used in DAMAGE_ALL; runs a do...while loop while wearslot <= MAX_WEAR_SLOTS int dicesize = 0, message = 0; // Message: 0 - severe, 1 - heavy, 2 - moderate, 3 - light, 4 - barely. int attempts = 0; // Essentially, we'll give the function 3 chances to find a piece of armor to damage. int material = 0; // Fill this value with what will be the material of item getting damaged. bool add_damage = FALSE; // Does your armor seep in that heat or cold? bool sub_damage = FALSE; // Does your armor block some of that heat or cold? struct obj_data *whichitem = NULL; struct obj_data *targ = NULL; struct obj_data *wielded = NULL; /* There's 2 different actions here: damaging 1 item or damaging all. So, let's deal with all items being damaged by, say, breath weapons and traps. We're going to make a check using a switch, and handle DAM_ALL first. */ switch (item_type_damaged) { case DAMAGE_ALL: /* Here we go. the long haul! So in here we need to run through every slot, check to see if it has any durability to damage. If it does, then we need to check it's material, check the type of damage, and then compare material vs. damage type and deal appropriate damage to durability. The easiest way to do this is using a do...while loop. So let's get started. */ do { whichitem = GET_EQ(ch, wearslot); if (GET_OBJ_MAX_DURAB(whichitem) != 0 && (whichitem != NULL)) { // Does the item have durability tracked? And is an item there in the first place? if (GET_OBJ_TYPE(whichitem) == ITEM_ARMOR) material = GET_OBJ_VAL(whichitem, 1); // If it's armor, material will be located here. else if (GET_OBJ_TYPE(whichitem) == ITEM_WEAPON) material = GET_OBJ_VAL(whichitem, 0); // If it's weapon, material will be located here. else material = MAT_CLOTH; // If it's not a weapon or armor, likely it is a type of clothing. Keeps things from... crashing. /* Durability checked, then we got the material. Should have attack type. Now to compare the two, deal appropriate damage. */ switch (attack_type) { case ATT_ACID: // Acid will deal high damage to cloth, leather, hide but to metals, not so much. Almost none to mithril and adamantium. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: case MAT_WOOD: dicesize = 20; message = MESSAGE_SEVERE; break; case MAT_COPPER: case MAT_BRONZE: dicesize = 12; message = MESSAGE_HEAVY; break; case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 8; message = MESSAGE_MODERATE; break; case MAT_MITHRIL: dicesize = 2; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 4; message = MESSAGE_LIGHT; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_COLD: // Cold barely damages metals, none to mithril and adamantium, but it WILL deal additional damage to the wearer. Light damage to cloth, etc. switch (material) { case MAT_CLOTH: dicesize = 4; message = MESSAGE_LIGHT; break; case MAT_LEATHER: case MAT_HIDE: dicesize = 4; message = MESSAGE_LIGHT; sub_damage = TRUE; break; case MAT_WOOD: dicesize = 4; message = MESSAGE_LIGHT; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 2; message = MESSAGE_BARELY; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 1; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 1; message = MESSAGE_BARELY; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_ELECTRIC: // Electric, like cold, barely damages items. But metal conducts, save mithril and adamantium. Wood blocks some of the damage. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: dicesize = 4; message = MESSAGE_LIGHT; break; case MAT_WOOD: dicesize = 4; message = MESSAGE_LIGHT; sub_damage = TRUE; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 4; message = MESSAGE_LIGHT; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 1; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 1; message = MESSAGE_BARELY; add_damage = TRUE; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_FIRE: // Fire damage deals lots of damage to wood, cloth, leather, etc. but not much to metals. Adds more damage if metal is worn. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: dicesize = 12; message = MESSAGE_HEAVY; break; case MAT_WOOD: dicesize = 20; message = MESSAGE_SEVERE; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 6; message = MESSAGE_MODERATE; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 2; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 2; message = MESSAGE_BARELY; add_damage = TRUE; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_PHYSICAL: // Huh... not sure WHAT would use this, but let's assume it does moderate damage to all but mithril and adamant. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: case MAT_WOOD: case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 6; message = MESSAGE_MODERATE; break; case MAT_MITHRIL: case MAT_ADAMANT: dicesize = 2; message = MESSAGE_BARELY; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_STEAM: // Steam deals moderate damage to cloth and such, barely any to metals but will heat them up and deal more damage. switch (material) { case MAT_CLOTH: dicesize = 6; message = MESSAGE_MODERATE; break; case MAT_LEATHER: case MAT_HIDE: case MAT_WOOD: dicesize = 6; message = MESSAGE_MODERATE; sub_damage = TRUE; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 4; message = MESSAGE_LIGHT; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 2; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 2; message = MESSAGE_BARELY; add_damage = TRUE; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; default: // Shouldn't get here but just default damage. dicesize = 6; message = MESSAGE_MODERATE; break; } /* Whew! We've gotten the damage dice dealt to the item. Also if the item blocks or adds damage to the player. Now we get to it! */ // Message, then damage to the item itself. If it breaks, kick it off into inventory. switch (message) { case MESSAGE_SEVERE: act("\tRThat attack does SEVERE damage to $p!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tR$n's $p took SEVERE damage from that attack!\tn", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_HEAVY: act("That attack does \tRHEAVY\tn damage to $p!", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p took \tRHEAVY\tn damage from that attack!\tn", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_MODERATE: act("That attack \tydamaged\tn $p!", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p took \tydamage\tn from that attack!", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_LIGHT: act("That attack does some \tgminor\tn damage to $p!", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p took \tgminor\tn damage from that attack!", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_BARELY: act("That attack hardly did any damage to $p...", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p hardly took any damage from that attack.", FALSE, ch, whichitem, 0, TO_ROOM); break; default: break; } GET_OBJ_DURABILITY(whichitem) -= rand_number(1, dicesize); if (GET_OBJ_DURABILITY(whichitem) < 0) GET_OBJ_DURABILITY(whichitem) = 0; if (GET_OBJ_DURABILITY(whichitem) == 0) { act("\tRYikes, $p\tR FELL APART!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tR$n's $p\tR FELL APART!\tn", FALSE, ch, whichitem, 0, TO_ROOM); obj_to_char(unequip_char(ch, wearslot), ch); } /* Players will love or hate this part... did the item block or deal more damage? */ if (add_damage == TRUE) { switch (attack_type) { case ATT_COLD: act("\tcThe cold seeps through $p, freezing you!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tcThe cold seeps through $n's $p, the icey chill dealing more damage!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 3); break; case ATT_ELECTRIC: act("\tYThe electricity shoots through $p, shocking you!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tYThe electricity shoots through $n's $p, shocking $m more!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 3); break; case ATT_FIRE: act("\tOThe heat from the flames make $p hot, burning you more!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tOThe heat from the flames makes $p hot, burning $n more!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 2); break; case ATT_STEAM: act("\tWThe steam heats up $p a lot, burning you more!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tWThe steam heats up $p a lot, burning $n more!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 4); break; } } if (sub_damage == TRUE) { switch (attack_type) { case ATT_COLD: act("\tBThe cold is somewhat blocked by $p, insulating you!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tBThe cold is somewhat blocked by $p, keeping $n insultated!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; case ATT_ELECTRIC: act("\tBYou are somewhat insulated from the electrical attack by $p!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tB$n is somewhat insulated from the electrical attack by $p!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; case ATT_FIRE: act("\tBYou are somewhat protected from the flames by $p!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tB$n is somewhat protected from the flames by $p!tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; case ATT_STEAM: act("\tBThe steam is blocked a little by $p, and doesn't heat it!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tB$n is somewhat protected from the steam attack by $p!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; } } } wearslot++; sub_damage = FALSE; add_damage = FALSE; } while (wearslot <= NUM_WEARS); return (0); break; // End of case DAMAGE_ALL code.

I've got weapon and armor damage coded in... but you know what would be fun? Comparing the material of the weapon versus the material of the armor and dealing item damage that way! And what if the attack is a physical non-weapon attack? Then we compare that. But what if it is a huge monster like, say, a dragon? Your sword will wear down quicker against such a beat compared to, say, a giant lizard. In order to determine that, then we need to find out the race of the monster (another snippet to do). Which opens up a whole new can of worms/possibilities.

Mind you, I have not yet had the time to test this all. I want to actually get this all in before I do that. And I apologize ahead of time for this.

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

More
26 Oct 2017 05:19 #7035 by Papaya Pete
So I've expanded it to compare two materials and their relative hardness and adjust the amount of damage to that material appropriately.
Code:
int damage_item(struct char_data *ch, int attack_type, int item_type_damaged, struct char_data *damager) { int wearslot = 0; // Used in DAMAGE_ALL; runs a do...while loop while whichitem <= MAX_WEAR_SLOTS int dicesize = 0, message = 0; // Message: 0 - severe, 1 - heavy, 2 - moderate, 3 - light, 4 - barely. int attempts = 0; // Essentially, we'll give the function 3 chances to find a piece of armor to damage. int material = 0; // Fill this value with what will be the material of item getting damaged. int oppmaterial = 0, hardnessdiff, hardtarget, harddamager, damage; bool add_damage = FALSE; // Does your armor seep in that heat or cold? bool sub_damage = FALSE; // Does your armor block some of that heat or cold? struct obj_data *whichitem = NULL; struct obj_data *targ = NULL; struct obj_data *wielded = NULL; struct obj_data *dwielded = NULL; /* There's 2 different actions here: damaging 1 item or damaging all. So, let's deal with all items being damaged by, say, breath weapons and traps. We're going to make a check using a switch, and handle DAM_ALL first. */ switch (item_type_damaged) { case DAMAGE_ALL: /* Here we go. the long haul! So in here we need to run through every slot, check to see if it has any durability to damage. If it does, then we need to check it's material, check the type of damage, and then compare material vs. damage type and deal appropriate damage to durability. The easiest way to do this is using a do...while loop. So let's get started. */ do { whichitem = GET_EQ(ch, wearslot); if (GET_OBJ_MAX_DURAB(whichitem) != 0 && (whichitem != NULL)) { // Does the item have durability tracked? And is an item there in the first place? if (GET_OBJ_TYPE(whichitem) == ITEM_ARMOR) material = GET_OBJ_VAL(whichitem, 1); // If it's armor, material will be located here. else if (GET_OBJ_TYPE(whichitem) == ITEM_WEAPON) material = GET_OBJ_VAL(whichitem, 0); // If it's weapon, material will be located here. else material = MAT_CLOTH; // If it's not a weapon or armor, likely it is a type of clothing. Keeps things from... crashing. /* Durability checked, then we got the material. Should have attack type. Now to compare the two, deal appropriate damage. */ switch (attack_type) { case ATT_ACID: // Acid will deal high damage to cloth, leather, hide but to metals, not so much. Almost none to mithril and adamantium. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: case MAT_WOOD: dicesize = 20; message = MESSAGE_SEVERE; break; case MAT_COPPER: case MAT_BRONZE: dicesize = 12; message = MESSAGE_HEAVY; break; case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 8; message = MESSAGE_MODERATE; break; case MAT_MITHRIL: dicesize = 2; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 4; message = MESSAGE_LIGHT; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_COLD: // Cold barely damages metals, none to mithril and adamantium, but it WILL deal additional damage to the wearer. Light damage to cloth, etc. switch (material) { case MAT_CLOTH: dicesize = 4; message = MESSAGE_LIGHT; break; case MAT_LEATHER: case MAT_HIDE: dicesize = 4; message = MESSAGE_LIGHT; sub_damage = TRUE; break; case MAT_WOOD: dicesize = 4; message = MESSAGE_LIGHT; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 2; message = MESSAGE_BARELY; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 1; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 1; message = MESSAGE_BARELY; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_ELECTRIC: // Electric, like cold, barely damages items. But metal conducts, save mithril and adamantium. Wood blocks some of the damage. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: dicesize = 4; message = MESSAGE_LIGHT; break; case MAT_WOOD: dicesize = 4; message = MESSAGE_LIGHT; sub_damage = TRUE; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 4; message = MESSAGE_LIGHT; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 1; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 1; message = MESSAGE_BARELY; add_damage = TRUE; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_FIRE: // Fire damage deals lots of damage to wood, cloth, leather, etc. but not much to metals. Adds more damage if metal is worn. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: dicesize = 12; message = MESSAGE_HEAVY; break; case MAT_WOOD: dicesize = 20; message = MESSAGE_SEVERE; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 6; message = MESSAGE_MODERATE; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 2; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 2; message = MESSAGE_BARELY; add_damage = TRUE; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_PHYSICAL: // Huh... not sure WHAT would use this, but let's assume it does moderate damage to all but mithril and adamant. switch (material) { case MAT_CLOTH: case MAT_LEATHER: case MAT_HIDE: case MAT_WOOD: case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 6; message = MESSAGE_MODERATE; break; case MAT_MITHRIL: case MAT_ADAMANT: dicesize = 2; message = MESSAGE_BARELY; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; case ATT_STEAM: // Steam deals moderate damage to cloth and such, barely any to metals but will heat them up and deal more damage. switch (material) { case MAT_CLOTH: dicesize = 6; message = MESSAGE_MODERATE; break; case MAT_LEATHER: case MAT_HIDE: case MAT_WOOD: dicesize = 6; message = MESSAGE_MODERATE; sub_damage = TRUE; break; case MAT_COPPER: case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 4; message = MESSAGE_LIGHT; add_damage = TRUE; break; case MAT_MITHRIL: dicesize = 2; message = MESSAGE_BARELY; sub_damage = TRUE; break; case MAT_ADAMANT: dicesize = 2; message = MESSAGE_BARELY; add_damage = TRUE; break; default: dicesize = 6; message = MESSAGE_MODERATE; break; } break; default: // Shouldn't get here but just default damage. dicesize = 6; message = MESSAGE_MODERATE; break; } /* Whew! We've gotten the damage dice dealt to the item. Also if the item blocks or adds damage to the player. Now we get to it! */ // Message, then damage to the item itself. If it breaks, kick it off into inventory. switch (message) { case MESSAGE_SEVERE: act("\tRThat attack does SEVERE damage to $p!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tR$n's $p took SEVERE damage from that attack!\tn", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_HEAVY: act("That attack does \tRHEAVY\tn damage to $p!", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p took \tRHEAVY\tn damage from that attack!\tn", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_MODERATE: act("That attack \tydamaged\tn $p!", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p took \tydamage\tn from that attack!", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_LIGHT: act("That attack does some \tgminor\tn damage to $p!", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p took \tgminor\tn damage from that attack!", FALSE, ch, whichitem, 0, TO_ROOM); break; case MESSAGE_BARELY: act("That attack hardly did any damage to $p...", FALSE, ch, whichitem, 0, TO_CHAR); act("$n's $p hardly took any damage from that attack.", FALSE, ch, whichitem, 0, TO_ROOM); break; default: break; } GET_OBJ_DURABILITY(whichitem) -= rand_number(1, dicesize); if (GET_OBJ_DURABILITY(whichitem) < 0) GET_OBJ_DURABILITY(whichitem) = 0; if (GET_OBJ_DURABILITY(whichitem) == 0) { act("\tRYikes, $p\tR FELL APART!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tR$n's $p\tR FELL APART!\tn", FALSE, ch, whichitem, 0, TO_ROOM); obj_to_char(unequip_char(ch, wearslot), ch); } /* Players will love or hate this part... did the item block or deal more damage? */ if (add_damage == TRUE) { switch (attack_type) { case ATT_COLD: act("\tcThe cold seeps through $p, freezing you!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tcThe cold seeps through $n's $p, the icey chill dealing more damage!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 3); break; case ATT_ELECTRIC: act("\tYThe electricity shoots through $p, shocking you!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tYThe electricity shoots through $n's $p, shocking $m more!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 3); break; case ATT_FIRE: act("\tOThe heat from the flames make $p hot, burning you more!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tOThe heat from the flames makes $p hot, burning $n more!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 2); break; case ATT_STEAM: act("\tWThe steam heats up $p a lot, burning you more!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tWThe steam heats up $p a lot, burning $n more!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) -= rand_number(1, 4); break; } } if (sub_damage == TRUE) { switch (attack_type) { case ATT_COLD: act("\tBThe cold is somewhat blocked by $p, insulating you!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tBThe cold is somewhat blocked by $p, keeping $n insultated!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; case ATT_ELECTRIC: act("\tBYou are somewhat insulated from the electrical attack by $p!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tB$n is somewhat insulated from the electrical attack by $p!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; case ATT_FIRE: act("\tBYou are somewhat protected from the flames by $p!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tB$n is somewhat protected from the flames by $p!tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; case ATT_STEAM: act("\tBThe steam is blocked a little by $p, and doesn't heat it!\tn", FALSE, ch, whichitem, 0, TO_CHAR); act("\tB$n is somewhat protected from the steam attack by $p!\tn", FALSE, ch, whichitem, 0, TO_ROOM); GET_HIT(ch) += rand_number(1, 2); break; } } } wearslot++; sub_damage = FALSE; add_damage = FALSE; } while (wearslot <= NUM_WEARS); return (0); break; // End of case DAMAGE_ALL code. /* So what do we need to know? The following: Is it a weapon or piece of armor? If a weapon, dual wielded or not? What's the location being damage, if armor? Once we know WHAT is getting damaged, then find the material. We also need to find the material of the opposing item (armor for weapon, weapon for armor) dealing damage. Then, knowing what kind of attack is dealing the damage, how effective is it against said material? Damage to item is dealt at the same time. Once all is said and done, then check to see if durability is 0 or less. Set it to 0 if so, and then kick it off of the player into inventory. */ case DAMAGE_WEAPON: // First, get material of weapon. Then, determine if armor was hit and that damaged it. Otherwise, normal rate of wear and tear. wielded = GET_EQ(ch, WEAR_WIELD); if (wielded != NULL) { material = GET_OBJ_VAL(GET_EQ(ch, WEAR_WIELD), 0); act("\tRYour $p\tR has been damaged!\tn", FALSE, ch, wielded, 0, TO_CHAR); act("\tR$n's $p\tR has been damaged!\tn", FALSE, ch, wielded, 0, TO_ROOM); } for (attempts = 1; attempts <= 3; attempts ++) { if ((targ = GET_EQ(ch, rand_number(0, NUM_WEARS))) != NULL) { attempts = 3; // Got a hit on an item, so loop is no longer needed. oppmaterial = GET_OBJ_VAL(targ, 1); // Grab the opposing material type } else oppmaterial = MAT_OTHER; } break; case DAMAGE_DWEAPON: wielded = GET_EQ(ch, WEAR_DWIELD); if (wielded != NULL) { material = GET_OBJ_VAL(GET_EQ(ch, WEAR_DWIELD), 0); act("\tRYour $p\tR has been damaged!\tn", FALSE, ch, wielded, 0, TO_CHAR); act("\tR$n's $p\tR has been damaged!\tn", FALSE, ch, wielded, 0, TO_ROOM); } for (attempts = 1; attempts <= 3; attempts ++) { if ((targ = GET_EQ(ch, rand_number(0, NUM_WEARS))) != NULL) { attempts = 3; // Got a hit on an item, so loop is no longer needed. oppmaterial = GET_OBJ_VAL(targ, 1); // Grab the opposing material type } else oppmaterial = MAT_OTHER; } break; case DAMAGE_ARMOR: for (attempts = 1; attempts <= 3; attempts ++) { if ((targ = GET_EQ(ch, rand_number(0, NUM_WEARS))) != NULL) { attempts = 3; // Got a hit on an item, so loop is no longer needed. material = GET_OBJ_VAL(targ, 1); act("\tRYour $p\tR has been damaged!\tn", FALSE, ch, targ, 0, TO_CHAR); act("\tR$n's $p\tR has been damaged!\tn", FALSE, ch, targ, 0, TO_ROOM); } } /* Time to pull up any weapons damager has on hand. If Dwielding, pick at random which weapon is the damager. */ wielded = GET_EQ(damager, WEAR_WIELD); dwielded = GET_EQ(damager, WEAR_DWIELD); if ((dwielded != NULL) && (wielded != NULL)) { if (rand_number(1, 2) == 1) oppmaterial = GET_OBJ_VAL(wielded, 0); else oppmaterial = GET_OBJ_VAL(dwielded, 0); } else if (wielded != NULL) oppmaterial = GET_OBJ_VAL(wielded, 0); if (wielded == NULL) oppmaterial = MAT_OTHER; break; default: send_to_char(ch, "Shouldn't see this, notify Admin immediately if possible.\r\n"); break; } /* Now we determine the hardness difference of the materials involved. hardnessdiff = material - oppmaterial; This is the general idea. */ switch (material) { case MAT_CLOTH: hardtarget = 1; break; case MAT_LEATHER: case MAT_HIDE: hardtarget = 2; break; case MAT_WOOD: hardtarget = 3; break; case MAT_COPPER: hardtarget = 4; break; case MAT_BRONZE: hardtarget = 5; break; case MAT_IRON: hardtarget = 6; break; case MAT_STEEL: hardtarget = 7; break; case MAT_ENDURIUM: hardtarget = 8; break; case MAT_MITHRIL: hardtarget = 9; break; case MAT_ADAMANT: hardtarget = 10; break; case MAT_OTHER: hardtarget = 1; break; default: hardtarget = 1; break; } switch (oppmaterial) { case MAT_CLOTH: harddamager = 1; break; case MAT_LEATHER: case MAT_HIDE: harddamager = 2; break; case MAT_WOOD: harddamager = 3; break; case MAT_COPPER: harddamager = 4; break; case MAT_BRONZE: harddamager = 5; break; case MAT_IRON: harddamager = 6; break; case MAT_STEEL: harddamager = 7; break; case MAT_ENDURIUM: harddamager = 8; break; case MAT_MITHRIL: harddamager = 9; break; case MAT_ADAMANT: harddamager = 10; break; case MAT_OTHER: harddamager = 1; break; default: harddamager = 1; break; } hardnessdiff = hardtarget - harddamager; /* We have the hardness ratings of each... high is better. The one being damaged wants his hardness to be higher than the attacker's. Example... Steel vs. Copper, 7 vs 4. Hardnessdiff = -3, so damage dealt to his steel item would be a third less. damage = damage * (-1 * hardnessdiff) if hardnessdiff < 0 */ switch (attack_type) { case ATT_PHYSICAL: // Normal 1d6 damage to bronze, iron, steel, endurium. 1d8 vs copper, leather, and hide. 1d10 vs cloth and wood. switch (material) { case MAT_CLOTH: case MAT_WOOD: dicesize = 12; break; case MAT_LEATHER: dicesize = 10; break; case MAT_HIDE: case MAT_COPPER: dicesize = 8; break; case MAT_BRONZE: case MAT_IRON: case MAT_STEEL: case MAT_ENDURIUM: dicesize = 6; break; case MAT_MITHRIL: dicesize = 4; break; case MAT_ADAMANT: dicesize = 2; break; default: dicesize = 6; break; } break; default: dicesize = 6; break; } damage = rand_number(1, dicesize); if (hardnessdiff > 0) damage *= hardnessdiff; else if (hardnessdiff < 0) { damage = damage / (-1 * hardnessdiff); if (damage == 0) damage = 1; } switch (item_type_damaged) { case DAMAGE_WEAPON: if (wielded != NULL) { GET_OBJ_DURABILITY(wielded) -= damage; if (GET_OBJ_DURABILITY(wielded) < 0) GET_OBJ_DURABILITY(wielded) = 0; if (GET_OBJ_DURABILITY(wielded) == 0) { act("\tRYikes, $p\tR FELL APART!\tn", FALSE, ch, wielded, 0, TO_CHAR); act("\tR$n's $p\tR FELL APART!\tn", FALSE, ch, wielded, 0, TO_ROOM); obj_to_char(unequip_char(ch, WEAR_WIELD), ch); } } break; case DAMAGE_DWEAPON: if (wielded != NULL) { GET_OBJ_DURABILITY(wielded) -= damage; if (GET_OBJ_DURABILITY(wielded) < 0) GET_OBJ_DURABILITY(wielded) = 0; if (GET_OBJ_DURABILITY(wielded) == 0) { act("\tRYikes, $p\tR FELL APART!\tn", FALSE, ch, wielded, 0, TO_CHAR); act("\tR$n's $p\tR FELL APART!\tn", FALSE, ch, wielded, 0, TO_ROOM); obj_to_char(unequip_char(ch, WEAR_DWIELD), ch); } } break; case DAMAGE_ARMOR: if (targ != NULL) { GET_OBJ_DURABILITY(targ) -= damage; if (GET_OBJ_DURABILITY(targ) < 0) GET_OBJ_DURABILITY(wielded) = 0; if (GET_OBJ_DURABILITY(targ) == 0) { act("\tRYikes, $p\tR FELL APART!\tn", FALSE, ch, targ, 0, TO_CHAR); act("\tR$n's $p\tR FELL APART!\tn", FALSE, ch, targ, 0, TO_ROOM); obj_to_char(unequip_char(ch, targ->worn_on), ch); } } break; default: send_to_char(ch, "Shouldn't see, please contact Admin immediately.\r\n"); break; } return (0); }

Obviously had to make some minor changes to the declaration of the function (we needed access to the opposing character's char_data), but it all compiles and should work fine. I was going to go even further and make further adjustments based on the attack type versus the type of armor, but found this is as far as I wanted to go in this regard.

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

More
17 Jan 2019 08:17 #8298 by Papaya Pete
This took me a whole year to finally test this out? That's kind of sad.

Anyways, I'm finally getting around to making some progress over here. As my test character ran around, I started to find some bugs that would crash the mud. One was during a battle with a boar, so i figured it had something to do with damaging an item he was wearing. Looking at the DAMAGE_ARMOR section in the damage_item function, I think the problem might be that it was attempting to damage an item that wasn't meant to be damaged. So, I rewrote it to the following:
Code:
case DAMAGE_ARMOR: for (attempts = 1; attempts <= 3; attempts ++) { wearslot = rand_number(0, NUM_WEARS); targ = GET_EQ(ch, wearslot); if ((targ != NULL) && (GET_OBJ_TYPE(GET_EQ(ch, wearslot)) == ITEM_ARMOR)) { attempts = 3; // Got a hit on an item, so loop is no longer needed. material = GET_OBJ_VAL(targ, 1); act("\tRYour $p\tR has been damaged!\tn", FALSE, ch, targ, 0, TO_CHAR); act("\tR$n's $p\tR has been damaged!\tn", FALSE, ch, targ, 0, TO_ROOM); } }

Lots of running around and attempting to finish the first quest have resulted in no more crashes so far. I'll update this as I find more mistake I made.

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

Time to create page: 0.281 seconds