diff --git a/aurorastation.dme b/aurorastation.dme index e2027aadcd7..7bf0701e296 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -307,6 +307,7 @@ #include "code\datums\observation\_debug.dm" #include "code\datums\observation\destroyed.dm" #include "code\datums\observation\equipped.dm" +#include "code\datums\observation\helpers.dm" #include "code\datums\observation\moved.dm" #include "code\datums\observation\observation.dm" #include "code\datums\observation\see_in_dark_set.dm" diff --git a/code/__defines/_layers.dm b/code/__defines/_layers.dm index 44011bcee2e..a018e75bff0 100644 --- a/code/__defines/_layers.dm +++ b/code/__defines/_layers.dm @@ -11,6 +11,7 @@ #define CABLE_LAYER 2.44 #define ABOVE_CABLE_LAYER (CABLE_LAYER + 0.1) #define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6 +#define ABOVE_OBJ_LAYER 3.01 #define UNDERDOOR 3.09 //Just barely under a closed door. #define DOOR_CLOSED_LAYER 3.1 //Above most items if closed #define BELOW_MOB_LAYER 3.7 diff --git a/code/datums/observation/helpers.dm b/code/datums/observation/helpers.dm new file mode 100644 index 00000000000..298896b5693 --- /dev/null +++ b/code/datums/observation/helpers.dm @@ -0,0 +1,14 @@ +/atom/movable/proc/move_to_turf(var/atom/movable/am, var/old_loc, var/new_loc) + var/turf/T = get_turf(new_loc) + if(T && T != loc) + forceMove(T) + +// Similar to above but we also follow into nullspace +/atom/movable/proc/move_to_turf_or_null(var/atom/movable/am, var/old_loc, var/new_loc) + var/turf/T = get_turf(new_loc) + if(T != loc) + forceMove(T) + +/atom/movable/proc/move_to_loc_or_null(var/atom/movable/am, var/old_loc, var/new_loc) + if(new_loc != loc) + forceMove(new_loc) \ No newline at end of file diff --git a/code/game/objects/items/shooting_range.dm b/code/game/objects/items/shooting_range.dm index 2126940f2ef..62c4f20c01a 100644 --- a/code/game/objects/items/shooting_range.dm +++ b/code/game/objects/items/shooting_range.dm @@ -1,115 +1,76 @@ +#define DECAL_SCORCH 1 +#define DECAL_BULLET 2 + // Targets, the things that actually get shot! /obj/item/target name = "shooting target" desc = "A shooting target." icon = 'icons/obj/target_stake.dmi' icon_state = "target_h" - density = 0 + var/obj/structure/target_stake/stake var/hp = 1800 - var/icon/virtualIcon - var/list/bulletholes = list() + var/icon/virtual_icon + var/list/bullet_holes - Destroy() - // if a target is deleted and associated with a stake, force stake to forget - for(var/obj/structure/target_stake/T in view(3,src)) - if(T.pinned_target == src) - T.pinned_target = null - T.density = 1 - break - return ..() // delete target +/obj/item/target/Destroy() + if(stake) + stake.set_target(null) + return ..() - Move() - ..() - // After target moves, check for nearby stakes. If associated, move to target - for(var/obj/structure/target_stake/M in view(3,src)) - if(M.density == 0 && M.pinned_target == src) - M.forceMove(loc) +/obj/item/target/attackby(var/obj/item/W, var/mob/user) + if(W.iswelder()) + if(hp == initial(hp)) + to_chat(user, SPAN_NOTICE("\The [src] is fully repaired.")) + return + var/obj/item/weldingtool/WT = W + if(WT.remove_fuel(0, user)) + cut_overlays() + LAZYCLEARLIST(bullet_holes) + icon = initial(icon) + hp = initial(hp) + to_chat(user, SPAN_NOTICE("You slice off \the [src]'s uneven chunks of steel and scorch marks.")) + return - // This may seem a little counter-intuitive but I assure you that's for a purpose. - // Stakes are the ones that carry targets, yes, but in the stake code we set - // a stake's density to 0 meaning it can't be pushed anymore. Instead of pushing - // the stake now, we have to push the target. +/obj/item/target/attack_hand(var/mob/user) + // taking pinned targets off! + if(stake) + stake.attack_hand(user) + else + return ..() +/obj/item/target/syndicate + icon_state = "target_s" + desc = "A shooting target that looks like a hostile agent." + hp = 2600 // i guess syndie targets are sturdier? - - attackby(obj/item/W as obj, mob/user as mob) - if (W.iswelder()) - var/obj/item/weldingtool/WT = W - if(WT.remove_fuel(0, user)) - cut_overlays() - to_chat(usr, "You slice off [src]'s uneven chunks of aluminum and scorch marks.") - return - - - attack_hand(mob/user as mob) - // taking pinned targets off! - var/obj/structure/target_stake/stake - for(var/obj/structure/target_stake/T in view(3,src)) - if(T.pinned_target == src) - stake = T - break - - if(stake) - if(stake.pinned_target) - stake.density = 1 - density = 0 - layer = OBJ_LAYER - - loc = user.loc - if(ishuman(user)) - if(!user.get_active_hand()) - user.put_in_hands(src) - to_chat(user, "You take the target out of the stake.") - else - src.forceMove(get_turf(user)) - to_chat(user, "You take the target out of the stake.") - - stake.pinned_target = null - return - - else - ..() - - syndicate - icon_state = "target_s" - desc = "A shooting target that looks like a hostile agent." - hp = 2600 // i guess syndie targets are sturdier? - alien - icon_state = "target_q" - desc = "A shooting target with a threatening silhouette." - hp = 2350 // alium onest too kinda +/obj/item/target/alien + icon_state = "target_q" + desc = "A shooting target with a threatening silhouette." + hp = 2350 // alium onest too kinda /obj/item/target/bullet_act(var/obj/item/projectile/Proj) var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!" var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1) - var/decaltype = 1 // 1 - scorch, 2 - bullet + var/decaltype = (Proj.damage_flags & DAM_BULLET) ? DECAL_BULLET : DECAL_SCORCH - if(istype(/obj/item/projectile/bullet, Proj)) - decaltype = 2 - - - virtualIcon = new(icon, icon_state) - - if( virtualIcon.GetPixel(p_x, p_y) ) // if the located pixel isn't blank (null) + virtual_icon = new(icon, icon_state) + if(virtual_icon.GetPixel(p_x, p_y)) // if the located pixel isn't blank (null) hp -= Proj.damage if(hp <= 0) - for(var/mob/O in oviewers()) - if ((O.client && !( O.blinded ))) - to_chat(O, "\The [src] breaks into tiny pieces and collapses!") + visible_message(SPAN_WARNING("\The [src] breaks into tiny pieces and collapses!")) qdel(src) + return // Create a temporary object to represent the damage var/obj/bmark = new bmark.pixel_x = p_x bmark.pixel_y = p_y bmark.icon = 'icons/effects/effects.dmi' - bmark.layer = 3.5 + bmark.layer = ABOVE_OBJ_LAYER bmark.icon_state = "scorch" - if(decaltype == 1) - // Energy weapons are hot. they scorch! - + if(decaltype == DECAL_SCORCH) // Energy weapons are hot. they scorch! // offset correction bmark.pixel_x-- bmark.pixel_y-- @@ -117,33 +78,27 @@ if(Proj.damage >= 20 || istype(Proj, /obj/item/projectile/beam/practice)) bmark.icon_state = "scorch" bmark.set_dir(pick(NORTH,SOUTH,EAST,WEST)) // random scorch design - - else bmark.icon_state = "light_scorch" - else - - // Bullets are hard. They make dents! + else // Bullets are hard. They make dents! bmark.icon_state = "dent" - if(Proj.damage >= 10 && bulletholes.len <= 35) // maximum of 35 bullet holes - if(decaltype == 2) // bullet + if(Proj.damage >= 10 && length(bullet_holes) <= 35) // maximum of 35 bullet holes + if(decaltype == DECAL_BULLET) if(prob(Proj.damage+30)) // bullets make holes more commonly! - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole + new /datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole else // Lasers! if(prob(Proj.damage-10)) // lasers make holes less commonly - new/datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole + new /datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole // draw bullet holes - for(var/datum/bullethole/B in bulletholes) + for(var/datum/bullethole/B in bullet_holes) + virtual_icon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right + virtual_icon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom - virtualIcon.DrawBox(null, B.b1x1, B.b1y, B.b1x2, B.b1y) // horizontal line, left to right - virtualIcon.DrawBox(null, B.b2x, B.b2y1, B.b2x, B.b2y2) // vertical line, top to bottom add_overlay(bmark) // add the decal - - icon = virtualIcon // apply bulletholes over decals - + icon = virtual_icon // apply bullet_holes over decals return return PROJECTILE_CONTINUE // the bullet/projectile goes through the target! @@ -161,21 +116,25 @@ var/b2y1 = 0 var/b2y2 = 0 - New(var/obj/item/target/Target, var/pixel_x = 0, var/pixel_y = 0) - if(!Target) return +/datum/bullethole/New(var/obj/item/target/Target, var/pixel_x = 0, var/pixel_y = 0) + if(!Target) + return - // Randomize the first box - b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4) - b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4) - b1y = pixel_y - if(prob(35)) - b1y += rand(-4,4) + // Randomize the first box + b1x1 = pixel_x - pick(1,1,1,1,2,2,3,3,4) + b1x2 = pixel_x + pick(1,1,1,1,2,2,3,3,4) + b1y = pixel_y + if(prob(35)) + b1y += rand(-4,4) - // Randomize the second box - b2x = pixel_x - if(prob(35)) - b2x += rand(-4,4) - b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4) - b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4) + // Randomize the second box + b2x = pixel_x + if(prob(35)) + b2x += rand(-4,4) + b2y1 = pixel_y + pick(1,1,1,1,2,2,3,3,4) + b2y2 = pixel_y - pick(1,1,1,1,2,2,3,3,4) - Target.bulletholes.Add(src) + LAZYADD(Target.bullet_holes, src) + +#undef DECAL_SCORCH +#undef DECAL_BULLET \ No newline at end of file diff --git a/code/game/objects/structures/target_stake.dm b/code/game/objects/structures/target_stake.dm index f9bcd547088..dbfa15da412 100644 --- a/code/game/objects/structures/target_stake.dm +++ b/code/game/objects/structures/target_stake.dm @@ -1,53 +1,62 @@ -// Basically they are for the firing range +// Target stakes for the firing range. /obj/structure/target_stake name = "target stake" desc = "A thin platform with negatively-magnetized wheels." icon = 'icons/obj/target_stake.dmi' icon_state = "target_stake" - density = 1 - w_class = ITEMSIZE_HUGE - flags = CONDUCT - var/obj/item/target/pinned_target // the current pinned target + density = TRUE + w_class = ITEMSIZE_IMMENSE + build_amt = 10 + var/obj/item/target/pinned_target - Move() - ..() - // Move the pinned target along with the stake - if(pinned_target in view(3, src)) - pinned_target.forceMove(loc) +/obj/structure/target_stake/Initialize(mapload) + . = ..() + material = SSmaterials.get_material_by_name(MATERIAL_STEEL) - else // Sanity check: if the pinned target can't be found in immediate view - pinned_target = null - density = 1 - - attackby(obj/item/W as obj, mob/user as mob) - // Putting objects on the stake. Most importantly, targets +/obj/structure/target_stake/attackby(var/obj/item/W, var/mob/user) + if(istype(W, /obj/item/target)) if(pinned_target) - return // get rid of that pinned target first! - - if(istype(W, /obj/item/target)) - density = 0 - W.density = 1 - user.remove_from_mob(W) - W.forceMove(loc) - W.layer = 3.1 - pinned_target = W - to_chat(user, "You slide the target into the stake.") + to_chat(user, SPAN_WARNING("\The [src] already has a target.")) + return + if(user.unEquip(W, FALSE, get_turf(src))) + to_chat(user, SPAN_NOTICE("You slide \the [W] into the stake.")) + set_target(W) return - - attack_hand(mob/user as mob) - // taking pinned targets off! + if(W.iswrench()) if(pinned_target) - density = 1 - pinned_target.density = 0 + to_chat(user, SPAN_WARNING("You cannot dismantle \the [src] while it has a target attached.")) + return + dismantle() + +/obj/structure/target_stake/attack_hand(var/mob/user) + . = ..() + if(pinned_target && ishuman(user)) + var/obj/item/target/T = pinned_target + to_chat(user, SPAN_NOTICE("You take \the [T] out of the stake.")) + set_target(null) + user.put_in_hands(T) + +/obj/structure/target_stake/proc/set_target(var/obj/item/target/T) + if(T) + density = FALSE + T.density = TRUE + T.pixel_x = 0 + T.pixel_y = 0 + T.layer = ABOVE_OBJ_LAYER + moved_event.register(T, src, /atom/movable/proc/move_to_turf) + moved_event.register(src, T, /atom/movable/proc/move_to_turf) + T.stake = src + pinned_target = T + else + density = TRUE + if(pinned_target) + pinned_target.density = FALSE pinned_target.layer = OBJ_LAYER + moved_event.unregister(pinned_target, src) + moved_event.unregister(src, pinned_target) + pinned_target.stake = null + pinned_target = null - pinned_target.forceMove(user.loc) - if(ishuman(user)) - if(!user.get_active_hand()) - user.put_in_hands(pinned_target) - to_chat(user, "You take the target out of the stake.") - else - pinned_target.forceMove(get_turf(user)) - to_chat(user, "You take the target out of the stake.") - - pinned_target = null +/obj/structure/target_stake/Destroy() + set_target(null) + return ..() \ No newline at end of file diff --git a/code/modules/materials/material_recipes.dm b/code/modules/materials/material_recipes.dm index 89aa8d138ef..043b557632e 100644 --- a/code/modules/materials/material_recipes.dm +++ b/code/modules/materials/material_recipes.dm @@ -67,6 +67,8 @@ new /datum/stack_recipe("custodial cart", /obj/structure/janitorialcart, BUILD_AMT, time = 120, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("closet", /obj/structure/closet, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("canister", /obj/machinery/portable_atmospherics/canister, 10, time = 15, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("target stake", /obj/structure/target_stake, BUILD_AMT, time = 15, one_per_turf = 1, on_floor = 1), + new /datum/stack_recipe("shooting target", /obj/item/target, 5, time = 10, one_per_turf = 0, on_floor = 1), new /datum/stack_recipe("dark office chair", /obj/structure/bed/chair/office/dark, BUILD_AMT, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("light office chair", /obj/structure/bed/chair/office/light, BUILD_AMT, one_per_turf = 1, on_floor = 1), new /datum/stack_recipe("plain comfy chair", /obj/structure/bed/chair/comfy, BUILD_AMT, one_per_turf = 1, on_floor = 1), diff --git a/html/changelogs/geeves-shooting_target_refactor.yml b/html/changelogs/geeves-shooting_target_refactor.yml new file mode 100644 index 00000000000..1ba536a283b --- /dev/null +++ b/html/changelogs/geeves-shooting_target_refactor.yml @@ -0,0 +1,8 @@ +author: Geeves + +delete-after: True + +changes: + - refactor: "Refactored shooting targets, they should now work a little more sanely." + - rscadd: "You can now construct shooting targets and target stakes out of steel in the Misc construction category." + - rscadd: "You can now deconstruct target stakes with a wrench." \ No newline at end of file