diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 3b90e26915a..2b820e813eb 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -1485,4 +1485,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// Prevents items from being speed potion-ed, but allows their speed to be altered in other ways #define TRAIT_NO_SPEED_POTION "no_speed_potion" +/// Demolition modifier when hitting this object is inverted (ie, 1 / demolition) +#define TRAIT_INVERTED_DEMOLITION "demolition_inverted" + // END TRAIT DEFINES diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 03f6bb0f714..ad79d09dde0 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -54,6 +54,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_HEARING_SENSITIVE" = TRAIT_HEARING_SENSITIVE, "TRAIT_HYPERSPACED" = TRAIT_HYPERSPACED, "TRAIT_IMMERSED" = TRAIT_IMMERSED, + "TRAIT_INVERTED_DEMOLITION" = TRAIT_INVERTED_DEMOLITION, "TRAIT_IRRADIATED" = TRAIT_IRRADIATED, "TRAIT_IS_AQUARIUM" = TRAIT_IS_AQUARIUM, "TRAIT_LAVA_IMMUNE" = TRAIT_LAVA_IMMUNE, @@ -83,8 +84,8 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_SILENT_REACTIONS" = TRAIT_SILENT_REACTIONS, "TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE, "TRAIT_SPELLS_TRANSFER_TO_LOC" = TRAIT_SPELLS_TRANSFER_TO_LOC, - "TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH" = TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH, "TRAIT_STOP_FISH_FLOPPING" = TRAIT_STOP_FISH_FLOPPING, + "TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH" = TRAIT_STOP_FISH_REPRODUCTION_AND_GROWTH, "TRAIT_TELEKINESIS_CONTROLLED" = TRAIT_TELEKINESIS_CONTROLLED, "TRAIT_UNDERFLOOR" = TRAIT_UNDERFLOOR, "TRAIT_UNIQUE_IMMERSE" = TRAIT_UNIQUE_IMMERSE, diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index bfe7ecaeff4..e9f8d6a1d0a 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -307,7 +307,7 @@ var/damage = attacking_item.force if(mob_biotypes & MOB_ROBOTIC) - damage *= attacking_item.demolition_mod + damage *= attacking_item.get_demolition_modifier(src) var/wounding = attacking_item.wound_bonus if((attacking_item.item_flags & SURGICAL_TOOL) && !user.combat_mode && body_position == LYING_DOWN && (LAZYLEN(surgeries) > 0)) diff --git a/code/game/objects/effects/spiderwebs.dm b/code/game/objects/effects/spiderwebs.dm index ed3253be9bd..d47c0059000 100644 --- a/code/game/objects/effects/spiderwebs.dm +++ b/code/game/objects/effects/spiderwebs.dm @@ -11,6 +11,7 @@ /obj/structure/spider/Initialize(mapload) . = ..() AddElement(/datum/element/atmos_sensitive, mapload) + ADD_TRAIT(src, TRAIT_INVERTED_DEMOLITION, INNATE_TRAIT) /obj/structure/spider/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0) if(damage_type == BURN)//the stickiness of the web mutes all attack sounds except fire damage type diff --git a/code/game/objects/items/chainsaw.dm b/code/game/objects/items/chainsaw.dm index 509a3a63856..dcbeec0181c 100644 --- a/code/game/objects/items/chainsaw.dm +++ b/code/game/objects/items/chainsaw.dm @@ -71,6 +71,9 @@ return COMPONENT_NO_DEFAULT_MESSAGE +/obj/item/chainsaw/get_demolition_modifier(obj/target) + return HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE) ? demolition_mod : 0.8 + /obj/item/chainsaw/suicide_act(mob/living/carbon/user) if(!HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE)) user.visible_message(span_suicide("[user] smashes [src] into [user.p_their()] neck, destroying [user.p_their()] esophagus! It looks like [user.p_theyre()] trying to commit suicide!")) diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/fireaxe.dm index 3b6727d6923..b6832d1f0f5 100644 --- a/code/game/objects/items/fireaxe.dm +++ b/code/game/objects/items/fireaxe.dm @@ -53,6 +53,9 @@ GLOBAL_DATUM(bridge_axe, /obj/item/fireaxe) GLOB.bridge_axe = null return ..() +/obj/item/fireaxe/get_demolition_modifier(obj/target) + return HAS_TRAIT(src, TRAIT_WIELDED) ? demolition_mod : 0.8 + /obj/item/fireaxe/update_icon_state() icon_state = "[base_icon_state]0" return ..() diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index 8a904ae953a..7e619c39396 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -102,6 +102,9 @@ playsound(loc, hitsound, get_clamped_volume(), TRUE, -1) add_fingerprint(user) +/obj/item/melee/energy/get_demolition_modifier(obj/target) + return HAS_TRAIT(src, TRAIT_TRANSFORM_ACTIVE) ? demolition_mod : 1 + /obj/item/melee/energy/update_icon_state() . = ..() if(!sword_color_icon) diff --git a/code/game/objects/obj_defense.dm b/code/game/objects/obj_defense.dm index 23d25970ecf..50123b958c7 100644 --- a/code/game/objects/obj_defense.dm +++ b/code/game/objects/obj_defense.dm @@ -4,7 +4,7 @@ var/damage_taken = hit_by.throwforce if(isitem(hit_by)) var/obj/item/as_item = hit_by - damage_taken *= as_item.demolition_mod + damage_taken *= as_item.get_demolition_modifier(src) take_damage(damage_taken, BRUTE, MELEE, 1, get_dir(src, hit_by)) /obj/ex_act(severity, target) @@ -35,7 +35,7 @@ var/damage_sustained = 0 if(!QDELETED(src)) //Bullet on_hit effect might have already destroyed this object damage_sustained = take_damage( - hitting_projectile.damage * hitting_projectile.demolition_mod, + hitting_projectile.damage * hitting_projectile.get_demolition_modifier(src), hitting_projectile.damage_type, hitting_projectile.armor_flag, FALSE, diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index 5e87f43d614..0c90051a5bf 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -25,6 +25,7 @@ var/bare_wound_bonus = 0 /// A multiplier to an object's force when used against a structure, vehicle, machine, or robot. + /// Use [/obj/proc/get_demolition_modifier] to get the value. var/demolition_mod = 1 /// Cached custom fire overlay @@ -74,7 +75,8 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) if(!attacking_item.force) return - var/total_force = (attacking_item.force * attacking_item.demolition_mod) + var/demo_mod = attacking_item.get_demolition_modifier(src) + var/total_force = (attacking_item.force * demo_mod) var/damage = take_damage(total_force, attacking_item.damtype, MELEE, TRUE, get_dir(src, user), attacking_item.armour_penetration) // Sanity in case one is null for some reason @@ -88,11 +90,15 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) if (picked_index && length(attacking_item.attack_verb_simple) >= picked_index) message_verb_simple = attacking_item.attack_verb_simple[picked_index] - if(attacking_item.demolition_mod > 1 && prob(damage * 5)) - message_verb_simple = "pulverise" - message_verb_continuous = "pulverises" + if(demo_mod > 1 && prob(damage * 5)) + if(HAS_TRAIT(src, TRAIT_INVERTED_DEMOLITION)) + message_verb_simple = "shred" + message_verb_continuous = "shreds" + else + message_verb_simple = "pulverise" + message_verb_continuous = "pulverises" - if(attacking_item.demolition_mod < 1) + if(demo_mod < 1) message_verb_simple = "ineffectively " + message_verb_simple message_verb_continuous = "ineffectively " + message_verb_continuous @@ -335,3 +341,9 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) throwforce /= strength_mod var/list/armor_mods = material.get_armor_modifiers(1 / multiplier) set_armor(get_armor().generate_new_with_multipliers(armor_mods)) + +/// Returns modifier to how much damage this object does to a target considered vulnerable to "demolition" (other objects, robots, etc) +/obj/proc/get_demolition_modifier(obj/target) + if(HAS_TRAIT(target, TRAIT_INVERTED_DEMOLITION)) + return (1 / demolition_mod) + return demolition_mod diff --git a/code/game/objects/structures/curtains.dm b/code/game/objects/structures/curtains.dm index a39348046da..cb9f7b3b34d 100644 --- a/code/game/objects/structures/curtains.dm +++ b/code/game/objects/structures/curtains.dm @@ -22,7 +22,8 @@ // see-through curtains should let emissives shine through if(!opaque_closed) blocks_emissive = EMISSIVE_BLOCK_NONE - return ..() + . = ..() + ADD_TRAIT(src, TRAIT_INVERTED_DEMOLITION, INNATE_TRAIT) /obj/structure/curtain/proc/toggle() open = !open diff --git a/code/modules/unit_tests/mecha_damage.dm b/code/modules/unit_tests/mecha_damage.dm index f922d342b49..a496de383c1 100644 --- a/code/modules/unit_tests/mecha_damage.dm +++ b/code/modules/unit_tests/mecha_damage.dm @@ -26,7 +26,7 @@ // The energy axe is chosen here due to having a high base force, to make sure we get over the equipment DT. var/obj/item/dummy_melee = allocate(/obj/item/melee/energy/axe) dummy_melee.force = 150 - var/expected_melee_damage = round(dummy_melee.force * (1 - expected_melee_armor / 100) * dummy_melee.demolition_mod * demo_mech.facing_modifiers[MECHA_FRONT_ARMOUR], DAMAGE_PRECISION) + var/expected_melee_damage = round(dummy_melee.force * (1 - expected_melee_armor / 100) * dummy_melee.get_demolition_modifier(demo_mech) * demo_mech.facing_modifiers[MECHA_FRONT_ARMOUR], DAMAGE_PRECISION) // Get a sample laser weapon. // The captain's laser gun here is chosen primarily because it deals more damage than normal lasers. diff --git a/code/modules/vehicles/mecha/mecha_defense.dm b/code/modules/vehicles/mecha/mecha_defense.dm index 547ae21eba4..da71540aa7c 100644 --- a/code/modules/vehicles/mecha/mecha_defense.dm +++ b/code/modules/vehicles/mecha/mecha_defense.dm @@ -317,7 +317,7 @@ if(!attacking_item.force) return - var/damage_taken = take_damage(attacking_item.force * attacking_item.demolition_mod, attacking_item.damtype, MELEE, 1, get_dir(src, user)) + var/damage_taken = take_damage(attacking_item.force * attacking_item.get_demolition_modifier(src), attacking_item.damtype, MELEE, 1, get_dir(src, user)) try_damage_component(damage_taken, user.zone_selected) var/hit_verb = length(attacking_item.attack_verb_simple) ? "[pick(attacking_item.attack_verb_simple)]" : "hit"