mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-29 19:11:51 +00:00
## About The Pull Request I have received feedback that after the prior changes in #81971, the gulag is still a little bit too subject to RNG. The main culprit (as in my previous PR) is Iron being kind of cheap and the fact that unlike the old Gulag you no longer have any way of headhunting more valuable materials (everything appears as boulders on your ore scanner). My solution to this is wider than the last one of tweaking point values, but also much simpler: Just make every boulder you mine be worth the same amount of points regardless of what is inside of it. On the average test I made I could comfortably mine about 40-45 boulders in ten minutes. We'll make some adjustments to that rather than leaving 40 as the target number; Most players upon being teleported to the gulag are going to spend a few minutes whining and bemoaning their fate instead of getting straight to work. I had the benefit of being able to make sure my run started as soon as a storm ended so I wouldn't need any kind of midpoint break. I was also always the only person playing on my local instance, there hadn't been any other pesky prisoners before me who had already mined out all the nearest available deposits. And of course, let us not forget, I am an MLG master league ss13 player who was surely performing well above average. So we'll round that down to: Each boulder is worth 33 points, meaning you need to collect 31 boulders to complete a 1000 point (roughly ten minute) sentence. How do I ensure that every boulder is worth the same amount of points? Well it's pretty easy. One boulder = one material sheet. One material sheet = 33 points. Simple. "Now Jacquerel", I hear you not saying because you don't want me to know about this thing you would prefer to do instead of hitting rocks outside; "if I simply smash all of the tables and microwaves and botany trays and bed in the gulag I can easily get like 65 sheets of Iron, which is almost enough to buy the freedom for two entire people!" Unfortunately I knew you were going to try and do that and the prisoner point machine will only give you points for material sheets which have been printed from the material smelter (well, any material smelter actually but you should probably use the one in the gulag). You'll be able to tell because if you examine a valid material sheet it will mention a little maker's mark on it, which is absent in the beat-up iron that you get from smashing furniture to bits. Also glass is worth 0 points. Don't waste time digging up that shit. As glass has had all of its point value removed, I have added a "work pit" to the gulag to compensate. You can pull boulders out of this indefinitely via effort, however it also stamcrits you every time. It's not very fun to do this, but that's because I would prefer you to go find the rocks out in the field instead. This is a last resort. You can do this if there's no boulders left to mine or if you really really really hate mining and would rather very slowly click on one tile repeatedly to get your boulders instead. As a tiny bonus doing this gives workout experience. This isn't a totally ideal solution but I think it'll do for now. ## Why It's Good For The Game What we want out of the gulag is: - Something where officers can vaguely approximate an expected sentence duration. - A task that requires players to actually be spending that time doing something to get out of here. - Produces at least some amount of useful materials. In I think roughly that order. I hope this change accomplishes all three of these in a way that is somewhat predictable rather than throwing darts at a board. ## Changelog 🆑 balance: Gulag mining has been rebalanced so that every boulder is worth the same amount of points to mine for a prisoner regardless of what it contains, and should be more consistent. add: A vent which boulders can be hauled out of by hand has been added to the gulag which you can use if there's nothing left to mine. It is very slow, but at least it gives you a workout... /🆑
292 lines
9.5 KiB
Plaintext
292 lines
9.5 KiB
Plaintext
/// Smelt amount per second
|
|
#define SMELT_AMOUNT 5
|
|
|
|
/**********************Mineral processing unit console**************************/
|
|
|
|
/obj/machinery/mineral
|
|
processing_flags = START_PROCESSING_MANUALLY
|
|
subsystem_type = /datum/controller/subsystem/processing/fastprocess
|
|
/// The current direction of `input_turf`, in relation to the machine.
|
|
var/input_dir = NORTH
|
|
/// The current direction, in relation to the machine, that items will be output to.
|
|
var/output_dir = SOUTH
|
|
/// The turf the machines listens to for items to pick up. Calls the `pickup_item()` proc.
|
|
var/turf/input_turf = null
|
|
/// Determines if this machine needs to pick up items. Used to avoid registering signals to `/mineral` machines that don't pickup items.
|
|
var/needs_item_input = FALSE
|
|
|
|
/obj/machinery/mineral/Initialize(mapload)
|
|
. = ..()
|
|
if(needs_item_input && anchored)
|
|
register_input_turf()
|
|
|
|
/// Gets the turf in the `input_dir` direction adjacent to the machine, and registers signals for ATOM_ENTERED and ATOM_CREATED. Calls the `pickup_item()` proc when it receives these signals.
|
|
/obj/machinery/mineral/proc/register_input_turf()
|
|
input_turf = get_step(src, input_dir)
|
|
if(input_turf) // make sure there is actually a turf
|
|
RegisterSignals(input_turf, list(COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON, COMSIG_ATOM_ENTERED), PROC_REF(pickup_item))
|
|
|
|
/// Unregisters signals that are registered the machine's input turf, if it has one.
|
|
/obj/machinery/mineral/proc/unregister_input_turf()
|
|
if(input_turf)
|
|
UnregisterSignal(input_turf, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON))
|
|
|
|
/obj/machinery/mineral/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
|
|
. = ..()
|
|
if(!needs_item_input || !anchored)
|
|
return
|
|
unregister_input_turf()
|
|
register_input_turf()
|
|
|
|
/obj/machinery/mineral/shuttleRotate(rotation, params)
|
|
. = ..()
|
|
input_dir = angle2dir(rotation + dir2angle(input_dir))
|
|
output_dir = angle2dir(rotation + dir2angle(output_dir))
|
|
|
|
/**
|
|
Base proc for all `/mineral` subtype machines to use. Place your item pickup behavior in this proc when you override it for your specific machine.
|
|
|
|
Called when the COMSIG_ATOM_ENTERED and COMSIG_ATOM_AFTER_SUCCESSFUL_INITIALIZED_ON signals are sent.
|
|
|
|
Arguments:
|
|
* source - the turf that is listening for the signals.
|
|
* target - the atom that just moved onto the `source` turf.
|
|
* oldLoc - the old location that `target` was at before moving onto `source`.
|
|
*/
|
|
/obj/machinery/mineral/proc/pickup_item(datum/source, atom/movable/target, atom/old_loc, list/atom/old_locs)
|
|
SIGNAL_HANDLER
|
|
|
|
return
|
|
|
|
/// Generic unloading proc. Takes an atom as an argument and forceMove's it to the turf adjacent to this machine in the `output_dir` direction.
|
|
/obj/machinery/mineral/proc/unload_mineral(atom/movable/unloaded_mineral)
|
|
unloaded_mineral.forceMove(drop_location())
|
|
var/turf/unload_turf = get_step(src, output_dir)
|
|
if(unload_turf)
|
|
unloaded_mineral.forceMove(unload_turf)
|
|
|
|
/obj/machinery/mineral/processing_unit_console
|
|
name = "production machine console"
|
|
icon = 'icons/obj/machines/mining_machines.dmi'
|
|
icon_state = "console"
|
|
density = TRUE
|
|
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN|INTERACT_MACHINE_ALLOW_SILICON|INTERACT_MACHINE_OPEN_SILICON
|
|
/// Connected ore processing machine.
|
|
var/obj/machinery/mineral/processing_unit/processing_machine
|
|
|
|
/obj/machinery/mineral/processing_unit_console/Initialize(mapload)
|
|
. = ..()
|
|
processing_machine = locate(/obj/machinery/mineral/processing_unit) in view(2, src)
|
|
if (processing_machine)
|
|
processing_machine.mineral_machine = src
|
|
else
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/obj/machinery/mineral/processing_unit_console/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "ProcessingConsole")
|
|
ui.open()
|
|
|
|
/obj/machinery/mineral/processing_unit_console/ui_static_data(mob/user)
|
|
return processing_machine.ui_static_data()
|
|
|
|
/obj/machinery/mineral/processing_unit_console/ui_data(mob/user)
|
|
return processing_machine.ui_data()
|
|
|
|
/obj/machinery/mineral/processing_unit_console/ui_act(action, list/params)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
switch(action)
|
|
if("setMaterial")
|
|
var/datum/material/new_material = locate(params["value"])
|
|
if(!istype(new_material))
|
|
return
|
|
|
|
processing_machine.selected_material = new_material
|
|
processing_machine.selected_alloy = null
|
|
return TRUE
|
|
|
|
if("setAlloy")
|
|
processing_machine.selected_material = null
|
|
processing_machine.selected_alloy = params["value"]
|
|
return TRUE
|
|
|
|
if("toggle")
|
|
processing_machine.on = !processing_machine.on
|
|
if(processing_machine.on)
|
|
processing_machine.begin_processing()
|
|
return TRUE
|
|
|
|
/obj/machinery/mineral/processing_unit_console/Destroy()
|
|
processing_machine = null
|
|
return ..()
|
|
|
|
|
|
/**********************Mineral processing unit**************************/
|
|
|
|
|
|
/obj/machinery/mineral/processing_unit
|
|
name = "furnace"
|
|
icon = 'icons/obj/machines/mining_machines.dmi'
|
|
icon_state = "furnace"
|
|
density = TRUE
|
|
needs_item_input = TRUE
|
|
var/on = FALSE
|
|
var/selected_alloy
|
|
var/obj/machinery/mineral/mineral_machine
|
|
var/datum/material/selected_material
|
|
var/datum/techweb/stored_research
|
|
///Proximity monitor associated with this atom, needed for proximity checks.
|
|
var/datum/proximity_monitor/proximity_monitor
|
|
///Material container for materials
|
|
var/datum/component/material_container/materials
|
|
/// What can be input into the machine?
|
|
var/accepted_type = /obj/item/stack
|
|
|
|
/obj/machinery/mineral/processing_unit/Initialize(mapload)
|
|
. = ..()
|
|
proximity_monitor = new(src, 1)
|
|
|
|
materials = AddComponent( \
|
|
/datum/component/material_container, \
|
|
SSmaterials.materials_by_category[MAT_CATEGORY_SILO], \
|
|
INFINITY, \
|
|
MATCONTAINER_EXAMINE, \
|
|
allowed_items = accepted_type \
|
|
)
|
|
if(!GLOB.autounlock_techwebs[/datum/techweb/autounlocking/smelter])
|
|
GLOB.autounlock_techwebs[/datum/techweb/autounlocking/smelter] = new /datum/techweb/autounlocking/smelter
|
|
stored_research = GLOB.autounlock_techwebs[/datum/techweb/autounlocking/smelter]
|
|
selected_material = GET_MATERIAL_REF(/datum/material/iron)
|
|
|
|
/obj/machinery/mineral/processing_unit/Destroy()
|
|
materials = null
|
|
mineral_machine = null
|
|
stored_research = null
|
|
return ..()
|
|
|
|
/obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/stack/O)
|
|
if(QDELETED(O))
|
|
return
|
|
var/material_amount = materials.get_item_material_amount(O)
|
|
if(!materials.has_space(material_amount))
|
|
unload_mineral(O)
|
|
else
|
|
materials.insert_item(O)
|
|
|
|
/obj/machinery/mineral/processing_unit/ui_static_data()
|
|
var/list/data = list()
|
|
|
|
for(var/datum/material/material as anything in materials.materials)
|
|
var/obj/display = initial(material.sheet_type)
|
|
data["materialIcons"] += list(
|
|
list(
|
|
"id" = REF(material),
|
|
"icon" = icon2base64(icon(initial(display.icon), icon_state = initial(display.icon_state), frame = 1)),
|
|
)
|
|
)
|
|
|
|
for(var/research in stored_research.researched_designs)
|
|
var/datum/design/design = SSresearch.techweb_design_by_id(research)
|
|
var/obj/display = initial(design.build_path)
|
|
data["alloyIcons"] += list(
|
|
list(
|
|
"id" = design.id,
|
|
"icon" = icon2base64(icon(initial(display.icon), icon_state = initial(display.icon_state), frame = 1)),
|
|
)
|
|
)
|
|
|
|
data += materials.ui_static_data()
|
|
|
|
return data
|
|
|
|
/obj/machinery/mineral/processing_unit/ui_data()
|
|
var/list/data = list()
|
|
|
|
data["materials"] = materials.ui_data()
|
|
data["selectedMaterial"] = selected_material?.name
|
|
|
|
data["alloys"] = list()
|
|
for(var/research in stored_research.researched_designs)
|
|
var/datum/design/design = SSresearch.techweb_design_by_id(research)
|
|
data["alloys"] += list(
|
|
list(
|
|
"name" = design.name,
|
|
"id" = design.id,
|
|
)
|
|
)
|
|
data["selectedAlloy"] = selected_alloy
|
|
|
|
data["state"] = on
|
|
|
|
return data
|
|
|
|
/obj/machinery/mineral/processing_unit/pickup_item(datum/source, atom/movable/target, direction)
|
|
if(QDELETED(target))
|
|
return
|
|
if(istype(target, accepted_type))
|
|
process_ore(target)
|
|
|
|
/obj/machinery/mineral/processing_unit/process(seconds_per_tick)
|
|
if(!on)
|
|
return PROCESS_KILL
|
|
|
|
if(selected_material)
|
|
smelt_ore(seconds_per_tick)
|
|
else if(selected_alloy)
|
|
smelt_alloy(seconds_per_tick)
|
|
|
|
/obj/machinery/mineral/processing_unit/proc/smelt_ore(seconds_per_tick = 2)
|
|
var/datum/material/mat = selected_material
|
|
if(!mat)
|
|
return
|
|
var/sheets_to_remove = (materials.materials[mat] >= (SHEET_MATERIAL_AMOUNT * SMELT_AMOUNT * seconds_per_tick) ) ? SMELT_AMOUNT * seconds_per_tick : round(materials.materials[mat] / SHEET_MATERIAL_AMOUNT)
|
|
if(!sheets_to_remove)
|
|
on = FALSE
|
|
else
|
|
var/out = get_step(src, output_dir)
|
|
materials.retrieve_sheets(sheets_to_remove, mat, out)
|
|
|
|
/obj/machinery/mineral/processing_unit/proc/smelt_alloy(seconds_per_tick = 2)
|
|
var/datum/design/alloy = stored_research.isDesignResearchedID(selected_alloy) //check if it's a valid design
|
|
if(!alloy)
|
|
on = FALSE
|
|
return
|
|
|
|
var/amount = can_smelt(alloy, seconds_per_tick)
|
|
|
|
if(!amount)
|
|
on = FALSE
|
|
return
|
|
|
|
materials.use_materials(alloy.materials, multiplier = amount)
|
|
|
|
generate_mineral(alloy.build_path)
|
|
|
|
/obj/machinery/mineral/processing_unit/proc/can_smelt(datum/design/D, seconds_per_tick = 2)
|
|
if(D.make_reagent)
|
|
return FALSE
|
|
|
|
var/build_amount = SMELT_AMOUNT * seconds_per_tick
|
|
|
|
for(var/mat_cat in D.materials)
|
|
var/required_amount = D.materials[mat_cat]
|
|
var/amount = materials.materials[mat_cat]
|
|
|
|
build_amount = min(build_amount, round(amount / required_amount))
|
|
|
|
return build_amount
|
|
|
|
/obj/machinery/mineral/processing_unit/proc/generate_mineral(P)
|
|
var/O = new P(src)
|
|
unload_mineral(O)
|
|
|
|
/// Only accepts ore, for the work camp
|
|
/obj/machinery/mineral/processing_unit/gulag
|
|
accepted_type = /obj/item/stack/ore
|
|
|
|
#undef SMELT_AMOUNT
|