From 167549065229a5272a32c145e5beb702aa02806d Mon Sep 17 00:00:00 2001 From: Jordan Brown Date: Mon, 30 Apr 2018 22:16:47 -0400 Subject: [PATCH] Modifies component transfer to make ChangeTurf able to transfer components --- code/__DEFINES/components.dm | 3 + code/datums/components/_component.dm | 36 ++-- code/datums/components/decal.dm | 8 +- code/datums/components/lockon_aiming.dm | 4 +- code/datums/components/mirage_border.dm | 9 +- .../components/storage/concrete/_concrete.dm | 199 ++++++++++++++++++ code/datums/components/storage/storage.dm | 2 +- code/datums/components/wet_floor.dm | 10 +- code/game/turfs/change_turf.dm | 11 +- 9 files changed, 253 insertions(+), 29 deletions(-) diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 67a44bbe01..512e2cc4d9 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -72,6 +72,9 @@ #define COMSIG_AREA_ENTERED "area_entered" //from base of area/Entered(): (atom/movable/M) #define COMSIG_AREA_EXITED "area_exited" //from base of area/Exited(): (atom/movable/M) +// /turf signals +#define COMSIG_TURF_CHANGE "turf_change" //from base of turf/ChangeTurf(): (path, list/new_baseturfs, flags, list/transferring_comps) + // /atom/movable signals #define COMSIG_MOVABLE_MOVED "movable_moved" //from base of atom/movable/Moved(): (/atom, dir) #define COMSIG_MOVABLE_CROSSED "movable_crossed" //from base of atom/movable/Crossed(): (/atom/movable) diff --git a/code/datums/components/_component.dm b/code/datums/components/_component.dm index 4076918ecf..6ec3f6f81e 100644 --- a/code/datums/components/_component.dm +++ b/code/datums/components/_component.dm @@ -101,7 +101,10 @@ /datum/component/proc/InheritComponent(datum/component/C, i_am_original) return -/datum/component/proc/OnTransfer(datum/new_parent) +/datum/component/proc/PreTransfer() + return + +/datum/component/proc/PostTransfer() return /datum/component/proc/_GetInverseTypeList(our_type = type) @@ -225,23 +228,26 @@ if(!.) return AddComponent(arglist(args)) -/datum/proc/TakeComponent(datum/component/C) - if(!C) +/datum/component/proc/RemoveComponent() + if(!parent) return - var/datum/helicopter = C.parent - if(helicopter == src) - //if we're taking to the same thing no need for anything + var/datum/old_parent = parent + PreTransfer() + _RemoveFromParent() + old_parent.SendSignal(COMSIG_COMPONENT_REMOVING, src) + +/datum/proc/TakeComponent(datum/component/target) + if(!target) return - if(C.OnTransfer(src) == COMPONENT_INCOMPATIBLE) - var/c_type = C.type - qdel(C) + if(target.parent) + target.RemoveComponent() + target.parent = src + if(target.PostTransfer() == COMPONENT_INCOMPATIBLE) + var/c_type = target.type + qdel(target) CRASH("Incompatible [c_type] transfer attempt to a [type]!") - return - C._RemoveFromParent() - helicopter.SendSignal(COMSIG_COMPONENT_REMOVING, C) - C.parent = src - if(C == AddComponent(C)) - C._JoinParent() + if(target == AddComponent(target)) + target._JoinParent() /datum/proc/TransferComponents(datum/target) var/list/dc = datum_components diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm index 0d8613bd86..8ee3d6d388 100644 --- a/code/datums/components/decal.dm +++ b/code/datums/components/decal.dm @@ -23,10 +23,12 @@ remove() return ..() -/datum/component/decal/OnTransfer(atom/thing) +/datum/component/decal/PreTransfer() remove() - remove(thing) - apply(thing) + +/datum/component/decal/PostTransfer() + remove() + apply() /datum/component/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color) if(!_icon || !_icon_state) diff --git a/code/datums/components/lockon_aiming.dm b/code/datums/components/lockon_aiming.dm index 02dfb8eaa0..cc41e793ed 100644 --- a/code/datums/components/lockon_aiming.dm +++ b/code/datums/components/lockon_aiming.dm @@ -238,5 +238,5 @@ cd++ CHECK_TICK -/datum/component/lockon_aiming/OnTransfer(datum/new_parent) - CRASH("Warning: Lockon aiming component transfer attempted, but transfer behavior is not implemented!") +/datum/component/lockon_aiming/PostTransfer(datum/new_parent) + return COMPONENT_INCOMPATIBLE diff --git a/code/datums/components/mirage_border.dm b/code/datums/components/mirage_border.dm index 41b22b231c..f91c5c8965 100644 --- a/code/datums/components/mirage_border.dm +++ b/code/datums/components/mirage_border.dm @@ -27,10 +27,13 @@ QDEL_NULL(holder) return ..() -/datum/component/mirage_border/OnTransfer(atom/thing) - if(!isturf(thing)) +/datum/component/mirage_border/PreTransfer() + holder.moveToNullspace() + +/datum/component/mirage_border/PostTransfer() + if(!isturf(parent)) return COMPONENT_INCOMPATIBLE - holder.forceMove(thing) + holder.forceMove(parent) /obj/effect/abstract/mirage_holder name = "Mirage holder" diff --git a/code/datums/components/storage/concrete/_concrete.dm b/code/datums/components/storage/concrete/_concrete.dm index 54b3fa031e..843280f947 100644 --- a/code/datums/components/storage/concrete/_concrete.dm +++ b/code/datums/components/storage/concrete/_concrete.dm @@ -1,3 +1,4 @@ +<<<<<<< HEAD // External storage-related logic: // /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages @@ -183,3 +184,201 @@ for(var/i in slaves) var/datum/component/storage/slave = i slave.update_icon() +======= + +// External storage-related logic: +// /mob/proc/ClickOn() in /_onclick/click.dm - clicking items in storages +// /mob/living/Move() in /modules/mob/living/living.dm - hiding storage boxes on mob movement + +/datum/component/storage/concrete + var/drop_all_on_deconstruct = TRUE + var/drop_all_on_destroy = FALSE + var/transfer_contents_on_component_transfer = FALSE + var/list/datum/component/storage/slaves = list() + + var/list/_contents_limbo // Where objects go to live mid transfer + var/list/_user_limbo // The last users before the component started moving + +/datum/component/storage/concrete/Initialize() + . = ..() + RegisterSignal(COMSIG_ATOM_CONTENTS_DEL, .proc/on_contents_del) + RegisterSignal(COMSIG_OBJ_DECONSTRUCT, .proc/on_deconstruct) + +/datum/component/storage/concrete/Destroy() + var/atom/real_location = real_location() + for(var/atom/_A in real_location) + _A.mouse_opacity = initial(_A.mouse_opacity) + if(drop_all_on_destroy) + do_quick_empty() + for(var/i in slaves) + var/datum/component/storage/slave = i + slave.change_master(null) + QDEL_LIST(_contents_limbo) + _user_limbo = null + return ..() + +/datum/component/storage/concrete/master() + return src + +/datum/component/storage/concrete/real_location() + return parent + +/datum/component/storage/concrete/PreTransfer() + if(is_using) + _user_limbo = is_using.Copy() + close_all() + if(transfer_contents_on_component_transfer) + _contents_limbo = list() + for(var/atom/movable/AM in parent) + _contents_limbo += AM + AM.moveToNullspace() + +/datum/component/storage/concrete/PostTransfer() + if(!isatom(parent)) + return COMPONENT_INCOMPATIBLE + if(transfer_contents_on_component_transfer) + for(var/i in _contents_limbo) + var/atom/movable/AM = i + AM.forceMove(parent) + _contents_limbo = null + if(_user_limbo) + for(var/i in _user_limbo) + show_to(i) + _user_limbo = null + +/datum/component/storage/concrete/_insert_physical_item(obj/item/I, override = FALSE) + . = TRUE + var/atom/real_location = real_location() + if(I.loc != real_location) + I.forceMove(real_location) + refresh_mob_views() + +/datum/component/storage/concrete/refresh_mob_views() + . = ..() + for(var/i in slaves) + var/datum/component/storage/slave = i + slave.refresh_mob_views() + +/datum/component/storage/concrete/emp_act(severity) + var/atom/real_location = real_location() + for(var/i in real_location) + var/atom/A = i + A.emp_act(severity) + +/datum/component/storage/concrete/proc/on_slave_link(datum/component/storage/S) + if(S == src) + return FALSE + slaves += S + return TRUE + +/datum/component/storage/concrete/proc/on_slave_unlink(datum/component/storage/S) + slaves -= S + return FALSE + +/datum/component/storage/concrete/proc/on_contents_del(atom/A) + var/atom/real_location = parent + if(A in real_location) + usr = null + remove_from_storage(A, null) + +/datum/component/storage/concrete/proc/on_deconstruct(disassembled) + if(drop_all_on_deconstruct) + do_quick_empty() + +/datum/component/storage/concrete/can_see_contents() + . = ..() + for(var/i in slaves) + var/datum/component/storage/slave = i + . |= slave.can_see_contents() + +//Resets screen loc and other vars of something being removed from storage. +/datum/component/storage/concrete/_removal_reset(atom/movable/thing) + thing.layer = initial(thing.layer) + thing.plane = initial(thing.plane) + thing.mouse_opacity = initial(thing.mouse_opacity) + if(thing.maptext) + thing.maptext = "" + +/datum/component/storage/concrete/remove_from_storage(atom/movable/AM, atom/new_location) + //Cache this as it should be reusable down the bottom, will not apply if anyone adds a sleep to dropped + //or moving objects, things that should never happen + var/atom/parent = src.parent + var/list/seeing_mobs = can_see_contents() + for(var/mob/M in seeing_mobs) + M.client.screen -= AM + if(ismob(parent.loc) && isitem(AM)) + var/obj/item/I = AM + var/mob/M = parent.loc + I.dropped(M) + if(new_location) + //Reset the items values + _removal_reset(AM) + AM.forceMove(new_location) + //We don't want to call this if the item is being destroyed + AM.on_exit_storage(src) + else + //Being destroyed, just move to nullspace now (so it's not in contents for the icon update) + AM.moveToNullspace() + refresh_mob_views() + if(isobj(parent)) + var/obj/O = parent + O.update_icon() + return TRUE + +/datum/component/storage/concrete/proc/slave_can_insert_object(datum/component/storage/slave, obj/item/I, stop_messages = FALSE, mob/M) + return TRUE + +/datum/component/storage/concrete/proc/handle_item_insertion_from_slave(datum/component/storage/slave, obj/item/I, prevent_warning = FALSE, M) + . = handle_item_insertion(I, prevent_warning, M, slave) + if(. && !prevent_warning) + slave.mob_item_insertion_feedback(usr, M, I) + +/datum/component/storage/concrete/handle_item_insertion(obj/item/I, prevent_warning = FALSE, mob/M, datum/component/storage/remote) //Remote is null or the slave datum + var/datum/component/storage/concrete/master = master() + var/atom/parent = src.parent + var/moved = FALSE + if(!istype(I)) + return FALSE + if(M) + if(!M.temporarilyRemoveItemFromInventory(I)) + return FALSE + else + moved = TRUE //At this point if the proc fails we need to manually move the object back to the turf/mob/whatever. + if(I.pulledby) + I.pulledby.stop_pulling() + if(silent) + prevent_warning = TRUE + if(!_insert_physical_item(I)) + if(moved) + if(M) + if(!M.put_in_active_hand(I)) + I.forceMove(parent.drop_location()) + else + I.forceMove(parent.drop_location()) + return FALSE + I.on_enter_storage(master) + refresh_mob_views() + I.mouse_opacity = MOUSE_OPACITY_OPAQUE //So you can click on the area around the item to equip it, instead of having to pixel hunt + if(M) + if(M.client && M.active_storage != src) + M.client.screen -= I + if(M.observers && M.observers.len) + for(var/i in M.observers) + var/mob/dead/observe = i + if(observe.client && observe.active_storage != src) + observe.client.screen -= I + if(!remote) + parent.add_fingerprint(M) + if(!prevent_warning) + mob_item_insertion_feedback(usr, M, I) + update_icon() + return TRUE + +/datum/component/storage/concrete/update_icon() + if(isobj(parent)) + var/obj/O = parent + O.update_icon() + for(var/i in slaves) + var/datum/component/storage/slave = i + slave.update_icon() +>>>>>>> 8ce7d19... Merge pull request #37565 from ninjanomnom/component-limbo diff --git a/code/datums/components/storage/storage.dm b/code/datums/components/storage/storage.dm index ba59712020..58ebf73d15 100644 --- a/code/datums/components/storage/storage.dm +++ b/code/datums/components/storage/storage.dm @@ -108,7 +108,7 @@ LAZYCLEARLIST(is_using) return ..() -/datum/component/storage/OnTransfer(datum/new_parent) +/datum/component/storage/PreTransfer() update_actions() /datum/component/storage/proc/update_actions() diff --git a/code/datums/components/wet_floor.dm b/code/datums/components/wet_floor.dm index 78b31802c9..afba151b9f 100644 --- a/code/datums/components/wet_floor.dm +++ b/code/datums/components/wet_floor.dm @@ -135,12 +135,14 @@ for(var/i in time_left_list) . |= text2num(i) -/datum/component/wet_floor/OnTransfer(datum/to_datum) - if(!isopenturf(to_datum)) - return COMPONENT_INCOMPATIBLE +/datum/component/wet_floor/PreTransfer() var/turf/O = parent O.cut_overlay(current_overlay) - var/turf/T = to_datum + +/datum/component/wet_floor/PostTransfer() + if(!isopenturf(parent)) + return COMPONENT_INCOMPATIBLE + var/turf/T = parent T.add_overlay(current_overlay) /datum/component/wet_floor/proc/add_wet(type, duration_minimum = 0, duration_add = 0, duration_maximum = MAXIMUM_WET_TIME, _permanent = FALSE) diff --git a/code/game/turfs/change_turf.dm b/code/game/turfs/change_turf.dm index 253ceb29ac..539911f6eb 100644 --- a/code/game/turfs/change_turf.dm +++ b/code/game/turfs/change_turf.dm @@ -68,11 +68,20 @@ GLOBAL_LIST_INIT(blacklisted_automated_baseturfs, typecacheof(list( blueprint_data = null var/list/old_baseturfs = baseturfs - changing_turf = TRUE + var/list/transferring_comps = list() + SendSignal(COMSIG_TURF_CHANGE, path, new_baseturfs, flags, transferring_comps) + for(var/i in transferring_comps) + var/datum/component/comp = i + comp.RemoveComponent() + + changing_turf = TRUE qdel(src) //Just get the side effects and call Destroy var/turf/W = new path(src) + for(var/i in transferring_comps) + W.TakeComponent(i) + if(new_baseturfs) W.baseturfs = new_baseturfs else