mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-11 08:06:33 +01:00
940d91bb62
## About The Pull Request Adds new floor types and natural decor to both Siderite and Shale biomes, as well as makes flora and fauna spawns differ between said biomes. <img width="1216" height="997" alt="dreamseeker_uIv1OgVkpD" src="https://github.com/user-attachments/assets/327d9caa-a58c-4d70-acbe-477da69b4d71" /> --- Basalt biome now spawns more legions and goliaths, but less watchers and no brimdemons. You can rarely find new volcanic pore rocks which will spew out lava when destroyed. <img width="505" height="361" alt="dreamseeker_TA9rXzOgad" src="https://github.com/user-attachments/assets/fb19a60a-c927-441b-abad-161ce5022a60" /> Siderite biome has a lot of rock formations and may sometimes spawn new stalagmites. You can expect to see a ton of bileworms, raptors and watchers there. <img width="747" height="613" alt="dreamseeker_uZgRX8qqh3" src="https://github.com/user-attachments/assets/d356f1c6-371a-4b8b-899b-470edb0d2790" /> Shale is full of lobstrocities, goldgrubs and brimdemons, and home to a new glowgrowth "plant" - colony of bioluminescent fungi growing on natural air vents. <img width="274" height="220" alt="dreamseeker_EtxiS4X9M7" src="https://github.com/user-attachments/assets/cbefba67-b618-4a65-ad12-9ee5182b650c" /> While it cannot be planted by itself, it contains luminescent fluid inside which will grant whoever eats it minor night vision as long as it is inside their bloodstream (as well as cyan-glowing eyes) --- Ruins now properly respect their biome's rock (and now floor as well) type, since it was broken for some of them previously. <details> <summary>More images under the dropdown</summary> <img width="1216" height="997" alt="dreamseeker_fpXXV0Rt3D" src="https://github.com/user-attachments/assets/fa790ca1-7045-490e-bcb2-c1f9da9f277c" /> <img width="414" height="303" alt="dreamseeker_l6E8S2fzCe" src="https://github.com/user-attachments/assets/8b10dcca-c546-41ce-9363-a12b0f225881" /> <img width="784" height="587" alt="dreamseeker_RUWQo0unNp" src="https://github.com/user-attachments/assets/d7364abc-ec68-4daf-b3cb-a03b8ba7e5de" /> <img width="1216" height="997" alt="dreamseeker_zoltABvkBw" src="https://github.com/user-attachments/assets/324f50f8-83c9-4451-8eff-33ebf81c1d0d" /> <img width="1125" height="571" alt="dreamseeker_ky5qvl2XtC" src="https://github.com/user-attachments/assets/ff08d22f-fc15-4961-b76e-7c10d7814096" /> </details> Credit for original versions of new flora/feature sprites to SentryPrimis on the /tg/station discord ## Why It's Good For The Game Makes biomes more distinct and interesting, as well as gives them unique atmosphere, since right now they only differ in rock type and mineral distribution. ## Changelog 🆑 SmArtKar, SentryPrimis add: Siderite and Shale lavaland biomes now have unique floors, as well as flora, features and fauna! fix: Fixed some ruins generating with default basalt walls instead of their biome's walls /🆑
738 lines
24 KiB
Plaintext
738 lines
24 KiB
Plaintext
#define ORESTACK_OVERLAYS_MAX 10
|
|
|
|
/**********************Mineral ores**************************/
|
|
|
|
/obj/item/stack/ore
|
|
name = "rock"
|
|
icon = 'icons/obj/ore.dmi'
|
|
icon_state = "ore"
|
|
inhand_icon_state = null
|
|
full_w_class = WEIGHT_CLASS_BULKY
|
|
singular_name = "ore chunk"
|
|
material_flags = MATERIAL_EFFECTS
|
|
novariants = TRUE // Ore stacks handle their icon updates themselves to keep the illusion that there's more going
|
|
drop_sound = SFX_STONE_DROP
|
|
pickup_sound = SFX_STONE_PICKUP
|
|
sound_vary = TRUE
|
|
/// How many points this ore gets you from the ore redemption machine
|
|
var/points = 0
|
|
/// What this ore defaults to being refined into
|
|
var/refined_type = null
|
|
/// How much experience do you get for mining this ore?
|
|
var/mine_experience = 5
|
|
var/list/stack_overlays
|
|
/// Used by mineral turfs for their scan overlay.
|
|
var/scan_state = ""
|
|
/// Chance that we'll spawn as a vein rather than a sole tile
|
|
var/spread_chance = 0
|
|
/// Type of ore vein we spawn, cluster/scatter/plain/branching
|
|
var/vein_type = ORE_VEIN_CLUSTER
|
|
/// Optimal distance from open turfs for us to spawn, 1 is next to an open tile
|
|
var/vein_distance = 1
|
|
/// Minimum distance that a vein can span, radius for cluster/scatter, maximum length for plain/branching
|
|
var/min_vein_size = 1
|
|
/// Minimum distance that a vein can span, radius for cluster/scatter, maximum length for plain/branching
|
|
var/max_vein_size = 2
|
|
|
|
/obj/item/stack/ore/update_overlays()
|
|
. = ..()
|
|
var/difference = min(ORESTACK_OVERLAYS_MAX, amount) - (LAZYLEN(stack_overlays)+1)
|
|
if(!difference)
|
|
return
|
|
|
|
if(difference < 0 && LAZYLEN(stack_overlays)) //amount < stack_overlays, remove excess.
|
|
if(LAZYLEN(stack_overlays)-difference <= 0)
|
|
stack_overlays = null
|
|
return
|
|
stack_overlays.len += difference
|
|
|
|
else //amount > stack_overlays, add some.
|
|
for(var/i in 1 to difference)
|
|
var/mutable_appearance/newore = mutable_appearance(icon, icon_state)
|
|
newore.pixel_w = rand(-8,8)
|
|
newore.pixel_z = rand(-8,8)
|
|
LAZYADD(stack_overlays, newore)
|
|
|
|
if(stack_overlays)
|
|
. += stack_overlays
|
|
|
|
/**
|
|
* Called when the ore is collected by an ore redemption machine. returns the ore itself.
|
|
* Normally, ores without a refined type aren't collected by the orm.
|
|
* It can also be overriden for more specific behavior (for example, sand is smelted into glass beforehand because of different mats).
|
|
*/
|
|
/obj/item/stack/ore/proc/on_orm_collection()
|
|
return isnull(refined_type) ? null : src
|
|
|
|
/obj/item/stack/ore/welder_act(mob/living/user, obj/item/I)
|
|
. = ..()
|
|
if(!refined_type)
|
|
return TRUE
|
|
|
|
if(!I.use_tool(src, user, 0, volume = 50))
|
|
return TRUE
|
|
|
|
var/sheets_made = values_sum(mats_per_unit) / SHEET_MATERIAL_AMOUNT
|
|
new refined_type(drop_location(), max(1, floor(sheets_made)))
|
|
use(max(1, ceil(1 / sheets_made)))
|
|
return TRUE
|
|
|
|
/obj/item/stack/ore/fire_act(exposed_temperature, exposed_volume)
|
|
. = ..()
|
|
if(isnull(refined_type))
|
|
return
|
|
|
|
var/probability = rand(0, 100) / 100
|
|
var/burn_value = probability * amount
|
|
var/amount_refined = floor(burn_value * values_sum(mats_per_unit) / SHEET_MATERIAL_AMOUNT)
|
|
if(amount_refined > 1)
|
|
new refined_type(drop_location(), amount_refined)
|
|
qdel(src)
|
|
|
|
/obj/item/stack/ore/uranium
|
|
name = "uranium ore"
|
|
icon_state = "uranium"
|
|
singular_name = "uranium ore chunk"
|
|
points = 30
|
|
material_flags = NONE
|
|
mats_per_unit = list(/datum/material/uranium = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/mineral/uranium
|
|
mine_experience = 6
|
|
scan_state = "rock_uranium"
|
|
spread_chance = 35
|
|
merge_type = /obj/item/stack/ore/uranium
|
|
vein_type = ORE_VEIN_PLAIN
|
|
vein_distance = 3
|
|
min_vein_size = 1
|
|
max_vein_size = 3
|
|
|
|
/obj/item/stack/ore/iron
|
|
name = "iron ore"
|
|
icon_state = "iron"
|
|
singular_name = "iron ore chunk"
|
|
points = 1
|
|
mats_per_unit = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/iron
|
|
mine_experience = 1
|
|
scan_state = "rock_iron"
|
|
spread_chance = 65
|
|
merge_type = /obj/item/stack/ore/iron
|
|
min_vein_size = 1
|
|
max_vein_size = 3
|
|
|
|
/obj/item/stack/ore/glass
|
|
name = "sand pile"
|
|
icon_state = "glass"
|
|
singular_name = "sand pile"
|
|
points = 1
|
|
mats_per_unit = list(/datum/material/sand = SHEET_MATERIAL_AMOUNT)
|
|
material_type = /datum/material/sand
|
|
refined_type = /obj/item/stack/sheet/glass
|
|
w_class = WEIGHT_CLASS_TINY
|
|
mine_experience = 0 //its sand
|
|
merge_type = /obj/item/stack/ore/glass
|
|
usable_for_construction = TRUE
|
|
|
|
GLOBAL_LIST_INIT(sand_recipes, list(\
|
|
new /datum/stack_recipe("pile of dirt", /obj/machinery/hydroponics/soil, 3, time = 1 SECONDS, crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_ONE_PER_TURF | CRAFT_ON_SOLID_GROUND, category = CAT_TOOLS), \
|
|
new /datum/stack_recipe("sandstone", /obj/item/stack/sheet/mineral/sandstone, 1, 1, 50, crafting_flags = CRAFT_NO_MATERIALS, category = CAT_MISC),\
|
|
new /datum/stack_recipe("aesthetic volcanic floor tile", /obj/item/stack/tile/basalt, 2, 1, 50, crafting_flags = NONE, category = CAT_TILES)\
|
|
))
|
|
|
|
/obj/item/stack/ore/glass/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt)
|
|
. = ..()
|
|
AddComponent(/datum/component/storm_hating)
|
|
|
|
/obj/item/stack/ore/glass/on_orm_collection() //we need to smelt the glass beforehand because the silo and orm don't accept sand mats
|
|
//If we spawn the sheet of glass on the turf the ORM is "listening" to, it'll get redeemed before we can use it as return value and weird stuff my happen.
|
|
var/obj/item/stack/sheet/glass = new refined_type(null, amount)
|
|
qdel(src)
|
|
return glass
|
|
|
|
/obj/item/stack/ore/glass/get_main_recipes()
|
|
. = ..()
|
|
. += GLOB.sand_recipes
|
|
|
|
/obj/item/stack/ore/glass/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
|
if(..() || !ishuman(hit_atom))
|
|
return
|
|
var/mob/living/carbon/human/C = hit_atom
|
|
if(C.is_eyes_covered())
|
|
C.visible_message(span_danger("[C]'s eye protection blocks the sand!"), span_warning("Your eye protection blocks the sand!"))
|
|
return
|
|
C.adjust_eye_blur(12 SECONDS)
|
|
C.adjust_stamina_loss(15) //the pain from your eyes burning does stamina damage
|
|
C.adjust_confusion(5 SECONDS)
|
|
to_chat(C, span_userdanger("\The [src] gets into your eyes! The pain, it burns!"))
|
|
qdel(src)
|
|
|
|
/obj/item/stack/ore/glass/ex_act(severity, target)
|
|
if(severity)
|
|
qdel(src)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/item/stack/ore/glass/thirty
|
|
amount = 30
|
|
|
|
/obj/item/stack/ore/glass/basalt
|
|
name = "volcanic ash"
|
|
icon_state = "volcanic_sand"
|
|
singular_name = "volcanic ash pile"
|
|
mine_experience = 0
|
|
merge_type = /obj/item/stack/ore/glass/basalt
|
|
|
|
/obj/item/stack/ore/glass/siderite
|
|
name = "siderite dust"
|
|
icon_state = "siderite_sand"
|
|
singular_name = "siderite dust pile"
|
|
mine_experience = 0
|
|
merge_type = /obj/item/stack/ore/glass/siderite
|
|
|
|
/obj/item/stack/ore/plasma
|
|
name = "plasma ore"
|
|
icon_state = "plasma"
|
|
singular_name = "plasma ore chunk"
|
|
points = 15
|
|
mats_per_unit = list(/datum/material/plasma = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/mineral/plasma
|
|
mine_experience = 5
|
|
scan_state = "rock_plasma"
|
|
spread_chance = 45
|
|
merge_type = /obj/item/stack/ore/plasma
|
|
vein_type = ORE_VEIN_PLAIN
|
|
min_vein_size = 2
|
|
max_vein_size = 4
|
|
|
|
/obj/item/stack/ore/plasma/welder_act(mob/living/user, obj/item/I)
|
|
to_chat(user, span_warning("You can't hit a high enough temperature to smelt [src] properly!"))
|
|
return TRUE
|
|
|
|
/obj/item/stack/ore/silver
|
|
name = "silver ore"
|
|
icon_state = "silver"
|
|
singular_name = "silver ore chunk"
|
|
points = 16
|
|
mine_experience = 3
|
|
mats_per_unit = list(/datum/material/silver = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/mineral/silver
|
|
scan_state = "rock_silver"
|
|
spread_chance = 35
|
|
merge_type = /obj/item/stack/ore/silver
|
|
vein_type = ORE_VEIN_BRANCH
|
|
min_vein_size = 0
|
|
max_vein_size = 2
|
|
|
|
/obj/item/stack/ore/gold
|
|
name = "gold ore"
|
|
icon_state = "gold"
|
|
singular_name = "gold ore chunk"
|
|
points = 18
|
|
mine_experience = 5
|
|
mats_per_unit = list(/datum/material/gold = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/mineral/gold
|
|
scan_state = "rock_gold"
|
|
spread_chance = 35
|
|
merge_type = /obj/item/stack/ore/gold
|
|
vein_type = ORE_VEIN_BRANCH
|
|
vein_distance = 2
|
|
min_vein_size = 0
|
|
max_vein_size = 2
|
|
|
|
/obj/item/stack/ore/diamond
|
|
name = "diamond ore"
|
|
icon_state = "diamond"
|
|
singular_name = "diamond ore chunk"
|
|
points = 50
|
|
mats_per_unit = list(/datum/material/diamond = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/mineral/diamond
|
|
mine_experience = 10
|
|
scan_state = "rock_diamond"
|
|
merge_type = /obj/item/stack/ore/diamond
|
|
vein_type = ORE_VEIN_SCATTER
|
|
spread_chance = 20
|
|
vein_distance = 4
|
|
min_vein_size = 1
|
|
max_vein_size = 2
|
|
|
|
/obj/item/stack/ore/diamond/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/raptor_food, speed_modifier = 0.05, health_modifier = -1, color_chances = string_list(list(/datum/raptor_color/yellow = 3)))
|
|
|
|
/obj/item/stack/ore/diamond/five
|
|
amount = 5
|
|
|
|
/obj/item/stack/ore/bananium
|
|
name = "bananium ore"
|
|
icon_state = "bananium"
|
|
singular_name = "bananium ore chunk"
|
|
points = 60
|
|
mats_per_unit = list(/datum/material/bananium = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/mineral/bananium
|
|
mine_experience = 15
|
|
scan_state = "rock_bananium"
|
|
merge_type = /obj/item/stack/ore/bananium
|
|
vein_type = ORE_VEIN_PLAIN
|
|
spread_chance = 20
|
|
vein_distance = 4
|
|
min_vein_size = 1
|
|
max_vein_size = 2
|
|
|
|
/obj/item/stack/ore/titanium
|
|
name = "titanium ore"
|
|
icon_state = "titanium"
|
|
singular_name = "titanium ore chunk"
|
|
points = 50
|
|
mats_per_unit = list(/datum/material/titanium = SHEET_MATERIAL_AMOUNT)
|
|
refined_type = /obj/item/stack/sheet/mineral/titanium
|
|
mine_experience = 3
|
|
scan_state = "rock_titanium"
|
|
spread_chance = 35
|
|
merge_type = /obj/item/stack/ore/titanium
|
|
min_vein_size = 1
|
|
max_vein_size = 2
|
|
|
|
/obj/item/stack/ore/slag
|
|
name = "slag"
|
|
desc = "Completely useless."
|
|
icon_state = "slag"
|
|
singular_name = "slag chunk"
|
|
merge_type = /obj/item/stack/ore/slag
|
|
|
|
/obj/item/gibtonite
|
|
name = "gibtonite ore"
|
|
desc = "Extremely explosive if struck with mining equipment, Gibtonite is often used by miners to speed up their work by using it as a mining charge. This material is illegal to possess by unauthorized personnel under space law."
|
|
icon = 'icons/obj/ore.dmi'
|
|
icon_state = "gibtonite"
|
|
inhand_icon_state = "Gibtonite ore"
|
|
w_class = WEIGHT_CLASS_BULKY
|
|
throw_range = 0
|
|
/// if the gibtonite is currently primed for explosion
|
|
var/primed = FALSE
|
|
/// how long does it take for this to detonate
|
|
var/det_time = 10 SECONDS
|
|
/// the timer
|
|
var/det_timer
|
|
/// How pure this gibtonite is, determines the explosion produced by it and is derived from the det_time of the rock wall it was taken from, higher value = better
|
|
var/quality = GIBTONITE_QUALITY_LOW
|
|
/// who attached the rig to us
|
|
var/attacher
|
|
/// the assembly rig
|
|
var/obj/item/assembly_holder/rig
|
|
/// the rig overlay
|
|
var/mutable_appearance/rig_overlay
|
|
|
|
/obj/item/gibtonite/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/two_handed, require_twohands=TRUE)
|
|
AddComponent(/datum/component/golem_food, consume_on_eat = FALSE, golem_food_key = /obj/item/gibtonite)
|
|
|
|
/obj/item/gibtonite/examine(mob/user)
|
|
. = ..()
|
|
if(rig)
|
|
. += span_warning("There is some kind of device <b>rigged</b> to it!")
|
|
else
|
|
. += span_notice("You could <b>rig</b> something to it.")
|
|
|
|
/obj/item/gibtonite/Destroy()
|
|
QDEL_NULL(rig)
|
|
rig_overlay = null
|
|
return ..()
|
|
|
|
/obj/item/gibtonite/Exited(atom/movable/gone, direction)
|
|
. = ..()
|
|
if(gone == rig)
|
|
rig = null
|
|
attacher = null
|
|
cut_overlays(rig_overlay)
|
|
UnregisterSignal(src, COMSIG_IGNITER_ACTIVATE)
|
|
|
|
/obj/item/gibtonite/IsSpecialAssembly()
|
|
return TRUE
|
|
|
|
/obj/item/gibtonite/attackby(obj/item/I, mob/user, list/modifiers, list/attack_modifiers)
|
|
if(istype(I, /obj/item/assembly_holder) && !rig)
|
|
var/obj/item/assembly_holder/holder = I
|
|
if(!(locate(/obj/item/assembly/igniter) in holder.assemblies))
|
|
return ..()
|
|
if(!user.transferItemToLoc(holder, src))
|
|
return
|
|
add_fingerprint(user)
|
|
rig = holder
|
|
holder.master = src
|
|
holder.on_attach()
|
|
rig_overlay = holder
|
|
rig_overlay.pixel_z -= 5
|
|
add_overlay(rig_overlay)
|
|
RegisterSignal(src, COMSIG_IGNITER_ACTIVATE, PROC_REF(igniter_prime))
|
|
log_bomber(user, "attached [holder] to ", src)
|
|
attacher = key_name(user)
|
|
user.balloon_alert_to_viewers("attached rig")
|
|
return
|
|
|
|
if(I.tool_behaviour == TOOL_WRENCH && rig)
|
|
rig.on_found()
|
|
if(QDELETED(src))
|
|
return
|
|
user.balloon_alert_to_viewers("detached rig")
|
|
user.log_message("detached [rig] from [src].", LOG_GAME)
|
|
user.put_in_hands(rig)
|
|
return
|
|
|
|
if(I.tool_behaviour == TOOL_MINING || istype(I, /obj/item/resonator) || I.force >= 10)
|
|
GibtoniteReaction(user, "A resonator has primed for detonation a")
|
|
return
|
|
|
|
if(istype(I, /obj/item/mining_scanner) || istype(I, /obj/item/t_scanner/adv_mining_scanner) || I.tool_behaviour == TOOL_MULTITOOL)
|
|
defuse(user)
|
|
return
|
|
|
|
return ..()
|
|
|
|
/// Stop the reaction and reduce ore explosive power
|
|
/obj/item/gibtonite/proc/defuse(mob/defuser)
|
|
if (!primed)
|
|
return
|
|
primed = FALSE
|
|
if(det_timer)
|
|
deltimer(det_timer)
|
|
defuser?.visible_message(span_notice("The chain reaction stopped! ...The ore's quality looks diminished."), span_notice("You stopped the chain reaction. ...The ore's quality looks diminished."))
|
|
icon_state = "gibtonite"
|
|
quality = GIBTONITE_QUALITY_LOW
|
|
|
|
/obj/item/gibtonite/attack_self(user)
|
|
if(wires)
|
|
wires.interact(user)
|
|
else
|
|
return ..()
|
|
|
|
/obj/item/gibtonite/bullet_act(obj/projectile/proj)
|
|
GibtoniteReaction(proj.firer, "A projectile has primed for detonation a")
|
|
return ..()
|
|
|
|
/obj/item/gibtonite/ex_act()
|
|
GibtoniteReaction(null, "An explosion has primed for detonation a")
|
|
return TRUE
|
|
|
|
/obj/item/gibtonite/proc/GibtoniteReaction(mob/user, triggered_by)
|
|
if(primed)
|
|
return
|
|
primed = TRUE
|
|
playsound(src,'sound/effects/hit_on_shattered_glass.ogg',50,TRUE)
|
|
icon_state = "gibtonite_active"
|
|
var/notify_admins = FALSE
|
|
if(!is_mining_level(z))//Only annoy the admins ingame if we're triggered off the mining zlevel
|
|
notify_admins = TRUE
|
|
|
|
if(user)
|
|
user.visible_message(span_warning("[user] strikes \the [src], causing a chain reaction!"), span_danger("You strike \the [src], causing a chain reaction."))
|
|
|
|
var/attacher_text = attacher ? "Igniter attacher: [ADMIN_LOOKUPFLW(attacher)]" : null
|
|
|
|
if(triggered_by)
|
|
log_bomber(user, triggered_by, src, attacher_text, notify_admins)
|
|
else
|
|
log_bomber(user, "Something has primed a", src, "for detonation.[attacher_text ? " " : ""][attacher_text]", notify_admins)
|
|
|
|
det_timer = addtimer(CALLBACK(src, PROC_REF(detonate), notify_admins), det_time, TIMER_STOPPABLE)
|
|
|
|
/obj/item/gibtonite/proc/detonate(notify_admins)
|
|
if(primed)
|
|
switch(quality)
|
|
if(GIBTONITE_QUALITY_HIGH)
|
|
explosion(src, devastation_range = 2, heavy_impact_range = 4, light_impact_range = 9, flame_range = 0, flash_range = 0, adminlog = notify_admins)
|
|
if(GIBTONITE_QUALITY_MEDIUM)
|
|
explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 5, flame_range = 0, flash_range = 0, adminlog = notify_admins)
|
|
if(GIBTONITE_QUALITY_LOW)
|
|
explosion(src, heavy_impact_range = 1, light_impact_range = 3, flame_range = 0, flash_range = 0, adminlog = notify_admins)
|
|
qdel(src)
|
|
|
|
/obj/item/gibtonite/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
|
. = ..()
|
|
if (throwingdatum.dist_travelled < 2 || !isliving(hit_atom))
|
|
return
|
|
var/mob/living/hit_mob = hit_atom
|
|
hit_mob.Paralyze(1.5 SECONDS)
|
|
hit_mob.Knockdown(8 SECONDS)
|
|
|
|
/obj/item/gibtonite/proc/igniter_prime()
|
|
SIGNAL_HANDLER
|
|
GibtoniteReaction(null, "An attached rig has primed a")
|
|
|
|
/obj/item/stack/ore/Initialize(mapload, new_amount, merge = TRUE, list/mat_override=null, mat_amt=1)
|
|
. = ..()
|
|
pixel_x = base_pixel_x + rand(0, 16) - 8
|
|
pixel_y = base_pixel_y + rand(0, 8) - 8
|
|
|
|
/obj/item/stack/ore/ex_act(severity, target)
|
|
if(severity >= EXPLODE_DEVASTATE)
|
|
qdel(src)
|
|
return TRUE
|
|
|
|
return FALSE
|
|
|
|
|
|
/*****************************Coin********************************/
|
|
|
|
// The coin's value is a value of its materials.
|
|
// Yes, the gold standard makes a come-back!
|
|
// This is the only way to make coins that are possible to produce on station actually worth anything.
|
|
/obj/item/coin
|
|
icon = 'icons/obj/economy.dmi'
|
|
name = "coin"
|
|
icon_state = "coin"
|
|
obj_flags = CONDUCTS_ELECTRICITY
|
|
force = 1
|
|
throwforce = 2
|
|
w_class = WEIGHT_CLASS_TINY
|
|
material_flags = MATERIAL_EFFECTS | MATERIAL_ADD_PREFIX | MATERIAL_COLOR | MATERIAL_AFFECT_STATISTICS
|
|
var/string_attached
|
|
var/list/sideslist = list("heads","tails")
|
|
var/cooldown = 0
|
|
var/value = 0
|
|
var/coinflip
|
|
///If you do not want this coin to be valued based on its materials and instead set a custom value set this to TRUE and set value to the desired value.
|
|
var/override_material_worth = FALSE
|
|
/// The name of the heads side of the coin
|
|
var/heads_name = "heads"
|
|
/// If the coin has an action or not
|
|
var/has_action = FALSE
|
|
|
|
/obj/item/coin/Initialize(mapload)
|
|
. = ..()
|
|
coinflip = pick(sideslist)
|
|
icon_state = "coin_[coinflip]"
|
|
pixel_x = base_pixel_x + rand(0, 16) - 8
|
|
pixel_y = base_pixel_y + rand(0, 8) - 8
|
|
add_traits(list(TRAIT_FISHING_BAIT, TRAIT_BAIT_ALLOW_FISHING_DUD), INNATE_TRAIT)
|
|
|
|
/obj/item/coin/finalize_material_effects(list/materials)
|
|
. = ..()
|
|
if(override_material_worth)
|
|
return
|
|
value = 0
|
|
for(var/datum/material/material as anything in materials)
|
|
value += material.value_per_unit * materials[material][MATERIAL_LIST_OPTIMAL_AMOUNT]
|
|
|
|
/obj/item/coin/get_item_credit_value()
|
|
return value
|
|
|
|
/obj/item/coin/suicide_act(mob/living/user)
|
|
user.visible_message(span_suicide("[user] contemplates suicide with \the [src]!"))
|
|
if (!attack_self(user))
|
|
user.visible_message(span_suicide("[user] couldn't flip \the [src]!"))
|
|
return SHAME
|
|
addtimer(CALLBACK(src, PROC_REF(manual_suicide), user), 1 SECONDS)//10 = time takes for flip animation
|
|
return MANUAL_SUICIDE_NONLETHAL
|
|
|
|
/obj/item/coin/proc/manual_suicide(mob/living/user)
|
|
var/index = sideslist.Find(coinflip)
|
|
if (index == 2)//tails
|
|
user.visible_message(span_suicide("\the [src] lands on [coinflip]! [user] promptly falls over, dead!"))
|
|
user.adjust_oxy_loss(200)
|
|
user.death(FALSE)
|
|
user.set_suicide(TRUE)
|
|
user.suicide_log()
|
|
else
|
|
user.visible_message(span_suicide("\the [src] lands on [coinflip]! [user] keeps on living!")) //Don't put it in your pocket. It's your lucky quarter.
|
|
|
|
/obj/item/coin/examine(mob/user)
|
|
. = ..()
|
|
. += span_info("It's worth [value] [MONEY_NAME_AUTOPURAL(value)].")
|
|
|
|
/obj/item/coin/attackby(obj/item/W, mob/user, list/modifiers, list/attack_modifiers)
|
|
if(istype(W, /obj/item/stack/cable_coil))
|
|
var/obj/item/stack/cable_coil/CC = W
|
|
if(string_attached)
|
|
to_chat(user, span_warning("There already is a string attached to this coin!"))
|
|
return
|
|
|
|
if (CC.use(1))
|
|
add_overlay("coin_string_overlay")
|
|
string_attached = 1
|
|
to_chat(user, span_notice("You attach a string to the coin."))
|
|
else
|
|
to_chat(user, span_warning("You need one length of cable to attach a string to the coin!"))
|
|
return
|
|
else
|
|
..()
|
|
|
|
/obj/item/coin/wirecutter_act(mob/living/user, obj/item/I)
|
|
..()
|
|
if(!string_attached)
|
|
return TRUE
|
|
|
|
new /obj/item/stack/cable_coil(drop_location(), 1)
|
|
overlays = list()
|
|
string_attached = null
|
|
to_chat(user, span_notice("You detach the string from the coin."))
|
|
return TRUE
|
|
|
|
/obj/item/coin/attack_self(mob/user)
|
|
if(cooldown < world.time)
|
|
if(string_attached) //does the coin have a wire attached
|
|
to_chat(user, span_warning("The coin won't flip very well with something attached!") )
|
|
return FALSE//do not flip the coin
|
|
cooldown = world.time + 15
|
|
flick("coin_[coinflip]_flip", src)
|
|
coinflip = pick(sideslist)
|
|
icon_state = "coin_[coinflip]"
|
|
playsound(user.loc, 'sound/items/coinflip.ogg', 50, TRUE)
|
|
var/oldloc = loc
|
|
sleep(1.5 SECONDS)
|
|
if(loc == oldloc && user && !user.incapacitated)
|
|
user.visible_message(span_notice("[user] flips [src]. It lands on [coinflip]."), \
|
|
span_notice("You flip [src]. It lands on [coinflip]."), \
|
|
span_hear("You hear the clattering of loose change."))
|
|
if(has_action)
|
|
if(coinflip == heads_name)
|
|
heads_action(user)
|
|
else
|
|
tails_action(user)
|
|
return TRUE//did the coin flip? useful for suicide_act
|
|
|
|
/obj/item/coin/proc/heads_action(mob/user)
|
|
return
|
|
|
|
/obj/item/coin/proc/tails_action(mob/user)
|
|
return
|
|
|
|
/obj/item/coin/gold
|
|
custom_materials = list(/datum/material/gold = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/silver
|
|
custom_materials = list(/datum/material/silver = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/diamond
|
|
custom_materials = list(/datum/material/diamond = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/plasma
|
|
custom_materials = list(/datum/material/plasma = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/uranium
|
|
custom_materials = list(/datum/material/uranium = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/titanium
|
|
custom_materials = list(/datum/material/titanium = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/titanium/grind_results()
|
|
return list(/datum/reagent/flash_powder = 8)
|
|
|
|
/obj/item/coin/bananium
|
|
custom_materials = list(/datum/material/bananium = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/adamantine
|
|
custom_materials = list(/datum/material/adamantine = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/mythril
|
|
custom_materials = list(/datum/material/mythril = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/mythril/grind_results()
|
|
return list(/datum/reagent/medicine/omnizine/godblood = 8)
|
|
|
|
/obj/item/coin/plastic
|
|
custom_materials = list(/datum/material/plastic = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/runite
|
|
custom_materials = list(/datum/material/runite = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/runite/grind_results()
|
|
return list(/datum/reagent/iron = 4, /datum/reagent/consumable/ethanol/ritual_wine = 4)
|
|
|
|
/obj/item/coin/twoheaded
|
|
desc = "Hey, this coin's the same on both sides!"
|
|
sideslist = list("heads")
|
|
|
|
/obj/item/coin/antagtoken
|
|
name = "antag token"
|
|
desc = "A novelty coin that helps the heart know what hard evidence cannot prove."
|
|
icon_state = "coin_valid"
|
|
custom_materials = list(/datum/material/plastic = COIN_MATERIAL_AMOUNT)
|
|
sideslist = list("valid", "salad")
|
|
heads_name = "valid"
|
|
material_flags = NONE
|
|
override_material_worth = TRUE
|
|
|
|
/obj/item/coin/antagtoken/grind_results()
|
|
return list(/datum/reagent/ants = 4, /datum/reagent/consumable/eggyolk = 4)
|
|
|
|
/obj/item/coin/iron
|
|
custom_materials = list(/datum/material/iron = COIN_MATERIAL_AMOUNT)
|
|
|
|
/obj/item/coin/gold/debug
|
|
custom_materials = list(/datum/material/gold = COIN_MATERIAL_AMOUNT)
|
|
desc = "If you got this somehow, be aware that it will dust you. Almost certainly."
|
|
|
|
/obj/item/coin/gold/debug/grind_results()
|
|
return list(/datum/reagent/gold/cursed = 8)
|
|
|
|
/obj/item/coin/gold/debug/attack_self(mob/user)
|
|
if(cooldown < world.time)
|
|
if(string_attached) //does the coin have a wire attached
|
|
to_chat(user, span_warning("The coin won't flip very well with something attached!") )
|
|
return FALSE//do not flip the coin
|
|
cooldown = world.time + 15
|
|
flick("coin_[coinflip]_flip", src)
|
|
coinflip = pick(sideslist)
|
|
icon_state = "coin_[coinflip]"
|
|
playsound(user.loc, 'sound/items/coinflip.ogg', 50, TRUE)
|
|
var/oldloc = loc
|
|
sleep(1.5 SECONDS)
|
|
if(loc == oldloc && user && !user.incapacitated)
|
|
user.visible_message(span_notice("[user] flips [src]. It lands on [coinflip]."), \
|
|
span_notice("You flip [src]. It lands on [coinflip]."), \
|
|
span_hear("You hear the clattering of loose change."))
|
|
SSeconomy.fire()
|
|
to_chat(user,"<span class='bounty'>[SSeconomy.inflation_value()] is the inflation value.</span>")
|
|
return TRUE//did the coin flip? useful for suicide_act
|
|
|
|
|
|
///Coins used in the dutchmen money bag.
|
|
/obj/item/coin/silver/doubloon
|
|
name = "doubloon"
|
|
|
|
/obj/item/coin/gold/doubloon
|
|
name = "doubloon"
|
|
|
|
/obj/item/coin/adamantine/doubloon
|
|
name = "doubloon"
|
|
|
|
/obj/item/coin/eldritch
|
|
name = "eldritch coin"
|
|
desc = "A surprisingly heavy, ornate coin. Its sides seem to depict a different image each time you look."
|
|
icon_state = "coin_heretic"
|
|
custom_materials = list(/datum/material/plasma = HALF_SHEET_MATERIAL_AMOUNT)
|
|
sideslist = list("heretic", "blade")
|
|
heads_name = "heretic"
|
|
has_action = TRUE
|
|
material_flags = NONE
|
|
/// The range at which airlocks are effected.
|
|
var/airlock_range = 5
|
|
|
|
/obj/item/coin/eldritch/grind_results()
|
|
return list(/datum/reagent/carbon = 5, /datum/reagent/toxin/plasma = 5, /datum/reagent/eldritch = 4)
|
|
|
|
/obj/item/coin/eldritch/heads_action(mob/user)
|
|
var/mob/living/living_user = user
|
|
if(!IS_HERETIC(user))
|
|
living_user.adjust_brute_loss(5)
|
|
return
|
|
for(var/obj/machinery/door/airlock/target_airlock in range(airlock_range, user))
|
|
if(target_airlock.density)
|
|
target_airlock.open()
|
|
continue
|
|
target_airlock.close(force_crush = TRUE)
|
|
|
|
/obj/item/coin/eldritch/tails_action(mob/user)
|
|
var/mob/living/living_user = user
|
|
if(!IS_HERETIC(user))
|
|
living_user.adjust_fire_loss(5)
|
|
return
|
|
for(var/obj/machinery/door/airlock/target_airlock in range(airlock_range, user))
|
|
if(target_airlock.locked)
|
|
target_airlock.unlock()
|
|
continue
|
|
target_airlock.lock()
|
|
|
|
#undef ORESTACK_OVERLAYS_MAX
|