diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index de4bd46139..f216a416c5 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -214,6 +214,8 @@ #define COMSIG_TURF_MULTIZ_DEL "turf_multiz_del" ///from base of turf/multiz_turf_new: (turf/source, direction) #define COMSIG_TURF_MULTIZ_NEW "turf_multiz_new" +/// from base of turf/proc/afterShuttleMove: (turf/new_turf) +#define COMSIG_TURF_AFTER_SHUTTLE_MOVE "turf_after_shuttle_move" // /atom/movable signals #define COMSIG_MOVABLE_PRE_MOVE "movable_pre_move" ///from base of atom/movable/Moved(): (/atom) diff --git a/code/datums/elements/decal.dm b/code/datums/elements/decal.dm index c3f9f1bd17..e3baf9aafa 100644 --- a/code/datums/elements/decal.dm +++ b/code/datums/elements/decal.dm @@ -4,75 +4,90 @@ var/cleanable var/description var/mutable_appearance/pic - var/list/num_decals_per_atom + /** + * A short lecture on decal element collision on rotation + * If a given decal's rotated version is identical to one of existing (at a same target), pre-rotation decals, + * then the rotated decal won't stay after when the colliding pre-rotation decal gets rotated, + * resulting in some decal elements colliding into nonexistence. This internal tick-tock prevents + * such collision by forcing a non-collision. + */ + var/rotated - var/first_dir // This stores the direction of the decal compared to the parent facing NORTH - -/datum/element/decal/Attach(datum/target, _icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255) +/datum/element/decal/Attach(atom/target, _icon, _icon_state, _dir, _cleanable=CLEAN_GOD, _color, _layer=TURF_LAYER, _description, _alpha=255, _rotated=FALSE) . = ..() - if(. == ELEMENT_INCOMPATIBLE || !_icon || !_icon_state || !isatom(target)) + if(!isatom(target) || (pic ? FALSE : !generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha, target))) return ELEMENT_INCOMPATIBLE - var/atom/A = target - if(!pic) - // It has to be made from an image or dir breaks because of a byond bug - var/temp_image = image(_icon, null, _icon_state, _layer, _dir) - pic = new(temp_image) - pic.color = _color - pic.alpha = _alpha - first_dir = _dir description = _description cleanable = _cleanable + rotated = _rotated - LAZYINITLIST(num_decals_per_atom) - - if(!num_decals_per_atom[A]) - if(first_dir) - RegisterSignal(A, COMSIG_ATOM_DIR_CHANGE, PROC_REF(rotate_react)) - if(cleanable) - RegisterSignal(A, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean_react)) - if(description) - RegisterSignal(A, COMSIG_PARENT_EXAMINE, PROC_REF(examine)) - RegisterSignal(A, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(apply_overlay), TRUE) - - num_decals_per_atom[A]++ - apply(A) - -/datum/element/decal/Detach(datum/target) - var/atom/A = target - num_decals_per_atom[A]-- - if(!num_decals_per_atom[A]) - UnregisterSignal(A, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE, - COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS)) - LAZYREMOVE(num_decals_per_atom, A) - apply(A) - return ..() - -/datum/element/decal/proc/apply(atom/target) + RegisterSignal(target,COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(apply_overlay), TRUE) + if(isturf(target)) + RegisterSignal(target,COMSIG_TURF_AFTER_SHUTTLE_MOVE, PROC_REF(shuttlemove_react), TRUE) if(target.flags_1 & INITIALIZED_1) target.update_icon() //could use some queuing here now maybe. - else if(!QDELETED(target) && num_decals_per_atom[target] == 1) - RegisterSignal(target, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE, PROC_REF(late_update_icon)) + else + RegisterSignal(target,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE,PROC_REF(late_update_icon), TRUE) if(isitem(target)) - addtimer(CALLBACK(target, TYPE_PROC_REF(/obj/item, update_slot_icon)), 0, TIMER_UNIQUE) + INVOKE_ASYNC(target, TYPE_PROC_REF(/obj/item, update_slot_icon), TRUE) + if(_dir) + RegisterSignal(target, COMSIG_ATOM_DIR_CHANGE, PROC_REF(rotate_react),TRUE) + if(_cleanable) + RegisterSignal(target, COMSIG_COMPONENT_CLEAN_ACT, PROC_REF(clean_react),TRUE) + if(_description) + RegisterSignal(target, COMSIG_PARENT_EXAMINE, PROC_REF(examine),TRUE) + +/datum/element/decal/proc/generate_appearance(_icon, _icon_state, _dir, _layer, _color, _alpha, source) + if(!_icon || !_icon_state) + return FALSE + var/temp_image = image(_icon, null, _icon_state, _layer, _dir) + pic = new(temp_image) + pic.color = _color + pic.alpha = _alpha + return TRUE + +/datum/element/decal/Detach(atom/source, force) + UnregisterSignal(source, list(COMSIG_ATOM_DIR_CHANGE, COMSIG_COMPONENT_CLEAN_ACT, COMSIG_PARENT_EXAMINE, COMSIG_ATOM_UPDATE_OVERLAYS,COMSIG_TURF_AFTER_SHUTTLE_MOVE)) + source.update_icon() + if(isitem(source)) + INVOKE_ASYNC(source, TYPE_PROC_REF(/obj/item, update_slot_icon)) + return ..() /datum/element/decal/proc/late_update_icon(atom/source) - source.update_icon() - UnregisterSignal(source,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE) + SIGNAL_HANDLER + + if(source && istype(source)) + source.update_icon() + UnregisterSignal(source,COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZE) + /datum/element/decal/proc/apply_overlay(atom/source, list/overlay_list) - if(first_dir) - pic.dir = first_dir == SOUTH ? source.dir : turn(first_dir, dir2angle(source.dir)-180) //Never turn a dir by 0. - for(var/i in 1 to num_decals_per_atom[source]) - overlay_list += pic + SIGNAL_HANDLER + + overlay_list += pic + +/datum/element/decal/proc/shuttlemove_react(datum/source, turf/newT) + SIGNAL_HANDLER + Detach(source) + newT.AddElement(/datum/element/decal, pic.icon, pic.icon_state, pic.dir, cleanable, pic.color, pic.layer, description, pic.alpha, rotated) + +/datum/element/decal/proc/rotate_react(datum/source, old_dir, new_dir) + SIGNAL_HANDLER -/datum/element/decal/proc/rotate_react(atom/source, old_dir, new_dir) if(old_dir == new_dir) return - source.update_icon() + Detach(source) + source.AddElement(/datum/element/decal, pic.icon, pic.icon_state, angle2dir(dir2angle(pic.dir)+dir2angle(new_dir)-dir2angle(old_dir)), cleanable, pic.color, pic.layer, description, pic.alpha, !rotated) /datum/element/decal/proc/clean_react(datum/source, strength) + SIGNAL_HANDLER + if(strength >= cleanable) Detach(source) + return TRUE + return NONE /datum/element/decal/proc/examine(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + examine_list += description diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm index 2e1cc2b606..27b84c152c 100644 --- a/code/game/objects/effects/decals/decal.dm +++ b/code/game/objects/effects/decals/decal.dm @@ -47,4 +47,4 @@ if(!istype(T)) //you know this will happen somehow CRASH("Turf decal initialized in an object/nullspace") var/turn_dir = 180 - dir2angle(T.dir) //Turning a dir by 0 results in a roulette of random dirs. - T.AddElement(/datum/element/decal, icon, icon_state, turn_dir ? turn(dir, turn_dir) : dir, CLEAN_GOD, color, null, null, alpha) + T.AddElement(/datum/element/decal, icon, icon_state, turn_dir ? turn(dir, turn_dir) : dir, CLEAN_GOD, color, null, null, alpha, FALSE) diff --git a/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm b/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm index bf9d5886a0..1c8bd86a31 100644 --- a/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm +++ b/code/modules/research/designs/autolathe_desings/autolathe_designs_sec_and_hacked.dm @@ -58,9 +58,9 @@ build_path = /obj/item/construction/rcd category = list("hacked", "Construction") -/datum/design/rpd +/datum/design/rpd_autolathe name = "Rapid Pipe Dispenser (RPD)" - id = "rpd" + id = "rpd_autolathe" build_type = AUTOLATHE | NO_PUBLIC_LATHE materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500) build_path = /obj/item/pipe_dispenser diff --git a/code/modules/shuttle/on_move.dm b/code/modules/shuttle/on_move.dm index 032687bd25..2f16402b0f 100644 --- a/code/modules/shuttle/on_move.dm +++ b/code/modules/shuttle/on_move.dm @@ -69,6 +69,7 @@ All ShuttleMove procs go here /turf/proc/afterShuttleMove(turf/oldT, rotation) //Dealing with the turf we left behind oldT.TransferComponents(src) + SEND_SIGNAL(oldT, COMSIG_TURF_AFTER_SHUTTLE_MOVE, src) //Mostly for decals var/shuttle_boundary = baseturfs.Find(/turf/baseturf_skipover/shuttle) if(shuttle_boundary) oldT.ScrapeAway(baseturfs.len - shuttle_boundary + 1)