From 2a2cd5124e87c2a2561ffcacf37e00097e29d1bd Mon Sep 17 00:00:00 2001 From: spookerton Date: Wed, 16 Nov 2022 17:20:20 +0000 Subject: [PATCH] fixed assorted ore bag/box bugs and perf issues mining satchels automatically collect ore if held in the hands, belt, or suit slot. pulling an ore box with a satchel collects ore into the ore box instead of the satchel, and empties the satchel if appropriate. hostile mining drones collect into ore boxes just like people would. Their collection checking view size is smaller. mining satchels and ore boxes only update their contents hints if examined after it changes, rather than up to once a second regardless of changes. various doubled messages removed. removed various dm-land loops in favor of contents addition where it makes sense. --- .../objects/items/weapons/storage/bags.dm | 115 ------------- .../objects/items/weapons/storage/bags/ore.dm | 115 +++++++++++++ code/modules/mining/ore_box.dm | 154 +++++++++--------- .../mechanical/drones/mining_drone.dm | 60 ++++--- polaris.dme | 1 + 5 files changed, 237 insertions(+), 208 deletions(-) create mode 100644 code/game/objects/items/weapons/storage/bags/ore.dm diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index fc558de63e5..6f46d25eb9e 100644 --- a/code/game/objects/items/weapons/storage/bags.dm +++ b/code/game/objects/items/weapons/storage/bags.dm @@ -73,121 +73,6 @@ can_hold = list() // any cant_hold = list(/obj/item/disk/nuclear) -// ----------------------------- -// Mining Satchel -// ----------------------------- -/* - * Mechoid - Orebags are the most common quick-gathering thing, and also have tons of lag associated with it. Their checks are going to be hyper-simplified due to this, and their INCREDIBLY singular target contents. - */ - -/obj/item/storage/bag/ore - name = "mining satchel" - desc = "This little bugger can be used to store and transport ores." - icon = 'icons/obj/mining.dmi' - icon_state = "satchel" - slot_flags = SLOT_BELT | SLOT_POCKET - w_class = ITEMSIZE_NORMAL - max_storage_space = ITEMSIZE_COST_NORMAL * 25 - max_w_class = ITEMSIZE_NORMAL - can_hold = list(/obj/item/ore) - var/stored_ore = list() - var/last_update = 0 - -/obj/item/storage/bag/ore/remove_from_storage(obj/item/W as obj, atom/new_location) - if(!istype(W)) return 0 - - if(new_location) - if(ismob(loc)) - W.dropped(usr) - if(ismob(new_location)) - W.hud_layerise() - else - W.reset_plane_and_layer() - W.forceMove(new_location) - else - W.forceMove(get_turf(src)) - - W.on_exit_storage(src) - update_icon() - return 1 - -/obj/item/storage/bag/ore/gather_all(turf/T as turf, mob/user as mob, var/silent = 0) - var/success = 0 - var/failure = 0 - for(var/obj/item/ore/I in T) //Only ever grabs ores. Doesn't do any extraneous checks, as all ore is the same size. Tons of checks means it causes hanging for up to three seconds. - if(contents.len >= max_storage_space) - failure = 1 - break - I.forceMove(src) - success = 1 - if(success && !failure && !silent) - to_chat(user, "You put everything in [src].") - else if(success && (!silent || (silent && contents.len >= max_storage_space))) - to_chat(user, "You fill the [src].") - else if(!silent) - to_chat(user, "You fail to pick anything up with \the [src].") - if(istype(user.pulling, /obj/structure/ore_box)) //Bit of a crappy way to do this, as it doubles spam for the user, but it works. - var/obj/structure/ore_box/O = user.pulling - O.attackby(src, user) - -/obj/item/storage/bag/ore/equipped(mob/user) - ..() - if(user.get_inventory_slot(src) == slot_wear_suit || slot_l_hand || slot_l_hand || slot_belt) //Basically every place they can go. Makes sure it doesn't unregister if moved to other slots. - GLOB.moved_event.register(user, src, /obj/item/storage/bag/ore/proc/autoload, user) - -/obj/item/storage/bag/ore/dropped(mob/user) - ..() - if(user.get_inventory_slot(src) == slot_wear_suit || slot_l_hand || slot_l_hand || slot_belt) //See above. This should really be a define. - GLOB.moved_event.register(user, src, /obj/item/storage/bag/ore/proc/autoload, user) - else - GLOB.moved_event.unregister(user, src) - -/obj/item/storage/bag/ore/proc/autoload(mob/user) - var/obj/item/ore/O = locate() in get_turf(src) - if(O) - gather_all(get_turf(src), user) - -/obj/item/storage/bag/ore/proc/rangedload(atom/A, mob/user) - var/obj/item/ore/O = locate() in get_turf(A) - if(O) - gather_all(get_turf(A), user) - -/obj/item/storage/bag/ore/examine(mob/user) - . = ..() - - if(!Adjacent(user)) //Can only check the contents of ore bags if you can physically reach them. - return . - - if(istype(user, /mob/living)) - add_fingerprint(user) - - if(!contents.len) - . += "It is empty." - - else if(world.time > last_update + 10) - update_ore_count() - last_update = world.time - - . += "It holds:" - for(var/ore in stored_ore) - . += "- [stored_ore[ore]] [ore]" - -/obj/item/storage/bag/ore/open(mob/user as mob) //No opening it for the weird UI of having shit-tons of ore inside it. - if(world.time > last_update + 10) - update_ore_count() - last_update = world.time - user.examinate(src) - -/obj/item/storage/bag/ore/proc/update_ore_count() //Stolen from ore boxes. - - stored_ore = list() - - for(var/obj/item/ore/O in contents) - if(stored_ore[O.name]) - stored_ore[O.name]++ - else - stored_ore[O.name] = 1 - // ----------------------------- // Plant bag // ----------------------------- diff --git a/code/game/objects/items/weapons/storage/bags/ore.dm b/code/game/objects/items/weapons/storage/bags/ore.dm new file mode 100644 index 00000000000..af57b009410 --- /dev/null +++ b/code/game/objects/items/weapons/storage/bags/ore.dm @@ -0,0 +1,115 @@ +/obj/item/storage/bag/ore + name = "mining satchel" + desc = "A handy-dandy container for your rock collection. Gneiss." + icon = 'icons/obj/mining.dmi' + icon_state = "satchel" + slot_flags = SLOT_BELT | SLOT_POCKET + w_class = ITEMSIZE_NORMAL + max_storage_space = ITEMSIZE_COST_NORMAL * 25 + max_w_class = ITEMSIZE_NORMAL + can_hold = list(/obj/item/ore) + + /// Rebuild stored_ore if true. Becomes true when contents changes. + var/stored_ore_dirty + + /// The current ore contents of the bag formatted by english_list. + var/stored_ore + + +/obj/item/storage/bag/ore/examine(mob/user) + . = ..() + if (!Adjacent(user) && !isobserver(user)) + return + if (isliving(user)) + add_fingerprint(user) + if (stored_ore_dirty) + stored_ore_dirty = FALSE + stored_ore = null + var/list/ores = list() + for (var/obj/item/ore/ore in contents) + ++ores[ore.name] + var/list/chunks = list() + for (var/name in ores) + chunks += "[ores[name]] [name]" + if (length(chunks)) + var/full = length(contents) >= max_storage_space + stored_ore = "[full ? "It is full! " : ""]It contains [english_list(chunks)]" + . += SPAN_ITALIC(stored_ore || "It is empty.") + + +/obj/item/storage/bag/ore/equipped(mob/living/user, into_slot) + ..() + switch (into_slot) + if (slot_wear_suit, slot_l_hand, slot_r_hand, slot_belt) + GLOB.moved_event.register(user, src, /obj/item/storage/bag/ore/proc/autoload, user) + + +/obj/item/storage/bag/ore/dropped(mob/living/user) + ..() + switch (user.get_inventory_slot(src)) + if (slot_wear_suit, slot_l_hand, slot_r_hand, slot_belt) + . = . //noop + else + GLOB.moved_event.unregister(user, src) + + +/obj/item/storage/bag/ore/remove_from_storage(obj/item/item, atom/into) + if (!istype(item)) + return FALSE + if (isloc(into)) + if (ismob(loc)) + item.dropped(usr) + if (ismob(into)) + item.hud_layerise() + else + item.reset_plane_and_layer() + else + item.forceMove(get_turf(src)) + item.on_exit_storage(src) + stored_ore_dirty = TRUE + update_icon() + return TRUE + + +/obj/item/storage/bag/ore/gather_all(turf/from, mob/living/user, silent, autoload) + var/obj/structure/ore_box/box = user.pulling + if (istype(box)) + var/gathered = length(contents) + if (gathered) + box.contents += contents + stored_ore_dirty = TRUE + for (var/obj/item/ore/ore in from) + box.contents += ore + ++gathered + if (gathered) + box.stored_ore_dirty = TRUE + if (!silent) + to_chat(user, SPAN_ITALIC("You collect all the ore into \the [box].")) + return + if (length(contents) >= max_storage_space) + if (!autoload && !silent) + to_chat(user, SPAN_WARNING("\The [src] is full.")) + return + var/gathered = 0 + var/available_space = max_storage_space - length(contents) + for (var/obj/item/ore/ore in from) + contents += ore + if (--available_space < 1) + if (!silent) + to_chat(user, SPAN_ITALIC("You completely fill \the [src] with ore.")) + return + ++gathered + if (gathered) + stored_ore_dirty = TRUE + if (!silent) + to_chat(user, SPAN_ITALIC("You collect all the ore with \the [src].")) + else if (!autoload && !silent) + to_chat(user, SPAN_WARNING("There's no ore there to collect.")) + + +/obj/item/storage/bag/ore/open(mob/living/user) + user.examinate(src) + + +/obj/item/storage/bag/ore/proc/autoload(mob/living/user) + gather_all(get_turf(src), user, FALSE, TRUE) diff --git a/code/modules/mining/ore_box.dm b/code/modules/mining/ore_box.dm index e1aab404401..cf79c8f671f 100644 --- a/code/modules/mining/ore_box.dm +++ b/code/modules/mining/ore_box.dm @@ -1,96 +1,102 @@ -/**********************Ore box**************************/ /obj/structure/ore_box - icon = 'icons/obj/mining.dmi' - icon_state = "orebox0" name = "ore box" desc = "A heavy box used for storing ore." - density = 1 - var/last_update = 0 - var/list/stored_ore = list() - -/obj/structure/ore_box/attackby(obj/item/W as obj, mob/user as mob) - if (istype(W, /obj/item/ore)) - user.remove_from_mob(W) - src.contents += W - - else if (istype(W, /obj/item/storage)) - var/obj/item/storage/S = W - if(!S.contents.len) - return - S.hide_from(usr) - for(var/obj/item/ore/O in S.contents) - S.remove_from_storage(O, src) //This will move the item to this item's contents - to_chat(user, "You empty the satchel into the box.") - - update_ore_count() - - return - -/obj/structure/ore_box/proc/update_ore_count() + icon = 'icons/obj/mining.dmi' + icon_state = "orebox0" + density = TRUE - stored_ore = list() + /// Rebuild stored_ore if true. Becomes true when contents changes. + var/stored_ore_dirty - for(var/obj/item/ore/O in contents) + /// The current ore contents of the bag formatted by english_list. + var/stored_ore - if(stored_ore[O.name]) - stored_ore[O.name]++ - else - stored_ore[O.name] = 1 /obj/structure/ore_box/examine(mob/user) . = ..() + if (!Adjacent(user) && !isobserver(user)) + return + if (isliving(user)) + add_fingerprint(user) + if (stored_ore_dirty) + stored_ore_dirty = FALSE + stored_ore = null + var/list/ores = list() + for (var/obj/item/ore/ore in contents) + ++ores[ore.name] + var/list/chunks = list() + for (var/name in ores) + chunks += "[ores[name]] [name]" + if (length(chunks)) + stored_ore = "It contains [english_list(chunks)]" + . += SPAN_ITALIC(stored_ore || "It is empty.") + + +/obj/structure/ore_box/attackby(obj/item/item, mob/living/user) + if (istype(item, /obj/item/ore)) + user.remove_from_mob(item, src) + stored_ore_dirty = TRUE + return TRUE + var/obj/item/storage/storage = item + if (istype(storage)) + . = TRUE + var/length = length(storage.contents) + if (!length) + to_chat(user, SPAN_WARNING("\The [storage] is empty.")) + return + var/gathered + var/obj/item/storage/bag/ore/bag = item + if (istype(bag)) + bag.stored_ore_dirty = TRUE + contents += bag.contents + gathered = TRUE + else + for (var/obj/item/ore/ore in storage) + storage.remove_from_storage(ore, src) + ++gathered + if (gathered) + to_chat(user, SPAN_ITALIC("You empty \the [storage] into \the [src].")) + stored_ore_dirty = TRUE + else + to_chat(user, SPAN_WARNING("\The [storage] contained no ore.")) - if(!Adjacent(user)) //Can only check the contents of ore boxes if you can physically reach them. - return . - - add_fingerprint(user) - - if(!contents.len) - . += "It is empty." - return . - if(world.time > last_update + 10) - update_ore_count() - last_update = world.time +/obj/structure/ore_box/ex_act(severity) + var/turf/turf = get_turf(src) + switch (severity) + if (1) + if (turf == loc) + turf.contents += contents + qdel(src) + if (2) + if (prob(50)) + return + if (turf == loc) + turf.contents += contents + qdel(src) - . += "It holds:" - for(var/ore in stored_ore) - . += "- [stored_ore[ore]] [ore]" /obj/structure/ore_box/verb/empty_box() set name = "Empty Ore Box" set category = "Object" set src in view(1) - - if(!ishuman(usr) && !isrobot(usr)) //Only living, intelligent creatures with gripping aparatti can empty ore boxes. - to_chat(usr, "You are physically incapable of emptying the ore box.") + var/mob/living/user = usr + if (!(ishuman(user) || isrobot(user))) + to_chat(user, SPAN_WARNING("You're not dextrous enough to do that.")) return - - if(usr.stat || usr.restrained()) + if (!Adjacent(user)) return - - if(!Adjacent(usr)) //You can only empty the box if you can physically reach it - to_chat(usr, "You cannot reach the ore box.") + if (user.stat || user.restrained()) + to_chat(user, SPAN_WARNING("You're in no condition to do that.")) return - - add_fingerprint(usr) - - if(contents.len < 1) - to_chat(usr, "The ore box is empty.") + add_fingerprint(user) + if (!length(contents)) + to_chat(user, SPAN_WARNING("\The [src] is empty.")) return - - for (var/obj/item/ore/O in contents) - contents -= O - O.loc = src.loc - to_chat(usr, "You empty the ore box.") - - return - -/obj/structure/ore_box/ex_act(severity) - if(severity == 1.0 || (severity < 3.0 && prob(50))) - for (var/obj/item/ore/O in contents) - O.loc = src.loc - O.ex_act(severity++) - qdel(src) - return \ No newline at end of file + user.visible_message( + SPAN_ITALIC("\The [user] empties \a [src]."), + SPAN_ITALIC("You empty \the [src]."), + range = 5 + ) + loc.contents += contents diff --git a/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm b/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm index 1c8270f8083..f0f5647ce0f 100644 --- a/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm +++ b/code/modules/mob/living/simple_mob/subtypes/mechanical/drones/mining_drone.dm @@ -106,26 +106,48 @@ return has_tool /mob/living/simple_mob/mechanical/mining_drone/handle_special() - if(my_storage && (get_AI_stance() in list(STANCE_APPROACH, STANCE_IDLE, STANCE_FOLLOW)) && !is_AI_busy() && isturf(loc) && (world.time > last_search + search_cooldown) && (my_storage.contents.len < my_storage.max_storage_space)) - last_search = world.time + if (!isturf(loc)) + return + if (!my_storage) + return + if (ai_holder?.busy) + return + if (world.time < last_search + search_cooldown) + return + switch (get_AI_stance()) + if (STANCE_APPROACH, STANCE_IDLE, STANCE_FOLLOW) + . = . //noop + else + return + var/max_space = my_storage.max_storage_space + var/obj/structure/ore_box/box = locate() in view(3, src) + if (istype(box)) + if (length(my_storage.contents)) + Beam(box, icon_state = "holo_beam", time = 1 SECONDS) + box.contents += my_storage.contents + my_storage.stored_ore_dirty = TRUE + box.stored_ore_dirty = TRUE + else if (length(my_storage.contents) >= max_space) + audible_message(SPAN_NOTICE("\The [src] emits a shrill beep; it's full!")) + return + for (var/turf/simulated/floor/floor in view(4, src)) + if (length(my_storage.contents) >= max_space) + audible_message(SPAN_NOTICE("\The [src] emits a shrill beep; it's full!")) + return + if (prob(50)) + continue + if (!(locate(/obj/item/ore) in floor)) + continue + Beam(floor, icon_state = "holo_beam", time = 0.5 SECONDS) + if (box) + for (var/obj/item/ore/ore in floor) + box.contents += ore + box.stored_ore_dirty = TRUE + Beam(box, icon_state = "holo_beam", time = 0.5 SECONDS) + else + my_storage.gather_all(floor, src) + my_storage.stored_ore_dirty = TRUE - for(var/turf/T in view(world.view,src)) - if(my_storage.contents.len >= my_storage.max_storage_space) - break - - if((locate(/obj/item/ore) in T) && prob(40)) - src.Beam(T, icon_state = "holo_beam", time = 0.5 SECONDS) - my_storage.rangedload(T, src) - - if(my_storage.contents.len >= my_storage.max_storage_space) - visible_message("\The [src] emits a shrill beep, indicating its storage is full.") - - var/obj/structure/ore_box/OB = locate() in view(2, src) - - if(istype(OB) && my_storage && my_storage.contents.len) - src.Beam(OB, icon_state = "rped_upgrade", time = 1 SECONDS) - for(var/obj/item/I in my_storage) - my_storage.remove_from_storage(I, OB) /decl/mob_organ_names/miningdrone hit_zones = list("chassis", "comms array", "sensor suite", "left excavator module", "right excavator module", "maneuvering thruster") \ No newline at end of file diff --git a/polaris.dme b/polaris.dme index 4275a12abbb..860ff32c05e 100644 --- a/polaris.dme +++ b/polaris.dme @@ -1162,6 +1162,7 @@ #include "code\game\objects\items\weapons\storage\toolbox.dm" #include "code\game\objects\items\weapons\storage\uplink_kits.dm" #include "code\game\objects\items\weapons\storage\wallets.dm" +#include "code\game\objects\items\weapons\storage\bags\ore.dm" #include "code\game\objects\items\weapons\tanks\jetpack.dm" #include "code\game\objects\items\weapons\tanks\tank_types.dm" #include "code\game\objects\items\weapons\tanks\tanks.dm"