Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Statuettes #417

Merged
merged 13 commits into from
Feb 23, 2024
1 change: 1 addition & 0 deletions maplestation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -6234,6 +6234,7 @@
#include "maplestation_modules\code\modules\antagonists\advanced_traitor\advanced_traitor.dm"
#include "maplestation_modules\code\modules\antagonists\infiltrator\advanced_infiltrator.dm"
#include "maplestation_modules\code\modules\antagonists\infiltrator\infiltrator.dm"
#include "maplestation_modules\code\modules\art\statuettes.dm"
#include "maplestation_modules\code\modules\cargo\costumes_toys.dm"
#include "maplestation_modules\code\modules\cargo\packs.dm"
#include "maplestation_modules\code\modules\client\preferences\_preferences.dm"
Expand Down
169 changes: 169 additions & 0 deletions maplestation_modules/code/modules/art/statuettes.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
//Copied mostly from statues.dm with edits to apply for an item
/obj/item/statue/custom
name = "custom statue"
icon = 'icons/obj/art/statue.dmi'
icon_state = "base"
obj_flags = UNIQUE_RENAME
appearance_flags = TILE_BOUND | PIXEL_SCALE | KEEP_TOGETHER//Added keep together in case targets has weird layering
w_class = WEIGHT_CLASS_SMALL
/// primary statue overlay
var/mutable_appearance/content_ma
var/static/list/greyscale_with_value_bump = list(0,0,0, 0,0,0, 0,0,1, 0,0,-0.05)

//When out in the world, is tiny like action figures, but can pick up to see better
/obj/item/statue/custom/Initialize(mapload)
. = ..()
AddElement(/datum/element/item_scaling, 0.4, 1)
AddComponent(/datum/component/simple_rotation)

/obj/item/statue/AltClick(mob/user)
return ..() // This hotkey is BLACKLISTED since it's used by /datum/component/simple_rotation

/obj/item/statue/custom/Destroy()
content_ma = null
return ..()

/obj/item/statue/custom/proc/set_visuals(model_appearance)
if(content_ma)
QDEL_NULL(content_ma)
content_ma = new
content_ma.appearance = model_appearance
content_ma.pixel_x = 0
content_ma.pixel_y = 0
content_ma.alpha = 255

var/static/list/plane_whitelist = list(FLOAT_PLANE, GAME_PLANE, FLOOR_PLANE)

/// Ideally we'd have knowledge what we're removing but i'd have to be done on target appearance retrieval
var/list/overlays_to_keep = list()
for(var/mutable_appearance/special_overlay as anything in content_ma.overlays)
var/mutable_appearance/real = new()
real.appearance = special_overlay
if(PLANE_TO_TRUE(real.plane) in plane_whitelist)
overlays_to_keep += real
content_ma.overlays = overlays_to_keep

var/list/underlays_to_keep = list()
for(var/mutable_appearance/special_underlay as anything in content_ma.underlays)
var/mutable_appearance/real = new()
real.appearance = special_underlay
if(PLANE_TO_TRUE(real.plane) in plane_whitelist)
underlays_to_keep += real
content_ma.underlays = underlays_to_keep

content_ma.appearance_flags &= ~KEEP_APART //Don't want this
content_ma.filters = filter(type="color",color=greyscale_with_value_bump,space=FILTER_COLOR_HSV)
content_ma.plane = FLOAT_PLANE
content_ma.layer = FLOAT_LAYER
update_appearance()

/obj/item/modeling_block/update_overlays()
. = ..()
if(!target_appearance_with_filters)
return
//We're only keeping one instance here that changes in the middle so we have to clone it to avoid managed overlay issues
var/mutable_appearance/clone = new(target_appearance_with_filters)
. += clone

/obj/item/statue/custom/update_overlays()
. = ..()
if(content_ma)
. += content_ma

//Inhand version of a carving block that doesnt need a chisel
/obj/item/modeling_block
name = "Modeling block"
desc = "Ready for sculpting. Look for a subject and use in hand to sculpt."
icon = 'icons/obj/art/statue.dmi'
icon_state = "block"
w_class = WEIGHT_CLASS_SMALL

/// The thing it will look like - Unmodified resulting statue appearance
var/current_target
/// Currently chosen preset statue type
var/current_preset_type
/// statue completion from 0 to 1.0
var/completion = 0
/// Greyscaled target with cutout filter
var/mutable_appearance/target_appearance_with_filters
/// HSV color filters parameters
var/static/list/greyscale_with_value_bump = list(0,0,0, 0,0,0, 0,0,1, 0,0,-0.05)

//Adding chisel vars
/// Block we're currently carving in
var/obj/item/modeling_block/prepared_block
/// If tracked user moves we stop sculpting
var/mob/living/tracked_user
/// Currently sculpting
var/sculpting = FALSE

/obj/item/modeling_block/Initialize(mapload)
. = ..()
AddElement(/datum/element/item_scaling, 0.4, 1)

// Add to plastic recipes
/obj/item/stack/sheet/plastic/get_main_recipes()
. = ..()
. += list(new /datum/stack_recipe("Modeling block", /obj/item/modeling_block, 2, check_density = FALSE))


/obj/item/modeling_block/Destroy()
current_target = null
target_appearance_with_filters = null
return ..()

// We aim at something nearby to turn into our sculpting target and not bop it
/obj/item/modeling_block/pre_attack(atom/target, mob/user)
. = ..()
if(.)
return .
if (!sculpting && ismovable(target))
set_target(target,user)
return TRUE

// We aim at something to turn into our sculpting target
/obj/item/modeling_block/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
. = ..()

if (!sculpting && ismovable(target))
set_target(target,user)
return . | AFTERATTACK_PROCESSED_ITEM

/obj/item/modeling_block/proc/is_viable_target(mob/living/user, atom/movable/target)
//Only things on turfs
if(!isturf(target.loc))
user.balloon_alert(user, "no sculpting subject!")
return FALSE
//No big icon things
var/list/icon_dimensions = get_icon_dimensions(target.icon)
if(icon_dimensions["width"] > 2*world.icon_size || icon_dimensions["height"] > 2*world.icon_size)
user.balloon_alert(user, "subject is too big!")
return FALSE
return TRUE

/obj/item/modeling_block/proc/set_target(atom/movable/target, mob/living/user)
if(!is_viable_target(user, target))
return
if(istype(target,/obj/item/statue/custom))
var/obj/item/statue/custom/original = target
current_target = original.content_ma
else
current_target = target.appearance
var/mutable_appearance/ma = current_target
user.balloon_alert(user, "sculpting [target.name]")

/obj/item/modeling_block/attack_self(mob/user)
if(current_target)
create_statue(user)
else
balloon_alert(user, "no sculpting subject!")

/obj/item/modeling_block/proc/create_statue(mob/user)
var/obj/item/statue/custom/new_statue = new(user.loc)
new_statue.set_visuals(current_target)
var/mutable_appearance/ma = current_target
new_statue.name = "statuette of [ma.name]"
new_statue.desc = "A carved statuette depicting [ma.name]."
qdel(src)
user.put_in_active_hand(new_statue)

Loading