diff --git a/code/datums/components/deadchat_control.dm b/code/datums/components/deadchat_control.dm index 6940caeb609..07a77299690 100644 --- a/code/datums/components/deadchat_control.dm +++ b/code/datums/components/deadchat_control.dm @@ -189,3 +189,20 @@ inputs["down"] = CALLBACK(GLOBAL_PROC, .proc/_step, parent, SOUTH) inputs["left"] = CALLBACK(GLOBAL_PROC, .proc/_step, parent, WEST) inputs["right"] = CALLBACK(GLOBAL_PROC, .proc/_step, parent, EAST) + +/** + * Deadchat Moves Things + * + * A special variant of the deadchat_control component that comes pre-baked with all the hottest inputs for spicy + * immovable rod. + */ +/datum/component/deadchat_control/immovable_rod/Initialize(_deadchat_mode, _inputs, _input_cooldown, _on_removal) + if(!istype(parent, /obj/effect/immovablerod)) + return COMPONENT_INCOMPATIBLE + + . = ..() + + inputs["up"] = CALLBACK(parent, /obj/effect/immovablerod.proc/walk_in_direction, NORTH) + inputs["down"] = CALLBACK(parent, /obj/effect/immovablerod.proc/walk_in_direction, SOUTH) + inputs["left"] = CALLBACK(parent, /obj/effect/immovablerod.proc/walk_in_direction, WEST) + inputs["right"] = CALLBACK(parent, /obj/effect/immovablerod.proc/walk_in_direction, EAST) diff --git a/code/modules/admin/smites/rod.dm b/code/modules/admin/smites/rod.dm index 6c4b50b2688..4797b3ab97e 100644 --- a/code/modules/admin/smites/rod.dm +++ b/code/modules/admin/smites/rod.dm @@ -1,6 +1,12 @@ /// Throw an immovable rod at the target /datum/smite/rod name = "Immovable Rod" + var/force_looping = FALSE + +/datum/smite/rod/configure(client/user) + var/loop_input = alert("Would you like this rod to force-loop across space z-levels?", "Loopy McLoopface", "Yes", "No") + + force_looping = (loop_input == "Yes") /datum/smite/rod/effect(client/user, mob/living/target) . = ..() @@ -8,4 +14,4 @@ var/startside = pick(GLOB.cardinals) var/turf/start_turf = spaceDebrisStartLoc(startside, target_turf.z) var/turf/end_turf = spaceDebrisFinishLoc(startside, target_turf.z) - new /obj/effect/immovablerod(start_turf, end_turf, target) + new /obj/effect/immovablerod(start_turf, end_turf, target, force_looping) diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index bb90502c9a2..0d3678201c3 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -13,17 +13,20 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 min_players = 15 max_occurrences = 5 var/atom/special_target - + var/force_looping = FALSE /datum/round_event_control/immovable_rod/admin_setup() if(!check_rights(R_FUN)) return - var/aimed = alert("Aimed at current location?","Sniperod", "Yes", "No") + var/aimed = alert("Aimed at current location?", "Sniperod", "Yes", "No") if(aimed == "Yes") special_target = get_turf(usr) - message_admins("[key_name_admin(usr)] has aimed an immovable rod at [AREACOORD(special_target)].") - log_admin("[key_name_admin(usr)] has aimed an immovable rod at [AREACOORD(special_target)].") + var/looper = alert("Would you like this rod to force-loop across space z-levels?", "Loopy McLoopface", "Yes", "No") + if(looper == "Yes") + force_looping = TRUE + message_admins("[key_name_admin(usr)] has aimed an immovable rod [force_looping ? "(forced looping)" : ""] at [AREACOORD(special_target)].") + log_admin("[key_name_admin(usr)] has aimed an immovable rod [force_looping ? "(forced looping)" : ""] at [AREACOORD(special_target)].") /datum/round_event/immovable_rod announceWhen = 5 @@ -36,7 +39,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 var/startside = pick(GLOB.cardinals) var/turf/endT = get_edge_target_turf(get_random_station_turf(), turn(startside, 180)) var/turf/startT = spaceDebrisStartLoc(startside, endT.z) - var/atom/rod = new /obj/effect/immovablerod(startT, endT, C.special_target) + var/atom/rod = new /obj/effect/immovablerod(startT, endT, C.special_target, C.force_looping) C.special_target = null //Cleanup for future event rolls. announce_to_ghosts(rod) @@ -68,13 +71,16 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 var/num_sentient_people_hit = 0 /// The rod levels up with each kill, increasing in size and auto-renaming itself. var/dnd_style_level_up = TRUE + /// Whether the rod can loop across other z-levels. The rod will still loop when the z-level is self-looping even if this is FALSE. + var/loopy_rod = FALSE -/obj/effect/immovablerod/New(atom/start, atom/end, aimed_at) +/obj/effect/immovablerod/New(atom/start, atom/end, aimed_at, force_looping) . = ..() SSaugury.register_doom(src, 2000) destination = end special_target = aimed_at + loopy_rod = force_looping AddElement(/datum/element/point_of_interest) @@ -109,7 +115,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 if(loc.density) Bump(loc) - // So, we're phasing as will harmlessly glide through things. Let's noogie everything in our loc's contents. + // So, we're phasing and will harmlessly glide through things. Let's noogie everything in our loc's contents. for(var/clong in loc.contents) if(clong == src) continue @@ -148,10 +154,13 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 if(destination) var/turf/target_turf = get_turf(destination) - // Note: There is no way to detect if this is because it spawned off the primary station - // z-level with a destination on the primary station z-level. As a result, maps with - // multiple station z-levels may find their immovable rods immediately deleting themselves. + // If the rod is a loopy_rod, run complete_trajectory() to get a new edge turf to fly to. + // Otherwise, qdel the rod. if(target_turf.z != z) + if(loopy_rod) + complete_trajectory() + return + qdel(src) return @@ -167,8 +176,7 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 /obj/effect/immovablerod/proc/complete_trajectory() // We hit what we wanted to hit, time to go. special_target = null - destination = get_edge_target_turf(src, dir) - walk_towards(src, destination, 1) + walk_in_direction(dir) /obj/effect/immovablerod/singularity_act() return @@ -269,3 +277,40 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 qdel(src) return TRUE + +/* Below are a couple of admin helper procs when dealing with immovable rod memes. */ +/** + * Stops your rod's automated movement. Sit... Stay... Good rod! + */ +/obj/effect/immovablerod/proc/sit_stay_good_rod() + walk(src, 0) + +/** + * Allows your rod to release restraint level zero and go for a walk. + * + * If walkies_location is set, rod will walk_towards the location, chasing it across z-levels if necessary. + * If walkies_location is not set, rod will call complete_trajectory() and follow the logic from that proc. + * + * Arguments: + * * walkies_location - Any atom that the immovable rod will now chase down as a special target. + */ +/obj/effect/immovablerod/proc/go_for_a_walk(walkies_location = null) + if(walkies_location) + special_target = walkies_location + walk_towards(src, special_target, 1) + return + + complete_trajectory() + +/obj/effect/immovablerod/deadchat_plays(mode = DEMOCRACY_MODE, cooldown = 6 SECONDS) + return AddComponent(/datum/component/deadchat_control/immovable_rod, mode, list(), cooldown) + +/** + * Rod will walk towards edge turf in the specified direction. + * + * Arguments: + * * direction - The direction to walk the rod towards: NORTH, SOUTH, EAST, WEST. + */ +/obj/effect/immovablerod/proc/walk_in_direction(direction) + destination = get_edge_target_turf(src, direction) + walk_towards(src, destination, 1)