Files
Bubberstation/code/modules/mining/mine_items.dm
norsvenska cd2d0797c9 Restores Northstar's shuttles to the codebase (#89423)
## About The Pull Request
Puts Northstar's shuttles and docks back into the code. This allows for
Northstar to be loaded by admins.

## Why It's Good For The Game

Per Maurukas, shuttles should stay in the code.


![image](https://github.com/user-attachments/assets/87b80dbc-e8e1-43e4-a776-d5c0e4b460a7)


![image](https://github.com/user-attachments/assets/e4a9f03d-be12-49b5-8d1b-ad7ceeadb10f)

## Changelog

Nothing player facing.
2025-02-10 18:20:42 -07:00

564 lines
19 KiB
Plaintext

/**********************Light************************/
//this item is intended to give the effect of entering the mine, so that light gradually fades. we also use the base effect for certain lighting effects while mapping.
/obj/effect/light_emitter
name = "light emitter"
icon_state = "lighting_marker"
anchored = TRUE
invisibility = INVISIBILITY_ABSTRACT
var/set_luminosity = 8
var/set_cap = 0
/obj/effect/light_emitter/Initialize(mapload)
. = ..()
set_light(set_luminosity, set_cap)
/obj/effect/light_emitter/singularity_pull(atom/singularity, current_size)
return
/obj/effect/light_emitter/singularity_act()
return
/obj/effect/light_emitter/podbay
set_cap = 1
/obj/effect/light_emitter/thunderdome
set_cap = 1
set_luminosity = 1.6
/obj/effect/light_emitter/fake_outdoors
light_color = COLOR_LIGHT_YELLOW
set_cap = 1
/**********************Miner Lockers**************************/
/obj/structure/closet/wardrobe/miner
name = "mining wardrobe"
icon_door = "mining_wardrobe"
/obj/structure/closet/wardrobe/miner/PopulateContents()
new /obj/item/storage/backpack/duffelbag/explorer(src)
new /obj/item/storage/backpack/explorer(src)
new /obj/item/storage/backpack/satchel/explorer(src)
new /obj/item/storage/backpack/messenger/explorer(src)
new /obj/item/clothing/under/rank/cargo/miner/lavaland(src)
new /obj/item/clothing/under/rank/cargo/miner/lavaland(src)
new /obj/item/clothing/under/rank/cargo/miner/lavaland(src)
new /obj/item/clothing/shoes/workboots/mining(src)
new /obj/item/clothing/shoes/workboots/mining(src)
new /obj/item/clothing/shoes/workboots/mining(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/clothing/gloves/color/black(src)
new /obj/item/clothing/suit/hooded/wintercoat/miner(src)
new /obj/item/clothing/suit/hooded/wintercoat/miner(src)
new /obj/item/clothing/suit/hooded/wintercoat/miner(src)
/obj/structure/closet/secure_closet/miner
name = "miner's equipment locker"
icon_state = "mining"
req_access = list(ACCESS_MINING)
/obj/structure/closet/secure_closet/miner/unlocked
locked = FALSE
/obj/structure/closet/secure_closet/miner/PopulateContents()
..()
new /obj/item/stack/sheet/mineral/sandbags(src, 5)
new /obj/item/storage/box/emptysandbags(src)
new /obj/item/card/mining_point_card(src)
new /obj/item/shovel(src)
new /obj/item/pickaxe/mini(src)
new /obj/item/radio/headset/headset_cargo/mining(src)
new /obj/item/flashlight/seclite(src)
new /obj/item/storage/bag/plants(src)
new /obj/item/storage/bag/ore(src)
new /obj/item/mining_scanner(src)
new /obj/item/clothing/glasses/meson(src)
if (HAS_TRAIT(SSstation, STATION_TRAIT_SMALLER_PODS))
new /obj/item/survivalcapsule/bathroom(src)
else
new /obj/item/survivalcapsule(src)
new /obj/item/assault_pod/mining(src)
/obj/structure/closet/secure_closet/miner/populate_contents_immediate()
. = ..()
new /obj/item/gun/energy/recharge/kinetic_accelerator(src)
/**********************Shuttle Computer**************************/
/obj/machinery/computer/shuttle/mining
name = "mining shuttle console"
desc = "Used to call and send the mining shuttle."
circuit = /obj/item/circuitboard/computer/mining_shuttle
shuttleId = "mining"
possible_destinations = "mining_home;mining_away;landing_zone_dock;mining_public"
no_destination_swap = TRUE
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/machinery/computer/shuttle/mining/attack_hand(mob/user, list/modifiers)
if(is_station_level(user.z) && user.mind && IS_HEAD_REVOLUTIONARY(user) && !(user.mind in dumb_rev_heads))
to_chat(user, span_warning("You get a feeling that leaving the station might be a REALLY dumb idea..."))
dumb_rev_heads += user.mind
return
if (HAS_TRAIT(user, TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION) && !is_station_level(user.z))
to_chat(user, span_warning("You get the feeling you shouldn't mess with this."))
return
if(isliving(user))
var/mob/living/living_user = user
for(var/obj/item/implant/exile/exile_implant in living_user.implants)
to_chat(living_user, span_warning("A warning flashes across the screen, and the shuttle controls lock in response to your exile implant."))
return
return ..()
/obj/machinery/computer/shuttle/mining/common
name = "lavaland shuttle console"
desc = "Used to call and send the lavaland shuttle."
circuit = /obj/item/circuitboard/computer/mining_shuttle/common
shuttleId = "mining_common"
possible_destinations = "commonmining_home;lavaland_common_away;landing_zone_dock;mining_public"
/obj/docking_port/stationary/mining_home
name = "SS13: Mining Dock"
shuttle_id = "mining_home"
roundstart_template = /datum/map_template/shuttle/mining/delta
width = 7
dwidth = 3
height = 5
/obj/docking_port/stationary/mining_home/kilo
roundstart_template = /datum/map_template/shuttle/mining/kilo
height = 10
/obj/docking_port/stationary/mining_home/northstar
roundstart_template = /datum/map_template/shuttle/mining/northstar
height = 6
/obj/docking_port/stationary/mining_home/nebula
roundstart_template = /datum/map_template/shuttle/mining/nebula
height = 10
/obj/docking_port/stationary/mining_home/common
name = "SS13: Common Mining Dock"
shuttle_id = "commonmining_home"
roundstart_template = /datum/map_template/shuttle/mining_common/meta
/obj/docking_port/stationary/mining_home/common/kilo
roundstart_template = /datum/map_template/shuttle/mining_common/kilo
/obj/docking_port/stationary/mining_home/common/northstar
roundstart_template = /datum/map_template/shuttle/mining_common/northstar
/obj/structure/closet/crate/miningcar
name = "mine cart"
desc = "A cart for use on rails. Or off rails, if you're so inclined."
icon_state = "miningcar"
base_icon_state = "miningcar"
drag_slowdown = 2
open_sound = 'sound/machines/trapdoor/trapdoor_open.ogg'
close_sound = 'sound/machines/trapdoor/trapdoor_shut.ogg'
set_dir_on_move = TRUE
can_buckle = TRUE
can_weld_shut = FALSE
/// Whether we're on a set of rails or just on the ground
var/on_rails = FALSE
/// How many turfs we are travelling, also functions as speed (more momentum = faster)
var/momentum = 0
/obj/structure/closet/crate/miningcar/Initialize(mapload)
. = ..()
AddElement(/datum/element/noisy_movement, 'sound/effects/tank_treads.ogg', 50)
if(locate(/obj/structure/minecart_rail) in loc)
update_rail_state(TRUE)
/obj/structure/closet/crate/miningcar/examine(mob/user)
. = ..()
if(on_rails)
. += span_notice("You can give this a bump to send it on its way, or drag it off the rails to drag it around.")
else
. += span_notice("Drag this onto a mine cart rail to set it on its way.")
// We don't want the locked crate overlay show up.
/obj/structure/closet/crate/miningcar/closet_update_overlays(list/new_overlays)
return
/obj/structure/closet/crate/miningcar/Move(atom/newloc, direct, glide_size_override, update_dir)
if(isnull(newloc))
return ..()
if(!on_rails)
return ..()
// Allows people to drag minecarts along the rails rather than solely shoving it
if(can_travel_on_turf(get_turf(newloc), direct))
return ..()
momentum = 0
return FALSE
/obj/structure/closet/crate/miningcar/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change)
. = ..()
if(!on_rails || momentum <= 0)
return
// Handling running OVER people
for(var/mob/living/smacked in loc)
if(smacked.body_position != LYING_DOWN)
continue
if(momentum <= 8)
momentum = floor(momentum / 2)
break
smack(smacked, 3, 1.5)
if(QDELETED(src))
break
/obj/structure/closet/crate/miningcar/is_buckle_possible(mob/living/target, force, check_loc)
return !opened && ..()
/obj/structure/closet/crate/miningcar/after_open(mob/living/user, force)
. = ..()
unbuckle_all_mobs()
// Hack: If a mob is buckled onto the cart, bumping the cart will instead bump the mob (because higher layer)
// So if we want to allow people to shove carts people are riding, we gotta check the mob for bumped and redirect it
/obj/structure/closet/crate/miningcar/post_buckle_mob(mob/living/buckled_mob)
RegisterSignal(buckled_mob, COMSIG_ATOM_BUMPED, PROC_REF(buckled_bumped))
RegisterSignal(buckled_mob, COMSIG_MOVABLE_BUMP_PUSHED, PROC_REF(block_bump_push))
/obj/structure/closet/crate/miningcar/post_unbuckle_mob(mob/living/unbuckled_mob)
UnregisterSignal(unbuckled_mob, list(COMSIG_ATOM_BUMPED, COMSIG_MOVABLE_BUMP_PUSHED))
/obj/structure/closet/crate/miningcar/proc/buckled_bumped(datum/source, atom/bumper)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(shove_off), bumper)
/**
* Called when the minecart smacks into someone.
*
* * smacked - The mob that was smacked.
* * damage_mod - How much to multiply the momentum by to get the damage.
* * momentum_mod - How much to divide the momentum by after the smack.
*/
/obj/structure/closet/crate/miningcar/proc/smack(mob/living/smacked, damage_mod = 2, momentum_mod = 2)
ASSERT(momentum_mod >= 1)
if(!smacked.apply_damage(damage_mod * momentum, BRUTE, BODY_ZONE_CHEST, wound_bonus = damage_mod * 10, attack_direction = dir))
return
if(get_integrity() <= max_integrity * 0.05)
smacked.visible_message(
span_danger("[src] smashes into [smacked], breaking into pieces!"),
span_userdanger("You are smacked by [src] as it breaks into pieces!"),
)
playsound(src, 'sound/effects/break_stone.ogg', 50, vary = TRUE)
momentum = 0
else
smacked.visible_message(
span_danger("[src] smashes into [smacked]!"),
span_userdanger("You are smacked by [src]!"),
)
playsound(src, 'sound/effects/bang.ogg', 50, vary = TRUE)
take_damage(max_integrity * 0.05)
momentum = floor(momentum / momentum_mod)
if(smacked.body_position == LYING_DOWN)
smacked.Paralyze(4 SECONDS)
return
smacked.Knockdown(5 SECONDS)
for(var/side_dir in shuffle(GLOB.alldirs))
// Don't throw people in front of the cart, and
// don't throw people in any direction behind us
if(side_dir == dir || (side_dir & REVERSE_DIR(dir)))
continue
var/turf/open/open_turf = get_step(src, side_dir)
if(!istype(open_turf))
continue
smacked.safe_throw_at(open_turf, 1, 3, spin = FALSE, gentle = TRUE)
/**
* Updates the state of the minecart to be on or off rails.
*/
/obj/structure/closet/crate/miningcar/proc/update_rail_state(new_state)
if(on_rails == new_state)
return
on_rails = new_state
if(on_rails)
drag_slowdown = 0.5
RegisterSignal(src, COMSIG_MOVABLE_BUMP_PUSHED, PROC_REF(block_bump_push))
else
drag_slowdown = 2
UnregisterSignal(src, COMSIG_MOVABLE_BUMP_PUSHED)
// We want a low move resistance so people can drag it along the tracks
// But we also don't want people to nudge it with a push (since it requires a do_after to set off)
/obj/structure/closet/crate/miningcar/proc/block_bump_push(datum/source, mob/living/bumper, force)
SIGNAL_HANDLER
if(on_rails)
return COMPONENT_NO_PUSH
if(force < MOVE_FORCE_STRONG)
return COMPONENT_NO_PUSH
return NONE
/obj/structure/closet/crate/miningcar/forceMove(atom/destination)
update_rail_state(FALSE)
return ..()
/obj/structure/closet/crate/miningcar/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
if(!isliving(user))
return
if(on_rails)
if(isopenturf(over))
try_take_off_rails(user, over)
return
if(istype(over, /obj/structure/minecart_rail) || (isopenturf(over) && (locate(/obj/structure/minecart_rail) in over)))
try_put_on_rails(user, get_turf(over))
return
/**
* Attempt to remove the cart from rails
*
* * user - The user attempting to remove the cart from the rails.
* * new_destination - The turf the cart will be moved to.
*/
/obj/structure/closet/crate/miningcar/proc/try_take_off_rails(mob/living/user, turf/open/new_destination)
balloon_alert(user, "removing from rails...")
if(!do_after(user, 2 SECONDS, src))
return
update_rail_state(FALSE)
Move(new_destination)
var/sound/thud_sound = sound('sound/items/weapons/thudswoosh.ogg')
thud_sound.pitch = 0.5
playsound(src, thud_sound, 50, TRUE)
/**
* Attempt to put the cart on rails
*
* * user - The user attempting to put the cart on the rails.
* * new_destination - The turf the cart will be moved to.
*/
/obj/structure/closet/crate/miningcar/proc/try_put_on_rails(mob/living/user, turf/open/new_destination)
balloon_alert(user, "putting on rails...")
if(!do_after(user, 2 SECONDS, src))
return
var/obj/structure/minecart_rail/set_rail = locate() in new_destination
if(isnull(set_rail))
return
Move(new_destination)
setDir(set_rail.dir)
update_rail_state(TRUE)
var/sound/click_sound = sound('sound/machines/click.ogg')
click_sound.pitch = 0.5
playsound(src, click_sound, 50, TRUE)
/obj/structure/closet/crate/miningcar/Bump(atom/bumped_atom)
. = ..()
if(.)
return
// Handling running INTO people
if(!isliving(bumped_atom) || momentum <= 0)
return
if(momentum <= 8)
momentum = floor(momentum / 2)
return
smack(bumped_atom)
/obj/structure/closet/crate/miningcar/Bumped(atom/movable/bumped_atom)
. = ..()
INVOKE_ASYNC(src, PROC_REF(shove_off), bumped_atom)
/// Starts the cart moving automatically.
/obj/structure/closet/crate/miningcar/proc/shove_off(atom/movable/bumped_atom)
if(!on_rails || momentum > 0)
return
var/movedir = bumped_atom.dir
var/turf/next_turf = get_step(src, movedir)
if(!can_travel_on_turf(next_turf, movedir))
return
if(isliving(bumped_atom))
var/obj/structure/minecart_rail/rail = locate() in loc
var/mob/living/bumper = bumped_atom
if(bumper.mob_size <= MOB_SIZE_SMALL)
return
if(DOING_INTERACTION_WITH_TARGET(bumper, src))
return
balloon_alert(bumper, "setting off...")
if(!do_after(bumper, 1.5 SECONDS, src))
return
if(QDELETED(rail) || !on_rails || !can_travel_on_turf(next_turf, movedir))
return
momentum += 20
else if(isitem(bumped_atom))
var/obj/item/bumped_item = bumped_atom
if(bumped_item.w_class <= WEIGHT_CLASS_SMALL)
return
momentum += bumped_item.w_class
else if(istype(bumped_atom, /obj/structure/closet/crate/miningcar))
var/obj/structure/closet/crate/miningcar/bumped_car = bumped_atom
if(bumped_car.momentum <= 0)
return
momentum += bumped_car.momentum
bumped_car.momentum = 0
if(momentum <= 0)
return
setDir(movedir)
var/datum/move_loop/loop = GLOB.move_manager.move(src, dir, delay = calculate_delay(), subsystem = SSconveyors, flags = MOVEMENT_LOOP_START_FAST|MOVEMENT_LOOP_IGNORE_PRIORITY)
RegisterSignal(loop, COMSIG_MOVELOOP_PREPROCESS_CHECK, PROC_REF(check_rail))
RegisterSignal(loop, COMSIG_MOVELOOP_POSTPROCESS, PROC_REF(decay_momentum))
/obj/structure/closet/crate/miningcar/proc/check_rail(datum/move_loop/move/source)
SIGNAL_HANDLER
if(momentum <= 0)
stack_trace("Mine cart moving on 0 momentum!")
GLOB.move_manager.stop_looping(src, SSconveyors)
return MOVELOOP_SKIP_STEP
// Forced to not move
if(anchored || !has_gravity())
return MOVELOOP_SKIP_STEP
// Going straight
if(can_travel_on_turf(get_step(src, dir)))
return NONE
// Trying to turn
for(var/next_dir in shuffle(list(turn(dir, 90), turn(dir, -90))))
if(!can_travel_on_turf(get_step(src, next_dir), dir|next_dir))
continue
momentum -= 1 // Extra cost for turning
if(momentum <= 0)
break
source.direction = next_dir
return NONE
// Can't go straight and cant turn = STOP
GLOB.move_manager.stop_looping(src, SSconveyors)
if(momentum >= 8)
visible_message(span_warning("[src] comes to a halt!"))
throw_contents()
else
visible_message(span_notice("[src] comes to a slow stop."))
momentum = 0
return MOVELOOP_SKIP_STEP
/obj/structure/closet/crate/miningcar/proc/decay_momentum(datum/move_loop/move/source)
SIGNAL_HANDLER
if(momentum > 0)
var/obj/structure/minecart_rail/railbreak/stop_break = locate() in loc
var/obj/structure/cable/cable = locate() in loc
// There is a break and it is powered, so STOP
if(stop_break && cable?.avail(10 KILO JOULES))
if(momentum >= 8)
visible_message(span_notice("[src] comes to a sudden stop."))
else
visible_message(span_notice("[src] comes to a stop."))
momentum = 0
GLOB.move_manager.stop_looping(src, SSconveyors)
cable.add_delayedload(10 KILO JOULES)
return
// This is a powered rail, so maintain speed
if(cable?.avail(1 KILO JOULES))
// Speeds up the cart to 5 or 10, then stops decay
if(momentum <= 5)
momentum = 5
cable.add_delayedload(0.5 KILO JOULES)
else if(momentum <= 10)
momentum = 10
cable.add_delayedload(1 KILO JOULES)
return
// Here is where actual slowdown happens
momentum -= 1
// No more momentum = STOP
if(momentum <= 0)
GLOB.move_manager.stop_looping(src, SSconveyors)
visible_message(span_notice("[src] comes to a slow stop."))
return
// Handles slowing down the move loop / cart
var/datum/move_loop/loop = GLOB.move_manager.processing_on(src, SSconveyors)
loop?.set_delay(calculate_delay())
/// Calculates how fast the cart is going
/obj/structure/closet/crate/miningcar/proc/calculate_delay()
return (-0.05 SECONDS * momentum) + 1.1 SECONDS
/// Checks if we can travel on the passed turf
/obj/structure/closet/crate/miningcar/proc/can_travel_on_turf(turf/next_turf, dir_to_check = dir)
for(var/obj/structure/minecart_rail/rail in next_turf)
if(rail.dir & (dir_to_check|REVERSE_DIR(dir_to_check)))
return TRUE
return FALSE
/// Throws all the contents of the cart out ahead
/obj/structure/closet/crate/miningcar/proc/throw_contents()
var/was_open = opened
var/list/to_yeet = contents.Copy()
var/yeet_rider = has_buckled_mobs()
if(yeet_rider)
to_yeet += buckled_mobs
unbuckle_all_mobs()
bust_open()
if(!opened)
return
if(!length(to_yeet))
if(!was_open)
visible_message(span_warning("[src] breaks open!"))
return
var/throw_distance = clamp(ceil(momentum / 3) - 4, 1, 5)
var/turf/some_distant_turf = get_edge_target_turf(src, dir)
for(var/atom/movable/yeeten in to_yeet)
yeeten.throw_at(some_distant_turf, throw_distance, 3, quickstart = TRUE)
if(was_open)
visible_message(span_warning("[src] spills its contents!"))
else
// Update this message if someone allows multiple people to ride one minecart
visible_message(span_warning("[src] breaks open, spilling its contents[yeet_rider ? " and throwing its rider":""]!"))
/obj/structure/minecart_rail
name = "cart rail"
desc = "Carries carts along the track."
icon = 'icons/obj/track.dmi'
icon_state = "track"
layer = TRAM_RAIL_LAYER
plane = FLOOR_PLANE
anchored = TRUE
move_resist = INFINITY
/obj/structure/minecart_rail/Initialize(mapload)
. = ..()
AddElement(/datum/element/give_turf_traits, string_list(list(TRAIT_TURF_IGNORE_SLOWDOWN)))
AddElement(/datum/element/footstep_override, footstep = FOOTSTEP_CATWALK)
for(var/obj/structure/closet/crate/miningcar/cart in loc)
cart.update_rail_state(TRUE)
/obj/structure/minecart_rail/examine(mob/user)
. = ..()
. += rail_examine()
/obj/structure/minecart_rail/proc/rail_examine()
return span_notice("Run a powered cable underneath it to power carts as they travel, maintaining their speed.")
/obj/structure/minecart_rail/railbreak
name = "cart rail brake"
desc = "Stops carts in their tracks. On the tracks. You get what I mean."
icon_state = "track_break"
can_buckle = TRUE
buckle_requires_restraints = TRUE
buckle_lying = NO_BUCKLE_LYING
/obj/structure/minecart_rail/railbreak/rail_examine()
return span_notice("Run a powered cable underneath it to stop carts that pass over it.")