From 573a81a4d90ae846de567c50aeb4ef29f92c49f5 Mon Sep 17 00:00:00 2001 From: Poojawa Date: Fri, 22 Sep 2017 09:31:39 -0500 Subject: [PATCH] Reapplies material componets --- code/__DEFINES/components.dm | 8 + code/_onclick/item_attack.dm | 9 +- .../{ => components}/material_container.dm | 107 +++++++--- code/datums/components/squeek.dm | 61 ++++++ code/game/machinery/autolathe.dm | 67 +++--- code/game/machinery/droneDispenser.dm | 33 +-- code/game/machinery/recycler.dm | 7 +- code/game/mecha/mech_fabricator.dm | 94 +++------ code/modules/clothing/shoes/bananashoes.dm | 38 +--- code/modules/mining/machine_processing.dm | 10 +- code/modules/mining/machine_redemption.dm | 18 +- code/modules/mining/mint.dm | 194 +++++++++--------- code/modules/research/circuitprinter.dm | 73 ++----- code/modules/research/experimentor.dm | 3 +- code/modules/research/protolathe.dm | 85 ++------ code/modules/research/rdconsole.dm | 51 +++-- sound/items/toysqueak1.ogg | Bin 0 -> 12956 bytes sound/items/toysqueak2.ogg | Bin 0 -> 14781 bytes sound/items/toysqueak3.ogg | Bin 0 -> 13778 bytes tgstation.dme | 3 +- 20 files changed, 416 insertions(+), 445 deletions(-) rename code/datums/{ => components}/material_container.dm (61%) create mode 100644 code/datums/components/squeek.dm create mode 100644 sound/items/toysqueak1.ogg create mode 100644 sound/items/toysqueak2.ogg create mode 100644 sound/items/toysqueak3.ogg diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 641454a799..94b9c84fb0 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -39,6 +39,14 @@ #define COMSIG_MOVABLE_COLLIDE "movable_collide" //from base of atom/movable/Collide(): (atom) #define COMSIG_MOVABLE_IMPACT "movable_impact" //from base of atom/movable/throw_impact(): (atom, throwingdatum) +// /obj/item signals +#define COMSIG_ITEM_ATTACK "item_attack" //from base of obj/item/attack(): (mob/living/target, mob/living/user) +#define COMSIG_ITEM_ATTACK_SELF "item_attack_self" //from base of obj/item/attack_self(): (mob) +#define COMSIG_ITEM_ATTACK_OBJ "item_attack_obj" //from base of obj/item/attack_obj(): (obj, mob) + +// /obj/item/clothing signals +#define COMSIG_SHOES_STEP_ACTION "shoes_step_action" //from base of obj/item/clothing/shoes/proc/step_action(): () + // /obj/machinery signals #define COMSIG_MACHINE_PROCESS "machine_process" //from machinery subsystem fire(): () #define COMSIG_MACHINE_PROCESS_ATMOS "machine_process_atmos" //from air subsystem process_atmos_machinery(): () \ No newline at end of file diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index 5265a8e8ea..987818924f 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -9,17 +9,18 @@ // Called when the item is in the active hand, and clicked; alternately, there is an 'activate held object' verb or you can hit pagedown. /obj/item/proc/attack_self(mob/user) - return + SendSignal(COMSIG_ITEM_ATTACK_SELF, user) + interact(user) /obj/item/proc/pre_attackby(atom/A, mob/living/user, params) //do stuff before attackby! return TRUE //return FALSE to avoid calling attackby after this proc does stuff // No comment /atom/proc/attackby(obj/item/W, mob/user, params) - return + return SendSignal(COMSIG_PARENT_ATTACKBY, W, user, params) /obj/attackby(obj/item/I, mob/living/user, params) - return I.attack_obj(src, user) + return ..() || I.attack_obj(src, user) /mob/living/attackby(obj/item/I, mob/living/user, params) user.changeNext_move(CLICK_CD_MELEE) @@ -35,6 +36,7 @@ /obj/item/proc/attack(mob/living/M, mob/living/user) + SendSignal(COMSIG_ITEM_ATTACK, M, user) if(flags_1 & NOBLUDGEON_1) return if(!force) @@ -54,6 +56,7 @@ //the equivalent of the standard version of attack() but for object targets. /obj/item/proc/attack_obj(obj/O, mob/living/user) + SendSignal(COMSIG_ITEM_ATTACK_OBJ, O, user) if(flags_1 & NOBLUDGEON_1) return user.changeNext_move(CLICK_CD_MELEE) diff --git a/code/datums/material_container.dm b/code/datums/components/material_container.dm similarity index 61% rename from code/datums/material_container.dm rename to code/datums/components/material_container.dm index a8863c70bc..55504d47d5 100644 --- a/code/datums/material_container.dm +++ b/code/datums/components/material_container.dm @@ -5,22 +5,34 @@ amount - raw amount of the mineral this container is holding, calculated by the defined value MINERAL_MATERIAL_AMOUNT=2000. max_amount - max raw amount of mineral this container can hold. sheet_type - type of the mineral sheet the container handles, used for output. - owner - object that this container is being used by, used for output. + parent - object that this container is being used by, used for output. MAX_STACK_SIZE - size of a stack of mineral sheets. Constant. */ -/datum/material_container +/datum/component/material_container var/total_amount = 0 var/max_amount var/sheet_type - var/obj/owner - var/list/materials = list() + var/list/materials + var/show_on_examine + var/list/allowed_typecache + var/last_inserted_type + var/last_amount_inserted + var/last_insert_success + var/datum/callback/precondition //MAX_STACK_SIZE = 50 //MINERAL_MATERIAL_AMOUNT = 2000 -/datum/material_container/New(obj/O, list/mat_list, max_amt = 0) - owner = O +/datum/component/material_container/Initialize(list/mat_list, max_amt = 0, _show_on_examine = FALSE, list/allowed_types, datum/callback/_precondition) + materials = list() max_amount = max(0, max_amt) + show_on_examine = _show_on_examine + if(allowed_types) + allowed_typecache = typecacheof(allowed_types) + precondition = _precondition + + RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/OnAttackBy) + RegisterSignal(COMSIG_PARENT_EXAMINE, .proc/OnExamine) var/list/possible_mats = list() for(var/mat_type in subtypesof(/datum/material)) @@ -31,12 +43,47 @@ var/mat_path = possible_mats[id] materials[id] = new mat_path() -/datum/material_container/Destroy() - owner = null - return ..() +/datum/component/material_container/proc/OnExamine(mob/user) + for(var/I in materials) + var/datum/material/M = materials[I] + var/amt = amount(M.id) + if(amt) + to_chat(user, "It has [amt] units of [lowertext(M.name)] stored.") + +/datum/component/material_container/proc/OnAttackBy(obj/item/I, mob/living/user) + var/list/tc = allowed_typecache + if(user.a_intent == INTENT_HARM || (I.flags_2 & HOLOGRAM_2) || (tc && !is_type_in_typecache(I, tc))) + return FALSE + . = TRUE + last_insert_success = FALSE + var/datum/callback/pc = precondition + if(pc && !pc.Invoke()) + return + var/material_amount = get_item_material_amount(I) + if(!material_amount) + to_chat(user, "[I] does not contain sufficient amounts of metal or glass to be accepted by [parent].") + return + if(!has_space(material_amount)) + to_chat(user, "[parent] is full. Please remove metal or glass from [parent] in order to insert more.") + return + if(!user.temporarilyRemoveItemFromInventory(I)) + to_chat(user, "[I] is stuck to you and cannot be placed into [parent].") + return + var/inserted = insert_item(I) + if(inserted) + last_insert_success = TRUE + if(istype(I, /obj/item/stack)) + to_chat(user, "You insert [inserted] sheet[inserted>1 ? "s" : ""] into [parent].") + if(!QDELETED(I)) + user.put_in_active_hand(I) + else + to_chat(user, "You insert a material total of [inserted] into [parent].") + qdel(I) + else + user.put_in_active_hand(I) //For inserting an amount of material -/datum/material_container/proc/insert_amount(amt, id = null) +/datum/component/material_container/proc/insert_amount(amt, id = null) if(amt > 0 && has_space(amt)) var/total_amount_saved = total_amount if(id) @@ -52,7 +99,7 @@ return (total_amount - total_amount_saved) return 0 -/datum/material_container/proc/insert_stack(obj/item/stack/S, amt = 0) +/datum/component/material_container/proc/insert_stack(obj/item/stack/S, amt = 0) if(amt <= 0) return 0 if(amt > S.amount) @@ -67,10 +114,12 @@ return 0 insert_materials(S,amt) + last_inserted_type = S.type S.use(amt) + last_amount_inserted = amt return amt -/datum/material_container/proc/insert_item(obj/item/I, multiplier = 1) +/datum/component/material_container/proc/insert_item(obj/item/I, multiplier = 1) if(!I) return 0 if(istype(I, /obj/item/stack)) @@ -82,9 +131,11 @@ return 0 insert_materials(I, multiplier) + last_inserted_type = I.type + last_amount_inserted = material_amount return material_amount -/datum/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only +/datum/component/material_container/proc/insert_materials(obj/item/I, multiplier = 1) //for internal usage only var/datum/material/M for(var/MAT in materials) M = materials[MAT] @@ -93,7 +144,7 @@ //For consuming material //mats is a list of types of material to use and the corresponding amounts, example: list(MAT_METAL=100, MAT_GLASS=200) -/datum/material_container/proc/use_amount(list/mats, multiplier=1) +/datum/component/material_container/proc/use_amount(list/mats, multiplier=1) if(!mats || !mats.len) return 0 @@ -112,7 +163,7 @@ return total_amount_save - total_amount -/datum/material_container/proc/use_amount_type(amt, id) +/datum/component/material_container/proc/use_amount_type(amt, id) var/datum/material/M = materials[id] if(M) if(M.amount >= amt) @@ -121,7 +172,7 @@ return amt return 0 -/datum/material_container/proc/can_use_amount(amt, id, list/mats) +/datum/component/material_container/proc/can_use_amount(amt, id, list/mats) if(amt && id) var/datum/material/M = materials[id] if(M && M.amount >= amt) @@ -136,7 +187,7 @@ return FALSE //For spawning mineral sheets; internal use only -/datum/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null) +/datum/component/material_container/proc/retrieve(sheet_amt, datum/material/M, target = null) if(!M.sheet_type) return 0 if(sheet_amt > 0) @@ -144,12 +195,12 @@ sheet_amt = round(M.amount / MINERAL_MATERIAL_AMOUNT) var/count = 0 while(sheet_amt > MAX_STACK_SIZE) - new M.sheet_type(get_turf(owner), MAX_STACK_SIZE) + new M.sheet_type(get_turf(parent), MAX_STACK_SIZE) count += MAX_STACK_SIZE use_amount_type(sheet_amt * MINERAL_MATERIAL_AMOUNT, M.id) sheet_amt -= MAX_STACK_SIZE if(round((sheet_amt * MINERAL_MATERIAL_AMOUNT) / MINERAL_MATERIAL_AMOUNT)) - var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(owner), sheet_amt) + var/obj/item/stack/sheet/s = new M.sheet_type(get_turf(parent), sheet_amt) if(target) s.forceMove(target) count += sheet_amt @@ -157,15 +208,15 @@ return count return 0 -/datum/material_container/proc/retrieve_sheets(sheet_amt, id, target = null) +/datum/component/material_container/proc/retrieve_sheets(sheet_amt, id, target = null) if(materials[id]) return retrieve(sheet_amt, materials[id], target) return 0 -/datum/material_container/proc/retrieve_amount(amt, id, target) +/datum/component/material_container/proc/retrieve_amount(amt, id, target) return retrieve_sheets(amount2sheet(amt), id, target) -/datum/material_container/proc/retrieve_all(target = null) +/datum/component/material_container/proc/retrieve_all(target = null) var/result = 0 var/datum/material/M for(var/MAT in materials) @@ -173,10 +224,10 @@ result += retrieve_sheets(amount2sheet(M.amount), MAT, target) return result -/datum/material_container/proc/has_space(amt = 0) +/datum/component/material_container/proc/has_space(amt = 0) return (total_amount + amt) <= max_amount -/datum/material_container/proc/has_materials(list/mats, multiplier=1) +/datum/component/material_container/proc/has_materials(list/mats, multiplier=1) if(!mats || !mats.len) return 0 @@ -187,23 +238,23 @@ return 0 return 1 -/datum/material_container/proc/amount2sheet(amt) +/datum/component/material_container/proc/amount2sheet(amt) if(amt >= MINERAL_MATERIAL_AMOUNT) return round(amt / MINERAL_MATERIAL_AMOUNT) return 0 -/datum/material_container/proc/sheet2amount(sheet_amt) +/datum/component/material_container/proc/sheet2amount(sheet_amt) if(sheet_amt > 0) return sheet_amt * MINERAL_MATERIAL_AMOUNT return 0 -/datum/material_container/proc/amount(id) +/datum/component/material_container/proc/amount(id) var/datum/material/M = materials[id] return M ? M.amount : 0 //returns the amount of material relevant to this container; //if this container does not support glass, any glass in 'I' will not be taken into account -/datum/material_container/proc/get_item_material_amount(obj/item/I) +/datum/component/material_container/proc/get_item_material_amount(obj/item/I) if(!istype(I)) return 0 var/material_amount = 0 diff --git a/code/datums/components/squeek.dm b/code/datums/components/squeek.dm new file mode 100644 index 0000000000..40fd0af598 --- /dev/null +++ b/code/datums/components/squeek.dm @@ -0,0 +1,61 @@ +/datum/component/squeak + var/static/list/default_squeak_sounds = list('sound/items/toysqueak1.ogg'=1, 'sound/items/toysqueak2.ogg'=1, 'sound/items/toysqueak3.ogg'=1) + var/list/override_squeak_sounds + var/squeak_chance = 100 + var/volume = 30 + + // This is so shoes don't squeak every step + var/steps = 0 + var/step_delay = 1 + + // This is to stop squeak spam from inhand usage + var/last_use = 0 + var/use_delay = 20 + +/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override) + if(custom_sounds) + override_squeak_sounds = custom_sounds + if(chance_override) + squeak_chance = chance_override + if(volume_override) + volume = volume_override + if(step_delay_override) + step_delay = step_delay_override + if(use_delay_override) + use_delay = use_delay_override + + if(istype(parent, /atom)) + RegisterSignal(COMSIG_ATOM_BLOB_ACT, .proc/play_squeak) + RegisterSignal(COMSIG_ATOM_HULK_ATTACK, .proc/play_squeak) + RegisterSignal(COMSIG_PARENT_ATTACKBY, .proc/play_squeak) + if(istype(parent, /atom/movable)) + RegisterSignal(COMSIG_MOVABLE_CROSSED, .proc/play_squeak) + RegisterSignal(COMSIG_MOVABLE_COLLIDE, .proc/play_squeak) + RegisterSignal(COMSIG_MOVABLE_IMPACT, .proc/play_squeak) + if(istype(parent, /obj/item)) + RegisterSignal(COMSIG_ITEM_ATTACK, .proc/play_squeak) + RegisterSignal(COMSIG_ITEM_ATTACK_SELF, .proc/use_squeak) + RegisterSignal(COMSIG_ITEM_ATTACK_OBJ, .proc/play_squeak) + if(istype(parent, /obj/item/clothing/shoes)) + RegisterSignal(COMSIG_SHOES_STEP_ACTION, .proc/step_squeak) + else + RegisterSignal(COMSIG_ATOM_ENTERED, .proc/play_squeak) + +/datum/component/squeak/proc/play_squeak() + if(prob(squeak_chance)) + if(!override_squeak_sounds) + playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1) + else + playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1) + +/datum/component/squeak/proc/step_squeak() + if(steps > step_delay) + play_squeak() + steps = 0 + else + steps++ + +/datum/component/squeak/proc/use_squeak() + if(last_use + use_delay < world.time) + last_use = world.time + play_squeak() \ No newline at end of file diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index c185a8f734..9fa53765ed 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -32,8 +32,6 @@ var/selected_category var/screen = 1 - var/datum/material_container/materials - var/list/categories = list( "Tools", "Electronics", @@ -48,15 +46,15 @@ ) /obj/machinery/autolathe/Initialize() - materials = new /datum/material_container(src, list(MAT_METAL, MAT_GLASS)) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS)) + . = ..() + wires = new /datum/wires/autolathe(src) files = new /datum/research/autolathe(src) matching_designs = list() - return ..() /obj/machinery/autolathe/Destroy() QDEL_NULL(wires) - QDEL_NULL(materials) return ..() /obj/machinery/autolathe/interact(mob/user) @@ -81,6 +79,7 @@ popup.open() /obj/machinery/autolathe/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() /obj/machinery/autolathe/attackby(obj/item/O, mob/user, params) @@ -123,42 +122,26 @@ busy = FALSE return 1 - if(O.flags_2 & HOLOGRAM_2) - return 1 + return ..() - var/material_amount = materials.get_item_material_amount(O) - if(!material_amount) - to_chat(user, "This object does not contain sufficient amounts of metal or glass to be accepted by the autolathe.") - return 1 - if(!materials.has_space(material_amount)) - to_chat(user, "The autolathe is full. Please remove metal or glass from the autolathe in order to insert more.") - return 1 - if(!user.temporarilyRemoveItemFromInventory(O)) - to_chat(user, "\The [O] is stuck to you and cannot be placed into the autolathe.") - return 1 - - busy = TRUE - var/inserted = materials.insert_item(O) - if(inserted) - if(istype(O, /obj/item/stack)) - if (O.materials[MAT_METAL]) - flick("autolathe_o",src)//plays metal insertion animation - if (O.materials[MAT_GLASS]) - flick("autolathe_r",src)//plays glass insertion animation - to_chat(user, "You insert [inserted] sheet[inserted>1 ? "s" : ""] to the autolathe.") - use_power(inserted*100) - if(!QDELETED(O)) - user.put_in_active_hand(O) +/obj/machinery/mecha_part_fabricator/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) + return + var/lit = M.last_inserted_type + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + use_power(max(500,M.last_amount_inserted/10)) else - to_chat(user, "You insert a material total of [inserted] to the autolathe.") - use_power(max(500,inserted/10)) - qdel(O) - else - user.put_in_active_hand(O) - - busy = FALSE - updateUsrDialog() - return 1 + var/obj/item/stack/S = lit + var/list/initmats = initial(S.materials) + if (initmats[MAT_METAL]) + flick("autolathe_o",src)//plays metal insertion animation + if (initmats[MAT_GLASS]) + flick("autolathe_r",src)//plays glass insertion animation + use_power(M.last_amount_inserted*100) + updateUsrDialog() /obj/machinery/autolathe/Topic(href, href_list) if(..()) @@ -193,6 +176,7 @@ var/power = max(2000, (metal_cost+glass_cost)*multiplier/5) + GET_COMPONENT(materials, /datum/component/material_container) if((materials.amount(MAT_METAL) >= metal_cost*multiplier*coeff) && (materials.amount(MAT_GLASS) >= glass_cost*multiplier*coeff)) busy = TRUE use_power(power) @@ -246,6 +230,7 @@ var/T = 0 for(var/obj/item/stock_parts/matter_bin/MB in component_parts) T += MB.rating*75000 + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = T T=1.2 for(var/obj/item/stock_parts/manipulator/M in component_parts) @@ -294,6 +279,7 @@ dat += "[D.name]" if(ispath(D.build_path, /obj/item/stack)) + GET_COMPONENT(materials, /datum/component/material_container) var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) if (max_multiplier>10 && !disabled) dat += " x10" @@ -325,6 +311,7 @@ dat += "[D.name]" if(ispath(D.build_path, /obj/item/stack)) + GET_COMPONENT(materials, /datum/component/material_container) var/max_multiplier = min(D.maxstack, D.materials[MAT_METAL] ?round(materials.amount(MAT_METAL)/D.materials[MAT_METAL]):INFINITY,D.materials[MAT_GLASS]?round(materials.amount(MAT_GLASS)/D.materials[MAT_GLASS]):INFINITY) if (max_multiplier>10 && !disabled) dat += " x10" @@ -339,6 +326,7 @@ return dat /obj/machinery/autolathe/proc/materials_printout() + GET_COMPONENT(materials, /datum/component/material_container) var/dat = "Total amount: [materials.total_amount] / [materials.max_amount] cm3
" for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] @@ -351,6 +339,7 @@ var/coeff = (ispath(D.build_path, /obj/item/stack) ? 1 : prod_coeff) + GET_COMPONENT(materials, /datum/component/material_container) if(D.materials[MAT_METAL] && (materials.amount(MAT_METAL) < (D.materials[MAT_METAL] * coeff * amount))) return 0 if(D.materials[MAT_GLASS] && (materials.amount(MAT_GLASS) < (D.materials[MAT_GLASS] * coeff * amount))) diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm index 2d848d95ed..5d7be7fbd8 100644 --- a/code/game/machinery/droneDispenser.dm +++ b/code/game/machinery/droneDispenser.dm @@ -22,7 +22,6 @@ var/icon_recharging = "recharge" var/icon_creating = "make" - var/datum/material_container/materials var/list/using_materials var/starting_amount = 0 var/metal_cost = 1000 @@ -55,14 +54,10 @@ /obj/machinery/droneDispenser/Initialize() . = ..() - materials = new(src, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT*MAX_STACK_SIZE*2) + var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS), MINERAL_MATERIAL_AMOUNT * MAX_STACK_SIZE * 2, TRUE) materials.insert_amount(starting_amount) using_materials = list(MAT_METAL=metal_cost, MAT_GLASS=glass_cost) -/obj/machinery/droneDispenser/Destroy() - QDEL_NULL(materials) - return ..() - /obj/machinery/droneDispenser/preloaded starting_amount = 5000 @@ -148,10 +143,6 @@ ..() if((mode == DRONE_RECHARGING) && !stat && recharging_text) to_chat(user, "[recharging_text]") - if(metal_cost) - to_chat(user, "It has [materials.amount(MAT_METAL)] units of metal stored.") - if(glass_cost) - to_chat(user, "It has [materials.amount(MAT_GLASS)] units of glass stored.") /obj/machinery/droneDispenser/power_change() ..() @@ -166,6 +157,7 @@ if((stat & (NOPOWER|BROKEN)) || !anchored) return + GET_COMPONENT(materials, /datum/component/material_container) if(!materials.has_materials(using_materials)) return // We require more minerals @@ -232,25 +224,8 @@ icon_state = icon_on /obj/machinery/droneDispenser/attackby(obj/item/O, mob/living/user) - if(istype(O, /obj/item/stack)) - if(!O.materials[MAT_METAL] && !O.materials[MAT_GLASS]) - return ..() - if(!metal_cost && !glass_cost) - to_chat(user, "There isn't a place to insert [O]!") - return - var/obj/item/stack/sheets = O - if(!user.canUnEquip(sheets)) - to_chat(user, "[O] is stuck to your hand, you can't get it off!") - return - - var/used = materials.insert_stack(sheets, sheets.amount) - - if(used) - to_chat(user, "You insert [used] sheet[used > 1 ? "s" : ""] into [src].") - else - to_chat(user, "The [src] isn't accepting the [sheets].") - - else if(istype(O, /obj/item/crowbar)) + if(istype(O, /obj/item/crowbar)) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() playsound(loc, O.usesound, 50, 1) to_chat(user, "You retrieve the materials from [src].") diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index b4bee2bdae..fbe02dca37 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -14,15 +14,14 @@ var/blood = 0 var/eat_dir = WEST var/amount_produced = 50 - var/datum/material_container/materials var/crush_damage = 1000 var/eat_victim_items = TRUE var/item_recycle_sound = 'sound/items/welder.ogg' /obj/machinery/recycler/Initialize() - materials = new /datum/material_container(src, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM)) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM)) + . = ..() update_icon() - return ..() /obj/machinery/recycler/RefreshParts() var/amt_made = 0 @@ -32,6 +31,7 @@ mat_mod *= 50000 for(var/obj/item/stock_parts/manipulator/M in component_parts) amt_made = 12.5 * M.rating //% of materials salvaged + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = mat_mod amount_produced = min(50, amt_made) + 50 @@ -126,6 +126,7 @@ /obj/machinery/recycler/proc/recycle_item(obj/item/I) I.loc = src.loc + GET_COMPONENT(materials, /datum/component/material_container) var/material_amount = materials.get_item_material_amount(I) if(!material_amount) qdel(I) diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 79c4971665..8efc14d966 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -12,7 +12,6 @@ circuit = /obj/item/circuitboard/machine/mechfab var/time_coeff = 1 var/component_coeff = 1 - var/datum/material_container/materials var/datum/research/files var/sync = 0 var/part_set @@ -36,9 +35,11 @@ ) /obj/machinery/mecha_part_fabricator/Initialize() + AddComponent(/datum/component/material_container, + list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), + FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) + . = ..() files = new /datum/research(src) //Setup the research data holder. - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE)) - return ..() /obj/machinery/mecha_part_fabricator/RefreshParts() var/T = 0 @@ -46,6 +47,7 @@ //maximum stocking amount (default 300000, 600000 at T4) for(var/obj/item/stock_parts/matter_bin/M in component_parts) T += M.rating + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = (200000 + (T*50000)) //resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55) @@ -113,6 +115,7 @@ /obj/machinery/mecha_part_fabricator/proc/output_available_resources() var/output + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] output += "[M.name]: [M.amount] cm³" @@ -133,6 +136,7 @@ /obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) if(D.reagents_list.len) // No reagents storage - no reagent designs. return 0 + GET_COMPONENT(materials, /datum/component/material_container) if(materials.has_materials(get_resources_w_coeff(D))) return 1 return 0 @@ -142,6 +146,7 @@ desc = "It's building \a [initial(D.name)]." var/list/res_coef = get_resources_w_coeff(D) + GET_COMPONENT(materials, /datum/component/material_container) materials.use_amount(res_coef) add_overlay("fab-active") use_power = ACTIVE_POWER_USE @@ -398,15 +403,34 @@ break if(href_list["remove_mat"] && href_list["material"]) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_sheets(text2num(href_list["remove_mat"]), href_list["material"]) updateUsrDialog() return /obj/machinery/mecha_part_fabricator/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() +/obj/machinery/mecha_part_fabricator/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) + return + var/lit = M.last_inserted_type + var/stack_name + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + stack_name = "bluespace" + else + var/obj/item/stack/S = lit + stack_name = material2name(initial(S.materials)[1]) + add_overlay("fab-load-[stack_name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[stack_name]"), 10) + updateUsrDialog() + /obj/machinery/mecha_part_fabricator/attackby(obj/item/W, mob/user, params) if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W)) return 1 @@ -417,55 +441,7 @@ if(default_deconstruction_crowbar(W)) return 1 - if(istype(W, /obj/item/stack/sheet)) - - if(!is_insertion_ready(user)) - return 1 - - var/material_amount = materials.get_item_material_amount(W) - - if(!try_insert(user, W, material_amount)) - return 1 - - var/inserted = materials.insert_item(W) - if(inserted) - to_chat(user, "You insert [inserted] sheet\s into [src].") - if(W && W.materials.len) - if(!QDELETED(W)) - user.put_in_active_hand(W) - var/mat_overlay = "fab-load-[material2name(W.materials[1])]" - add_overlay(mat_overlay) - sleep(10) - if(!QDELETED(src)) - cut_overlay(mat_overlay) //No matter what the overlay shall still be deleted - - updateUsrDialog() - - else if(istype(W, /obj/item/ore/bluespace_crystal)) - - if(!is_insertion_ready(user)) - return 1 - - var/material_amount = materials.get_item_material_amount(W) - - if(!try_insert(user, W, material_amount)) - return 1 - - var/inserted = materials.insert_item(W) - if(inserted) - to_chat(user, "You add [W] to the [src].") - if(W && W.materials.len) - qdel(W) - var/mat_overlay = "fab-load-bluespace" - add_overlay(mat_overlay) - sleep(10) - if(!QDELETED(src)) - cut_overlay(mat_overlay) - - updateUsrDialog() - - else - return ..() + return ..() /obj/machinery/mecha_part_fabricator/proc/material2name(ID) return copytext(ID,2) @@ -479,17 +455,3 @@ return FALSE return TRUE - - -/obj/machinery/mecha_part_fabricator/proc/try_insert(mob/user, obj/item/I, material_amount) - if(!material_amount) - to_chat(user, "This object does not contain sufficient amounts of materials to be accepted by [src].") - return FALSE - if(!materials.has_space(material_amount)) - to_chat(user, "\The [src] is full. Please remove some materials from [src] in order to insert more.") - return FALSE - if(!user.temporarilyRemoveItemFromInventory(I)) - to_chat(user, "\The [I] is stuck to you and cannot be placed into [src].") - return FALSE - - return TRUE \ No newline at end of file diff --git a/code/modules/clothing/shoes/bananashoes.dm b/code/modules/clothing/shoes/bananashoes.dm index e10f089eb8..bf3a1f28e0 100644 --- a/code/modules/clothing/shoes/bananashoes.dm +++ b/code/modules/clothing/shoes/bananashoes.dm @@ -5,59 +5,39 @@ desc = "Lost prototype of advanced clown tech. Powered by bananium, these shoes leave a trail of chaos in their wake." icon_state = "clown_prototype_off" var/on = FALSE - var/datum/material_container/bananium actions_types = list(/datum/action/item_action/toggle) -/obj/item/clothing/shoes/clown_shoes/banana_shoes/New() - ..() - bananium = new/datum/material_container(src,list(MAT_BANANIUM),200000) +/obj/item/clothing/shoes/clown_shoes/banana_shoes/Initialize() + . = ..() + AddComponent(/datum/component/material_container, list(MAT_BANANIUM), 200000, TRUE) + AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 75) /obj/item/clothing/shoes/clown_shoes/banana_shoes/step_action() + . = ..() if(on) - if(footstep > 1)//honks when its on - playsound(src, 'sound/items/bikehorn.ogg', 75, 1) - footstep = 0 - else - footstep++ - new/obj/item/grown/bananapeel/specialpeel(get_step(src,turn(usr.dir, 180))) //honk + GET_COMPONENT(bananium, /datum/component/material_container) bananium.use_amount_type(100, MAT_BANANIUM) if(bananium.amount(MAT_BANANIUM) < 100) on = !on flags_1 &= ~NOSLIP_1 update_icon() to_chat(loc, "You ran out of bananium!") - else - ..() /obj/item/clothing/shoes/clown_shoes/banana_shoes/attack_self(mob/user) + GET_COMPONENT(bananium, /datum/component/material_container) var/sheet_amount = bananium.retrieve_all() if(sheet_amount) to_chat(user, "You retrieve [sheet_amount] sheets of bananium from the prototype shoes.") else to_chat(user, "You cannot retrieve any bananium from the prototype shoes.") -/obj/item/clothing/shoes/clown_shoes/banana_shoes/attackby(obj/item/O, mob/user, params) - if(!bananium.get_item_material_amount(O)) - to_chat(user, "This item has no bananium!") - return - if(!user.dropItemToGround(O)) - to_chat(user, "You can't drop [O]!") - return - - var/bananium_amount = bananium.insert_item(O) - if(bananium_amount) - to_chat(user, "You insert [O] into the prototype shoes.") - qdel(O) - else - to_chat(user, "You are unable to insert more bananium!") - /obj/item/clothing/shoes/clown_shoes/banana_shoes/examine(mob/user) ..() - var/ban_amt = bananium.amount(MAT_BANANIUM) - to_chat(user, "The shoes are [on ? "enabled" : "disabled"]. There is [ban_amt ? ban_amt : "no"] bananium left.") + to_chat(user, "The shoes are [on ? "enabled" : "disabled"]") /obj/item/clothing/shoes/clown_shoes/banana_shoes/ui_action_click(mob/user) + GET_COMPONENT(bananium, /datum/component/material_container) if(bananium.amount(MAT_BANANIUM)) on = !on update_icon() diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm index 8428036860..0927a0ba88 100644 --- a/code/modules/mining/machine_processing.dm +++ b/code/modules/mining/machine_processing.dm @@ -66,7 +66,6 @@ density = TRUE anchored = TRUE var/obj/machinery/mineral/CONSOLE = null - var/datum/material_container/materials var/on = FALSE var/selected_material = MAT_METAL var/selected_alloy = null @@ -75,12 +74,11 @@ /obj/machinery/mineral/processing_unit/Initialize() . = ..() proximity_monitor = new(src, 1) - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), INFINITY) files = new /datum/research/smelter(src) /obj/machinery/mineral/processing_unit/Destroy() CONSOLE = null - QDEL_NULL(materials) QDEL_NULL(files) return ..() @@ -89,6 +87,7 @@ process_ore(AM) /obj/machinery/mineral/processing_unit/proc/process_ore(obj/item/ore/O) + GET_COMPONENT(materials, /datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!materials.has_space(material_amount)) unload_mineral(O) @@ -100,6 +99,7 @@ /obj/machinery/mineral/processing_unit/proc/get_machine_data() var/dat = "Smelter control console

" + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] dat += "[M.name]: [M.amount] cm³" @@ -165,6 +165,7 @@ continue*/ /obj/machinery/mineral/processing_unit/proc/smelt_ore() + GET_COMPONENT(materials, /datum/component/material_container) var/datum/material/mat = materials.materials[selected_material] if(mat) var/sheets_to_remove = (mat.amount >= (MINERAL_MATERIAL_AMOUNT * SMELT_AMOUNT) ) ? SMELT_AMOUNT : round(mat.amount / MINERAL_MATERIAL_AMOUNT) @@ -187,6 +188,7 @@ on = FALSE return + GET_COMPONENT(materials, /datum/component/material_container) materials.use_amount(alloy.materials, amount) generate_mineral(alloy.build_path) @@ -197,6 +199,7 @@ var/build_amount = SMELT_AMOUNT + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] @@ -214,6 +217,7 @@ unload_mineral(O) /obj/machinery/mineral/processing_unit/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm index abead3ab9a..38e02474f4 100644 --- a/code/modules/mining/machine_redemption.dm +++ b/code/modules/mining/machine_redemption.dm @@ -22,17 +22,15 @@ var/list/ore_values = list(MAT_GLASS = 1, MAT_METAL = 1, MAT_PLASMA = 15, MAT_SILVER = 16, MAT_GOLD = 18, MAT_TITANIUM = 30, MAT_URANIUM = 30, MAT_DIAMOND = 50, MAT_BLUESPACE = 50, MAT_BANANIUM = 60) var/message_sent = FALSE var/list/ore_buffer = list() - var/datum/material_container/materials var/datum/research/files var/obj/item/disk/design_disk/inserted_disk /obj/machinery/mineral/ore_redemption/Initialize() . = ..() - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY) + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE),INFINITY) files = new /datum/research/smelter(src) /obj/machinery/mineral/ore_redemption/Destroy() - QDEL_NULL(materials) QDEL_NULL(files) return ..() @@ -57,6 +55,7 @@ if(O && O.refined_type) points += O.points * point_upgrade + GET_COMPONENT(materials, /datum/component/material_container) var/material_amount = materials.get_item_material_amount(O) if(!material_amount) @@ -75,6 +74,7 @@ var/build_amount = 0 + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in D.materials) var/M = D.materials[mat_id] var/datum/material/redemption_mat = materials.materials[mat_id] @@ -110,6 +110,7 @@ var/has_minerals = FALSE + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT @@ -148,6 +149,7 @@ /obj/machinery/mineral/ore_redemption/attackby(obj/item/W, mob/user, params) if(exchange_parts(user, W)) return + GET_COMPONENT(materials, /datum/component/material_container) if(default_pry_open(W)) materials.retrieve_all() return @@ -181,16 +183,10 @@ if(user.transferItemToLoc(W, src)) inserted_disk = W return TRUE - - if(istype(W, /obj/item/stack/sheet)) - var/obj/item/stack/sheet/S = W - var/inserted = materials.insert_stack(S, S.amount) - to_chat(user, "You add [inserted] [S] sheets to \the [src].") - return - return ..() /obj/machinery/mineral/ore_redemption/on_deconstruction() + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() @@ -213,6 +209,7 @@ data["claimedPoints"] = inserted_id.mining_points data["materials"] = list() + GET_COMPONENT(materials, /datum/component/material_container) for(var/mat_id in materials.materials) var/datum/material/M = materials.materials[mat_id] var/sheet_amount = M.amount ? M.amount / MINERAL_MATERIAL_AMOUNT : "0" @@ -236,6 +233,7 @@ /obj/machinery/mineral/ore_redemption/ui_act(action, params) if(..()) return + GET_COMPONENT(materials, /datum/component/material_container) switch(action) if("Eject") if(!inserted_id) diff --git a/code/modules/mining/mint.dm b/code/modules/mining/mint.dm index e48db7c6fd..1a4e4c5ed1 100644 --- a/code/modules/mining/mint.dm +++ b/code/modules/mining/mint.dm @@ -1,107 +1,103 @@ -/**********************Mint**************************/ - - -/obj/machinery/mineral/mint - name = "coin press" - icon = 'icons/obj/economy.dmi' - icon_state = "coinpress0" +/**********************Mint**************************/ + + +/obj/machinery/mineral/mint + name = "coin press" + icon = 'icons/obj/economy.dmi' + icon_state = "coinpress0" density = TRUE anchored = TRUE - var/datum/material_container/materials - var/newCoins = 0 //how many coins the machine made in it's last load + var/newCoins = 0 //how many coins the machine made in it's last load var/processing = FALSE - var/chosen = MAT_METAL //which material will be used to make coins - var/coinsToProduce = 10 - speed_process = 1 - - + var/chosen = MAT_METAL //which material will be used to make coins + var/coinsToProduce = 10 + speed_process = 1 + + /obj/machinery/mineral/mint/Initialize() . = ..() - materials = new /datum/material_container(src, - list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM), - max_amt = MINERAL_MATERIAL_AMOUNT*50) - -/obj/machinery/mineral/mint/Destroy() - QDEL_NULL(materials) - return ..() - -/obj/machinery/mineral/mint/process() - var/turf/T = get_step(src, input_dir) - if(!T) - return - - for(var/obj/item/stack/sheet/O in T) - materials.insert_stack(O, O.amount) - -/obj/machinery/mineral/mint/attack_hand(mob/user) - var/dat = "Coin Press
" - - for(var/mat_id in materials.materials) - var/datum/material/M = materials.materials[mat_id] - if(!M.amount && chosen != mat_id) - continue - dat += "
[M.name] amount: [M.amount] cm3 " - if (chosen == mat_id) - dat += "Chosen" - else - dat += "Choose" - - var/datum/material/M = materials.materials[chosen] - - dat += "

Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.
" - dat += "-10 " - dat += "-5 " - dat += "-1 " - dat += "+1 " - dat += "+5 " - dat += "+10 " - - dat += "

In total this machine produced [newCoins] coins." - dat += "
Make coins" - user << browse(dat, "window=mint") - -/obj/machinery/mineral/mint/Topic(href, href_list) - if(..()) - return - usr.set_machine(src) - src.add_fingerprint(usr) - if(processing==1) - to_chat(usr, "The machine is processing.") - return - if(href_list["choose"]) - if(materials.materials[href_list["choose"]]) - chosen = href_list["choose"] - if(href_list["chooseAmt"]) - coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000) - if(href_list["makeCoins"]) - var/temp_coins = coinsToProduce + AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_PLASMA, MAT_SILVER, MAT_GOLD, MAT_URANIUM, MAT_DIAMOND, MAT_BANANIUM), MINERAL_MATERIAL_AMOUNT * 50) + +/obj/machinery/mineral/mint/process() + var/turf/T = get_step(src, input_dir) + if(!T) + return + + GET_COMPONENT(materials, /datum/component/material_container) + for(var/obj/item/stack/sheet/O in T) + materials.insert_stack(O, O.amount) + +/obj/machinery/mineral/mint/attack_hand(mob/user) + var/dat = "Coin Press
" + + GET_COMPONENT(materials, /datum/component/material_container) + for(var/mat_id in materials.materials) + var/datum/material/M = materials.materials[mat_id] + if(!M.amount && chosen != mat_id) + continue + dat += "
[M.name] amount: [M.amount] cm3 " + if (chosen == mat_id) + dat += "Chosen" + else + dat += "Choose" + + var/datum/material/M = materials.materials[chosen] + + dat += "

Will produce [coinsToProduce] [lowertext(M.name)] coins if enough materials are available.
" + dat += "-10 " + dat += "-5 " + dat += "-1 " + dat += "+1 " + dat += "+5 " + dat += "+10 " + + dat += "

In total this machine produced [newCoins] coins." + dat += "
Make coins" + user << browse(dat, "window=mint") + +/obj/machinery/mineral/mint/Topic(href, href_list) + if(..()) + return + usr.set_machine(src) + src.add_fingerprint(usr) + if(processing==1) + to_chat(usr, "The machine is processing.") + return + GET_COMPONENT(materials, /datum/component/material_container) + if(href_list["choose"]) + if(materials.materials[href_list["choose"]]) + chosen = href_list["choose"] + if(href_list["chooseAmt"]) + coinsToProduce = Clamp(coinsToProduce + text2num(href_list["chooseAmt"]), 0, 1000) + if(href_list["makeCoins"]) + var/temp_coins = coinsToProduce processing = TRUE - icon_state = "coinpress1" - var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2 - var/datum/material/M = materials.materials[chosen] - if(!M || !M.coin_type) - updateUsrDialog() - return - - while(coinsToProduce > 0 && materials.use_amount_type(coin_mat, chosen)) - create_coins(M.coin_type) - coinsToProduce-- - newCoins++ - src.updateUsrDialog() - sleep(5) - - icon_state = "coinpress0" + icon_state = "coinpress1" + var/coin_mat = MINERAL_MATERIAL_AMOUNT * 0.2 + var/datum/material/M = materials.materials[chosen] + if(!M || !M.coin_type) + updateUsrDialog() + return + + while(coinsToProduce > 0 && materials.use_amount_type(coin_mat, chosen)) + create_coins(M.coin_type) + coinsToProduce-- + newCoins++ + src.updateUsrDialog() + sleep(5) + + icon_state = "coinpress0" processing = FALSE - coinsToProduce = temp_coins - src.updateUsrDialog() - return - -/obj/machinery/mineral/mint/proc/create_coins(P) - var/turf/T = get_step(src,output_dir) - if(T) - var/obj/item/O = new P(src) - var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T) - if(!M) - M = new /obj/item/storage/bag/money(src) - unload_mineral(M) + coinsToProduce = temp_coins + src.updateUsrDialog() + return + +/obj/machinery/mineral/mint/proc/create_coins(P) + var/turf/T = get_step(src,output_dir) + if(T) + var/obj/item/O = new P(src) + var/obj/item/storage/bag/money/M = locate(/obj/item/storage/bag/money, T) + if(!M) + M = new /obj/item/storage/bag/money(src) + unload_mineral(M) O.loc = M \ No newline at end of file diff --git a/code/modules/research/circuitprinter.dm b/code/modules/research/circuitprinter.dm index ad2345afe5..f9a2c0d63c 100644 --- a/code/modules/research/circuitprinter.dm +++ b/code/modules/research/circuitprinter.dm @@ -11,7 +11,6 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). container_type = OPENCONTAINER_1 circuit = /obj/item/circuitboard/machine/circuit_imprinter - var/datum/material_container/materials var/efficiency_coeff var/list/categories = list( @@ -29,20 +28,18 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). ) /obj/machinery/r_n_d/circuit_imprinter/Initialize() - materials = new(src, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE)) + AddComponent(/datum/component/material_container, list(MAT_GLASS, MAT_GOLD, MAT_DIAMOND, MAT_METAL, MAT_BLUESPACE), + FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) create_reagents(0) return ..() -/obj/machinery/r_n_d/circuit_imprinter/Destroy() - QDEL_NULL(materials) - return ..() - /obj/machinery/r_n_d/circuit_imprinter/RefreshParts() reagents.maximum_volume = 0 for(var/obj/item/reagent_containers/glass/G in component_parts) reagents.maximum_volume += G.volume G.reagents.trans_to(src, G.reagents.total_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = 0 for(var/obj/item/stock_parts/matter_bin/M in component_parts) materials.max_amount += M.rating * 75000 @@ -59,6 +56,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). /obj/machinery/r_n_d/circuit_imprinter/proc/check_mat(datum/design/being_built, M) // now returns how many times the item can be built with the material var/list/all_materials = being_built.reagents_list + being_built.materials + GET_COMPONENT(materials, /datum/component/material_container) var/A = materials.amount(M) if(!A) A = reagents.get_reagent_amount(M) @@ -69,6 +67,7 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). /obj/machinery/r_n_d/circuit_imprinter/on_deconstruction() for(var/obj/item/reagent_containers/glass/G in component_parts) reagents.trans_to(G, G.reagents.maximum_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() @@ -77,52 +76,20 @@ using metal and glass, it uses glass and reagents (usually sulfuric acis). linked_console.linked_imprinter = null ..() -/obj/machinery/r_n_d/circuit_imprinter/Insert_Item(obj/item/O, mob/user) - - if(istype(O, /obj/item/stack/sheet)) - . = 1 - if(!is_insertion_ready(user)) +/obj/machinery/r_n_d/circuit_imprinter/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) return - var/sheet_material = materials.get_item_material_amount(O) - if(!sheet_material) - return - - if(!materials.has_space(sheet_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - var/obj/item/stack/sheet/stack = O - var/amount = round(input("How many sheets do you want to add?") as num)//No decimals - if(!in_range(src, stack) || !user.Adjacent(src)) - return - var/amount_inserted = materials.insert_stack(O,amount) - if(!amount_inserted) - return 1 + var/lit = M.last_inserted_type + var/stack_name + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + stack_name = "bluespace" + use_power(MINERAL_MATERIAL_AMOUNT / 10) else - use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount_inserted/10))) - to_chat(user, "You add [amount_inserted] sheets to the [src.name].") - updateUsrDialog() - - else if(istype(O, /obj/item/ore/bluespace_crystal)) //Bluespace crystals can be either a stack or an item - . = 1 - if(!is_insertion_ready(user)) - return - var/bs_material = materials.get_item_material_amount(O) - if(!bs_material) - return - - if(!materials.has_space(bs_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - materials.insert_item(O) - use_power(MINERAL_MATERIAL_AMOUNT/10) - to_chat(user, "You add [O] to the [src.name].") - qdel(O) - updateUsrDialog() - - else if(user.a_intent != INTENT_HARM) - to_chat(user, "You cannot insert this item into the [name]!") - return 1 - else - return 0 \ No newline at end of file + var/obj/item/stack/S = lit + stack_name = initial(S.name) + use_power(max(1000, (MINERAL_MATERIAL_AMOUNT * M.last_amount_inserted / 10))) + add_overlay("protolathe_[stack_name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "protolathe_[stack_name]"), 10) diff --git a/code/modules/research/experimentor.dm b/code/modules/research/experimentor.dm index cbbb73652b..4d8938b1b8 100644 --- a/code/modules/research/experimentor.dm +++ b/code/modules/research/experimentor.dm @@ -418,8 +418,9 @@ if(exp == SCANTYPE_OBLITERATE) visible_message("[exp_on] activates the crushing mechanism, [exp_on] is destroyed!") if(linked_console.linked_lathe) + GET_COMPONENT_FROM(linked_materials, /datum/component/material_container, linked_console.linked_lathe) for(var/material in exp_on.materials) - linked_console.linked_lathe.materials.insert_amount( min((linked_console.linked_lathe.materials.max_amount - linked_console.linked_lathe.materials.total_amount), (exp_on.materials[material])), material) + linked_materials.insert_amount( min((linked_materials.max_amount - linked_materials.total_amount), (exp_on.materials[material])), material) if(prob(EFFECT_PROB_LOW) && criticalReaction) visible_message("[src]'s crushing mechanism slowly and smoothly descends, flattening the [exp_on]!") new /obj/item/stack/sheet/plasteel(get_turf(pick(oview(1,src)))) diff --git a/code/modules/research/protolathe.dm b/code/modules/research/protolathe.dm index 7a18a5e630..88c902a70d 100644 --- a/code/modules/research/protolathe.dm +++ b/code/modules/research/protolathe.dm @@ -14,7 +14,6 @@ Note: Must be placed west/left of and R&D console to function. container_type = OPENCONTAINER_1 circuit = /obj/item/circuitboard/machine/protolathe - var/datum/material_container/materials var/efficiency_coeff var/list/categories = list( @@ -34,11 +33,9 @@ Note: Must be placed west/left of and R&D console to function. /obj/machinery/r_n_d/protolathe/Initialize() create_reagents(0) - materials = new(src, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE)) - return ..() - -/obj/machinery/r_n_d/protolathe/Destroy() - QDEL_NULL(materials) + AddComponent(/datum/component/material_container, + list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TITANIUM, MAT_BLUESPACE), + FALSE, list(/obj/item/stack, /obj/item/ore/bluespace_crystal), CALLBACK(src, .proc/is_insertion_ready)) return ..() /obj/machinery/r_n_d/protolathe/RefreshParts() @@ -47,6 +44,7 @@ Note: Must be placed west/left of and R&D console to function. reagents.maximum_volume += G.volume G.reagents.trans_to(src, G.reagents.total_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.max_amount = 0 for(var/obj/item/stock_parts/matter_bin/M in component_parts) materials.max_amount += M.rating * 75000 @@ -59,6 +57,7 @@ Note: Must be placed west/left of and R&D console to function. /obj/machinery/r_n_d/protolathe/proc/check_mat(datum/design/being_built, M) // now returns how many times the item can be built with the material var/list/all_materials = being_built.reagents_list + being_built.materials + GET_COMPONENT(materials, /datum/component/material_container) var/A = materials.amount(M) if(!A) A = reagents.get_reagent_amount(M) @@ -69,6 +68,7 @@ Note: Must be placed west/left of and R&D console to function. /obj/machinery/r_n_d/protolathe/on_deconstruction() for(var/obj/item/reagent_containers/glass/G in component_parts) reagents.trans_to(G, G.reagents.maximum_volume) + GET_COMPONENT(materials, /datum/component/material_container) materials.retrieve_all() ..() @@ -77,63 +77,20 @@ Note: Must be placed west/left of and R&D console to function. linked_console.linked_lathe = null ..() -/obj/machinery/r_n_d/protolathe/Insert_Item(obj/item/O, mob/user) - - if(istype(O, /obj/item/stack/sheet)) - . = 1 - if(!is_insertion_ready(user)) +/obj/machinery/r_n_d/protolathe/ComponentActivated(datum/component/C) + ..() + if(istype(C, /datum/component/material_container)) + var/datum/component/material_container/M = C + if(!M.last_insert_success) return - var/sheet_material = materials.get_item_material_amount(O) - if(!sheet_material) - return - - if(!materials.has_space(sheet_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - var/obj/item/stack/sheet/stack = O - var/amount = round(input("How many sheets do you want to add?") as num)//No decimals - if(!in_range(src, stack) || !user.Adjacent(src)) - return - var/amount_inserted = materials.insert_stack(O,amount) - if(!amount_inserted) - return 1 + var/lit = M.last_inserted_type + var/stack_name + if(ispath(lit, /obj/item/ore/bluespace_crystal)) + stack_name = "bluespace" + use_power(MINERAL_MATERIAL_AMOUNT / 10) else - var/stack_name = stack.name - busy = TRUE - use_power(max(1000, (MINERAL_MATERIAL_AMOUNT*amount_inserted/10))) - to_chat(user, "You add [amount_inserted] sheets to the [src.name].") - add_overlay("protolathe_[stack_name]") - sleep(10) - cut_overlay("protolathe_[stack_name]") - busy = FALSE - updateUsrDialog() - - else if(istype(O, /obj/item/ore/bluespace_crystal)) //Bluespace crystals can be either a stack or an item - . = 1 - if(!is_insertion_ready(user)) - return - var/bs_material = materials.get_item_material_amount(O) - if(!bs_material) - return - - if(!materials.has_space(bs_material)) - to_chat(user, "The [src.name]'s material bin is full! Please remove material before adding more.") - return 1 - - materials.insert_item(O) - busy = TRUE - use_power(MINERAL_MATERIAL_AMOUNT/10) - to_chat(user, "You add [O] to the [src.name].") - qdel(O) - add_overlay("protolathe_bluespace") - sleep(10) - cut_overlay("protolathe_bluespace") - busy = FALSE - updateUsrDialog() - - else if(user.a_intent != INTENT_HARM) - to_chat(user, "You cannot insert this item into the [name]!") - return 1 - else - return 0 + var/obj/item/stack/S = lit + stack_name = initial(S.name) + use_power(max(1000, (MINERAL_MATERIAL_AMOUNT * M.last_amount_inserted / 10))) + add_overlay("protolathe_[stack_name]") + addtimer(CALLBACK(src, /atom/proc/cut_overlay, "protolathe_[stack_name]"), 10) diff --git a/code/modules/research/rdconsole.dm b/code/modules/research/rdconsole.dm index 2f60e280ec..ee2cba39fd 100644 --- a/code/modules/research/rdconsole.dm +++ b/code/modules/research/rdconsole.dm @@ -169,6 +169,15 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(href_list["menu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code. var/temp_screen = text2num(href_list["menu"]) screen = temp_screen + + + var/datum/component/material_container/linked_materials + if(linked_lathe) + linked_materials = linked_lathe.GetComponent(/datum/component/material_container) + + var/datum/component/material_container/imprinter_materials + if(linked_imprinter) + imprinter_materials = linked_imprinter.GetComponent(/datum/component/material_container) if(href_list["category"]) selected_category = href_list["category"] @@ -315,7 +324,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(linked_lathe) //Also sends salvaged materials to a linked protolathe, if any. for(var/material in linked_destroy.loaded_item.materials) - linked_lathe.materials.insert_amount(min((linked_lathe.materials.max_amount - linked_lathe.materials.total_amount), (linked_destroy.loaded_item.materials[material]*(linked_destroy.decon_mod/10))), material) + linked_materials.insert_amount(min((linked_materials.max_amount - linked_materials.total_amount), (linked_destroy.loaded_item.materials[material]*(linked_destroy.decon_mod/10))), material) SSblackbox.add_details("item_deconstructed","[linked_destroy.loaded_item.type]") linked_destroy.loaded_item = null for(var/obj/I in linked_destroy.contents) @@ -421,7 +430,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, for(var/MAT in being_built.materials) efficient_mats[MAT] = being_built.materials[MAT]*coeff - if(!linked_lathe.materials.has_materials(efficient_mats, amount)) + if(!linked_materials.has_materials(efficient_mats, amount)) linked_lathe.say("Not enough materials to complete prototype.") enough_materials = 0 g2g = 0 @@ -433,7 +442,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, g2g = 0 if(enough_materials) - linked_lathe.materials.use_amount(efficient_mats, amount) + linked_materials.use_amount(efficient_mats, amount) for(var/R in being_built.reagents_list) linked_lathe.reagents.remove_reagent(R, being_built.reagents_list[R]*coeff) @@ -497,7 +506,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, for(var/MAT in being_built.materials) efficient_mats[MAT] = being_built.materials[MAT]/coeff - if(!linked_imprinter.materials.has_materials(efficient_mats)) + if(!imprinter_materials.has_materials(efficient_mats)) linked_imprinter.say("Not enough materials to complete prototype.") enough_materials = 0 g2g = 0 @@ -509,7 +518,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, g2g = 0 if(enough_materials) - linked_imprinter.materials.use_amount(efficient_mats) + imprinter_materials.use_amount(efficient_mats) for(var/R in being_built.reagents_list) linked_imprinter.reagents.remove_reagent(R, being_built.reagents_list[R]/coeff) @@ -536,7 +545,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, linked_lathe.reagents.clear_reagents() else if(href_list["ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material - linked_lathe.materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["ejectsheet"]) + linked_materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["ejectsheet"]) //Circuit Imprinter Materials else if(href_list["disposeI"] && linked_imprinter) //Causes the circuit imprinter to dispose of a single reagent (all of it) @@ -546,7 +555,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, linked_imprinter.reagents.clear_reagents() else if(href_list["imprinter_ejectsheet"] && linked_imprinter) //Causes the imprinter to eject a sheet of material - linked_imprinter.materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["imprinter_ejectsheet"]) + imprinter_materials.retrieve_sheets(text2num(href_list["eject_amt"]), href_list["imprinter_ejectsheet"]) else if(href_list["find_device"]) //The R&D console looks for devices nearby to link up with. @@ -634,6 +643,14 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(linked_imprinter == null) screen = 4.0 + + var/datum/component/material_container/linked_materials + if(linked_lathe) + linked_materials = linked_lathe.GetComponent(/datum/component/material_container) + + var/datum/component/material_container/imprinter_materials + if(linked_imprinter) + imprinter_materials = linked_imprinter.GetComponent(/datum/component/material_container) switch(screen) //////////////////////R&D CONSOLE SCREENS////////////////// @@ -823,7 +840,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Material Storage" dat += "Chemical Storage
" dat += "

Protolathe Menu:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" + dat += "Material Amount: [linked_materials.total_amount] / [linked_materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" dat += "
\ @@ -841,7 +858,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Protolathe Menu" dat += "

Browsing [selected_category]:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" + dat += "Material Amount: [linked_materials.total_amount] / [linked_materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" var/coeff = linked_lathe.efficiency_coeff @@ -879,7 +896,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Protolathe Menu" dat += "

Search results:


" - dat += "Material Amount: [linked_lathe.materials.total_amount] / [linked_lathe.materials.max_amount]
" + dat += "Material Amount: [linked_materials.total_amount] / [linked_materials.max_amount]
" dat += "Chemical Volume: [linked_lathe.reagents.total_volume] / [linked_lathe.reagents.maximum_volume]
" var/coeff = linked_lathe.efficiency_coeff @@ -916,8 +933,8 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(!linked_lathe) dat += "ERROR: Protolathe connection failed." else - for(var/mat_id in linked_lathe.materials.materials) - var/datum/material/M = linked_lathe.materials.materials[mat_id] + for(var/mat_id in linked_materials.materials) + var/datum/material/M = linked_materials.materials[mat_id] dat += "* [M.amount] of [M.name]: " if(M.amount >= MINERAL_MATERIAL_AMOUNT) dat += "Eject " if(M.amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " @@ -944,7 +961,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Material Storage" dat += "Chemical Storage
" dat += "

Circuit Imprinter Menu:


" - dat += "Material Amount: [linked_imprinter.materials.total_amount]
" + dat += "Material Amount: [imprinter_materials.total_amount]
" dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" dat += "\ @@ -961,7 +978,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Circuit Imprinter Menu" dat += "

Browsing [selected_category]:


" - dat += "Material Amount: [linked_imprinter.materials.total_amount]
" + dat += "Material Amount: [imprinter_materials.total_amount]
" dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" var/coeff = linked_imprinter.efficiency_coeff @@ -991,7 +1008,7 @@ won't update every console in existence) but it's more of a hassle to do. Also, dat += "Main Menu" dat += "Circuit Imprinter Menu" dat += "

Search results:


" - dat += "Material Amount: [linked_imprinter.materials.total_amount]
" + dat += "Material Amount: [imprinter_materials.total_amount]
" dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]
" var/coeff = linked_imprinter.efficiency_coeff @@ -1028,8 +1045,8 @@ won't update every console in existence) but it's more of a hassle to do. Also, if(!linked_imprinter) dat += "ERROR: Protolathe connection failed." else - for(var/mat_id in linked_imprinter.materials.materials) - var/datum/material/M = linked_imprinter.materials.materials[mat_id] + for(var/mat_id in imprinter_materials.materials) + var/datum/material/M = imprinter_materials.materials[mat_id] dat += "* [M.amount] of [M.name]: " if(M.amount >= MINERAL_MATERIAL_AMOUNT) dat += "Eject " if(M.amount >= MINERAL_MATERIAL_AMOUNT*5) dat += "5x " diff --git a/sound/items/toysqueak1.ogg b/sound/items/toysqueak1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..e64a6fb179d114ab0146593cbfa0c8171504649f GIT binary patch literal 12956 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 BufzZV literal 0 HcmV?d00001 diff --git a/sound/items/toysqueak2.ogg b/sound/items/toysqueak2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..fddf1edfb926c20dbfd01608870b6f09cd8809fd GIT binary patch literal 14781 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 literal 0 HcmV?d00001 diff --git a/sound/items/toysqueak3.ogg b/sound/items/toysqueak3.ogg new file mode 100644 index 0000000000000000000000000000000000000000..338f4d8aa90bb5188cb86eb5a9814974e0634b32 GIT binary patch literal 13778 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 literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index d852af48c0..a0365fdd75 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -263,7 +263,6 @@ #include "code\datums\hud.dm" #include "code\datums\map_config.dm" #include "code\datums\martial.dm" -#include "code\datums\material_container.dm" #include "code\datums\mind.dm" #include "code\datums\mutable_appearance.dm" #include "code\datums\mutations.dm" @@ -286,7 +285,9 @@ #include "code\datums\antagonists\ninja.dm" #include "code\datums\components\archaeology.dm" #include "code\datums\components\component.dm" +#include "code\datums\components\material_container.dm" #include "code\datums\components\slippery.dm" +#include "code\datums\components\squeek.dm" #include "code\datums\diseases\_disease.dm" #include "code\datums\diseases\_MobProcs.dm" #include "code\datums\diseases\anxiety.dm"