diff --git a/citadel.dme b/citadel.dme index 8bfc4bba8e6d..caad047997bf 100644 --- a/citadel.dme +++ b/citadel.dme @@ -205,6 +205,7 @@ #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_radiation.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_x_act.dm" +#include "code\__DEFINES\dcs\signals\signals_atom\signals_movable-update_icon.dm" #include "code\__DEFINES\dcs\signals\signals_item\signals_item-clickchain.dm" #include "code\__DEFINES\dcs\signals\signals_item\signals_item-interaction.dm" #include "code\__DEFINES\dcs\signals\signals_item\signals_item_economy.dm" @@ -808,6 +809,7 @@ #include "code\datums\components\items\passive_parry.dm" #include "code\datums\components\items\wielding.dm" #include "code\datums\components\mobs\block_frame.dm" +#include "code\datums\components\mobs\mob_self_horizontal_inversion.dm" #include "code\datums\components\mobs\parry_frame.dm" #include "code\datums\components\movable\aquarium.dm" #include "code\datums\components\movable\spatial_grid.dm" @@ -1072,6 +1074,7 @@ #include "code\game\atoms\movable\movable-logging.dm" #include "code\game\atoms\movable\movable-movement.dm" #include "code\game\atoms\movable\movable-throw.dm" +#include "code\game\atoms\movable\movable-update_icon.dm" #include "code\game\atoms\movable\movable.dm" #include "code\game\atoms\movable\pulling.dm" #include "code\game\atoms\movable\vv.dm" @@ -4133,6 +4136,7 @@ #include "code\modules\mob\observer\dead\orbit.dm" #include "code\modules\mob\observer\dead\perspective.dm" #include "code\modules\mob\observer\dead\say.dm" +#include "code\modules\mob\verbs\horizontal_invert_self.dm" #include "code\modules\modular_computers\laptop_vendor.dm" #include "code\modules\modular_computers\computers\modular_computer\core.dm" #include "code\modules\modular_computers\computers\modular_computer\damage.dm" diff --git a/code/__DEFINES/_cooldowns.dm b/code/__DEFINES/_cooldowns.dm index 2355b1005b8d..a066d0e543eb 100644 --- a/code/__DEFINES/_cooldowns.dm +++ b/code/__DEFINES/_cooldowns.dm @@ -90,3 +90,6 @@ // admin verb cooldowns #define CD_INTERNET_SOUND "internet_sound" + +//* /mob +#define CD_INDEX_MOB_VERB_INVERT_SELF "mob-verb-invert-self" diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_movable-update_icon.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_movable-update_icon.dm new file mode 100644 index 000000000000..216daf08a302 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_movable-update_icon.dm @@ -0,0 +1,10 @@ +/** + * Anything relating to update icon/rendering + */ + +/// Called at the base of base_transform with the matrix that's being generated. +/// * Signature: (matrix/applying) +#define COMSIG_MOVABLE_BASE_TRANSFORM "movable-base_transform" +/// Called at the base of update_transform with the matrix that's being generated. +/// * Signature: (matrix/old_matrix, matrix/new_matrix) +#define COMSIG_MOVABLE_ON_UPDATE_TRANSFORM "movable-on_update_transform" diff --git a/code/datums/components/mobs/mob_self_horizontal_inversion.dm b/code/datums/components/mobs/mob_self_horizontal_inversion.dm new file mode 100644 index 000000000000..79df9ca7c29e --- /dev/null +++ b/code/datums/components/mobs/mob_self_horizontal_inversion.dm @@ -0,0 +1,33 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/** + * Component added to a mob by the mob themselves to invert themselves horizontally. + */ +/datum/component/mob_self_horizontal_inversion + registered_type = /datum/component/mob_self_horizontal_inversion + +/datum/component/mob_self_horizontal_inversion/Initialize() + if(!ismob(parent)) + return COMPONENT_INCOMPATIBLE + return ..() + +/datum/component/mob_self_horizontal_inversion/RegisterWithParent() + . = ..() + RegisterSignal(parent, COMSIG_MOVABLE_BASE_TRANSFORM, PROC_REF(alter_base_transform)) + var/mob/target = parent + var/matrix/to_apply = target.transform + to_apply.Scale(-1, 1) + target.set_transform(to_apply) + +/datum/component/mob_self_horizontal_inversion/UnregisterFromParent() + . = ..() + UnregisterSignal(parent, COMSIG_MOVABLE_BASE_TRANSFORM) + var/mob/target = parent + var/matrix/to_apply = target.transform + to_apply.Scale(-1, 1) + target.set_transform(to_apply) + +/datum/component/mob_self_horizontal_inversion/proc/alter_base_transform(datum/source, matrix/applying) + SIGNAL_HANDLER + applying.Scale(-1, 1) diff --git a/code/game/atoms/movable/movable-update_icon.dm b/code/game/atoms/movable/movable-update_icon.dm new file mode 100644 index 000000000000..56bae6eb034f --- /dev/null +++ b/code/game/atoms/movable/movable-update_icon.dm @@ -0,0 +1,47 @@ +// Ok ok I know it says update_icon but this actually has everything from // +// update_appearance to update_transform and others. // + +// todo: rework UPDATE_ICON flags or something for "should we transform" + +/** + * Our transform is reset at the base of /atom/movable/proc/update_transform() + */ +/atom/movable/proc/update_transform() + SHOULD_CALL_PARENT(TRUE) + SHOULD_NOT_SLEEP(TRUE) + SHOULD_NOT_OVERRIDE(TRUE) + + var/matrix/new_transform = matrix() + var/matrix/old_transform = transform + + base_transform(new_transform) + apply_transform(new_transform) + + SEND_SIGNAL(src, COMSIG_MOVABLE_ON_UPDATE_TRANSFORM, old_transform, new_transform) + +/atom/movable/proc/apply_transform(matrix/to_apply) + SHOULD_NOT_SLEEP(TRUE) + transform = to_apply + +/** + * Changing the transform before ..() and after ..() is allowed. + * + * @return the matrix to apply. + */ +/atom/movable/proc/base_transform(matrix/applying) + SHOULD_CALL_PARENT(TRUE) + SHOULD_NOT_SLEEP(TRUE) + applying.Scale(icon_scale_x, icon_scale_y) + applying.Turn(icon_rotation) + SEND_SIGNAL(src, COMSIG_MOVABLE_BASE_TRANSFORM, applying) + return applying + +/** + * Immediate transform modify. + * + * todo: this should use apply_transform and use update icon flags or something, like NO_ANIMATIONS + */ +/atom/movable/proc/set_transform(matrix/new_transform) + var/matrix/old_transform = transform + src.transform = new_transform + SEND_SIGNAL(src, COMSIG_MOVABLE_ON_UPDATE_TRANSFORM, old_transform, new_transform) diff --git a/code/game/atoms/movable/movable.dm b/code/game/atoms/movable/movable.dm index 9be084a15cc5..bed10f12c2d3 100644 --- a/code/game/atoms/movable/movable.dm +++ b/code/game/atoms/movable/movable.dm @@ -175,10 +175,13 @@ //? Icon Scale /// Used to scale icons up or down horizonally in update_transform(). + // todo: should this be here? var/icon_scale_x = 1 /// Used to scale icons up or down vertically in update_transform(). + // todo: should this be here? var/icon_scale_y = 1 /// Used to rotate icons in update_transform() + // todo: should this be here? var/icon_rotation = 0 //? Pixel Offsets @@ -256,13 +259,6 @@ /atom/movable/proc/get_icon_scale_y() return icon_scale_y -// todo: refactor this shit -/atom/movable/proc/update_transform() - var/matrix/M = matrix() - M.Scale(icon_scale_x, icon_scale_y) - M.Turn(icon_rotation) - src.transform = M - // Use this to set the object's scale. /atom/movable/proc/adjust_scale(new_scale_x, new_scale_y) if(isnull(new_scale_y)) diff --git a/code/game/objects/structures/flora/trees.dm b/code/game/objects/structures/flora/trees.dm index fe7ac42a99f0..c7e74d35019d 100644 --- a/code/game/objects/structures/flora/trees.dm +++ b/code/game/objects/structures/flora/trees.dm @@ -18,14 +18,15 @@ /obj/structure/flora/tree/Initialize(mapload) icon_state = choose_icon_state() - return ..() -/obj/structure/flora/tree/update_transform() - var/matrix/M = matrix() - M.Scale(icon_scale_x, icon_scale_y) - M.Translate(0, 16*(icon_scale_y-1)) - animate(src, transform = M, time = 10) +/obj/structure/flora/tree/apply_transform(matrix/to_apply) + animate(src, transform = to_apply, time = 1 SECONDS) + +/obj/structure/flora/tree/base_transform(matrix/applying) + var/matrix/base_matrix = ..() + base_matrix.Translate(0, 16 * (icon_scale_y - 1)) + return base_matrix // Override this for special icons. /obj/structure/flora/tree/proc/choose_icon_state() diff --git a/code/modules/clothing/accessories/halo.dm b/code/modules/clothing/accessories/halo.dm index 28646511a0b0..de07cf47854d 100644 --- a/code/modules/clothing/accessories/halo.dm +++ b/code/modules/clothing/accessories/halo.dm @@ -30,11 +30,11 @@ /obj/item/clothing/accessory/halo_projector/equipped(mob/user, slot, flags) . = ..() - RegisterSignal(user, COMSIG_MOB_UPDATE_TRANSFORM, PROC_REF(on_update_transform)) + RegisterSignal(user, COMSIG_MOVABLE_ON_UPDATE_TRANSFORM, PROC_REF(on_update_transform)) /obj/item/clothing/accessory/halo_projector/unequipped(mob/user, slot, flags) . = ..() - UnregisterSignal(user, COMSIG_MOB_UPDATE_TRANSFORM) + UnregisterSignal(user, COMSIG_MOVABLE_ON_UPDATE_TRANSFORM) /obj/item/clothing/accessory/halo_projector/proc/on_update_transform(datum/source, matrix/old_transform, matrix/new_transform) SIGNAL_HANDLER diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index be9af271b290..251cfc5f004e 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -29,9 +29,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) /mob/living/carbon/human/update_icons_huds() stack_trace("CANARY: Old human update_icons_huds was called.") -/mob/living/carbon/human/update_transform() - var/matrix/old_matrix = transform - var/matrix/M = matrix() +/mob/living/carbon/human/base_transform(matrix/applying) + SHOULD_CALL_PARENT(FALSE) // handle scaling first, we don't want to have massive mobs still shift to align to tile // when they're laying down. @@ -40,8 +39,8 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) if(istype(species)) desired_scale_x *= species.icon_scale_x desired_scale_y *= species.icon_scale_y - M.Scale(desired_scale_x, desired_scale_y) - M.Translate(0, 16 * (desired_scale_y - 1)) + applying.Scale(desired_scale_x, desired_scale_y) + applying.Translate(0, 16 * (desired_scale_y - 1)) // Mark atom as wide/long for ZM. if (desired_scale_x > 1) @@ -54,21 +53,23 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) zmm_flags &= ~ZMM_LOOKBESIDE // handle turning - M.Turn(lying) + applying.Turn(lying) // extremely lazy heuristic to see if we should shift down to appear to be, well, down. if(lying < -45 || lying > 45) - M.Translate(1,-6) + applying.Translate(1,-6) // fall faster if incapacitated - var/anim_time = CHECK_MOBILITY(src, MOBILITY_CAN_STAND)? 3 : 1 - - animate(src, transform = M, time = anim_time, flags = ANIMATION_PARALLEL) appearance_flags = fuzzy? (appearance_flags & ~(PIXEL_SCALE)) : (appearance_flags | PIXEL_SCALE) - SEND_SIGNAL(src, COMSIG_MOB_UPDATE_TRANSFORM, old_matrix, M) + + SEND_SIGNAL(src, COMSIG_MOVABLE_BASE_TRANSFORM, applying) + return applying + +/mob/living/carbon/human/apply_transform(matrix/to_apply) + var/anim_time = CHECK_MOBILITY(src, MOBILITY_CAN_STAND)? 3 : 1 + animate(src, transform = to_apply, time = anim_time, flags = ANIMATION_PARALLEL) update_icon_special() //May contain transform-altering things update_ssd_overlay() - /* --------------------------------------- */ //Recomputes every icon on the mob. Expensive. //Useful if the species changed, or there's some diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b01ba32341a6..27bbaa55efc3 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -583,19 +583,21 @@ default behaviour is: if(!isnull(M.icon_scale_y_percent)) . *= M.icon_scale_y_percent -/mob/living/update_transform() - var/matrix/old_matrix = transform - // First, get the correct size. +/mob/living/base_transform(matrix/applying) + SHOULD_CALL_PARENT(FALSE) + var/desired_scale_x = size_multiplier * icon_scale_x var/desired_scale_y = size_multiplier * icon_scale_y - // Now for the regular stuff. - var/matrix/M = matrix() - M.Scale(desired_scale_x, desired_scale_y) - M.Translate(0, 16*(desired_scale_y-1)) + applying.Scale(desired_scale_x, desired_scale_y) + applying.Translate(0, 16 * (desired_scale_y - 1)) + + SEND_SIGNAL(src, COMSIG_MOVABLE_BASE_TRANSFORM, applying) + return applying + +/mob/living/apply_transform(matrix/to_apply) + animate(src, transform = to_apply, time = 1 SECONDS) update_ssd_overlay() - animate(src, transform = M, time = 10) - SEND_SIGNAL(src, COMSIG_MOB_UPDATE_TRANSFORM, old_matrix, M) // This handles setting the client's color variable, which makes everything look a specific color. // This proc is here so it can be called without needing to check if the client exists, or if the client relogs. diff --git a/code/modules/mob/living/silicon/pai/mobility.dm b/code/modules/mob/living/silicon/pai/mobility.dm index 42350a53da04..7d5bd608ca45 100644 --- a/code/modules/mob/living/silicon/pai/mobility.dm +++ b/code/modules/mob/living/silicon/pai/mobility.dm @@ -149,24 +149,21 @@ return FALSE return TRUE -/mob/living/silicon/pai/update_transform(animate = TRUE) - . = ..() - var/matrix/M = matrix() - var/desired_scale_x = size_multiplier * icon_scale_x - var/desired_scale_y = size_multiplier * icon_scale_y - M.Scale(desired_scale_x, desired_scale_y) - M.Translate(0, 16*(desired_scale_y-1)) +/mob/living/silicon/pai/base_transform(matrix/applying) + var/matrix/to_apply = ..() + /// No chassis means pAI is using a hologram var/turning_value_to_use = 0 if(!chassis) turning_value_to_use = lying /// Handle turning - M.Turn(turning_value_to_use) + to_apply.Turn(turning_value_to_use) + /// Extremely lazy heuristic to see if we should shift down to appear to be, well, down. if(turning_value_to_use < -45 || turning_value_to_use > 45) - M.Translate(1,-6) + to_apply.Translate(1,-6) + + return to_apply - if(animate) - animate(src, transform = M, time = 1, flags = ANIMATION_PARALLEL) - else - transform = M +/mob/living/silicon/pai/apply_transform(matrix/to_apply) + animate(src, transform = to_apply, time = 1 SECONDS, flags = ANIMATION_PARALLEL) diff --git a/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm index 1e3d344a322f..94c06aea5d9d 100644 --- a/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm +++ b/code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm @@ -171,13 +171,7 @@ return return ..() -/mob/living/simple_mob/vore/hostile/morph/update_transform() - if(morphed) - var/matrix/old_matrix = transform - var/matrix/M = matrix() - M.Scale(icon_scale_x, icon_scale_y) - M.Turn(icon_rotation) - src.transform = M - SEND_SIGNAL(src, COMSIG_MOB_UPDATE_TRANSFORM, old_matrix, M) - else - ..() +/mob/living/simple_mob/vore/hostile/morph/base_transform(matrix/applying) + var/old_size_multiplier = size_multiplier + . = ..() + size_multiplier = old_size_multiplier diff --git a/code/modules/mob/verbs/horizontal_invert_self.dm b/code/modules/mob/verbs/horizontal_invert_self.dm new file mode 100644 index 000000000000..09adab8dbc59 --- /dev/null +++ b/code/modules/mob/verbs/horizontal_invert_self.dm @@ -0,0 +1,23 @@ +//* This file is explicitly licensed under the MIT license. *// +//* Copyright (c) 2024 Citadel Station Developers *// + +/mob/verb/horizontal_invert_self() + set name = "Invert Yourself (Horizontal)" + set desc = "Mirror your sprite across the N-S axis." + set category = VERB_CATEGORY_IC + + // todo: remote control? mobs that don't allow it? + + if(TIMER_COOLDOWN_CHECK(src, CD_INDEX_MOB_VERB_INVERT_SELF)) + // todo: don't usr lol + to_chat(usr, SPAN_WARNING("You can't do that yet!")) + return + TIMER_COOLDOWN_START(src, CD_INDEX_MOB_VERB_INVERT_SELF, 0.5 SECONDS) + + log_game("[key_name(usr)] invoked horizontal_invert_self on [key_name(src)].") + + var/datum/component/mob_self_horizontal_inversion/inversion = GetComponent(/datum/component/mob_self_horizontal_inversion) + if(inversion) + qdel(inversion) + else + AddComponent(/datum/component/mob_self_horizontal_inversion) diff --git a/code/modules/vehicles/sealed/mecha/mecha_appearance.dm b/code/modules/vehicles/sealed/mecha/mecha_appearance.dm index 4f61f5603cee..9d8ca1a731da 100644 --- a/code/modules/vehicles/sealed/mecha/mecha_appearance.dm +++ b/code/modules/vehicles/sealed/mecha/mecha_appearance.dm @@ -13,13 +13,13 @@ // How many pixels do we bump the pilot upward? var/pilot_lift = 0 -/obj/vehicle/sealed/mecha/update_transform() - // Now for the regular stuff. - var/matrix/M = matrix() - M.Scale(icon_scale_x, icon_scale_y) - M.Translate(0, 16*(icon_scale_y-1)) - animate(src, transform = M, time = 10) - return +/obj/vehicle/sealed/mecha/apply_transform(matrix/to_apply) + animate(src, transform = to_apply, time = 1 SECONDS) + +/obj/vehicle/sealed/mecha/base_transform(matrix/applying) + var/matrix/base_matrix = ..() + base_matrix.Translate(0, 16 * (icon_scale_y - 1)) + return base_matrix /obj/vehicle/sealed/mecha/update_icon() if(!initial_icon)