Files
Polaris/code/modules/mining/mine_turfs.dm
Mechoid 7dc13d532f Demolishing Mobs (#9264)
* Work on the Bluespace Worm, Again.

Space worms propagate their sprites/tooltips/meat types/segment types from the head back.
Space worms have modified organ lists, only having a brain in their head.

Bluespace worms have a unique sprite done by Sypsoti/Schnayy

Bluespace worms have more xeno-organs in addition.

Bluespace worms convert eaten things to Magmellite, instead of Phoron.

* Target through walls.

Distance traveled when not hitting a solid structure during charge is based on the length of the worm.

Bluespace Worms drop xeno hide.

* can_demolish includes trees and barricades

simplemobs can now actually attack trees

* Truncated version of my Bluespace Worm pr.
Simplemob AI can be permitted to demolish walls, mineral turfs, and other common obstructions.

Simplemob AI can be given vision through walls, to make greater use of wall demolishing.

Spaceworm now has an AI controller with x-ray and demolishing capability to tunnel through rock / into buildings, and a wind-up charge that devours impacted mobs or structures.

* Thermic spiders are demolishers, and able to detect prey through walls.

* Inert.

* Decreased chance for thermic spiders to spawn, matching carriers and webslingers.

* Adjust for continued response & thoughts.

Thermic dropped to only Demolishing by default. Still a barricade buster, not a wallhacker.
Phorogenic bumped to be Demolishing. It's big, purple, and unlikely to care there's a twig in the way of its target.

Thermic now has an xray variant for PoI or adminspawn, similar to carriers having the recursion variant.

* Spiders:
Demolishing Phorogen and Thermic moved to subtypes

AI targeting only loops over range once, typecache manually checked for machines instead of making a new list from range again.

* AI targeting dist check instead of range

== FALSE check is a ! prefix, me.

Worm no longer early returns off its overshoot charge call as it does nothing but end the proc regardless of a successful movement

* Pain in two letters.
2024-01-14 14:10:24 -08:00

808 lines
25 KiB
Plaintext

var/global/list/mining_overlay_cache = list()
/**********************Mineral deposits**************************/
/turf/unsimulated/mineral
name = "impassable rock"
icon = 'icons/turf/walls.dmi'
icon_state = "rock-dark"
density = 1
/turf/simulated/mineral //wall piece
name = "rock"
icon = 'icons/turf/walls.dmi'
icon_state = "rock"
oxygen = 0
nitrogen = 0
opacity = 1
density = 1
blocks_air = 1
temperature = T0C
can_dirty = FALSE
var/floor_name = "sand"
var/rock_side_icon_state = "rock_side"
var/sand_icon_state = "asteroid"
var/rock_icon_state = "rock"
var/sand_icon_path = 'icons/turf/flooring/asteroid.dmi' // Override this on a subtype turf if you want a custom icon
var/rock_icon_path = 'icons/turf/walls.dmi' // Override this on a subtype turf if you want a custom icon
var/random_icon = 0
var/ore/mineral
var/sand_dug
var/mined_ore = 0
var/last_act = 0
var/overlay_detail
var/overlay_detail_icon_path = 'icons/turf/flooring/decals.dmi' // Override this on a subtype turf if you want a custom icon
var/datum/geosample/geologic_data
var/excavation_level = 0
var/list/finds
var/next_rock = 0
var/archaeo_overlay = ""
var/excav_overlay = ""
var/obj/item/last_find
var/datum/artifact_find/artifact_find
var/ignore_mapgen
var/static/list/ore_types = list(
"hematite" = /obj/item/ore/iron,
"uranium" = /obj/item/ore/uranium,
"gold" = /obj/item/ore/gold,
"silver" = /obj/item/ore/silver,
"diamond" = /obj/item/ore/diamond,
"phoron" = /obj/item/ore/phoron,
"osmium" = /obj/item/ore/osmium,
"hydrogen" = /obj/item/ore/hydrogen,
"silicates" = /obj/item/ore/glass,
"carbon" = /obj/item/ore/coal,
"verdantium" = /obj/item/ore/verdantium,
"marble" = /obj/item/ore/marble,
"lead" = /obj/item/ore/lead,
"copper" = /obj/item/ore/copper,
// "tin" = /obj/item/ore/tin,
"bauxite" = /obj/item/ore/bauxite,
"magmellite" = /obj/item/ore/magmellite,
// "painite" = /obj/item/ore/painite,
// "quartz" = /obj/item/ore/quartz,
"rutile" = /obj/item/ore/rutile
)
has_resources = 1
/turf/simulated/mineral/ChangeTurf(turf/N, tell_universe, force_lighting_update, preserve_outdoors)
clear_ore_effects()
. = ..()
/turf/simulated/mineral/xenoarch
name = "random digsite"
/turf/simulated/mineral/xenoarch/Initialize()
. = ..()
name = "rock"
make_digsite(rand(0,2))
/turf/simulated/mineral/ore
name = "random ore"
/turf/simulated/mineral/ore/Initialize()
. = ..()
name = "rock"
make_ore(prob(30))
// Alternative rock wall sprites.
/turf/simulated/mineral/light
icon_state = "rock-light"
rock_side_icon_state = "rock_side-light"
sand_icon_state = "sand-light"
rock_icon_state = "rock-light"
random_icon = 1
/turf/simulated/mineral/alt
icon_state = "rock-alt"
rock_side_icon_state = "rock_side-alt"
sand_icon_state = "asteroid"
rock_icon_state = "rock-alt"
/turf/simulated/mineral/icey
icon_state = "rock-icey"
rock_side_icon_state = "rock_side-icey"
sand_icon_state = "sand-icey" // to be replaced
rock_icon_state = "rock-icey"
/turf/simulated/mineral/crystal
icon_state = "rock-crystal"
rock_side_icon_state = "rock_side-crystal"
sand_icon_state = "sand-icey" // to be replaced
rock_icon_state = "rock-crystal"
/turf/simulated/mineral/crystal_shiny
icon_state = "rock-crystal-shiny"
rock_side_icon_state = "rock_side-crystal"
sand_icon_state = "sand-icey" // to be replaced
rock_icon_state = "rock-crystal-shiny"
/turf/simulated/mineral/moon
icon_state = "rock-moon"
rock_side_icon_state = "rock_side-moon"
sand_icon_state = "moonsand_fine"
rock_icon_state = "rock-moon"
/turf/simulated/mineral/moon/xenoarch
name = "random thor digsite"
/turf/simulated/mineral/moon/xenoarch/Initialize()
. = ..()
name = "rock"
make_digsite(rand(0,2))
/turf/simulated/mineral/moon/ore
name = "random thor ore"
/turf/simulated/mineral/moon/ore/Initialize()
. = ..()
name = "rock"
make_ore(prob(30))
/turf/simulated/mineral/ignore_mapgen
ignore_mapgen = 1
/turf/simulated/mineral/floor
name = "sand"
icon = 'icons/turf/flooring/asteroid.dmi'
icon_state = "asteroid"
density = 0
opacity = 0
blocks_air = 0
can_build_into_floor = TRUE
/turf/simulated/mineral/floor/mud
icon_state = "mud"
sand_icon_state = "mud"
/turf/simulated/mineral/floor/dirt
icon_state = "dirt"
sand_icon_state = "dirt"
//Alternative sand floor sprite.
/turf/simulated/mineral/floor/light
icon_state = "sand-light"
sand_icon_state = "sand-light"
/turf/simulated/mineral/floor/icey
icon_state = "sand-icey"
sand_icon_state = "sand-icey" // to be replaced
/turf/simulated/mineral/floor/light_border
icon_state = "sand-light-border"
sand_icon_state = "sand-light-border"
/turf/simulated/mineral/floor/light_nub
icon_state = "sand-light-nub"
sand_icon_state = "sand-light-nub"
/turf/simulated/mineral/floor/light_corner
icon_state = "sand-light-corner"
sand_icon_state = "sand-light-corner"
/turf/simulated/mineral/floor/moon
icon_state = "moonsand_fine"
sand_icon_state = "moonsand_fine"
/turf/simulated/mineral/floor/ignore_mapgen
ignore_mapgen = 1
/turf/simulated/mineral/proc/make_floor()
if(!density && !opacity)
return
density = 0
opacity = 0
blocks_air = 0
can_build_into_floor = TRUE
clear_ore_effects()
update_general()
/turf/simulated/mineral/proc/make_wall()
if(density && opacity)
return
density = 1
opacity = 1
blocks_air = 1
can_build_into_floor = FALSE
update_general()
/turf/simulated/mineral/proc/update_general()
update_icon(1)
recalc_atom_opacity()
if(ticker && ticker.current_state == GAME_STATE_PLAYING)
reconsider_lights()
if(air_master)
air_master.mark_for_update(src)
/turf/simulated/mineral/proc/get_cached_border(var/cache_id, var/direction, var/icon_file, var/icon_state, var/offset = 32)
//Cache miss
if(!mining_overlay_cache["[cache_id]_[direction]"])
var/image/new_cached_image = image(icon_state, dir = direction, layer = ABOVE_TURF_LAYER)
switch(direction)
if(NORTH)
new_cached_image.pixel_y = offset
if(SOUTH)
new_cached_image.pixel_y = -offset
if(EAST)
new_cached_image.pixel_x = offset
if(WEST)
new_cached_image.pixel_x = -offset
mining_overlay_cache["[cache_id]_[direction]"] = new_cached_image
return new_cached_image
//Cache hit
return mining_overlay_cache["[cache_id]_[direction]"]
/turf/simulated/mineral/Initialize()
. = ..()
if(prob(20))
overlay_detail = "[sand_icon_state][rand(0,9)]"
update_icon(1)
if(density && mineral)
. = INITIALIZE_HINT_LATELOAD
if(random_icon)
dir = pick(alldirs)
. = INITIALIZE_HINT_LATELOAD
var/decl/flooring/F = GET_DECL(/decl/flooring/sand)
footstep_sounds = F?.footstep_sounds
/turf/simulated/mineral/LateInitialize()
if(density && mineral)
MineralSpread()
/turf/simulated/mineral/update_icon(var/update_neighbors)
cut_overlays()
//We are a wall (why does this system work like this??)
if(density)
if(mineral)
name = "[mineral.display_name] deposit"
else
name = "rock"
icon = rock_icon_path
icon_state = rock_icon_state
//Apply overlays if we should have borders
for(var/direction in cardinal)
var/turf/T = get_step(src,direction)
if(istype(T) && !T.density)
add_overlay(get_cached_border(rock_side_icon_state,direction,icon,rock_side_icon_state))
if(archaeo_overlay)
add_overlay(archaeo_overlay)
if(excav_overlay)
add_overlay(excav_overlay)
//We are a sand floor
else
name = floor_name
icon = sand_icon_path
icon_state = sand_icon_state
if(sand_dug)
add_overlay("dug_overlay")
//Apply overlays if there's space
for(var/direction in cardinal)
if(istype(get_step(src, direction), /turf/space) && !istype(get_step(src, direction), /turf/space/cracked_asteroid))
add_overlay(get_cached_border("asteroid_edge",direction,icon,"asteroid_edges", 0))
//Or any time
else
var/turf/T = get_step(src, direction)
if(istype(T) && T.density)
add_overlay(get_cached_border(rock_side_icon_state,direction,rock_icon_path,rock_side_icon_state))
if(overlay_detail)
if(overlay_detail in icon_states(icon))
add_overlay(overlay_detail_icon_path,overlay_detail)
if(update_neighbors)
for(var/direction in alldirs)
if(istype(get_step(src, direction), /turf/simulated/mineral))
var/turf/simulated/mineral/M = get_step(src, direction)
M.update_icon()
if(istype(get_step(src, direction), /turf/simulated/wall/solidrock))
var/turf/simulated/wall/solidrock/M = get_step(src, direction)
M.update_icon()
/turf/simulated/mineral/ex_act(severity)
switch(severity)
if(2.0)
if (prob(70))
mined_ore = 1 //some of the stuff gets blown up
GetDrilled()
if(1.0)
mined_ore = 2 //some of the stuff gets blown up
GetDrilled()
if(severity <= 2 && length(resources)) // Now to expose the ore lying under the sand.
spawn(1) // Otherwise most of the ore is lost to the explosion, which makes this rather moot.
for(var/ore in resources)
var/amount_to_give = rand(CEILING(resources[ore] / 2, 1), resources[ore]) // Should result in at least one piece of ore.
for(var/i = 1 to amount_to_give)
var/oretype = ore_types[ore]
if(oretype)
new oretype(src)
resources = null
/turf/simulated/mineral/bullet_act(var/obj/item/projectile/Proj) // only emitters for now
if(Proj.excavation_amount)
var/newDepth = excavation_level + Proj.excavation_amount // Used commonly below
if(newDepth >= 200) // first, if the turf is completely drilled then don't bother checking for finds and just drill it
GetDrilled(0)
//destroy any archaeological finds
if(finds && finds.len)
var/datum/find/F = finds[1]
if(newDepth > F.excavation_required) // Digging too deep with something as clumsy or random as a blaster will destroy artefacts
finds.Remove(finds[1])
if(prob(50))
artifact_debris()
excavation_level += Proj.excavation_amount
update_archeo_overlays(Proj.excavation_amount)
/turf/simulated/mineral/attack_generic(var/mob/living/L, var/damage = 0, var/attack_text = "clawed")
. = ..()
if(!damage)
visible_message(SPAN_NOTICE("\The [L] [attack_text] \the [src] ineffectively."))
return FALSE
else
excavation_level = excavation_level + damage
visible_message(SPAN_WARNING("\The [L] [attack_text] \the [src], scattering [pick("gravel", "sand", "dust")]!"))
if(excavation_level >= 200)
GetDrilled(0)
return TRUE
/turf/simulated/mineral/Bumped(AM)
. = ..()
if(!density)
return .
if(istype(AM,/mob/living/carbon/human))
var/mob/living/carbon/human/H = AM
var/obj/item/pickaxe/P = H.get_inactive_hand()
if(istype(P))
src.attackby(P, H)
else if(istype(AM,/mob/living/silicon/robot))
var/mob/living/silicon/robot/R = AM
if(istype(R.module_active,/obj/item/pickaxe))
attackby(R.module_active,R)
else if(istype(AM,/obj/mecha))
var/obj/mecha/M = AM
if(istype(M.selected,/obj/item/mecha_parts/mecha_equipment/tool/drill))
M.selected.action(src)
/turf/simulated/mineral/proc/MineralSpread()
if(mineral && mineral.spread)
for(var/trydir in cardinal)
if(prob(mineral.spread_chance))
var/turf/simulated/mineral/target_turf = get_step(src, trydir)
if(istype(target_turf) && target_turf.density && !target_turf.mineral)
target_turf.mineral = mineral
target_turf.UpdateMineral()
target_turf.MineralSpread()
/turf/simulated/mineral/proc/UpdateMineral()
clear_ore_effects()
if((atom_flags & ATOM_INITIALIZED) && istype(mineral))
new /obj/effect/mineral(src, mineral)
update_icon()
//Not even going to touch this pile of spaghetti
/turf/simulated/mineral/attackby(obj/item/W as obj, mob/user as mob)
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
to_chat(user, "<span class='warning'>You don't have the dexterity to do this!</span>")
return
if(!density)
var/valid_tool = 0
var/digspeed = 40
if(istype(W, /obj/item/shovel))
var/obj/item/shovel/S = W
valid_tool = 1
digspeed = S.digspeed
if(istype(W, /obj/item/pickaxe))
var/obj/item/pickaxe/P = W
if(P.sand_dig)
valid_tool = 1
digspeed = P.digspeed
if(valid_tool)
if (sand_dug)
to_chat(user, "<span class='warning'>This area has already been dug.</span>")
return
var/turf/T = user.loc
if (!(istype(T)))
return
to_chat(user, "<span class='notice'>You start digging.</span>")
playsound(user, 'sound/effects/rustle1.ogg', 50, 1)
if(!do_after(user,digspeed)) return
to_chat(user, "<span class='notice'>You dug a hole.</span>")
GetDrilled()
else if(istype(W,/obj/item/storage/bag/ore))
var/obj/item/storage/bag/ore/S = W
if(S.collection_mode)
for(var/obj/item/ore/O in contents)
O.attackby(W,user)
return
else if(istype(W,/obj/item/storage/bag/fossils))
var/obj/item/storage/bag/fossils/S = W
if(S.collection_mode)
for(var/obj/item/fossil/F in contents)
F.attackby(W,user)
return
else if(istype(W, /obj/item/stack/rods))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
return
var/obj/item/stack/rods/R = W
if (R.use(1))
to_chat(user, "<span class='notice'>Constructing support lattice ...</span>")
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
new /obj/structure/lattice(get_turf(src))
else if(istype(W, /obj/item/stack/tile/floor))
var/obj/structure/lattice/L = locate(/obj/structure/lattice, src)
if(L)
var/obj/item/stack/tile/floor/S = W
if (S.get_amount() < 1)
return
qdel(L)
playsound(src, 'sound/weapons/Genhit.ogg', 50, 1)
ChangeTurf(/turf/simulated/floor)
S.use(1)
return
else
to_chat(user, "<span class='warning'>The plating is going to need some support.</span>")
return
else
if (istype(W, /obj/item/core_sampler))
geologic_data.UpdateNearbyArtifactInfo(src)
var/obj/item/core_sampler/C = W
C.sample_item(src, user)
return
if (istype(W, /obj/item/depth_scanner))
var/obj/item/depth_scanner/C = W
C.scan_atom(user, src)
return
if (istype(W, /obj/item/measuring_tape))
var/obj/item/measuring_tape/P = W
user.visible_message("<span class='notice'>\The [user] extends \a [P] towards \the [src].</span>","<span class='notice'>You extend \the [P] towards \the [src].</span>")
if(do_after(user, 15))
to_chat(user, "<span class='notice'>\The [src] has been excavated to a depth of [excavation_level]cm.</span>")
return
if(istype(W, /obj/item/xenoarch_multi_tool))
var/obj/item/xenoarch_multi_tool/C = W
if(C.mode) //Mode means scanning
C.depth_scanner.scan_atom(user, src)
else
user.visible_message("<span class='notice'>\The [user] extends \the [C] over \the [src], a flurry of red beams scanning \the [src]'s surface!</span>", "<span class='notice'>You extend \the [C] over \the [src], a flurry of red beams scanning \the [src]'s surface!</span>")
if(do_after(user, 15))
to_chat(user, "<span class='notice'>\The [src] has been excavated to a depth of [excavation_level]cm.</span>")
return
if (istype(W, /obj/item/pickaxe))
if(!istype(user.loc, /turf))
return
var/obj/item/pickaxe/P = W
if(last_act + P.digspeed > world.time)//prevents message spam
return
last_act = world.time
playsound(user, P.drill_sound, 20, 1)
var/newDepth = excavation_level + P.excavation_amount // Used commonly below
//handle any archaeological finds we might uncover
var/fail_message = ""
if(finds && finds.len)
var/datum/find/F = finds[1]
if(newDepth > F.excavation_required) // Digging too deep can break the item. At least you won't summon a Balrog (probably)
fail_message = ". <b>[pick("There is a crunching noise","[W] collides with some different rock","Part of the rock face crumbles away","Something breaks under [W]")]</b>"
wreckfinds(P.destroy_artefacts)
to_chat(user, "<span class='notice'>You start [P.drill_verb][fail_message].</span>")
if(do_after(user,P.digspeed))
if(finds && finds.len)
var/datum/find/F = finds[1]
if(newDepth == F.excavation_required) // When the pick hits that edge just right, you extract your find perfectly, it's never confined in a rock
excavate_find(1, F)
else if(newDepth > F.excavation_required - F.clearance_range) // Not quite right but you still extract your find, the closer to the bottom the better, but not above 80%
excavate_find(prob(80 * (F.excavation_required - newDepth) / F.clearance_range), F)
to_chat(user, "<span class='notice'>You finish [P.drill_verb] \the [src].</span>")
if(newDepth >= 200) // This means the rock is mined out fully
if(P.destroy_artefacts)
GetDrilled(0)
else
excavate_turf()
return
excavation_level += P.excavation_amount
update_archeo_overlays(P.excavation_amount)
//drop some rocks
next_rock += P.excavation_amount
while(next_rock > 50)
next_rock -= 50
var/obj/item/ore/O = new(src)
geologic_data.UpdateNearbyArtifactInfo(src)
O.geologic_data = geologic_data
return
return attack_hand(user)
/turf/simulated/mineral/proc/wreckfinds(var/destroy = FALSE)
if(!destroy && prob(90)) //nondestructive methods have a chance of letting you step away to not trash things
if(prob(25))
excavate_find(prob(5), finds[1])
else if(prob(50) || destroy) //destructive methods will always destroy finds, no bowls menacing with spikes for you
finds.Remove(finds[1])
if(prob(50))
artifact_debris()
/turf/simulated/mineral/proc/update_archeo_overlays(var/excavation_amount = 0)
var/updateIcon = 0
//archaeo overlays
if(!archaeo_overlay && finds && finds.len)
var/datum/find/F = finds[1]
if(F.excavation_required <= excavation_level + F.view_range)
cut_overlay(archaeo_overlay)
archaeo_overlay = "overlay_archaeo[rand(1,3)]"
add_overlay(archaeo_overlay)
else if(archaeo_overlay && (!finds || !finds.len))
cut_overlay(archaeo_overlay)
archaeo_overlay = null
//there's got to be a better way to do this
var/update_excav_overlay = 0
if(excavation_level >= 150)
if(excavation_level - excavation_amount < 150)
update_excav_overlay = 1
else if(excavation_level >= 100)
if(excavation_level - excavation_amount < 100)
update_excav_overlay = 1
else if(excavation_level >= 50)
if(excavation_level - excavation_amount < 50)
update_excav_overlay = 1
//update overlays displaying excavation level
if( !(excav_overlay && excavation_level > 0) || update_excav_overlay )
var/excav_quadrant = round(excavation_level / 25) + 1
if(excav_quadrant > 5)
excav_quadrant = 5
cut_overlay(excav_overlay)
excav_overlay = "overlay_excv[excav_quadrant]_[rand(1,3)]"
add_overlay(excav_overlay)
if(updateIcon)
update_icon()
/turf/simulated/mineral/proc/clear_ore_effects()
for(var/obj/effect/mineral/M in contents)
qdel(M)
/turf/simulated/mineral/proc/DropMineral()
if(!mineral)
return
clear_ore_effects()
var/obj/item/ore/O = new mineral.ore (src)
if(istype(O))
geologic_data.UpdateNearbyArtifactInfo(src)
O.geologic_data = geologic_data
return O
/turf/simulated/mineral/proc/excavate_turf()
var/obj/structure/boulder/B
if(artifact_find)
if( excavation_level > 0 || prob(15) )
//boulder with an artifact inside
B = new(src)
if(artifact_find)
B.artifact_find = artifact_find
else
artifact_debris(1)
else if(prob(5))
//empty boulder
B = new(src)
if(B)
GetDrilled(0)
else
GetDrilled(1)
return
/turf/simulated/mineral/proc/GetDrilled(var/artifact_fail = 0)
if(!density)
if(!sand_dug)
sand_dug = 1
for(var/i=0;i<5;i++)
new/obj/item/ore/glass(src)
update_icon()
return
if (mineral && mineral.result_amount)
//if the turf has already been excavated, some of it's ore has been removed
for (var/i = 1 to mineral.result_amount - mined_ore)
DropMineral()
GLOB.rocks_drilled_roundstat++
//destroyed artifacts have weird, unpleasant effects
//make sure to destroy them before changing the turf though
if(artifact_find && artifact_fail)
var/pain = 0
if(prob(50))
pain = 1
for(var/mob/living/M in range(src, 200))
to_chat(M, "<span class='danger'>[pick("A high-pitched [pick("keening","wailing","whistle")]","A rumbling noise like [pick("thunder","heavy machinery")]")] somehow penetrates your mind before fading away!</span>")
if(pain)
flick("pain",M.pain)
if(prob(50))
M.adjustBruteLoss(5)
else
M.flash_eyes()
if(prob(50))
M.Stun(5)
SSradiation.flat_radiate(src, 25, 100)
if(prob(25))
excavate_find(prob(5), finds[1])
else if(rand(1,500) == 1)
visible_message("<span class='notice'>An old dusty crate was buried within!</span>")
new /obj/structure/closet/crate/secure/decalock/loot(src)
make_floor()
update_icon(1)
/turf/simulated/mineral/proc/excavate_find(var/is_clean = 0, var/datum/find/F)
//with skill and luck, players can cleanly extract finds
//otherwise, they come out inside a chunk of rock
var/obj/item/X
if(is_clean)
X = new /obj/item/archaeological_find(src, F.find_type)
else
X = new /obj/item/strangerock(src, F.find_type)
geologic_data.UpdateNearbyArtifactInfo(src)
var/obj/item/strangerock/SR = X
SR.geologic_data = geologic_data
//some find types delete the /obj/item/archaeological_find and replace it with something else, this handles when that happens
//yuck
var/display_name = "Something"
if(!X)
X = last_find
if(X)
display_name = X.name
//many finds are ancient and thus very delicate - luckily there is a specialised energy suspension field which protects them when they're being extracted
if(prob(F.prob_delicate))
var/obj/effect/suspension_field/S = locate() in src
if(!S)
if(X)
visible_message("<span class='danger'>\The [pick("[display_name] crumbles away into dust","[display_name] breaks apart")].</span>")
qdel(X)
finds.Remove(F)
/turf/simulated/mineral/proc/artifact_debris(var/severity = 0)
//cael's patented random limited drop componentized loot system!
//sky's patented non-mischievious overhaul!
//Give a random amount of loot from 1 to 3 or 5, varying on severity.
for(var/j in 1 to rand(1, 3 + max(min(severity, 1), 0) * 2))
switch(rand(1,7))
if(1)
new /obj/item/stack/rods(src, rand(5,25))
if(2)
new /obj/item/stack/material/plasteel(src, rand(5,25))
if(3)
new /obj/item/stack/material/steel(src, rand(5,25))
if(4)
new /obj/item/stack/material/plasteel(src, rand(5,25))
if(5)
for(var/i=1 to rand(1,3))
new /obj/item/material/shard(src)
if(6)
for(var/i=1 to rand(1,3))
new /obj/item/material/shard/phoron(src)
if(7)
new /obj/item/stack/material/uranium(src, rand(5,25))
/turf/simulated/mineral/proc/make_ore(var/rare_ore)
if(mineral)
return
var/mineral_name
if(rare_ore)
mineral_name = pickweight(list("marble" = 5,/* "quartz" = 15,*/ "copper" = 10, /*"tin" = 5,*/ "bauxite" = 5, "uranium" = 15, "platinum" = 20, "hematite" = 15, "rutile" = 20, "carbon" = 15, "diamond" = 3, "gold" = 15, "silver" = 15, "phoron" = 25, "lead" = 5, "magmellite" = 1, "verdantium" = 2/*, "painite" = 1*/))
else
mineral_name = pickweight(list("marble" = 3,/* "quartz" = 10,*/ "copper" = 20, /*"tin" = 15,*/ "bauxite" = 15, "uranium" = 10, "platinum" = 10, "hematite" = 70, "rutile" = 15, "carbon" = 70, "diamond" = 2, "gold" = 10, "silver" = 10, "phoron" = 20, "lead" = 3, "magmellite" = 1, "verdantium" = 1/*, "painite" = 1*/))
if(mineral_name && (mineral_name in GLOB.ore_data))
mineral = GLOB.ore_data[mineral_name]
if(atom_flags & ATOM_INITIALIZED)
UpdateMineral()
update_icon()
// The value of range is turf-radius.
// digsite_type allows you to specify what type of digsite is spawned. code/modules/xenoarchaeology/finds/finds_defines.dm
// allow_anomalies is the probability, if any, of spawning an artifact in a turf, in the range. Garden and Animal digsites overwrite this probability.
/turf/simulated/mineral/proc/make_digsite(var/range = 0, var/digsite_type , var/allow_anomalies = 5)
var/digsite = digsite_type ? digsite_type : get_random_digsite_type()
for(var/turf/simulated/mineral/T in range(range,src))
if(LAZYLEN(T.finds))
continue
if(isnull(T.geologic_data))
T.geologic_data = new /datum/geosample(T)
if(isnull(T.finds) || isemptylist(T.finds))
T.finds = list()
if(prob(50))
T.finds.Add(new /datum/find(digsite, rand(10, 190)))
else if(prob(75))
T.finds.Add(new /datum/find(digsite, rand(10, 90)))
T.finds.Add(new /datum/find(digsite, rand(110, 190)))
else
T.finds.Add(new /datum/find(digsite, rand(10, 50)))
T.finds.Add(new /datum/find(digsite, rand(60, 140)))
T.finds.Add(new /datum/find(digsite, rand(150, 190)))
//sometimes a find will be close enough to the surface to show
var/datum/find/F = T.finds[1]
if(F.excavation_required <= F.view_range)
T.archaeo_overlay = "overlay_archaeo[rand(1,3)]"
T.update_icon()
if(!isnull(allow_anomalies) && prob(allow_anomalies))
//have a chance for an artifact to spawn here, but not in animal or plant digsites
if(isnull(T.artifact_find) && digsite != DIGSITE_GARDEN && digsite != DIGSITE_ANIMAL)
T.artifact_find = new()
T.update_icon()