Skip to content

Commit

Permalink
adds a verb to invert yourself 180 degrees horizontally. also, refact…
Browse files Browse the repository at this point in the history
…ors update transform. (Citadel-Station-13#6909)

look, mom! components can hook transform updates now. surely this will be used responsibly and i won't have to revisit this in the future. 

when do we get structs so we can go full ECS pattern with appearance updates? having this fragmented across multiple procs is kinda annoying!
  • Loading branch information
silicons authored Dec 12, 2024
1 parent 3eed2b6 commit c1737d4
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 66 deletions.
4 changes: 4 additions & 0 deletions citadel.dme
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions code/__DEFINES/_cooldowns.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Original file line number Diff line number Diff line change
@@ -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"
33 changes: 33 additions & 0 deletions code/datums/components/mobs/mob_self_horizontal_inversion.dm
Original file line number Diff line number Diff line change
@@ -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)
47 changes: 47 additions & 0 deletions code/game/atoms/movable/movable-update_icon.dm
Original file line number Diff line number Diff line change
@@ -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)
10 changes: 3 additions & 7 deletions code/game/atoms/movable/movable.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down
13 changes: 7 additions & 6 deletions code/game/objects/structures/flora/trees.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 2 additions & 2 deletions code/modules/clothing/accessories/halo.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 13 additions & 12 deletions code/modules/mob/living/carbon/human/update_icons.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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)
Expand All @@ -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
Expand Down
20 changes: 11 additions & 9 deletions code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
23 changes: 10 additions & 13 deletions code/modules/mob/living/silicon/pai/mobility.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
14 changes: 4 additions & 10 deletions code/modules/mob/living/simple_mob/subtypes/vore/morph/morph.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 23 additions & 0 deletions code/modules/mob/verbs/horizontal_invert_self.dm
Original file line number Diff line number Diff line change
@@ -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)
14 changes: 7 additions & 7 deletions code/modules/vehicles/sealed/mecha/mecha_appearance.dm
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit c1737d4

Please sign in to comment.