From 4a76edf5fa2e663aef5895c695846424dbd3d968 Mon Sep 17 00:00:00 2001 From: Jack Edge Date: Thu, 19 May 2016 16:19:52 +0100 Subject: [PATCH] Fixes #17790, and cleans up drone dispenser code - Drone dispensers now run on a timer based system like what shuttles do. - Fixed #17790, they now dispense drones. - Fixed what was a probably really old bug in material containers that no one's encountered before probably. - Dispensers don't prompt you for sheet amounts, they eat them all like an autolathe. - Dispensers now, by default, only pump out three shells before pausing. --- code/datums/material_container.dm | 7 +- code/game/machinery/droneDispenser.dm | 288 ++++++++++++++++---------- 2 files changed, 186 insertions(+), 109 deletions(-) diff --git a/code/datums/material_container.dm b/code/datums/material_container.dm index 21752e31bd6..daae39f0819 100644 --- a/code/datums/material_container.dm +++ b/code/datums/material_container.dm @@ -53,7 +53,8 @@ M.amount += amt total_amount += amt else - for(var/datum/material/M in materials) + for(var/i in materials) + var/datum/material/M = materials[i] M.amount += amt total_amount += amt return (total_amount - total_amount_saved) @@ -135,7 +136,7 @@ return TRUE else if(istype(mats)) for(var/M in mats) - if(materials[M] && mats[M] <= materials[M]) + if(materials[M] && (mats[M] <= materials[M])) continue else return FALSE @@ -276,4 +277,4 @@ /datum/material/bananium/New() ..() material_type = MAT_BANANIUM - sheet_type = /obj/item/stack/sheet/mineral/bananium \ No newline at end of file + sheet_type = /obj/item/stack/sheet/mineral/bananium diff --git a/code/game/machinery/droneDispenser.dm b/code/game/machinery/droneDispenser.dm index c9836d94f24..56bb85cf53b 100644 --- a/code/game/machinery/droneDispenser.dm +++ b/code/game/machinery/droneDispenser.dm @@ -1,15 +1,23 @@ +#define DRONE_PRODUCTION "production" +#define DRONE_RECHARGING "recharging" +#define DRONE_READY "ready" + /obj/machinery/droneDispenser //Most customizable machine 2015 name = "drone shell dispenser" - desc = "A hefty machine that, when supplied with metal and glass, will periodically create a drone shell. Does not need to be manually operated." + desc = "A hefty machine that, when supplied with metal and glass, \ + will periodically create a drone shell. \ + Does not need to be manually operated." + icon = 'icons/obj/machines/droneDispenser.dmi' icon_state = "on" anchored = 1 density = 1 - var/health = 100 //The health of the drone dispenser. It will break if it goes below 0 + var/health = 100 var/max_health = 100 - var/icon_off = "off" //These variables allow for different icons when creating custom dispensers + //These variables allow for different icons when creating custom dispensers + var/icon_off = "off" var/icon_on = "on" var/icon_recharging = "recharge" var/icon_creating = "make" @@ -20,9 +28,16 @@ var/glass_cost = 1000 var/power_used = 1000 - var/droneMadeRecently = 0 + var/mode = DRONE_READY + var/timer var/cooldownTime = 1800 //3 minutes - var/dispense_type = /obj/item/drone_shell //The item the dispenser will create + var/production_time = 30 + //The item the dispenser will create + var/dispense_type = /obj/item/drone_shell + + // The maximum number of "idle" drone shells it will make before + // ceasing production. Set to 0 for infinite. + var/maximum_idle = 3 var/work_sound = 'sound/items/rped.ogg' var/create_sound = 'sound/items/Deconstruct.ogg' @@ -31,7 +46,8 @@ var/begin_create_message = "whirs to life!" var/end_create_message = "dispenses a drone shell." var/recharge_message = "pings." - var/recharging_text = "It is whirring and clicking. It seems to be recharging." + var/recharging_text = "It is whirring and clicking. \ + It seems to be recharging." var/break_message = "lets out a tinny alarm before falling dark." var/break_sound = 'sound/machines/warning-buzzer.ogg' @@ -39,15 +55,14 @@ /obj/machinery/droneDispenser/New() ..() health = max_health - materials = new(src, list(MAT_METAL=1, MAT_GLASS=1), MINERAL_MATERIAL_AMOUNT*MAX_STACK_SIZE*2) + materials = new(src, list(MAT_METAL=1, MAT_GLASS=1), + MINERAL_MATERIAL_AMOUNT*MAX_STACK_SIZE*2) + using_materials = list(MAT_METAL=metal_cost, MAT_GLASS=glass_cost) - SSmachine.processing |= src /obj/machinery/droneDispenser/Destroy() - SSmachine.processing -= src qdel(materials) - materials = null - return ..() + . = ..() /obj/machinery/droneDispenser/preloaded/New() ..() @@ -55,9 +70,11 @@ /obj/machinery/droneDispenser/syndrone //Please forgive me name = "syndrone shell dispenser" - desc = "A suspicious machine that will create Syndicate exterminator drones when supplied with metal and glass. Disgusting." + desc = "A suspicious machine that will create Syndicate \ + exterminator drones when supplied with metal and glass. Disgusting." dispense_type = /obj/item/drone_shell/syndrone - cooldownTime = 100 //If we're gonna be a jackass, go the full mile - 10 second recharge timer + //If we're gonna be a jackass, go the full mile - 10 second recharge timer + cooldownTime = 100 end_create_message = "dispenses a suspicious drone shell." /obj/machinery/droneDispenser/syndrone/New() @@ -66,15 +83,20 @@ /obj/machinery/droneDispenser/syndrone/badass //Please forgive me name = "badass syndrone shell dispenser" - desc = "A suspicious machine that will create Syndicate exterminator drones when supplied with metal and glass. Disgusting. This one seems ominous." + desc = "A suspicious machine that will create Syndicate \ + exterminator drones when supplied with metal and glass. \ + Disgusting. This one seems ominous." dispense_type = /obj/item/drone_shell/syndrone/badass end_create_message = "dispenses a ominous suspicious drone shell." // I don't need your forgiveness, this is awesome. /obj/machinery/droneDispenser/snowflake name = "snowflake drone shell dispenser" - desc = "A hefty machine that, when supplied with metal and glass, will periodically create a snowflake drone shell. Does not need to be manually operated." - dispense_type = /obj/item/drone_shell/snowflake //The item the dispenser will create + desc = "A hefty machine that, when supplied with metal and glass, \ + will periodically create a snowflake drone shell. \ + Does not need to be manually operated." + dispense_type = /obj/item/drone_shell/snowflake + end_create_message = "dispenses a snowflake drone shell." // Those holoprojectors aren't cheap metal_cost = 2000 glass_cost = 2000 @@ -84,9 +106,12 @@ ..() materials.insert_amount(10000) -/obj/machinery/droneDispenser/hivebot //An example of a custom drone dispenser. This one requires no materials and creates basic hivebots +// An example of a custom drone dispenser. +// This one requires no materials and creates basic hivebots +/obj/machinery/droneDispenser/hivebot name = "hivebot fabricator" - desc = "A large, bulky machine that whirs with activity, steam hissing from vents in its sides." + desc = "A large, bulky machine that whirs with activity, \ + steam hissing from vents in its sides." icon = 'icons/obj/objects.dmi' icon_state = "hivebot_fab" icon_off = "hivebot_fab" @@ -105,7 +130,8 @@ /obj/machinery/droneDispenser/swarmer name = "swarmer fabricator" - desc = "An alien machine of unknown origin. It whirs and hums with green-blue light, the air above it shimmering." + desc = "An alien machine of unknown origin. \ + It whirs and hums with green-blue light, the air above it shimmering." icon = 'icons/obj/machines/gateway.dmi' icon_state = "toffcenter" icon_off = "toffcenter" @@ -115,9 +141,12 @@ metal_cost = 0 glass_cost = 0 cooldownTime = 300 //30 seconds + maximum_idle = 0 // Swarmers have no restraint dispense_type = /obj/item/device/unactivated_swarmer - begin_create_message = "hums softly as an interface appears above it, scrolling by at unreadable speed." - end_create_message = "materializes a strange shell, which drops to the ground." + begin_create_message = "hums softly as an interface appears above it, \ + scrolling by at unreadable speed." + end_create_message = "materializes a strange shell, which drops to the \ + ground." recharging_text = "Its lights are slowly increasing in brightness." work_sound = 'sound/effects/EMPulse.ogg' create_sound = 'sound/effects/phasein.ogg' @@ -126,132 +155,179 @@ /obj/machinery/droneDispenser/examine(mob/user) ..() - if(droneMadeRecently && !stat && recharging_text) + if((mode == DRONE_RECHARGING) && !stat && recharging_text) user << "[recharging_text]" if(stat & BROKEN) - user << "[src] is smoking and steadily buzzing. It seems to be broken." + user << "[src] is smoking and steadily buzzing. \ + It seems to be broken." if(metal_cost) - user << "It has [materials.amount(MAT_METAL)] units of metal stored." + user << "It has [materials.amount(MAT_METAL)] \ + units of metal stored." if(glass_cost) - user << "It has [materials.amount(MAT_GLASS)] units of glass stored." + user << "It has [materials.amount(MAT_GLASS)] \ + units of glass stored." /obj/machinery/droneDispenser/power_change() ..() - if(stat & BROKEN) - return + if(powered()) + stat &= ~NOPOWER else - if(powered()) - stat &= ~NOPOWER - else - icon_state = "off" - stat |= NOPOWER + stat |= NOPOWER + update_icon() /obj/machinery/droneDispenser/process() ..() - if(stat & (NOPOWER|BROKEN) || !anchored) + if((stat & (NOPOWER|BROKEN)) || !anchored) return - if((metal_cost && glass_cost) && materials.can_use_amount(mats=using_materials)) + + if(!materials.has_materials(using_materials)) + return // We require more minerals + + // We are currently in the middle of something + if(timer > world.time) return - if(droneMadeRecently) - icon_state = icon_recharging - return - droneMadeRecently = 1 - if(begin_create_message) - visible_message("[src] [begin_create_message]") - if(work_sound) - playsound(src, work_sound, 50, 1) - icon_state = icon_creating - sleep(30) - icon_state = icon_on - materials.use_amount(using_materials) - if(power_used) - use_power(power_used) - new dispense_type(loc) - if(create_sound) - playsound(src, create_sound, 50, 1) - if(end_create_message) - visible_message("[src] [end_create_message]") - icon_state = icon_recharging - sleep(cooldownTime) - if(!(stat & BROKEN)) - icon_state = icon_on - else + + switch(mode) + if(DRONE_READY) + // If we have X drone shells already on our turf + if(maximum_idle && (count_shells() >= maximum_idle)) + return // then do nothing; check again next tick + if(begin_create_message) + visible_message("\ + [src] [begin_create_message]") + if(work_sound) + playsound(src, work_sound, 50, 1) + mode = DRONE_PRODUCTION + timer = world.time + production_time + update_icon() + + if(DRONE_PRODUCTION) + materials.use_amount(using_materials) + if(power_used) + use_power(power_used) + + new dispense_type(loc) + + if(create_sound) + playsound(src, create_sound, 50, 1) + if(end_create_message) + visible_message("[src] \ + [end_create_message]") + + mode = DRONE_RECHARGING + timer = world.time + cooldownTime + update_icon() + + if(DRONE_RECHARGING) + if(recharge_sound) + playsound(src, recharge_sound, 50, 1) + if(recharge_message) + visible_message("\ + [src] [recharge_message]") + + mode = DRONE_READY + update_icon() + +/obj/machinery/droneDispenser/proc/count_shells() + . = 0 + for(var/a in loc) + if(istype(a, dispense_type)) + .++ + +/obj/machinery/droneDispenser/update_icon() + if(stat & (BROKEN|NOPOWER)) icon_state = icon_off - droneMadeRecently = 0 - if(recharge_sound) - playsound(src, recharge_sound, 50, 1) - if(recharge_message) - visible_message("[src] [recharge_message]") + else if(mode == DRONE_RECHARGING) + icon_state = icon_recharging + else if(mode == DRONE_PRODUCTION) + icon_state = icon_creating + else + 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) - user << "There isn't a place to insert [O]!" - return - var/stack = 1 - var/obj/item/stack/sheets - sheets = O - stack = (input(user, "How many sheets do you want to add?.", "Drone Dispenser", "[stack]") as num) - if(stack <= 0) - return - if(!user.canUseTopic(src)) + user << "There isn't a place \ + to insert [O]!" return + var/obj/item/stack/sheets = O if(!user.canUnEquip(sheets)) - user << "[O] is stuck to your hand, you can't get it off!" + user << "[O] is stuck to your hand, \ + you can't get it off!" return - stack = Clamp(stack, 1, sheets.max_amount) - stack = materials.insert_stack(sheets, stack) - if(stack) - user << "You insert [stack] sheet[stack > 1 ? "s" : ""] into [src]." + + var/used = materials.insert_stack(sheets, sheets.amount) + + if(used) + user << "You insert [used] \ + sheet[used > 1 ? "s" : ""] into [src]." else - user << "The [src] can't use [sheets]." + user << "The [src] isn't accepting the \ + [sheets]." else if(istype(O, /obj/item/weapon/weldingtool)) - if(stat & BROKEN) - var/obj/item/weapon/weldingtool/WT = O - if(!WT.isOn()) - return - if(WT.get_fuel() < 1) - user << "You need more fuel to complete this task!" - return - playsound(src, 'sound/items/Welder.ogg', 50, 1) - user.visible_message("[user] begins patching up [src] with [WT].", \ - "You begin restoring the damage to [src]...") - if(!do_after(user, 40/O.toolspeed, target = src)) - return - if(!src || !WT.remove_fuel(1, user)) return - user.visible_message("[user] fixes [src]!", \ - "You restore [src] to operation.") - stat &= ~BROKEN - health = max_health - if(!stat) - icon_state = icon_on - else + if(!(stat & BROKEN)) user << "[src] doesn't need repairs." + return + + var/obj/item/weapon/weldingtool/WT = O + + if(!WT.isOn()) + return + + if(WT.get_fuel() < 1) + user << "You need more fuel to \ + complete this task!" + return + + playsound(src, 'sound/items/Welder.ogg', 50, 1) + user.visible_message( + "[user] begins patching up \ + [src] with [WT].", + "You begin restoring the \ + damage to [src]...") + + if(!do_after(user, 40/O.toolspeed, target = src)) + return + if(!src || !WT.remove_fuel(1, user)) + return + + user.visible_message( + "[user] fixes [src]!", + "You restore [src] to operation.") + + stat &= ~BROKEN + health = max_health + update_icon() else return ..() -/obj/machinery/droneDispenser/take_damage(damage, damage_type = BRUTE, sound_effect = 1) - switch(damage_type) +/obj/machinery/droneDispenser/take_damage(dmg, dmg_type=BRUTE, hit_sound=TRUE) + // But why would you hurt the dispenser? + switch(dmg_type) if(BURN) - if(sound_effect) + if(hit_sound) playsound(src.loc, 'sound/items/Welder.ogg', 100, 1) if(BRUTE) - if(sound_effect) - if(damage) + if(hit_sound) + if(dmg) playsound(loc, 'sound/weapons/smash.ogg', 50, 1) else playsound(loc, 'sound/weapons/tap.ogg', 50, 1) else return - health = max(health - damage, 0) + health = max(health - dmg, 0) if(!health && !(stat & BROKEN)) if(break_message) - audible_message("[src] [break_message]") + audible_message("[src] \ + [break_message]") if(break_sound) playsound(src, break_sound, 50, 1) stat |= BROKEN - icon_state = icon_off + update_icon() +#undef DRONE_PRODUCTION +#undef DRONE_RECHARGING +#undef DRONE_READY