diff --git a/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
index db896ab95c5..7bde2d91f8f 100644
--- a/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
+++ b/_maps/map_files/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
@@ -656,7 +656,7 @@
/turf/simulated/floor/plasteel/lavaland_air,
/area/ruin/powered/clownplanet)
"bf" = (
-/turf/simulated/mineral/clown/volcanic,
+/turf/simulated/mineral/volcanic/clown,
/area/ruin/powered/clownplanet)
"bg" = (
/obj/item/pickaxe,
@@ -1006,7 +1006,7 @@
/obj/structure/disposalpipe/segment/corner{
dir = 8
},
-/turf/simulated/mineral/clown/volcanic,
+/turf/simulated/mineral/volcanic/clown,
/area/ruin/powered/clownplanet)
"pv" = (
/obj/machinery/light{
diff --git a/_maps/map_files/generic/Lavaland.dmm b/_maps/map_files/generic/Lavaland.dmm
index a3047e86d7a..c1955a7c2c5 100644
--- a/_maps/map_files/generic/Lavaland.dmm
+++ b/_maps/map_files/generic/Lavaland.dmm
@@ -73,7 +73,7 @@
/turf/simulated/mineral/random/volcanic,
/area/lavaland/surface/outdoors/unexplored)
"an" = (
-/turf/simulated/mineral/random/labormineral/volcanic,
+/turf/simulated/mineral/random/volcanic/labormineral,
/area/lavaland/surface/outdoors)
"ao" = (
/obj/effect/spawner/random_spawners/dirt_maybe,
diff --git a/code/__DEFINES/turfs.dm b/code/__DEFINES/turfs.dm
index b1104bbf713..9306a89a616 100644
--- a/code/__DEFINES/turfs.dm
+++ b/code/__DEFINES/turfs.dm
@@ -10,3 +10,6 @@
/// Returns a list of around us
#define TURF_NEIGHBORS(turf) (CORNER_BLOCK_OFFSET(turf, 3, 3, -1, -1) - turf)
+
+#define MINERAL_PREVENT_DIG 0 //! A mineral turf should not be changed when mined.
+#define MINERAL_ALLOW_DIG 1 //! A mineral turf should be dug out when mined.
diff --git a/code/datums/ores.dm b/code/datums/ores.dm
new file mode 100644
index 00000000000..7e0747669ab
--- /dev/null
+++ b/code/datums/ores.dm
@@ -0,0 +1,204 @@
+/datum/ore
+ /// The type of ore that is dropped. Expected to be a subtype of [/obj/item/stack/ore].
+ var/drop_type
+ /// The lower bound for the amount of randomized ore dropped.
+ var/drop_min = 1
+ /// The upper bound for the amount of randomized ore dropped.
+ var/drop_max = 5
+ /// The probability that the ore will spread to nearby [/turf/simulated/mineral]s when placed.
+ var/spread_chance = 0
+ /// The icon state of the ore used for mining scanner overlays.
+ var/scan_icon_state = ""
+
+/**
+ * Called when the containing turf is "mined", such as with a pickaxe or other
+ * digging implement.
+ *
+ * Returns [MINERAL_ALLOW_DIG] if the containing turf should be changed to its
+ * "dug" state, [MINERAL_PREVENT_DIG] if it should remain as is.
+ */
+/datum/ore/proc/on_mine(turf/source, mob/user, triggered_by_explosion = FALSE)
+ var/amount = rand(drop_min, drop_max)
+
+ if(ispath(drop_type, /obj/item/stack/ore))
+ new drop_type(source, amount)
+ SSticker.score?.score_ore_mined++
+ SSblackbox.record_feedback("tally", "ore_mined", amount, type)
+ else
+ stack_trace("[source.type] [COORD(source)] had non-ore stack [drop_type]")
+
+ return MINERAL_ALLOW_DIG
+
+/datum/ore/iron
+ drop_type = /obj/item/stack/ore/iron
+ spread_chance = 20
+ scan_icon_state = "rock_Iron"
+
+/datum/ore/uranium
+ drop_type = /obj/item/stack/ore/uranium
+ spread_chance = 5
+ scan_icon_state = "rock_Uranium"
+
+/datum/ore/diamond
+ drop_type = /obj/item/stack/ore/diamond
+ scan_icon_state = "rock_Diamond"
+
+/datum/ore/gold
+ drop_type = /obj/item/stack/ore/gold
+ spread_chance = 5
+ scan_icon_state = "rock_Gold"
+
+/datum/ore/silver
+ drop_type = /obj/item/stack/ore/silver
+ spread_chance = 5
+ scan_icon_state = "rock_Silver"
+
+/datum/ore/titanium
+ drop_type = /obj/item/stack/ore/titanium
+ spread_chance = 5
+ scan_icon_state = "rock_Titanium"
+
+/datum/ore/plasma
+ drop_type = /obj/item/stack/ore/plasma
+ spread_chance = 8
+ scan_icon_state = "rock_Plasma"
+
+/datum/ore/bluespace
+ drop_type = /obj/item/stack/ore/bluespace_crystal
+ drop_min = 1
+ drop_max = 1
+ scan_icon_state = "rock_BScrystal"
+
+/datum/ore/bananium
+ drop_type = /obj/item/stack/ore/bananium
+ drop_min = 3
+ drop_max = 3
+ scan_icon_state = "rock_Clown"
+
+/datum/ore/tranquillite
+ drop_type = /obj/item/stack/ore/tranquillite
+ drop_min = 3
+ drop_max = 3
+
+/datum/ore/ancient_basalt
+ drop_type = /obj/item/stack/ore/glass/basalt/ancient
+ drop_min = 2
+ drop_max = 2
+
+#define GIBTONITE_UNSTRUCK 0 //! The gibtonite ore is dormant.
+#define GIBTONITE_ACTIVE 1 //! The gibtonite ore is in its detonation countdown.
+#define GIBTONITE_STABLE 2 //! The gibtonite ore has been stabilized and its detonation countdown is cancelled.
+#define GIBTONITE_DETONATE 3 //! The gibtonite ore is about to explode.
+
+/datum/ore/gibtonite
+ drop_max = 1
+ scan_icon_state = "rock_Gibtonite"
+ /// Amount of time from mining before gibtonite explodes.
+ var/detonate_time
+ /// The world.time that the detonate countdown started at.
+ var/detonate_start_time
+ /// The amount of time remaining if the gibtonite was stabilized before explosion, in half-seconds.
+ var/remaining_time
+ /// The state the ore is in. One of [GIBTONITE_UNSTRUCK], [GIBTONITE_ACTIVE], [GIBTONITE_STABLE], or [GIBTONITE_DETONATE].
+ var/stage = GIBTONITE_UNSTRUCK
+ /// The overlay used for when the gibtonite is in its detonation countdown mode.
+ var/mutable_appearance/activated_overlay
+ /// Whether an admin log should be generated for this gibtonite's detonation.
+ /// Typically enabled if the detonation doesn't occur on the station z-level.
+ /// Note that this is only for explosions caused while the gibtonite is still
+ /// unmined, in contrast to [/obj/item/gibtonite/proc/GibtoniteReaction].
+ var/notify_admins = FALSE
+
+/datum/ore/gibtonite/New()
+ // So you don't know exactly when the hot potato will explode
+ detonate_time = rand(4 SECONDS, 5 SECONDS)
+
+/datum/ore/gibtonite/proc/explosive_reaction(turf/source, mob/user, triggered_by_explosion = FALSE)
+ activated_overlay = mutable_appearance(source.icon, "rock_Gibtonite_active", ON_EDGED_TURF_LAYER)
+ source.add_overlay(activated_overlay)
+ source.name = "gibtonite deposit"
+ source.desc = "An active gibtonite reserve. Run!"
+ stage = GIBTONITE_ACTIVE
+ source.visible_message("There was gibtonite inside! It's going to explode!")
+
+ if(!is_mining_level(source.z))
+ notify_admins = TRUE
+ if(!triggered_by_explosion)
+ message_admins("[key_name_admin(user)] has triggered a gibtonite deposit reaction at [ADMIN_VERBOSEJMP(source)].")
+ else
+ message_admins("An explosion has triggered a gibtonite deposit reaction at [ADMIN_VERBOSEJMP(source)].")
+
+ if(!triggered_by_explosion)
+ log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [AREACOORD(source)].")
+ else
+ log_game("An explosion has triggered a gibtonite deposit reaction at [AREACOORD(source)].")
+
+ RegisterSignal(source, COMSIG_PARENT_ATTACKBY, PROC_REF(on_parent_attackby))
+ detonate_start_time = world.time
+ addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/ore/gibtonite, detonate), source), detonate_time)
+
+/datum/ore/gibtonite/on_mine(turf/source, mob/user, triggered_by_explosion = FALSE)
+ switch(stage)
+ if(GIBTONITE_UNSTRUCK)
+ playsound(src,'sound/effects/hit_on_shattered_glass.ogg', 50, TRUE)
+ explosive_reaction(source, user, triggered_by_explosion)
+ return MINERAL_PREVENT_DIG
+ if(GIBTONITE_ACTIVE)
+ detonate(source)
+
+ return MINERAL_ALLOW_DIG
+ if(GIBTONITE_STABLE)
+ var/obj/item/gibtonite/gibtonite = new(source)
+ if(remaining_time <= 0)
+ gibtonite.quality = 3
+ gibtonite.icon_state = "Gibtonite ore 3"
+ if(remaining_time >= 1 && remaining_time <= 2)
+ gibtonite.quality = 2
+ gibtonite.icon_state = "Gibtonite ore 2"
+
+ return MINERAL_ALLOW_DIG
+
+ return MINERAL_PREVENT_DIG
+
+/datum/ore/gibtonite/proc/on_parent_attackby(turf/source, obj/item/attacker, mob/user)
+ SIGNAL_HANDLER // COMSIG_PARENT_ATTACKBY
+
+ if(istype(attacker, /obj/item/mining_scanner) || istype(attacker, /obj/item/t_scanner/adv_mining_scanner) && stage == GIBTONITE_ACTIVE)
+ user.visible_message("[user] holds [attacker] to [src]...", "You use [attacker] to locate where to cut off the chain reaction and attempt to stop it...")
+ defuse(source)
+ return COMPONENT_NO_AFTERATTACK
+
+/datum/ore/gibtonite/proc/detonate(turf/simulated/mineral/source)
+ if(stage == GIBTONITE_STABLE)
+ return
+
+ stage = GIBTONITE_DETONATE
+ explosion(source, 1, 3, 5, adminlog = notify_admins)
+
+ if(!istype(source))
+ return
+
+ // Dunno where else to put this
+ source.ChangeTurf(source.turf_type, source.defer_change)
+ addtimer(CALLBACK(source, TYPE_PROC_REF(/turf, AfterChange)), 1, TIMER_UNIQUE)
+
+/datum/ore/gibtonite/proc/defuse(turf/source)
+ var/world_time = world.time // Grab this immediately so we're fairly calculating countdown time
+ if(stage == GIBTONITE_ACTIVE)
+ source.cut_overlay(activated_overlay)
+ activated_overlay.icon_state = "rock_Gibtonite_inactive"
+ source.add_overlay(activated_overlay)
+ source.desc = "An inactive gibtonite reserve. The ore can be extracted."
+ stage = GIBTONITE_STABLE
+
+ // ticks remaining / 10 = seconds remaining * 2 countdown decrements every second
+ remaining_time = floor((detonate_time - (world_time - detonate_start_time)) / 5)
+
+ if(remaining_time < 0)
+ remaining_time = 0
+ source.visible_message("The chain reaction was stopped! The gibtonite had [remaining_time] reactions left till the explosion!")
+
+#undef GIBTONITE_UNSTRUCK
+#undef GIBTONITE_ACTIVE
+#undef GIBTONITE_STABLE
+#undef GIBTONITE_DETONATE
diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm
index 3d9e34d5706..fdba192ee85 100644
--- a/code/game/turfs/simulated/minerals.dm
+++ b/code/game/turfs/simulated/minerals.dm
@@ -20,37 +20,54 @@
color = COLOR_ROCK
var/environment_type = "asteroid"
var/turf/simulated/floor/plating/turf_type = /turf/simulated/floor/plating/asteroid/airless
- var/mineralType = null
- var/mineralAmt = 3
- var/spread = 0 //will the seam spread?
- var/spreadChance = 0 //the percentile chance of an ore spreading to the neighboring tiles
var/last_act = 0
- var/scan_state = "" //Holder for the image we display when we're pinged by a mining scanner
+
var/defer_change = 0
var/mine_time = 4 SECONDS //Changes how fast the turf is mined by pickaxes, multiplied by toolspeed
/// Should this be set to the normal rock colour on init?
var/should_reset_color = TRUE
+ /// The ore type, if any, that should spawn in the wall on Initialize.
+ /// Expected to be a subtype of [/datum/ore].
+ var/preset_ore_type
+ /// The representation of the unmined ore in the wall, if any.
+ var/datum/ore/ore
+
/turf/simulated/mineral/Initialize(mapload)
. = ..()
+
if(should_reset_color)
color = COLOR_ROCK
- if(mineralType && mineralAmt && spread && spreadChance)
- for(var/dir in GLOB.cardinal)
- if(prob(spreadChance))
- var/turf/T = get_step(src, dir)
- if(istype(T, /turf/simulated/mineral/random))
- Spread(T)
+ if(preset_ore_type)
+ set_ore(preset_ore_type)
+
AddComponent(/datum/component/debris, DEBRIS_ROCK, -20, 10, 1)
-/turf/simulated/mineral/proc/Spread(turf/T)
- T.ChangeTurf(type)
+/turf/simulated/mineral/proc/set_ore(ore_type)
+ if(!ore_type)
+ return
+
+ if(ore)
+ qdel(ore)
+
+ ore = new ore_type()
+ if(ore.spread_chance)
+ for(var/dir in GLOB.cardinal)
+ if(prob(ore.spread_chance))
+ var/turf/simulated/mineral/T = get_step(src, dir)
+ if(istype(T))
+ T.set_ore(ore_type)
/turf/simulated/mineral/shuttleRotate(rotation)
QUEUE_SMOOTH(src)
/turf/simulated/mineral/attackby(obj/item/I, mob/user, params)
+ // TODO: Just sticking this here for now because attack chain refactor is coming later
+ // No point in threading this through everything right now
+ if(SEND_SIGNAL(src, COMSIG_PARENT_ATTACKBY, I, user, params) & COMPONENT_NO_AFTERATTACK)
+ return
+
if(!user.IsAdvancedToolUser())
to_chat(usr, "You don't have the dexterity to do this!")
return
@@ -75,13 +92,19 @@
else
return attack_hand(user)
-/turf/simulated/mineral/proc/gets_drilled()
- if(mineralType && (mineralAmt > 0))
- new mineralType(src, mineralAmt)
- SSticker.score?.score_ore_mined++
- SSblackbox.record_feedback("tally", "ore_mined", mineralAmt, mineralType)
+/turf/simulated/mineral/proc/mine_ore(mob/user, triggered_by_explosion)
+ if(!ore)
+ return MINERAL_ALLOW_DIG
+
for(var/obj/effect/temp_visual/mining_overlay/M in src)
qdel(M)
+
+ return ore.on_mine(src, user, triggered_by_explosion)
+
+/turf/simulated/mineral/proc/gets_drilled(mob/user, triggered_by_explosion = FALSE)
+ if(mine_ore(user, triggered_by_explosion) == MINERAL_PREVENT_DIG)
+ return
+
ChangeTurf(turf_type, defer_change)
addtimer(CALLBACK(src, PROC_REF(AfterChange)), 1, TIMER_UNIQUE)
playsound(src, 'sound/effects/break_stone.ogg', 50, 1) //beautiful destruction
@@ -135,29 +158,27 @@
gets_drilled(null, 1)
/turf/simulated/mineral/random
- var/mineralSpawnChanceList = list(/turf/simulated/mineral/uranium = 5, /turf/simulated/mineral/diamond = 1, /turf/simulated/mineral/gold = 10,
- /turf/simulated/mineral/silver = 12, /turf/simulated/mineral/plasma = 20, /turf/simulated/mineral/iron = 40, /turf/simulated/mineral/titanium = 11,
- /turf/simulated/mineral/gibtonite = 4, /turf/simulated/mineral/bscrystal = 1)
- //Currently, Adamantine won't spawn as it has no uses. -Durandan
- var/mineralChance = 13
+ var/mineralSpawnChanceList = list(
+ /datum/ore/iron = 40,
+ /datum/ore/plasma = 20,
+ /datum/ore/silver = 12,
+ /datum/ore/titanium = 11,
+ /datum/ore/gold = 10,
+ /datum/ore/uranium = 5,
+ /datum/ore/gibtonite = 4,
+ /datum/ore/bluespace = 1,
+ /datum/ore/diamond = 1,
+ )
+
+ var/mineralChance = 10
/turf/simulated/mineral/random/Initialize(mapload)
+ . = ..()
mineralSpawnChanceList = typelist("mineralSpawnChanceList", mineralSpawnChanceList)
-
- . = ..()
if(prob(mineralChance))
- var/path = pickweight(mineralSpawnChanceList)
- var/turf/T = ChangeTurf(path, FALSE, TRUE, TRUE)
-
- if(T && ismineralturf(T))
- var/turf/simulated/mineral/M = T
- M.mineralAmt = rand(1, 5)
- M.environment_type = environment_type
- M.turf_type = turf_type
- M.baseturf = baseturf
- src = M
- M.levelupdate()
+ var/new_ore_type = pickweight(mineralSpawnChanceList)
+ set_ore(new_ore_type)
/turf/simulated/mineral/ancient
name = "ancient rock"
@@ -169,8 +190,6 @@
layer = MAP_EDITOR_TURF_LAYER
real_layer = TURF_LAYER
should_reset_color = FALSE
- mineralAmt = 2
- mineralType = /obj/item/stack/ore/glass/basalt/ancient
baseturf = /turf/simulated/floor/plating/asteroid/ancient
/turf/simulated/mineral/ancient/attackby(obj/item/I, mob/user, params)
@@ -269,14 +288,27 @@
color = COLOR_YELLOW
mineralChance = 25
mineralSpawnChanceList = list(
- /turf/simulated/mineral/uranium = 35, /turf/simulated/mineral/diamond = 30, /turf/simulated/mineral/gold = 45, /turf/simulated/mineral/titanium = 45,
- /turf/simulated/mineral/silver = 50, /turf/simulated/mineral/plasma = 50, /turf/simulated/mineral/bscrystal = 20)
+ /datum/ore/silver = 50,
+ /datum/ore/plasma = 50,
+ /datum/ore/gold = 45,
+ /datum/ore/titanium = 45,
+ /datum/ore/uranium = 35,
+ /datum/ore/diamond = 30,
+ /datum/ore/bluespace = 20,
+ )
/turf/simulated/mineral/random/high_chance/clown
mineralChance = 40
mineralSpawnChanceList = list(
- /turf/simulated/mineral/uranium = 35, /turf/simulated/mineral/diamond = 2, /turf/simulated/mineral/gold = 5, /turf/simulated/mineral/silver = 5,
- /turf/simulated/mineral/iron = 30, /turf/simulated/mineral/clown = 15, /turf/simulated/mineral/mime = 15, /turf/simulated/mineral/bscrystal = 10)
+ /datum/ore/uranium = 35,
+ /datum/ore/iron = 30,
+ /datum/ore/bananium = 15,
+ /datum/ore/tranquillite = 15,
+ /datum/ore/bluespace = 10,
+ /datum/ore/gold = 5,
+ /datum/ore/silver = 5,
+ /datum/ore/diamond = 2,
+ )
/turf/simulated/mineral/random/high_chance/volcanic
environment_type = "basalt"
@@ -289,16 +321,29 @@
atmos_environment = ENVIRONMENT_LAVALAND
defer_change = 1
mineralSpawnChanceList = list(
- /turf/simulated/mineral/uranium/volcanic = 35, /turf/simulated/mineral/diamond/volcanic = 30, /turf/simulated/mineral/gold/volcanic = 45, /turf/simulated/mineral/titanium/volcanic = 45,
- /turf/simulated/mineral/silver/volcanic = 50, /turf/simulated/mineral/plasma/volcanic = 50, /turf/simulated/mineral/bscrystal/volcanic = 20)
+ /datum/ore/silver = 50,
+ /datum/ore/plasma = 50,
+ /datum/ore/gold = 45,
+ /datum/ore/titanium = 45,
+ /datum/ore/uranium = 35,
+ /datum/ore/diamond = 30,
+ /datum/ore/bluespace = 20,
+ )
/turf/simulated/mineral/random/low_chance
color = COLOR_VIOLET
mineralChance = 6
mineralSpawnChanceList = list(
- /turf/simulated/mineral/uranium = 2, /turf/simulated/mineral/diamond = 1, /turf/simulated/mineral/gold = 4, /turf/simulated/mineral/titanium = 4,
- /turf/simulated/mineral/silver = 6, /turf/simulated/mineral/plasma = 15, /turf/simulated/mineral/iron = 40,
- /turf/simulated/mineral/gibtonite = 2, /turf/simulated/mineral/bscrystal = 1)
+ /datum/ore/iron = 40,
+ /datum/ore/plasma = 15,
+ /datum/ore/silver = 6,
+ /datum/ore/gold = 4,
+ /datum/ore/titanium = 4,
+ /datum/ore/gibtonite = 2,
+ /datum/ore/uranium = 2,
+ /datum/ore/diamond = 1,
+ /datum/ore/bluespace = 1,
+ )
/turf/simulated/mineral/random/volcanic
environment_type = "basalt"
@@ -311,343 +356,52 @@
atmos_environment = ENVIRONMENT_LAVALAND
defer_change = 1
- mineralChance = 10
- mineralSpawnChanceList = list(
- /turf/simulated/mineral/uranium/volcanic = 5,
- /turf/simulated/mineral/diamond/volcanic = 1,
- /turf/simulated/mineral/gold/volcanic = 10,
- /turf/simulated/mineral/titanium/volcanic = 11,
- /turf/simulated/mineral/silver/volcanic = 12,
- /turf/simulated/mineral/plasma/volcanic = 20,
- /turf/simulated/mineral/iron/volcanic = 40,
- /turf/simulated/mineral/gibtonite/volcanic = 4,
- /turf/simulated/mineral/bscrystal/volcanic = 1
- )
-
/turf/simulated/mineral/random/labormineral
mineralSpawnChanceList = list(
- /turf/simulated/mineral/uranium = 3, /turf/simulated/mineral/diamond = 1, /turf/simulated/mineral/gold = 8, /turf/simulated/mineral/titanium = 8,
- /turf/simulated/mineral/silver = 20, /turf/simulated/mineral/plasma = 30, /turf/simulated/mineral/iron = 95,
- /turf/simulated/mineral/gibtonite = 2)
+ /datum/ore/iron = 95,
+ /datum/ore/plasma = 30,
+ /datum/ore/silver = 20,
+ /datum/ore/gold = 8,
+ /datum/ore/titanium = 8,
+ /datum/ore/uranium = 3,
+ /datum/ore/gibtonite = 2,
+ /datum/ore/diamond = 1,
+ )
color = COLOR_MAROON
-/turf/simulated/mineral/random/labormineral/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/lava/mapping_lava
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
+/turf/simulated/mineral/random/volcanic/labormineral
mineralSpawnChanceList = list(
- /turf/simulated/mineral/uranium/volcanic = 3, /turf/simulated/mineral/diamond/volcanic = 1, /turf/simulated/mineral/gold/volcanic = 8, /turf/simulated/mineral/titanium/volcanic = 8,
- /turf/simulated/mineral/silver/volcanic = 20, /turf/simulated/mineral/plasma/volcanic = 30, /turf/simulated/mineral/bscrystal/volcanic = 1, /turf/simulated/mineral/gibtonite/volcanic = 2,
- /turf/simulated/mineral/iron/volcanic = 95)
+ /datum/ore/iron = 95,
+ /datum/ore/plasma = 30,
+ /datum/ore/silver = 20,
+ /datum/ore/titanium = 8,
+ /datum/ore/gold = 8,
+ /datum/ore/uranium = 3,
+ /datum/ore/gibtonite = 2,
+ /datum/ore/bluespace = 1,
+ /datum/ore/diamond = 1,
+ )
// Actual minerals
-/turf/simulated/mineral/iron
- mineralType = /obj/item/stack/ore/iron
- spreadChance = 20
- spread = 1
- scan_state = "rock_Iron"
-
-/turf/simulated/mineral/iron/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/uranium
- mineralType = /obj/item/stack/ore/uranium
- spreadChance = 5
- spread = 1
- scan_state = "rock_Uranium"
-
-/turf/simulated/mineral/uranium/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/diamond
- mineralType = /obj/item/stack/ore/diamond
- spreadChance = 0
- spread = 1
- scan_state = "rock_Diamond"
-
-/turf/simulated/mineral/diamond/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/gold
- mineralType = /obj/item/stack/ore/gold
- spreadChance = 5
- spread = 1
- scan_state = "rock_Gold"
-
-/turf/simulated/mineral/gold/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/silver
- mineralType = /obj/item/stack/ore/silver
- spreadChance = 5
- spread = 1
- scan_state = "rock_Silver"
-
-/turf/simulated/mineral/silver/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/titanium
- mineralType = /obj/item/stack/ore/titanium
- spreadChance = 5
- spread = 1
- scan_state = "rock_Titanium"
-
-/turf/simulated/mineral/titanium/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/plasma
- mineralType = /obj/item/stack/ore/plasma
- spreadChance = 8
- spread = 1
- scan_state = "rock_Plasma"
-
-/turf/simulated/mineral/plasma/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
/turf/simulated/mineral/clown
- mineralType = /obj/item/stack/ore/bananium
- mineralAmt = 3
- spreadChance = 0
- spread = 0
- scan_state = "rock_Clown"
-
-/turf/simulated/mineral/clown/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/mime
- mineralType = /obj/item/stack/ore/tranquillite
- mineralAmt = 3
- spreadChance = 0
- spread = 0
-
-/turf/simulated/mineral/mime/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-/turf/simulated/mineral/bscrystal
- mineralType = /obj/item/stack/ore/bluespace_crystal
- mineralAmt = 1
- spreadChance = 0
- spread = 0
- scan_state = "rock_BScrystal"
-
-/turf/simulated/mineral/bscrystal/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
+ preset_ore_type = /datum/ore/bananium
/turf/simulated/mineral/volcanic
environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt
- baseturf = /turf/simulated/floor/plating/asteroid/basalt
+ turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
+ baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
oxygen = LAVALAND_OXYGEN
nitrogen = LAVALAND_NITROGEN
temperature = LAVALAND_TEMPERATURE
atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
atmos_environment = ENVIRONMENT_LAVALAND
+ defer_change = 1
+
+/turf/simulated/mineral/volcanic/clown
+ preset_ore_type = /datum/ore/bananium
/turf/simulated/mineral/volcanic/lava_land_surface
environment_type = "basalt"
turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
baseturf = /turf/simulated/floor/lava/mapping_lava
defer_change = 1
-
-//gibtonite state defines
-#define GIBTONITE_UNSTRUCK 0
-#define GIBTONITE_ACTIVE 1
-#define GIBTONITE_STABLE 2
-#define GIBTONITE_DETONATE 3
-
-// Gibtonite
-/turf/simulated/mineral/gibtonite
- mineralAmt = 1
- spreadChance = 0
- spread = 0
- scan_state = "rock_Gibtonite"
- var/det_time = 8 //Countdown till explosion, but also rewards the player for how close you were to detonation when you defuse it
- var/stage = GIBTONITE_UNSTRUCK //How far into the lifecycle of gibtonite we are
- var/activated_ckey = null //These are to track who triggered the gibtonite deposit for logging purposes
- var/activated_name = null
- var/mutable_appearance/activated_overlay
-
-/turf/simulated/mineral/gibtonite/Initialize(mapload)
- det_time = rand(8,10) //So you don't know exactly when the hot potato will explode
- . = ..()
-
-/turf/simulated/mineral/gibtonite/attackby(obj/item/I, mob/user, params)
- if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) && stage == 1)
- user.visible_message("[user] holds [I] to [src]...", "You use [I] to locate where to cut off the chain reaction and attempt to stop it...")
- defuse()
- else
- return ..()
-
-/turf/simulated/mineral/gibtonite/proc/explosive_reaction(mob/user = null, triggered_by_explosion = 0)
- if(stage == GIBTONITE_UNSTRUCK)
- activated_overlay = mutable_appearance(icon, "rock_Gibtonite_active", ON_EDGED_TURF_LAYER)
- add_overlay(activated_overlay)
- name = "gibtonite deposit"
- desc = "An active gibtonite reserve. Run!"
- stage = GIBTONITE_ACTIVE
- visible_message("There was gibtonite inside! It's going to explode!")
- var/turf/bombturf = get_turf(src)
- var/area/A = get_area(bombturf)
-
- var/notify_admins = 0
- if(!is_mining_level(z))
- notify_admins = 1
- if(!triggered_by_explosion)
- message_admins("[key_name_admin(user)] has triggered a gibtonite deposit reaction at [A.name] (JMP).")
- else
- message_admins("An explosion has triggered a gibtonite deposit reaction at [A.name] (JMP).")
-
- if(!triggered_by_explosion)
- log_game("[key_name(user)] has triggered a gibtonite deposit reaction at [A.name] ([A.x], [A.y], [A.z]).")
- else
- log_game("An explosion has triggered a gibtonite deposit reaction at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
-
- countdown(notify_admins)
-
-/turf/simulated/mineral/gibtonite/proc/countdown(notify_admins = 0)
- set waitfor = 0
- while(istype(src, /turf/simulated/mineral/gibtonite) && stage == GIBTONITE_ACTIVE && det_time > 0 && mineralAmt >= 1)
- det_time--
- sleep(5)
- if(istype(src, /turf/simulated/mineral/gibtonite))
- if(stage == GIBTONITE_ACTIVE && det_time <= 0 && mineralAmt >= 1)
- var/turf/bombturf = get_turf(src)
- mineralAmt = 0
- stage = GIBTONITE_DETONATE
- explosion(bombturf, 1, 3, 5, adminlog = notify_admins)
-
-/turf/simulated/mineral/gibtonite/proc/defuse()
- if(stage == GIBTONITE_ACTIVE)
- cut_overlay(activated_overlay)
- activated_overlay.icon_state = "rock_Gibtonite_inactive"
- add_overlay(activated_overlay)
- desc = "An inactive gibtonite reserve. The ore can be extracted."
- stage = GIBTONITE_STABLE
- if(det_time < 0)
- det_time = 0
- visible_message("The chain reaction was stopped! The gibtonite had [det_time] reactions left till the explosion!")
-
-/turf/simulated/mineral/gibtonite/gets_drilled(mob/user, triggered_by_explosion = 0)
- if(stage == GIBTONITE_UNSTRUCK && mineralAmt >= 1) //Gibtonite deposit is activated
- playsound(src,'sound/effects/hit_on_shattered_glass.ogg', 50, TRUE)
- explosive_reaction(user, triggered_by_explosion)
- return
- if(stage == GIBTONITE_ACTIVE && mineralAmt >= 1) //Gibtonite deposit goes kaboom
- var/turf/bombturf = get_turf(src)
- mineralAmt = 0
- stage = GIBTONITE_DETONATE
- explosion(bombturf,1,2,5, adminlog = 0)
- if(stage == GIBTONITE_STABLE) //Gibtonite deposit is now benign and extractable. Depending on how close you were to it blowing up before defusing, you get better quality ore.
- var/obj/item/gibtonite/G = new(src)
- if(det_time <= 0)
- G.quality = 3
- G.icon_state = "Gibtonite ore 3"
- if(det_time >= 1 && det_time <= 2)
- G.quality = 2
- G.icon_state = "Gibtonite ore 2"
-
- ChangeTurf(turf_type, defer_change)
- addtimer(CALLBACK(src, PROC_REF(AfterChange)), 1, TIMER_UNIQUE)
-
-
-/turf/simulated/mineral/gibtonite/volcanic
- environment_type = "basalt"
- turf_type = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- baseturf = /turf/simulated/floor/plating/asteroid/basalt/lava_land_surface
- oxygen = LAVALAND_OXYGEN
- nitrogen = LAVALAND_NITROGEN
- temperature = LAVALAND_TEMPERATURE
- atmos_mode = ATMOS_MODE_EXPOSED_TO_ENVIRONMENT
- atmos_environment = ENVIRONMENT_LAVALAND
- defer_change = 1
-
-#undef GIBTONITE_UNSTRUCK
-#undef GIBTONITE_ACTIVE
-#undef GIBTONITE_STABLE
-#undef GIBTONITE_DETONATE
diff --git a/code/modules/mining/equipment/mineral_scanner.dm b/code/modules/mining/equipment/mineral_scanner.dm
index e610361bdd6..77b915f9427 100644
--- a/code/modules/mining/equipment/mineral_scanner.dm
+++ b/code/modules/mining/equipment/mineral_scanner.dm
@@ -26,8 +26,8 @@
/obj/item/mining_scanner/admin/attack_self(mob/user)
for(var/turf/simulated/mineral/M in world)
- if(M.scan_state)
- M.icon_state = M.scan_state
+ if(M.ore?.scan_icon_state)
+ M.icon_state = M.ore.scan_icon_state
qdel(src)
/obj/item/t_scanner/adv_mining_scanner
@@ -61,7 +61,7 @@
/proc/mineral_scan_pulse(turf/T, range = world.view)
var/list/minerals = list()
for(var/turf/simulated/mineral/M in range(range, T))
- if(M.scan_state)
+ if(M.ore?.scan_icon_state)
minerals += M
if(LAZYLEN(minerals))
for(var/turf/simulated/mineral/M in minerals)
@@ -69,7 +69,7 @@
if(oldC)
qdel(oldC)
var/obj/effect/temp_visual/mining_overlay/C = new /obj/effect/temp_visual/mining_overlay(M)
- C.icon_state = M.scan_state
+ C.icon_state = M.ore.scan_icon_state
/obj/effect/temp_visual/mining_overlay
plane = FULLSCREEN_PLANE
diff --git a/code/modules/mining/equipment/mining_charges.dm b/code/modules/mining/equipment/mining_charges.dm
index 6a1c104327a..730fb314195 100644
--- a/code/modules/mining/equipment/mining_charges.dm
+++ b/code/modules/mining/equipment/mining_charges.dm
@@ -81,8 +81,9 @@
S.start()
for(var/turf/simulated/mineral/rock in circlerangeturfs(location, boom_sizes[3]))
var/distance = get_dist_euclidian(location, rock)
- if(distance <= boom_sizes[3])
- rock.mineralAmt += 3 // if rock is going to get drilled, add bonus mineral amount
+ if(distance <= boom_sizes[3] && rock.ore)
+ rock.ore.drop_max += 3 // if rock is going to get drilled, add bonus mineral amount
+ rock.ore.drop_min += 3
rock.gets_drilled()
for(var/mob/living/carbon/C in circlerange(location, boom_sizes[3]))
var/distance = get_dist_euclidian(location, C)
diff --git a/paradise.dme b/paradise.dme
index 9f597f0c4fc..421676544b8 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -397,6 +397,7 @@
#include "code\datums\mixed.dm"
#include "code\datums\movement_detector.dm"
#include "code\datums\mutable_appearance.dm"
+#include "code\datums\ores.dm"
#include "code\datums\particles.dm"
#include "code\datums\pathfinding_mover.dm"
#include "code\datums\periodic_news.dm"
diff --git a/tools/UpdatePaths/Scripts/27043_mineral_ore_migration.txt b/tools/UpdatePaths/Scripts/27043_mineral_ore_migration.txt
new file mode 100644
index 00000000000..c2ffeb0b617
--- /dev/null
+++ b/tools/UpdatePaths/Scripts/27043_mineral_ore_migration.txt
@@ -0,0 +1,2 @@
+/turf/simulated/mineral/random/labormineral/volcanic : /turf/simulated/mineral/random/volcanic/labormineral
+/turf/simulated/mineral/clown/volcanic : /turf/simulated/mineral/volcanic/clown