diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index a5106be41e..9c4d3009e4 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -919,7 +919,7 @@ FIRE ALARM /obj/machinery/firealarm/attack_ai(mob/user as mob) return src.attack_hand(user) -/obj/machinery/firealarm/bullet_act(BLAH) +/obj/machinery/firealarm/bullet_act() return src.alarm() /obj/machinery/firealarm/emp_act(severity) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 934aeec09c..7f7a02b5f0 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -624,6 +624,14 @@ var/list/turret_icons // Emagged turrets again use twice as much power due to higher firing rates use_power(reqpower * (2 * (emagged || lethal)) * (2 * emagged)) + //Turrets aim for the center of mass by default. + //If the target is grabbing someone then the turret smartly aims for extremities + var/obj/item/weapon/grab/G = locate() in target + if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people. + A.def_zone = pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg") + else + A.def_zone = pick("chest", "groin") + //Shooting Code: A.current = T A.starting = T diff --git a/code/game/machinery/turrets.dm b/code/game/machinery/turrets.dm index 3581c51e18..87edc01204 100644 --- a/code/game/machinery/turrets.dm +++ b/code/game/machinery/turrets.dm @@ -266,6 +266,15 @@ else A = new /obj/item/projectile/energy/electrode( loc ) use_power(200) + + //Turrets aim for the center of mass by default. + //If the target is grabbing someone then the turret smartly aims for extremities + var/obj/item/weapon/grab/G = locate() in target + if(G && G.state >= GRAB_NECK) //works because mobs are currently not allowed to upgrade to NECK if they are grabbing two people. + A.def_zone = pick("head", "l_hand", "r_hand", "l_foot", "r_foot", "l_arm", "r_arm", "l_leg", "r_leg") + else + A.def_zone = pick("chest", "groin") + A.current = T A.starting = T A.yo = U.y - T.y diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 2893b4f3a1..8f24a93c10 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -146,7 +146,7 @@ return - return -1 // the bullet/projectile goes through the target! Ie, you missed + return PROJECTILE_CONTINUE // the bullet/projectile goes through the target! // Small memory holder entity for transparent bullet holes diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm index 38caaa3230..67bf484f39 100644 --- a/code/game/objects/structures/girders.dm +++ b/code/game/objects/structures/girders.dm @@ -25,7 +25,7 @@ /obj/structure/girder/bullet_act(var/obj/item/projectile/Proj) //Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder) if(Proj.original != src && !prob(cover)) - return -1 //pass through + return PROJECTILE_CONTINUE //pass through //Tasers and the like should not damage girders. if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN)) diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 569a4eb3b9..5f5dcaa48a 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -94,7 +94,7 @@ passthrough = 1 if(passthrough) - . = -1 + . = PROJECTILE_CONTINUE damage = between(0, (damage - Proj.damage)*(Proj.damage_type == BRUTE? 0.4 : 1), 10) //if the bullet passes through then the grille avoids most of the damage src.health -= damage*0.2 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 29832ae1ec..0de5729ec9 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -10,9 +10,11 @@ emp_act /mob/living/carbon/human/bullet_act(var/obj/item/projectile/P, var/def_zone) - var/obj/item/organ/external/organ = get_organ(check_zone(def_zone)) - if(!organ) - return + def_zone = check_zone(def_zone) + if(!has_organ(def_zone)) + return PROJECTILE_FORCE_MISS //if they don't have the organ in question then the projectile just passes by. + + var/obj/item/organ/external/organ = get_organ() //Shields if(check_shields(P.damage, "the [P.name]")) @@ -37,7 +39,7 @@ emp_act // redirect the projectile P.redirect(new_x, new_y, curloc, src) - return -1 // complete projectile permutation + return PROJECTILE_CONTINUE // complete projectile permutation //Shrapnel if(P.can_embed()) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 0a716ded34..0911a22593 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -264,11 +264,11 @@ var/list/global/organ_rel_size = list( /proc/get_zone_with_miss_chance(zone, var/mob/target, var/miss_chance_mod = 0, var/ranged_attack=0) zone = check_zone(zone) - // you cannot miss if your target is prone or restrained - if(target.buckled || target.lying) - return zone - // if your target is being grabbed aggressively by someone you cannot miss either if(!ranged_attack) + // you cannot miss if your target is prone or restrained + if(target.buckled || target.lying) + return zone + // if your target is being grabbed aggressively by someone you cannot miss either for(var/obj/item/weapon/grab/G in target.grabbed_by) if(G.state >= GRAB_AGGRESSIVE) return zone diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index f13ad24287..6d8c40c16c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -165,14 +165,17 @@ //roll to-hit miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier, 0) - var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1)) - if(!hit_zone) + var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1 || original != target_mob)) //if the projectile hits a target we weren't originally aiming at then retain the chance to miss + + var/result = PROJECTILE_FORCE_MISS + if(hit_zone) + def_zone = hit_zone //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part + result = target_mob.bullet_act(src, def_zone) + + if(result == PROJECTILE_FORCE_MISS) visible_message("\The [src] misses [target_mob] narrowly!") return 0 - //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part - def_zone = hit_zone - //hit messages if(silenced) target_mob << "You've been hit in the [parse_zone(def_zone)] by \the [src]!" @@ -193,7 +196,7 @@ msg_admin_attack("UNKNOWN shot [target_mob] ([target_mob.ckey]) with \a [src] (JMP)") //sometimes bullet_act() will want the projectile to continue flying - if (target_mob.bullet_act(src, def_zone) == -1) + if (result == PROJECTILE_CONTINUE) return 0 return 1 @@ -227,7 +230,7 @@ else passthrough = 1 //so ghosts don't stop bullets else - passthrough = (A.bullet_act(src, def_zone) == -1) //backwards compatibility + passthrough = (A.bullet_act(src, def_zone) == PROJECTILE_CONTINUE) //backwards compatibility if(isturf(A)) for(var/obj/O in A) O.bullet_act(src) diff --git a/code/setup.dm b/code/setup.dm index 62fe99ac67..73d0f1611a 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -720,6 +720,10 @@ var/list/be_special_flags = list( #define FILE_DRM 16 // Some files want to not be copied/moved. This is them complaining that you tried. #define NETWORK_FAILURE 32 +// Special return values from bullet_act(). Positive return values are already used to indicate the blocked level of the projectile. +#define PROJECTILE_CONTINUE -1 //if the projectile should continue flying after calling bullet_act() +#define PROJECTILE_FORCE_MISS -2 //if the projectile should treat the attack as a miss (suppresses attack and admin logs) - only applies to mobs. + // Some on_mob_life() procs check for alien races. #define IS_DIONA 1 #define IS_VOX 2 diff --git a/html/changelogs/HarpyEagle-dev-freeze.yml b/html/changelogs/HarpyEagle-dev-freeze.yml index a999f1236d..d7bf101a08 100644 --- a/html/changelogs/HarpyEagle-dev-freeze.yml +++ b/html/changelogs/HarpyEagle-dev-freeze.yml @@ -1,3 +1,4 @@ author: HarpyEagle -changes: [] delete-after: false +changes: + - bugfix: "Fixed projectiles being able to hit people in body parts that they don't have. This will also mean that the less limbs someone has the less effective they will be as a body shield." \ No newline at end of file