Expanding the Experimental MODsuit Bepis Node with three new modules. (#75801)

## About The Pull Request
So, I've had this idea to make a contribution to the Bepis feature with
some modsuit stuff. The gimmicky stuff is ok and a good way to even out
the better content since it has game of chance design it has (you can
find those disks in space anyway so...). However, the Experimental
MODsuit node feels very underwhelming right now, compared to how big
that feature is.

This PR adds three MOD modules to the Experimental MODsuit node, plus
two more:
- Magneto Charger: While the Modsuit is activated, each step the user
takes will charge the installed power cell by a tiny bit, enough to
sustain a standard modsuit of generic slow speed with only a few, easy
modules installed. It won't work in zero G, while flying, pulled by
someone else, on a conveyor belt, riding a vehicle or crawling on the
floor, though.
- Recycler: It collects (most) garbage and casings off the ground and
recycles them into material sheets that can be dispensed on an adjacent
location or storage with with Middle Mouse Button. Doesn't clean debris,
and scuffed because most trash doesn't yield material anyway.
- - It also has two subtypes, unbound from the node: one that dispenses
riot foam darts and can be found on the black market, and another that
dispenses the more innocuous foam darts, rarely found in maints.
- Shooting Assistant: A configurable module. On Stormtrooper mode, it
will give the user a faster fire rate (the double tap trait) at the cost
of accuracy. On Sharpshooter mode, it will improve the user accuracy and
make their shots ricochet against walls at least once (if the hit atom
allows that, that is, e.g. lasers don't ricochet against iron walls), at
the cost of movement speed. Both modes also prevent the user from dual
wielding guns.

To make the Stormtrooper mode stackable with the poor aim quirk and
refrain from making a new trait for the sharpshooter mode, the gun
spread code in gun.dm has also received a little refactor and cleanup.
Also, it's been tested.

## Why It's Good For The Game
The Experimental MODsuit node is quite shabby and could use something
extra to make it more appealing to MODsuit enjoyers.

Also doubles down as a small addition to the black market and maint
loot, and code cleanup, since gun code gives off some garbled vibes.

## Changelog

🆑
add: Expanded the Experimental MODsuit Bepis node with three new
modules: Magneto Charger, Recycler and Shooting Assistant.
add: Added a Riot Foam Recycler module to the black market, as well a
more innocuous version as maint loot.
/🆑
This commit is contained in:
Ghom
2023-06-14 23:00:05 -04:00
committed by GitHub
parent ee7b79b1af
commit 2bb4dfe76c
24 changed files with 443 additions and 50 deletions
+32 -16
View File
@@ -30,11 +30,22 @@
var/datum/callback/precondition
/// A callback invoked after materials are inserted into this container
var/datum/callback/after_insert
/// A callback invoked after sheets are retrieve from this container
var/datum/callback/after_retrieve
/// The material container flags. See __DEFINES/materials.dm.
var/mat_container_flags
/// Sets up the proper signals and fills the list of materials with the appropriate references.
/datum/component/material_container/Initialize(list/init_mats, max_amt = 0, _mat_container_flags=NONE, list/allowed_mats=init_mats, list/allowed_items, datum/callback/_insertion_check, datum/callback/_precondition, datum/callback/_after_insert)
/datum/component/material_container/Initialize(list/init_mats,
max_amt = 0,
_mat_container_flags=NONE,
list/allowed_mats=init_mats,
list/allowed_items,
datum/callback/_insertion_check,
datum/callback/_precondition,
datum/callback/_after_insert,
datum/callback/_after_retrieve)
if(!isatom(parent))
return COMPONENT_INCOMPATIBLE
@@ -52,6 +63,7 @@
insertion_check = _insertion_check
precondition = _precondition
after_insert = _after_insert
after_retrieve = _after_retrieve
for(var/mat in init_mats) //Make the assoc list material reference -> amount
var/mat_ref = GET_MATERIAL_REF(mat)
@@ -79,6 +91,8 @@
QDEL_NULL(precondition)
if(after_insert)
QDEL_NULL(after_insert)
if(after_retrieve)
QDEL_NULL(after_retrieve)
return ..()
@@ -240,40 +254,40 @@
/// Proc specifically for inserting items, returns the amount of materials entered.
/datum/component/material_container/proc/insert_item(obj/item/weapon, multiplier = 1, breakdown_flags = mat_container_flags)
if(QDELETED(weapon))
return -1
return MATERIAL_INSERT_ITEM_NO_MATS
multiplier = CEILING(multiplier, 0.01)
var/obj/item/target = weapon
var/material_amount = get_item_material_amount(target, breakdown_flags) * multiplier
if(!material_amount)
return -1
return MATERIAL_INSERT_ITEM_NO_MATS
var/obj/item/stack/item_stack
if(isstack(weapon) && !has_space(material_amount)) //not enugh space split and feed as many sheets possible
item_stack = weapon
var/space_left = max_amount - total_amount
if(!space_left)
return -2
return MATERIAL_INSERT_ITEM_NO_SPACE
var/material_per_sheet = material_amount / item_stack.amount
var/sheets_to_insert = round(space_left / material_per_sheet)
if(!sheets_to_insert)
return -2
return MATERIAL_INSERT_ITEM_NO_SPACE
target = split_stack(item_stack, sheets_to_insert)
material_amount = get_item_material_amount(target, breakdown_flags) * multiplier
if(!has_space(material_amount))
return -2
return MATERIAL_INSERT_ITEM_NO_SPACE
last_inserted_id = insert_item_materials(target, multiplier, breakdown_flags)
if(!isnull(last_inserted_id))
if(after_insert)
after_insert.Invoke(target, last_inserted_id, material_amount)
after_insert.Invoke(target, last_inserted_id, material_amount, src)
qdel(target) //item gone
return material_amount
else if(!isnull(item_stack) && item_stack != target) //insertion failed, merge the split stack back into the original
var/obj/item/stack/inserting_stack = target
item_stack.add(inserting_stack.amount)
qdel(inserting_stack)
return 0
return MATERIAL_INSERT_ITEM_FAILURE
/**
* Inserts the relevant materials from an item into this material container.
@@ -406,8 +420,8 @@
return total_amount_save - total_amount
/// For spawning mineral sheets at a specific location. Used by machines to output sheets.
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, datum/material/M, atom/target = null)
if(!M.sheet_type)
/datum/component/material_container/proc/retrieve_sheets(sheet_amt, datum/material/material, atom/target = null)
if(!material.sheet_type)
return 0 //Add greyscale sheet handling here later
if(sheet_amt <= 0)
return 0
@@ -415,18 +429,20 @@
if(!target)
var/atom/parent_atom = parent
target = parent_atom.drop_location()
if(materials[M] < (sheet_amt * SHEET_MATERIAL_AMOUNT))
sheet_amt = round(materials[M] / SHEET_MATERIAL_AMOUNT)
if(materials[material] < (sheet_amt * SHEET_MATERIAL_AMOUNT))
sheet_amt = round(materials[material] / SHEET_MATERIAL_AMOUNT)
var/count = 0
while(sheet_amt > MAX_STACK_SIZE)
new M.sheet_type(target, MAX_STACK_SIZE, null, list((M) = SHEET_MATERIAL_AMOUNT))
var/obj/item/stack/sheet/new_sheets = new material.sheet_type(target, MAX_STACK_SIZE, null, list((material) = SHEET_MATERIAL_AMOUNT))
after_retrieve?.Invoke(new_sheets)
count += MAX_STACK_SIZE
use_amount_mat(sheet_amt * SHEET_MATERIAL_AMOUNT, M)
use_amount_mat(sheet_amt * SHEET_MATERIAL_AMOUNT, material)
sheet_amt -= MAX_STACK_SIZE
if(sheet_amt >= 1)
new M.sheet_type(target, sheet_amt, null, list((M) = SHEET_MATERIAL_AMOUNT))
var/obj/item/stack/sheet/new_sheets = new material.sheet_type(target, sheet_amt, null, list((material) = SHEET_MATERIAL_AMOUNT))
after_retrieve?.Invoke(new_sheets)
count += sheet_amt
use_amount_mat(sheet_amt * SHEET_MATERIAL_AMOUNT, M)
use_amount_mat(sheet_amt * SHEET_MATERIAL_AMOUNT, material)
return count
+11 -1
View File
@@ -534,11 +534,21 @@
desc = "You've never hit anything you were aiming for in your life."
icon = FA_ICON_BULLSEYE
value = -4
mob_trait = TRAIT_POOR_AIM
medical_record_text = "Patient possesses a strong tremor in both hands."
hardcore_value = 3
mail_goodies = list(/obj/item/cardboard_cutout) // for target practice
/datum/quirk/poor_aim/add(client/client_source)
RegisterSignal(quirk_holder, COMSIG_MOB_FIRED_GUN, PROC_REF(on_mob_fired_gun))
/datum/quirk/poor_aim/remove(client/client_source)
UnregisterSignal(quirk_holder, COMSIG_MOB_FIRED_GUN)
/datum/quirk/poor_aim/proc/on_mob_fired_gun(mob/user, obj/item/gun/gun_fired, target, params, zone_override, list/bonus_spread_values)
SIGNAL_HANDLER
bonus_spread_values[MIN_BONUS_SPREAD_INDEX] += 10
bonus_spread_values[MAX_BONUS_SPREAD_INDEX] += 35
/datum/quirk/prosopagnosia
name = "Prosopagnosia"
desc = "You have a mental disorder that prevents you from being able to recognize faces at all."