From 5c44996ffb655633cf94b2c2a997ff5a451b65eb Mon Sep 17 00:00:00 2001 From: crazyraio2 <44246096+crazyraio2@users.noreply.github.com> Date: Tue, 18 Aug 2020 21:30:47 -0300 Subject: [PATCH] yeet, help me --- sandcode/code/_HELPERS/unsorted.dm | 12 + sandcode/code/__DEFINES/combat.dm | 6 + .../controllers/subsystem/bluespace_locker.dm | 69 +++++ .../code/game/area/Space_Station_13_areas.dm | 7 + .../closets/bluespace_locker.dm | 283 ++++++++++++++++++ sandcode/icons/obj/closet.dmi | Bin 0 -> 4290 bytes tgstation.dme | 5 + 7 files changed, 382 insertions(+) create mode 100644 sandcode/code/_HELPERS/unsorted.dm create mode 100644 sandcode/code/__DEFINES/combat.dm create mode 100644 sandcode/code/controllers/subsystem/bluespace_locker.dm create mode 100644 sandcode/code/game/area/Space_Station_13_areas.dm create mode 100644 sandcode/code/game/objects/structures/crates_lockers/closets/bluespace_locker.dm create mode 100644 sandcode/icons/obj/closet.dmi diff --git a/sandcode/code/_HELPERS/unsorted.dm b/sandcode/code/_HELPERS/unsorted.dm new file mode 100644 index 0000000000..945032216e --- /dev/null +++ b/sandcode/code/_HELPERS/unsorted.dm @@ -0,0 +1,12 @@ +//i have no idea what the difference is between this and get_turf() +/proc/get_turf_global(atom/A, recursion_limit = 5) + var/turf/T = get_turf(A) + if(!T) + return + if(recursion_limit <= 0) + return T + if(T.loc) + var/area/R = T.loc + if(R.global_turf_object) + return get_turf_global(R.global_turf_object, recursion_limit - 1) + return T diff --git a/sandcode/code/__DEFINES/combat.dm b/sandcode/code/__DEFINES/combat.dm new file mode 100644 index 0000000000..d7c1d86228 --- /dev/null +++ b/sandcode/code/__DEFINES/combat.dm @@ -0,0 +1,6 @@ +/*ALL DEFINES RELATED TO COMBAT GO HERE*/ + +//Actual combat defines + +//click cooldowns, in tenths of a second, used for various combat actions +#define CLICK_CD_BREAKOUT 100 diff --git a/sandcode/code/controllers/subsystem/bluespace_locker.dm b/sandcode/code/controllers/subsystem/bluespace_locker.dm new file mode 100644 index 0000000000..0412d6e82c --- /dev/null +++ b/sandcode/code/controllers/subsystem/bluespace_locker.dm @@ -0,0 +1,69 @@ +SUBSYSTEM_DEF(bluespace_locker) + name = "Bluespace Locker" + flags = SS_NO_FIRE + var/obj/structure/closet/bluespace/internal/internal_locker = null + var/obj/structure/closet/bluespace/external/external_locker = null + +/datum/controller/subsystem/bluespace_locker/Initialize() + bluespaceify_random_locker() + if(external_locker) + external_locker.take_contents() + return ..() + +/datum/controller/subsystem/bluespace_locker/proc/bluespaceify_random_locker() + if(external_locker) + return + // basically any normal-looking locker that isn't a secure one + var/list/valid_lockers = typecacheof(typesof(/obj/structure/closet) - typesof(/obj/structure/closet/body_bag)\ + - typesof(/obj/structure/closet/secure_closet) - typesof(/obj/structure/closet/cabinet)\ + - typesof(/obj/structure/closet/cardboard) - typesof(/obj/structure/closet/crate)\ + - typesof(/obj/structure/closet/supplypod) - typesof(/obj/structure/closet/stasis)\ + - typesof(/obj/structure/closet/abductor) - typesof(/obj/structure/closet/bluespace), only_root_path = TRUE) + + var/list/lockers_list = list() + for(var/obj/structure/closet/L in world) + if(is_station_level(L.z) && is_type_in_typecache(L, valid_lockers)) + lockers_list += L + if(!lockers_list.len) + // Congratulations, you managed to destroy all the lockers somehow. + // Now let's make a new one. + var/targetturf = find_safe_turf() + if(!targetturf) + if(GLOB.blobstart.len > 0) + targetturf = get_turf(pick(GLOB.blobstart)) + else + CRASH("Unable to find a blobstart landmark") + lockers_list += new /obj/structure/closet(targetturf) + var/obj/structure/closet/L = pick(lockers_list) + + var/obj/structure/closet/bluespace/external/E = new(L.loc) + E.contents = L.contents + E.name = L.name + E.desc = L.desc + if(L.opened) + E.open() + E.icon = L.icon + E.icon_state = L.icon_state + E.icon_door = L.icon_door + E.icon_door_override = L.icon_door_override + E.icon_welded = L.icon_welded + qdel(L) + + relink_lockers() + +/datum/controller/subsystem/bluespace_locker/proc/relink_lockers() + if(!internal_locker) + return + //var/area/A = get_area(internal_locker) + //A.global_turf_object = external_locker + internal_locker.update_mirage() + if(!external_locker) + return + if(external_locker.opened) + internal_locker.close() + else + internal_locker.contents += external_locker.contents + internal_locker.open() + internal_locker.dump_contents() + internal_locker.update_icon() + external_locker.update_icon() \ No newline at end of file diff --git a/sandcode/code/game/area/Space_Station_13_areas.dm b/sandcode/code/game/area/Space_Station_13_areas.dm new file mode 100644 index 0000000000..e278cb774c --- /dev/null +++ b/sandcode/code/game/area/Space_Station_13_areas.dm @@ -0,0 +1,7 @@ +/area/bluespace_locker + name = "Bluespace Locker" + icon_state = "away" + requires_power = FALSE + has_gravity = STANDARD_GRAVITY + noteleport = TRUE + hidden = TRUE diff --git a/sandcode/code/game/objects/structures/crates_lockers/closets/bluespace_locker.dm b/sandcode/code/game/objects/structures/crates_lockers/closets/bluespace_locker.dm new file mode 100644 index 0000000000..d1456979e4 --- /dev/null +++ b/sandcode/code/game/objects/structures/crates_lockers/closets/bluespace_locker.dm @@ -0,0 +1,283 @@ +/obj/structure/closet/bluespace + name = "bluespace locker" + +/obj/structure/closet/bluespace/proc/get_other_locker() + return SSbluespace_locker.internal_locker + +/obj/structure/closet/bluespace/open() + var/obj/structure/closet/other = get_other_locker() + if(!other) + return ..() + if(!opened) + . = ..() + other.close() + dump_contents() + +/obj/structure/closet/bluespace/close() + var/obj/structure/closet/other = get_other_locker() + if(!other) + return ..() + if(opened) + . = ..() + other.contents += contents + other.open() + +/obj/structure/closet/bluespace/internal + name = "bluespace locker portal" + icon_state = null + desc = "" + cutting_tool = null + can_weld_shut = FALSE + anchored = TRUE + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF + var/list/mirage_whitelist = list() + +/obj/structure/closet/bluespace/internal/Initialize() + if(SSbluespace_locker.internal_locker && SSbluespace_locker.internal_locker != src) + qdel(src) + return + SSbluespace_locker.internal_locker = src + ..() + +/obj/structure/closet/bluespace/internal/get_other_locker() + return SSbluespace_locker.external_locker + +/obj/structure/closet/bluespace/internal/can_open(user) + var/obj/structure/closet/other = get_other_locker() + if(!other) + return FALSE + if(!other.opened) + return TRUE + return other.can_close(user) +/obj/structure/closet/bluespace/internal/can_close(user) + var/obj/structure/closet/other = get_other_locker() + if(!other || other.opened) + return TRUE + return other.can_open(user) + +/obj/structure/closet/bluespace/internal/tool_interact(obj/item/W, mob/user) + return + +/obj/structure/closet/bluespace/internal/attack_hand(mob/living/user) + var/obj/structure/closet/other = get_other_locker() + if(!other) + return ..() + if(!other.opened && (other.welded || other.locked)) + if(ismovable(other.loc)) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + var/atom/movable/AM = other.loc + AM.relay_container_resist(user, other) + return + + //okay, so the closet is either welded or locked... resist!!! + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + other.visible_message("[other] begins to shake violently!") + to_chat(user, "You start pushing the door open... (this will take about [DisplayTimeText(other.breakout_time)].)") + if(do_after(user,(other.breakout_time), target = src)) + if(!user || user.stat != CONSCIOUS || other.opened || (!other.locked && !other.welded)) + return + //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting + other.bust_open() + user.visible_message("[user] successfully broke out of [other]!", + "You successfully break out of [other]!") + else + if(!other.opened) //so we don't get the message if we resisted multiple times and succeeded. + to_chat(user, "You fail to break out of [other]!") + else + return ..() + +/obj/structure/closet/bluespace/internal/update_icon() + cut_overlays() + var/obj/structure/closet/other = get_other_locker() + if(!other) + other = src + var/mutable_appearance/masked_icon = mutable_appearance('sandcode/icons/obj/closet.dmi', "bluespace_locker_mask") + masked_icon.appearance_flags = KEEP_TOGETHER + var/mutable_appearance/masking_icon = mutable_appearance(other.icon, other.icon_state) + masking_icon.blend_mode = BLEND_MULTIPLY + masked_icon.add_overlay(masking_icon) + //add_overlay(image('yogstation/icons/obj/closet.dmi', "bluespace_locker_frame")) + add_overlay(masked_icon) + if(!opened) + layer = OBJ_LAYER + if(other.icon_door) + add_overlay(image(other.icon, "[other.icon_door]_door")) + else + add_overlay(image(other.icon, "[other.icon_state]_door")) + else + layer = BELOW_OBJ_LAYER + if(other.icon_door_override) + add_overlay(image(other.icon, "[other.icon_door]_open")) + else + add_overlay(image(other.icon, "[other.icon_state]_open")) + +/obj/structure/closet/bluespace/external/onTransitZ(old_z,new_z) + var/obj/structure/closet/O = get_other_locker() + if(O) + var/area/A = get_area(O) + if(A) + for(var/atom/movable/M in A) + M.onTransitZ(old_z,new_z) + return ..() + +/obj/structure/closet/bluespace/internal/proc/update_mirage() + var/area/A = get_area(src) + for(var/atom/movable/M in A) + if(M == src) // in case someone somehow manages to teleport the bluespace locker inside of itself + continue + M.update_parallax_contents() + var/turf/internal_origin + var/turf/external_origin = get_turf(get_other_locker()) + for(var/obj/effect/landmark/bluespace_locker_origin/L in A) + internal_origin = get_turf(L) + break + mirage_whitelist.len = 0 + for(var/turf/T in view(11, external_origin)) + mirage_whitelist[T] = TRUE + for(var/turf/open/space/bluespace_locker_mirage/T in A) + T.internal_origin = internal_origin + T.external_origin = external_origin + T.turf_whitelist = mirage_whitelist + T.update_mirage() + +/obj/structure/closet/bluespace/external/Initialize() + if(SSbluespace_locker.external_locker && SSbluespace_locker.external_locker != src) + qdel(src) + return + SSbluespace_locker.external_locker = src + ..() + +/obj/structure/closet/bluespace/external/Destroy() + SSbluespace_locker.external_locker = null + SSbluespace_locker.bluespaceify_random_locker() + return ..() + +/obj/structure/closet/bluespace/external/can_open() + if(welded || locked) + return FALSE + return TRUE + +/obj/structure/closet/bluespace/external/can_close() + if(welded || locked) + return FALSE + return TRUE + + +/obj/structure/closet/bluespace/external/Moved() + var/obj/structure/closet/bluespace/internal/C = get_other_locker() + if(C) + C.update_mirage() + return ..() + +/obj/structure/closet/bluespace/external/afterShuttleMove() + var/obj/structure/closet/bluespace/internal/C = get_other_locker() + if(C) + C.update_mirage() + return ..() + +/obj/effect/landmark/bluespace_locker_origin + name = "bluespace locker origin" + +/turf/open/space/bluespace_locker_mirage + density = 1 + icon_state = "black" + blocks_air = 1 + name = "holographic projection" + desc = "A holographic projection of the area surrounding the bluespace locker" + flags_1 = NOJAUNT_1 + var/turf/internal_origin + var/turf/external_origin + var/turf/external_origin_prev + var/turf/external_origin_prev_prev + var/turf/external_origin_prev_time = -1 + var/list/turf_whitelist + var/reset_timer_id + +/turf/open/space/bluespace_locker_mirage/CanBuildHere() + return FALSE + +/turf/open/space/bluespace_locker_mirage/proc/update_mirage() + if(!internal_origin || !external_origin) + vis_contents = list() + return + if(external_origin == external_origin_prev) + return + if(world.time == external_origin_prev_time) + external_origin_prev = external_origin_prev_prev + cut_overlays() + var/glide_dir = 0 + if(external_origin_prev && external_origin_prev.z != external_origin && abs(external_origin.x - external_origin_prev.x) <= 1 && abs(external_origin.y - external_origin_prev.y) <= 1) + glide_dir = get_dir(external_origin_prev, external_origin) + var/turf/target_turf = locate(external_origin.x + x - internal_origin.x, external_origin.y + y - internal_origin.y, external_origin.z) + if(!target_turf || (turf_whitelist && !turf_whitelist[target_turf])) + vis_contents = list() + var/mutable_appearance/M = mutable_appearance('icons/turf/space.dmi', "black") + M.layer = TURF_LAYER + M.plane = FLOOR_PLANE + add_overlay(M) + else + vis_contents = list(target_turf) + if(glide_dir) + var/dx = 0 + var/dy = 0 + var/px = 0 + var/py = 0 + var/add_reset_timer + if(glide_dir & 1) + dy++ + if(glide_dir & 2) + dy-- + if(glide_dir & 4) + dx++ + if(glide_dir & 8) + dx-- + var/list/fullbrights = list() + var/area/A = target_turf.loc + if(!IS_DYNAMIC_LIGHTING(A)) + fullbrights += new /obj/effect/fullbright() + for(var/cdir in GLOB.cardinals) + if(!(glide_dir & cdir)) + continue + var/odir = turn(cdir, 180) + var/turf/T = get_step(src, odir) + if(T && T.type != /turf/open/space/bluespace_locker_mirage) + vis_contents += get_step(target_turf, odir) + add_reset_timer = TRUE + if(odir == 8) + px = -32 + if(odir == 2) + py = -32 + A = target_turf.loc + if(!IS_DYNAMIC_LIGHTING(A)) + var/obj/effect/fullbright/F = new() + switch(odir) + if(1) + F.pixel_y = 32 + if(2) + F.pixel_y = -32 + if(4) + F.pixel_x = 32 + if(8) + F.pixel_x = -32 + fullbrights += F + for(var/V in fullbrights) + var/obj/F = V + F.pixel_x -= px // cancel out the pixel_x/y in the parent + F.pixel_y -= py + add_overlay(fullbrights) + if(add_reset_timer) + reset_timer_id = addtimer(CALLBACK(src, /turf/open/space/bluespace_locker_mirage.proc/reset_to_self), world.tick_lag * 4, TIMER_UNIQUE | TIMER_NO_HASH_WAIT | TIMER_OVERRIDE | TIMER_STOPPABLE) + else if(reset_timer_id) + deltimer(reset_timer_id) + pixel_x = px + dx*32 + pixel_y = py + dy*32 + animate(src, pixel_x = px, pixel_y = py, time = world.tick_lag * 4, flags = ANIMATION_END_NOW) + external_origin_prev_time = world.time + external_origin_prev_prev = external_origin_prev + external_origin_prev = external_origin + +/turf/open/space/bluespace_locker_mirage/proc/reset_to_self() + reset_timer_id = null + update_mirage() diff --git a/sandcode/icons/obj/closet.dmi b/sandcode/icons/obj/closet.dmi new file mode 100644 index 0000000000000000000000000000000000000000..d4c17819462f8b6181575ea0d00897970835fb89 GIT binary patch literal 4290 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