From c3f5870df53e749284bcddbc06055ec0532cc5f0 Mon Sep 17 00:00:00 2001 From: Incoming5643 Date: Mon, 25 Jul 2016 05:14:28 -0400 Subject: [PATCH] Adds limb destroyer behavior to hostile mobs. (#19451) * Adds limb destroyer behavior to hostile mobs. Mobs with this behavior will (usually [thanks proc/ran_zone]) attack the weakest limb of a mob until it gets dismembered Adds ishostile() for this pretty specific situation Behavior added to viscerators * Generalizes the ability to dismember with an unarmed strike to living * Gives xenos limb_destroyer at WJohn consultation If a monkey or a human is var edited to have destroyer, that works now fixes a potential runtime --- code/__DEFINES/is_helpers.dm | 2 ++ .../living/carbon/alien/humanoid/humanoid.dm | 1 + .../mob/living/carbon/carbon_defense.dm | 24 ++++++++++++++++++- .../living/carbon/human/human_attackalien.dm | 3 ++- .../living/carbon/human/human_attackpaw.dm | 3 +++ .../mob/living/carbon/human/human_defense.dm | 8 +++++-- .../mob/living/carbon/human/species.dm | 2 ++ code/modules/mob/living/living_defines.dm | 2 ++ .../living/simple_animal/hostile/hostile.dm | 1 - .../living/simple_animal/hostile/syndicate.dm | 1 + .../research/xenobiology/xenobiology.dm | 2 +- 11 files changed, 43 insertions(+), 6 deletions(-) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index f4a9088c345..43933ce6127 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -77,6 +77,8 @@ #define isguardian(A) (istype(A, /mob/living/simple_animal/hostile/guardian)) +#define ishostile(A) (istype(A, /mob/living/simple_animal/hostile)) + #define islimb(A) (istype(A, /obj/item/bodypart)) #define isbot(A) (istype(A, /mob/living/simple_animal/bot)) diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm index b7fe9f9fd2f..051bdb1add5 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm @@ -3,6 +3,7 @@ icon_state = "alien_s" pass_flags = PASSTABLE butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1) + limb_destroyer = 1 var/obj/item/r_store = null var/obj/item/l_store = null var/caste = "" diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 4fc25452cda..31a7cc60e3a 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -103,4 +103,26 @@ "[src] devours you!") C.forceMove(src) stomach_contents.Add(C) - add_logs(src, C, "devoured") \ No newline at end of file + add_logs(src, C, "devoured") + +/mob/living/carbon/proc/dismembering_strike(mob/living/attacker, dam_zone) + if(!attacker.limb_destroyer || !has_limbs) + return dam_zone + var/obj/item/bodypart/affecting + if(dam_zone && attacker.client) + affecting = get_bodypart(ran_zone(dam_zone)) + else + var/list/things_to_ruin = shuffle(bodyparts.Copy()) + for(var/B in things_to_ruin) + var/obj/item/bodypart/bodypart = B + if(bodypart.body_zone == "head" || bodypart.body_zone == "chest") + continue + if(!affecting || ((affecting.get_damage() / affecting.max_damage) < (bodypart.get_damage() / bodypart.max_damage))) + affecting = bodypart + if(affecting) + dam_zone = affecting.body_zone + if(affecting.get_damage() >= affecting.max_damage) + affecting.dismember() + return null + return affecting.body_zone + return dam_zone diff --git a/code/modules/mob/living/carbon/human/human_attackalien.dm b/code/modules/mob/living/carbon/human/human_attackalien.dm index 3f7acda2524..f3a4606fc72 100644 --- a/code/modules/mob/living/carbon/human/human_attackalien.dm +++ b/code/modules/mob/living/carbon/human/human_attackalien.dm @@ -19,7 +19,8 @@ playsound(loc, 'sound/weapons/slice.ogg', 25, 1, -1) visible_message("[M] has slashed at [src]!", \ "[M] has slashed at [src]!") - + if(!dismembering_strike(M, M.zone_selected)) //Dismemberment successful + return 1 apply_damage(damage, BRUTE, affecting, armor_block) if (prob(30)) visible_message("[M] has wounded [src]!", \ diff --git a/code/modules/mob/living/carbon/human/human_attackpaw.dm b/code/modules/mob/living/carbon/human/human_attackpaw.dm index 63dcd230169..4c666a86799 100644 --- a/code/modules/mob/living/carbon/human/human_attackpaw.dm +++ b/code/modules/mob/living/carbon/human/human_attackpaw.dm @@ -6,6 +6,9 @@ ..() //shaking return 0 + if(M.limb_destroyer) + dismembering_strike(M, affecting.body_zone) + if(can_inject(M, 1, affecting))//Thick suits can stop monkey bites. if(..()) //successful monkey bite, this handles disease contraction. var/damage = rand(1, 3) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 1727fe4f0de..d8d73767278 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -271,7 +271,9 @@ var/damage = rand(M.melee_damage_lower, M.melee_damage_upper) if(check_shields(damage, "the [M.name]", null, MELEE_ATTACK, M.armour_penetration)) return 0 - var/dam_zone = pick("chest", "l_hand", "r_hand", "l_leg", "r_leg") + var/dam_zone = dismembering_strike(M, pick("chest", "l_hand", "r_hand", "l_leg", "r_leg")) + if(!dam_zone) //Dismemberment successful + return 1 var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) var/armor = run_armor_check(affecting, "melee", armour_penetration = M.armour_penetration) apply_damage(damage, M.melee_damage_type, affecting, armor) @@ -301,7 +303,9 @@ if(check_shields(damage, "the [M.name]")) return 0 - var/dam_zone = pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg", "groin") + var/dam_zone = dismembering_strike(M, pick("head", "chest", "l_arm", "r_arm", "l_leg", "r_leg")) + if(!dam_zone) //Dismemberment successful + return 1 var/obj/item/bodypart/affecting = get_bodypart(ran_zone(dam_zone)) var/armor_block = run_armor_check(affecting, "melee") diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index b32fce8c02b..6e518ead263 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -970,6 +970,8 @@ H.visible_message("[M] has [atk_verb]ed [H]!", \ "[M] has [atk_verb]ed [H]!") + if(M.limb_destroyer) + H.dismembering_strike(M, affecting.body_zone) H.apply_damage(damage, BRUTE, affecting, armor_block) add_logs(M, H, "punched") if((H.stat != DEAD) && damage >= M.dna.species.punchstunthreshold) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index e56d5bc7dd6..51fc556a6cb 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -41,6 +41,8 @@ var/bloodcrawl = 0 //0 No blood crawling, BLOODCRAWL for bloodcrawling, BLOODCRAWL_EAT for crawling+mob devour var/holder = null //The holder for blood crawling var/ventcrawler = 0 //0 No vent crawling, 1 vent crawling in the nude, 2 vent crawling always + var/limb_destroyer = 0 //1 Sets AI behavior that allows mobs to target and dismember limbs with their basic attack. + var/floating = 0 var/mob_size = MOB_SIZE_HUMAN var/metabolism_efficiency = 1 //more or less efficiency to metabolize helpful/harmful reagents and regulate body temperature.. diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 07a52affb0f..fa4f0104228 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -41,7 +41,6 @@ var/stat_attack = 0 //Mobs with stat_attack to 1 will attempt to attack things that are unconscious, Mobs with stat_attack set to 2 will attempt to attack the dead. var/stat_exclusive = 0 //Mobs with this set to 1 will exclusively attack things defined by stat_attack, stat_attack 2 means they will only attack corpses var/attack_same = 0 //Set us to 1 to allow us to attack our own faction, or 2, to only ever attack our own faction - var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_IDLE (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever) var/atom/targets_from = null //all range/attack/etc. calculations should be done from this atom, defaults to the mob itself, useful for Vehicles and such diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index bb6135079d1..871e7a9d9e0 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -161,6 +161,7 @@ minbodytemp = 0 mob_size = MOB_SIZE_TINY flying = 1 + limb_destroyer = 1 speak_emote = list("states") bubble_icon = "syndibot" gold_core_spawnable = 1 diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index 123694aef90..90749a39bc0 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -596,7 +596,7 @@ /obj/effect/timestop/proc/unfreeze_mob(mob/living/M) M.AdjustStunned(-10, 1, 1) M.anchored = 0 - if(istype(M, /mob/living/simple_animal/hostile)) + if(ishostile(M)) var/mob/living/simple_animal/hostile/H = M H.AIStatus = initial(H.AIStatus)