Skip to content

Commit

Permalink
Merge pull request #4593 from MistakeNot4892/feature/gemstones
Browse files Browse the repository at this point in the history
Adding gemstones.
  • Loading branch information
out-of-phaze authored Dec 7, 2024
2 parents 000cefa + 1d54ca2 commit 076f629
Show file tree
Hide file tree
Showing 21 changed files with 303 additions and 71 deletions.
3 changes: 3 additions & 0 deletions code/game/turfs/flooring/_flooring.dm
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,6 @@ var/global/list/flooring_cache = list()

/decl/flooring/proc/handle_environment_proc(turf/floor/target)
return PROCESS_KILL

/decl/flooring/proc/handle_turf_digging(turf/floor/target)
return TRUE
4 changes: 4 additions & 0 deletions code/game/turfs/flooring/flooring_grass.dm
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
return TRUE
return ..()

/decl/flooring/grass/handle_turf_digging(turf/floor/target)
target.set_flooring(null)
return FALSE

/decl/flooring/grass/wild
name = "wild grass"
icon = 'icons/turf/flooring/wildgrass.dmi'
Expand Down
29 changes: 21 additions & 8 deletions code/game/turfs/floors/floor_digging.dm
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/turf/floor
var/gemstone_dropped = FALSE

/turf/floor/proc/is_fundament()
var/decl/flooring/flooring = get_topmost_flooring()
return flooring ? !flooring.constructed : TRUE
Expand All @@ -23,21 +26,31 @@
/turf/floor/can_dig_trench(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
return can_be_dug(tool_hardness, using_tool) && get_physical_height() > -(FLUID_DEEP)

/turf/floor/dig_trench(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
if(!is_fundament())
/turf/floor/dig_trench(mob/user, tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
if(is_fundament())
handle_trench_digging(user)

/turf/floor/proc/handle_trench_digging(mob/user)
var/decl/flooring/flooring = get_topmost_flooring()
if(!flooring.handle_turf_digging(src))
return
var/new_height = max(get_physical_height()-TRENCH_DEPTH_PER_ACTION, -(FLUID_DEEP))
var/height_diff = abs(get_physical_height()-new_height)
// Only drop mats if we actually changed the turf height sufficiently.
var/old_height = get_physical_height()
var/new_height = max(old_height-TRENCH_DEPTH_PER_ACTION, -(FLUID_DEEP))
var/height_diff = abs(old_height-new_height)
if(height_diff >= TRENCH_DEPTH_PER_ACTION)
drop_diggable_resources()
drop_diggable_resources(user)
set_physical_height(new_height)

/turf/floor/dig_pit(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
/turf/floor/dig_pit(mob/user, tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
return has_flooring() ? null : ..()

/turf/floor/get_diggable_resources()
var/decl/material/my_material = get_material()
if(is_fundament() && istype(my_material) && my_material.dug_drop_type && (get_physical_height() > -(FLUID_DEEP)))
return list(my_material.dug_drop_type = list(3, 2))
return null
. = list()
.[my_material.dug_drop_type] = list("amount" = 3, "variance" = 2, "material" = my_material.type)
if(!gemstone_dropped && prob(my_material.gemstone_chance) && LAZYLEN(my_material.gemstone_types))
gemstone_dropped = TRUE
var/gem_mat = pick(my_material.gemstone_types)
.[/obj/item/gemstone] = list("amount" = 1, "material" = gem_mat)
38 changes: 26 additions & 12 deletions code/game/turfs/turf_digging.dm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// Return an assoc list of resource item type to a base and a random component
/// ex. return list(/obj/item/stack/material/ore/handful/sand = list(3, 2))
/// Return an assoc list of resource item type to a metadata list containing base amount, random component, and material override
/// ex. return list(/obj/item/stack/material/ore/handful/sand = list("amount" = 3, "variance" = 2, "material" = /decl/material/foo))
/turf/proc/get_diggable_resources()
return null

Expand All @@ -10,17 +10,31 @@
/turf/proc/can_be_dug(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
return FALSE

/turf/proc/drop_diggable_resources()
/turf/proc/drop_diggable_resources(mob/user)
SHOULD_CALL_PARENT(TRUE)
var/list/diggable_resources = get_diggable_resources()
if(!length(diggable_resources))
return
for(var/resource_type in diggable_resources)
var/list/resource_amounts = diggable_resources[resource_type]

var/list/resource_data = diggable_resources[resource_type]
var/list/loot = list()
var/amount = max(1, resource_data["amount"] + resource_data["variance"])
var/spawn_material = resource_data["material"]

if(ispath(resource_type, /obj/item/stack))
LAZYADD(., new resource_type(src, resource_amounts[1] + rand(resource_amounts[2]), get_material_type()))
loot += new resource_type(src, amount, spawn_material)
else
LAZYADD(., new resource_type(src, get_material_type()))
for(var/i = 1 to amount)
loot += new resource_type(src, spawn_material)

if(length(loot))
if(user)
for(var/obj/item/thing in loot)
if(thing.material && thing.material != get_material())
to_chat(user, SPAN_NOTICE("You unearth \a [thing]!"))
LAZYADD(., loot)

clear_diggable_resources()

// Procs for digging pits.
Expand All @@ -29,10 +43,10 @@

/turf/proc/try_dig_pit(var/mob/user, var/obj/item/tool, using_tool = TOOL_SHOVEL)
if((!user && !tool) || tool.do_tool_interaction(using_tool, user, src, 5 SECONDS, check_skill = SKILL_HAULING, set_cooldown = TRUE))
return dig_pit(tool?.material?.hardness, using_tool)
return dig_pit(user, tool?.material?.hardness, using_tool)
return null

/turf/proc/dig_pit(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
/turf/proc/dig_pit(mob/user, tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
return can_dig_pit(tool_hardness, using_tool) && new /obj/structure/pit(src)

// Procs for digging farms.
Expand All @@ -44,10 +58,10 @@
if(!material?.tillable)
return
if((!user && !tool) || tool.do_tool_interaction(using_tool, user, src, 5 SECONDS, set_cooldown = TRUE, check_skill = SKILL_BOTANY))
return dig_farm(tool?.material?.hardness, using_tool)
return dig_farm(user, tool?.material?.hardness, using_tool)
return null

/turf/proc/dig_farm(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
/turf/proc/dig_farm(mob/user, tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
return can_dig_farm(tool_hardness, using_tool) && new /obj/machinery/portable_atmospherics/hydroponics/soil(src)

// Proc for digging trenches.
Expand All @@ -56,8 +70,8 @@

/turf/proc/try_dig_trench(mob/user, obj/item/tool, using_tool = TOOL_SHOVEL)
if((!user && !tool) || tool.do_tool_interaction(using_tool, user, src, 2.5 SECONDS, check_skill = SKILL_HAULING, set_cooldown = TRUE))
return dig_trench(tool?.material?.hardness, using_tool)
return dig_trench(user, tool?.material?.hardness, using_tool)
return null

/turf/proc/dig_trench(tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
/turf/proc/dig_trench(mob/user, tool_hardness = MAT_VALUE_MALLEABLE, using_tool = TOOL_SHOVEL)
return FALSE
5 changes: 5 additions & 0 deletions code/game/turfs/walls/wall_natural.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
var/image/ore_overlay
var/static/list/exterior_wall_shine_cache = list()
var/being_mined = FALSE
var/gem_dropped = FALSE

/turf/wall/natural/flooded
flooded = /decl/material/liquid/water
Expand Down Expand Up @@ -150,6 +151,10 @@
if(prob(30) && !ramp_slope_direction && material)
var/drop_type = material.ore_type || /obj/item/stack/material/ore
pass_geodata_to(new drop_type(src, material.ore_result_amount, material.type))
if(!gem_dropped && material && prob(material.gemstone_chance) && LAZYLEN(material.gemstone_types))
gem_dropped = TRUE
new /obj/item/gemstone(get_turf(src), pickweight(material.gemstone_types))
visible_message(SPAN_NOTICE("A glimmer of colour shines amongst the rubble..."))

/turf/wall/natural/proc/pass_geodata_to(obj/O)
var/datum/extension/geological_data/ours = get_extension(src, /datum/extension/geological_data)
Expand Down
89 changes: 89 additions & 0 deletions code/modules/gemstones/_gemstone.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
var/global/list/_available_gemstone_cuts

/proc/get_available_gemstone_cuts()
if(!global._available_gemstone_cuts)
global._available_gemstone_cuts = list()
for(var/decl/gemstone_cut/cut as anything in decls_repository.get_decls_of_type_unassociated(/decl/gemstone_cut))
if(cut.can_be_cut)
global._available_gemstone_cuts += cut
return global._available_gemstone_cuts

/obj/item/gemstone
name = "uncut gemstone"
desc = "A hunk of uncut gemstone."
icon = 'icons/obj/items/gemstones/uncut.dmi'
w_class = ITEM_SIZE_TINY
material = /decl/material/solid/gemstone/diamond
material_alteration = MAT_FLAG_ALTERATION_COLOR // Name and desc are handled manually.
var/decl/gemstone_cut/cut = /decl/gemstone_cut/uncut
var/work_skill = SKILL_CONSTRUCTION

/obj/item/gemstone/Initialize(ml, material_key)
cut = GET_DECL(cut)
. = ..()
update_from_cut()

/obj/item/gemstone/proc/update_from_cut()
icon = cut.icon
desc = cut.desc
update_name()
update_icon()

/obj/item/gemstone/update_name()
SetName("[cut.adjective] [material.solid_name]")

/obj/item/gemstone/get_single_monetary_worth()
. = ..() * cut.worth_multiplier

/obj/item/gemstone/attackby(obj/item/used_item, mob/user)
if(IS_HAMMER(used_item) && !user.check_intent(I_FLAG_HARM)) // TOOL_CHISEL when?
if(!cut.can_attempt_cut)
to_chat(user, SPAN_WARNING("\The [src] has already been cut."))
return TRUE
var/decl/gemstone_cut/desired_cut = input(user, "What cut would you like to attempt?", "Cut Gemstone") as null|anything in get_available_gemstone_cuts()
if(!desired_cut || QDELETED(src) || QDELETED(user) || !CanPhysicallyInteract(user) || !cut.can_attempt_cut)
return TRUE
user.visible_message(SPAN_NOTICE("\The [user] begins carefully cutting \the [src]."))
if(!user.do_skilled(10 SECONDS, work_skill, src, check_holding = TRUE) || !CanPhysicallyInteract(user))
if(QDELETED(src) || !cut.can_attempt_cut || QDELETED(user))
return TRUE
to_chat(user, SPAN_DANGER("You were interrupted, botching the cut!"))
cut = GET_DECL(/decl/gemstone_cut/poor)
else
if(QDELETED(src) || !cut.can_attempt_cut || QDELETED(user))
return TRUE
user.visible_message(SPAN_NOTICE("\The [user] finishes cutting \the [src]."))
if(user.skill_fail_prob(work_skill, 100, SKILL_EXPERT))
to_chat(user, SPAN_DANGER("You've done a really poor job..."))
cut = GET_DECL(/decl/gemstone_cut/poor)
else
cut = desired_cut
update_from_cut()
return TRUE
. = ..()

// Subtypes for mapping/spawning etc.
/obj/item/gemstone/poor
name = "poorly-cut diamond"
cut = /decl/gemstone_cut/poor
icon = 'icons/obj/items/gemstones/poor.dmi'

/obj/item/gemstone/baguette
name = "baguette-cut diamond"
cut = /decl/gemstone_cut/baguette
icon = 'icons/obj/items/gemstones/baguette.dmi'

/obj/item/gemstone/hexagon
name = "hexagon-cut diamond"
cut = /decl/gemstone_cut/hexagon
icon = 'icons/obj/items/gemstones/hexagon.dmi'

/obj/item/gemstone/octagon
name = "octagon-cut diamond"
cut = /decl/gemstone_cut/octagon
icon = 'icons/obj/items/gemstones/octagon.dmi'

/obj/item/gemstone/round
name = "round-cut diamond"
cut = /decl/gemstone_cut/round
icon = 'icons/obj/items/gemstones/round.dmi'
75 changes: 75 additions & 0 deletions code/modules/gemstones/gemstone_cuts.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/decl/gemstone_cut
abstract_type = /decl/gemstone_cut
var/worth_multiplier = 1.5
var/name
var/desc
var/adjective
var/icon
// Can we cut this cut into a new cut?
var/can_attempt_cut = FALSE
// Can we attempt to cut to this cut?
var/can_be_cut = TRUE

/decl/gemstone_cut/validate()
. = ..()
if(!istext(name))
. += "invalid or null name"
if(!istext(desc))
. += "invalid or null desc"
if(!istext(adjective))
. += "invalid or null adjective"
if(icon)
if(!check_state_in_icon(ICON_STATE_WORLD, icon))
. += "missing world state from '[icon]'"
if(!check_state_in_icon(ICON_STATE_INV, icon))
. += "missing inventory state from '[icon]'"
var/check_state = "[ICON_STATE_WORLD]-set"
if(!check_state_in_icon(check_state, icon))
. += "missing state '[check_state]' from '[icon]'"
check_state = "[ICON_STATE_INV]-set"
if(!check_state_in_icon(check_state, icon))
. += "missing state '[check_state]' from '[icon]'"
else
. += "null or unset icon"

// Subtypes below.
/decl/gemstone_cut/uncut
name = "uncut"
adjective = "uncut"
desc = "A rough, uncut gemstone."
icon = 'icons/obj/items/gemstones/uncut.dmi'
can_attempt_cut = TRUE
can_be_cut = FALSE
worth_multiplier = 1

/decl/gemstone_cut/poor
name = "poorly-cut"
adjective = "poorly-cut"
desc = "A poorly-cut and uneven gemstone."
icon = 'icons/obj/items/gemstones/poor.dmi'
worth_multiplier = 0.5
can_be_cut = FALSE

/decl/gemstone_cut/baguette
name = "baguette"
adjective = "baguette-cut"
desc = "A square-cut gemstone."
icon = 'icons/obj/items/gemstones/baguette.dmi'

/decl/gemstone_cut/hexagon
name = "hexagon"
adjective = "hexagon-cut"
desc = "A hexagon-cut gemstone."
icon = 'icons/obj/items/gemstones/hexagon.dmi'

/decl/gemstone_cut/octagon
name = "octagon"
adjective = "octagon-cut"
desc = "A octagon-cut gemstone."
icon = 'icons/obj/items/gemstones/octagon.dmi'

/decl/gemstone_cut/round
name = "round"
adjective = "round-cut"
desc = "A round-cut gemstone."
icon = 'icons/obj/items/gemstones/round.dmi'
5 changes: 5 additions & 0 deletions code/modules/materials/_materials.dm
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/gas_overlay)
/// If an item has a null paint_verb, it automatically sets it based on material.
var/paint_verb = "painted"

/// Chance of a natural wall made of this material dropping a gemstone, if the gemstone_types list is populated.
var/gemstone_chance = 5
/// Assoc weighted list of gemstone material types to weighting.
var/list/gemstone_types

// Placeholders for light tiles and rglass.
/decl/material/proc/reinforce(var/mob/user, var/obj/item/stack/material/used_stack, var/obj/item/stack/material/target_stack, var/use_sheets = 1)
if(!used_stack.can_use(use_sheets))
Expand Down
Loading

0 comments on commit 076f629

Please sign in to comment.