Skip to content

Commit

Permalink
Move padding onto an extension
Browse files Browse the repository at this point in the history
  • Loading branch information
out-of-phaze committed Feb 4, 2025
1 parent 0fbbe85 commit dad0cfa
Show file tree
Hide file tree
Showing 17 changed files with 350 additions and 325 deletions.
1 change: 1 addition & 0 deletions code/__defines/tools.dm
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
#define IS_KNIFE(A) IS_TOOL(A, TOOL_KNIFE)
#define IS_HAMMER(A) IS_TOOL(A, TOOL_HAMMER)
#define IS_HOE(A) IS_TOOL(A, TOOL_HOE)
#define IS_SHEARS(A) IS_TOOL(A, TOOL_SHEARS)

#define IS_HEMOSTAT(A) IS_TOOL(A, TOOL_HEMOSTAT)
#define IS_RETRACTOR(A) IS_TOOL(A, TOOL_RETRACTOR)
Expand Down
16 changes: 12 additions & 4 deletions code/datums/extensions/extensions.dm
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@
qdel(existing_extension)

if(initial(extension_base_type.flags) & EXTENSION_FLAG_IMMEDIATE)
var/datum/extension/created = construct_extension_instance(extension_type, source, args.Copy(3))
var/list/construct_args = args.Copy(3)
var/datum/extension/created = construct_extension_instance(extension_type, source, construct_args)
source.extensions[extension_base_type] = created
created.post_construction()
if(length(construct_args))
created.post_construction(arglist(construct_args))
else
created.post_construction()
return created

var/list/extension_data = list(extension_type, source)
Expand Down Expand Up @@ -89,9 +93,13 @@
return
if(islist(.)) //a list, so it's expecting to be lazy-loaded
var/list/extension_data = .
var/datum/extension/created = construct_extension_instance(extension_data[1], extension_data[2], extension_data.Copy(3))
var/list/construct_args = extension_data.Copy(3)
var/datum/extension/created = construct_extension_instance(extension_data[1], extension_data[2], construct_args)
source.extensions[base_type] = created
created.post_construction()
if(length(construct_args))
created.post_construction(arglist(construct_args))
else
created.post_construction()
return created

//Fast way to check if it has an extension, also doesn't trigger instantiation of lazy loaded extensions
Expand Down
132 changes: 132 additions & 0 deletions code/datums/extensions/padding/padding.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// TODO: Maybe generalize this to handle any sort of component-composition that can have a separate material and painting?
/// An extension that unifies padding state and interactions.
/datum/extension/padding
abstract_type = /datum/extension/padding
base_type = /datum/extension/padding
expected_type = /obj
flags = EXTENSION_FLAG_IMMEDIATE // logic must run on creation
/// The paint color for the padding represented by this extension.
/// '#FFFFFF' is treated as 'painted white', while 'null' is treated as 'unpainted'.
VAR_PROTECTED/padding_color
VAR_PROTECTED/decl/material/padding_material
// TODO: Add some better way of determining if a stack is usable, for more extensibility in modpacks.
/// What stack types can be used to add padding?
VAR_PRIVATE/static/padding_stack_types = list(
/obj/item/stack/material/skin, // leather, fur
/obj/item/stack/material/bolt, // cloth
)
/// An internal variable used to hold a typecache for the above list.
VAR_PRIVATE/static/_padding_stack_typecache

/datum/extension/padding/New(datum/holder, _padding_material, _padding_color)
. = ..()
if(!_padding_stack_typecache)
_padding_stack_typecache = typecacheof(padding_stack_types)

// Must be here so our holder's get_extension calls work.
/datum/extension/padding/post_construction(_padding_material, _padding_color)
. = ..()
add_padding(_padding_material, _padding_color)

/// Returns an object's padding material.
/datum/extension/padding/proc/get_padding_material()
RETURN_TYPE(/decl/material)
return padding_material

/// Returns the color of the padding, either the painted/dyed color or (optionally) the underlying material color.
/datum/extension/padding/proc/get_padding_color(use_material_color = TRUE)
var/decl/material/padding_material = get_padding_material()
return padding_color || (use_material_color ? padding_material?.color : null)

/// Used to change just the paint color on padding.
/datum/extension/padding/proc/set_padding_color(new_color)
padding_color = new_color

/datum/extension/padding/proc/handle_use_item(obj/item/used_item, mob/user)
if(isstack(used_item))
if(padding_material)
to_chat(user, SPAN_NOTICE("\The [holder] is already padded."))
return TRUE
var/decl/material/new_padding_material = used_item.material
if(!is_type_in_typecache(used_item, _padding_stack_typecache) || !(new_padding_material.flags & MAT_FLAG_PADDING))
to_chat(user, SPAN_NOTICE("You cannot pad \the [holder] with that."))
return TRUE
var/obj/item/stack/used_stack = used_item
if(!used_stack.can_use(1))
to_chat(user, SPAN_NOTICE("You need at least [used_stack.get_string_for_amount(1)] to pad \the [holder]."))
return TRUE
if(!used_item.user_can_attack_with(user, holder))
return TRUE
to_chat(user, SPAN_NOTICE("You pad \the [holder] with [used_stack.get_string_for_amount(1)]."))
used_stack.use(1)
if(new_padding_material.sound_manipulate)
playsound(get_turf(holder), new_padding_material.sound_manipulate, 50, TRUE)
add_padding(new_padding_material.type, used_stack.paint_color)
return TRUE
else if(IS_SHEARS(used_item)) // can use shears or wirecutters
if(!padding_material)
to_chat(user, SPAN_NOTICE("\The [holder] has no padding to remove."))
return TRUE
if(!used_item.user_can_attack_with(user, holder))
return TRUE
to_chat(user, SPAN_NOTICE("You remove \the [padding_material.adjective_name] padding from \the [holder]."))
var/use_tool_sound = used_item.get_tool_sound(TOOL_SHEARS)
if(use_tool_sound)
playsound(get_turf(holder), use_tool_sound, 100, TRUE)
remove_padding()
return TRUE
return FALSE

// TODO: Unify this somewhere on /obj, maybe?
/datum/extension/padding/proc/update_holder_name()
if(QDELETED(src) || QDELETED(holder))
return
if(istype(holder, /obj/structure))
var/obj/structure/structure_holder = holder
structure_holder.update_materials() // update name and description if needed
else if(isitem(holder))
var/obj/item/item_holder = holder
item_holder.update_name()

/datum/extension/padding/proc/add_padding(padding_type, new_padding_color, do_icon_update = TRUE)
ASSERT(padding_type)
var/old_padding_material = padding_material
padding_material = ispath(padding_type) ? GET_DECL(padding_type) : padding_type
padding_color = new_padding_color
update_matter(old_padding_material, padding_material)
if(do_icon_update)
var/obj/obj_holder = holder
addtimer(CALLBACK(src, PROC_REF(update_holder_name)), 0, TIMER_UNIQUE) // Update at the end of the tick.
obj_holder.queue_icon_update()

/datum/extension/padding/proc/remove_padding(do_icon_update = TRUE)
if(padding_material)
var/list/res = padding_material.create_object(get_turf(holder))
if(padding_color)
for(var/obj/item/thing in res)
thing.set_color(padding_color)
var/old_padding_material = padding_material
padding_material = null
padding_color = null
update_matter(old_padding_material, padding_material)
if(do_icon_update)
var/obj/obj_holder = holder
if(istype(obj_holder, /obj/structure))
var/obj/structure/structure_holder = obj_holder
structure_holder.update_materials() // update name and description if needed
else if(isitem(obj_holder))
var/obj/item/item_holder = obj_holder
item_holder.update_name()
obj_holder.queue_icon_update()

/datum/extension/padding/proc/update_matter(decl/material/old_padding, decl/material/new_padding)
var/obj/obj_holder = holder
var/matter_mult = obj_holder.get_matter_amount_modifier()
if(LAZYLEN(obj_holder.matter) && old_padding)
obj_holder.matter[old_padding.type] -= MATTER_AMOUNT_TRACE * matter_mult
if(!obj_holder.matter[old_padding.type])
obj_holder.matter -= old_padding.type
if(new_padding)
LAZYINITLIST(obj_holder.matter)
obj_holder.matter[new_padding.type] += MATTER_AMOUNT_TRACE * matter_mult
UNSETEMPTY(obj_holder.matter)
3 changes: 3 additions & 0 deletions code/game/objects/__objs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@
wrench_floor_bolts(user, null, used_item)
update_icon()
return TRUE
var/datum/extension/padding/padding_extension = get_extension(src, __IMPLIED_TYPE__)
if(padding_extension && padding_extension.handle_use_item(used_item, user))
return TRUE
return ..()

/obj/proc/wrench_floor_bolts(mob/user, delay = 2 SECONDS, obj/item/tool)
Expand Down
42 changes: 24 additions & 18 deletions code/game/objects/items/crutches.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,20 @@
material_alteration = MAT_FLAG_ALTERATION_ALL
w_class = ITEM_SIZE_LARGE
max_health = null // autoset from material
/// The material used for the padding. If null, the crutch is unpadded. Initially a typepath, set to an instance in Initialize.
var/decl/material/padding_material
/// The color used for the padding, in the case of paint or dye. If null, falls back to padding material color.
var/padding_color = null
/// The padding extension type for this item. If null, no extension is created and this item cannot be padded.
var/padding_extension_type = /datum/extension/padding
/// The initial material used when instantiating this item's padding extension.
/// Should not be modified at runtime.
var/decl/material/initial_padding_material
/// The initial color used for the padding, representing paint or dye.
/// If null, falls back to material color if we have MAT_FLAG_ALTERATION_COLOR.
/// COLOR_WHITE is treated differently than null color is.
var/initial_padding_color

/obj/item/crutch/Initialize(ml, material_key)
padding_material = GET_DECL(padding_material)
return ..()

// potential todo: to avoid matter shenanigans make padding a separate item that can be removed via alt interaction and added via attackby?
// add padding by clicking with sewing tools in active hand and fabric in offhand?
/obj/item/crutch/create_matter()
. = ..()
if(padding_material)
matter[padding_material.type] += MATTER_AMOUNT_TRACE
if(padding_extension_type && initial_padding_material)
get_or_create_extension(src, padding_extension_type, initial_padding_material, initial_padding_color)

/obj/item/crutch/get_stance_support_value()
return LIMB_UNUSABLE
Expand All @@ -32,28 +31,35 @@

/obj/item/crutch/on_update_icon()
. = ..()
var/datum/extension/padding/padding_extension = get_extension(src, __IMPLIED_TYPE__)
var/decl/material/padding_material = padding_extension?.get_padding_material()
if(padding_material)
add_overlay(overlay_image(icon, "[icon_state]-padding", padding_color || padding_material.color, RESET_COLOR | RESET_ALPHA))
add_overlay(overlay_image(icon, "[icon_state]-padding", padding_extension.get_padding_color(material_alteration & MAT_FLAG_ALTERATION_COLOR), RESET_COLOR | RESET_ALPHA))

/obj/item/crutch/apply_additional_mob_overlays(mob/living/user_mob, bodytype, image/overlay, slot, bodypart, use_fallback_if_icon_missing = TRUE)
var/datum/extension/padding/padding_extension = get_extension(src, __IMPLIED_TYPE__)
var/decl/material/padding_material = padding_extension?.get_padding_material()
if(padding_material)
overlay.add_overlay(overlay_image(icon, "[overlay.icon_state]-padding", padding_color || padding_material.color, RESET_COLOR | RESET_ALPHA))
overlay.add_overlay(overlay_image(icon, "[overlay.icon_state]-padding", padding_extension.get_padding_color(material_alteration & MAT_FLAG_ALTERATION_COLOR), RESET_COLOR | RESET_ALPHA))
. = ..()

/obj/item/crutch/examine(mob/user, distance, infix, suffix)
. = ..()
var/datum/extension/padding/padding_extension = get_extension(src, __IMPLIED_TYPE__)
var/decl/material/padding_material = padding_extension?.get_padding_material()
if(padding_material)
to_chat(user, "It has been padded with [padding_color ? "<font color='[padding_color]'>[padding_material.paint_verb]</font> " : null][padding_material.use_name].")
var/padding_paint_color = padding_extension.get_padding_color(FALSE) // do not include material color
to_chat(user, "It has been padded with [padding_paint_color ? "<font color='[padding_paint_color]'>[padding_material.paint_verb]</font> " : null][padding_material.use_name].")

/obj/item/crutch/aluminum
material = /decl/material/solid/metal/aluminium

/obj/item/crutch/aluminum/padded
padding_material = /decl/material/solid/organic/plastic/foam
padding_color = COLOR_GRAY20
initial_padding_material = /decl/material/solid/organic/plastic/foam
initial_padding_color = COLOR_GRAY20

/obj/item/crutch/wooden
material = /decl/material/solid/organic/wood/oak

/obj/item/crutch/wooden/padded
padding_material = /decl/material/solid/organic/leather
initial_padding_material = /decl/material/solid/organic/leather
Loading

0 comments on commit dad0cfa

Please sign in to comment.