diff --git a/code/game/objects/items/weapons/storage/bags.dm b/code/game/objects/items/weapons/storage/bags.dm index fc558de63e..6f46d25eb9 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 0000000000..af57b00941 --- /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 e1aab40440..cf79c8f671 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() + icon = 'icons/obj/mining.dmi' + icon_state = "orebox0" + density = TRUE -/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 + /// Rebuild stored_ore if true. Becomes true when contents changes. + var/stored_ore_dirty - 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.") + /// The current ore contents of the bag formatted by english_list. + var/stored_ore - update_ore_count() - - return - -/obj/structure/ore_box/proc/update_ore_count() - - 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 /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.") - if(!Adjacent(user)) //Can only check the contents of ore boxes if you can physically reach them. - return . - add_fingerprint(user) +/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(!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 1c8270f808..f0f5647ce0 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 4275a12abb..860ff32c05 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"