| [material] | " - material_bottom += "[stored_material[material]]/[storage_capacity[material]] | " - - dat += "[material_top.Join()]
| [R.hidden ? "*" : ""][can_make ? "" : ""][R.name][can_make ? "" : ""][R.hidden ? "*" : ""][multiplier_string.Join()] | [material_string.Join()] |
| Command | " - jobs_all += "||
| Special | "//Colony Director in special because he is head of heads ~Intercross21 - jobs_all += "Colony Director | " + jobs_all += "|
| Special | "//Site Manager in special because he is head of heads ~Intercross21 + jobs_all += "Site Manager | " jobs_all += "Custom | " counter = 0 diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 463773fdf7..8f33d05787 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -39,12 +39,16 @@ var/secured_wires = 0 var/datum/wires/airlock/wires = null - var/open_sound_powered = 'sound/machines/airlock.ogg' - var/open_sound_unpowered = 'sound/machines/airlockforced.ogg' - var/close_sound_powered = 'sound/machines/airlockclose.ogg' + var/open_sound_powered = 'sound/machines/door/covert1o.ogg' + var/open_sound_unpowered = 'sound/machines/door/airlockforced.ogg' + var/close_sound_powered = 'sound/machines/door/covert1c.ogg' + var/legacy_open_powered = 'sound/machines/door/old_airlock.ogg' + var/legacy_close_powered = 'sound/machines/door/old_airlockclose.ogg' + var/department_open_powered = null + var/department_close_powered = null var/denied_sound = 'sound/machines/deniedbeep.ogg' - var/bolt_up_sound = 'sound/machines/boltsup.ogg' - var/bolt_down_sound = 'sound/machines/boltsdown.ogg' + var/bolt_up_sound = 'sound/machines/door/boltsup.ogg' + var/bolt_down_sound = 'sound/machines/door/boltsdown.ogg' /obj/machinery/door/airlock/attack_generic(var/mob/living/user, var/damage) if(stat & (BROKEN|NOPOWER)) @@ -81,7 +85,7 @@ if(do_after(user,5 SECONDS,src)) visible_message("\The [user] forces \the [src] open, sparks flying from its electronics!") src.do_animate("spark") - playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1, volume_channel = VOLUME_CHANNEL_DOORS) src.locked = 0 src.welded = 0 update_icon() @@ -90,7 +94,7 @@ else if(src.density) visible_message("\The [user] begins forcing \the [src] open!") if(do_after(user, 5 SECONDS,src)) - playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1, volume_channel = VOLUME_CHANNEL_DOORS) visible_message("\The [user] forces \the [src] open!") open(1) else @@ -112,40 +116,66 @@ icon = 'icons/obj/doors/Doorcom.dmi' req_one_access = list(access_heads) assembly_type = /obj/structure/door_assembly/door_assembly_com + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/cmd3o.ogg' + department_close_powered = 'sound/machines/door/cmd3c.ogg' /obj/machinery/door/airlock/security name = "Security Airlock" icon = 'icons/obj/doors/Doorsec.dmi' req_one_access = list(access_security) assembly_type = /obj/structure/door_assembly/door_assembly_sec + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/sec1o.ogg' + department_close_powered = 'sound/machines/door/sec1c.ogg' /obj/machinery/door/airlock/engineering name = "Engineering Airlock" icon = 'icons/obj/doors/Dooreng.dmi' req_one_access = list(access_engine) assembly_type = /obj/structure/door_assembly/door_assembly_eng + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/eng1o.ogg' + department_close_powered = 'sound/machines/door/eng1c.ogg' /obj/machinery/door/airlock/engineeringatmos name = "Atmospherics Airlock" icon = 'icons/obj/doors/Doorengatmos.dmi' req_one_access = list(access_atmospherics) assembly_type = /obj/structure/door_assembly/door_assembly_eat + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/eng1o.ogg' + department_close_powered = 'sound/machines/door/eng1c.ogg' /obj/machinery/door/airlock/medical name = "Medical Airlock" icon = 'icons/obj/doors/Doormed.dmi' req_one_access = list(access_medical) assembly_type = /obj/structure/door_assembly/door_assembly_med + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/med1o.ogg' + department_close_powered = 'sound/machines/door/med1c.ogg' /obj/machinery/door/airlock/maintenance name = "Maintenance Access" icon = 'icons/obj/doors/Doormaint.dmi' //req_one_access = list(access_maint_tunnels) //VOREStation Edit - Maintenance is open access assembly_type = /obj/structure/door_assembly/door_assembly_mai + open_sound_powered = 'sound/machines/door/door2o.ogg' + close_sound_powered = 'sound/machines/door/door2c.ogg' /obj/machinery/door/airlock/maintenance/cargo icon = 'icons/obj/doors/Doormaint_cargo.dmi' req_one_access = list(access_cargo) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/door2o.ogg' + department_close_powered = 'sound/machines/door/door2c.ogg' /obj/machinery/door/airlock/maintenance/command icon = 'icons/obj/doors/Doormaint_command.dmi' @@ -153,6 +183,8 @@ /obj/machinery/door/airlock/maintenance/common icon = 'icons/obj/doors/Doormaint_common.dmi' + open_sound_powered = 'sound/machines/door/hall3o.ogg' + close_sound_powered = 'sound/machines/door/hall3c.ogg' /obj/machinery/door/airlock/maintenance/engi icon = 'icons/obj/doors/Doormaint_engi.dmi' @@ -177,6 +209,8 @@ name = "External Airlock" icon = 'icons/obj/doors/Doorext.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_ext + open_sound_powered = 'sound/machines/door/space1o.ogg' + close_sound_powered = 'sound/machines/door/space1c.ogg' /obj/machinery/door/airlock/external/glass/bolted icon_state = "door_locked" // So it looks visibly bolted in map editor @@ -193,12 +227,16 @@ opacity = 0 glass = 1 req_one_access = list(access_external_airlocks) + open_sound_powered = 'sound/machines/door/space1o.ogg' + close_sound_powered = 'sound/machines/door/space1c.ogg' /obj/machinery/door/airlock/glass name = "Glass Airlock" icon = 'icons/obj/doors/Doorglass.dmi' hitsound = 'sound/effects/Glasshit.ogg' - open_sound_powered = 'sound/machines/windowdoor.ogg' + open_sound_powered = 'sound/machines/door/hall1o.ogg' + close_sound_powered = 'sound/machines/door/hall1c.ogg' + legacy_open_powered = 'sound/machines/door/windowdoor.ogg' maxhealth = 300 explosion_resistance = 5 opacity = 0 @@ -209,12 +247,16 @@ icon = 'icons/obj/doors/Doorele.dmi' req_one_access = list(access_cent_general) opacity = 1 + open_sound_powered = 'sound/machines/door/cmd3o.ogg' + close_sound_powered = 'sound/machines/door/cmd3c.ogg' /obj/machinery/door/airlock/glass_centcom name = "Airlock" icon = 'icons/obj/doors/Dooreleglass.dmi' opacity = 0 glass = 1 + open_sound_powered = 'sound/machines/door/cmd3o.ogg' + close_sound_powered = 'sound/machines/door/cmd3c.ogg' /obj/machinery/door/airlock/vault name = "Vault" @@ -224,6 +266,8 @@ secured_wires = 1 assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity //Until somebody makes better sprites. req_one_access = list(access_heads_vault) + open_sound_powered = 'sound/machines/door/vault1o.ogg' + close_sound_powered = 'sound/machines/door/vault1c.ogg' /obj/machinery/door/airlock/vault/bolted icon_state = "door_locked" @@ -242,6 +286,9 @@ opacity = 1 assembly_type = /obj/structure/door_assembly/door_assembly_hatch req_one_access = list(access_maint_tunnels) + open_sound_powered = 'sound/machines/door/hatchopen.ogg' + close_sound_powered = 'sound/machines/door/hatchclose.ogg' + open_sound_unpowered = 'sound/machines/door/hatchforced.ogg' /obj/machinery/door/airlock/maintenance_hatch name = "Maintenance Hatch" @@ -250,6 +297,9 @@ opacity = 1 assembly_type = /obj/structure/door_assembly/door_assembly_mhatch req_one_access = list(access_maint_tunnels) + open_sound_powered = 'sound/machines/door/hatchopen.ogg' + close_sound_powered = 'sound/machines/door/hatchclose.ogg' + open_sound_unpowered = 'sound/machines/door/hatchforced.ogg' /obj/machinery/door/airlock/glass_command name = "Command Airlock" @@ -261,6 +311,10 @@ assembly_type = /obj/structure/door_assembly/door_assembly_com glass = 1 req_one_access = list(access_heads) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/cmd1o.ogg' + department_close_powered = 'sound/machines/door/cmd1c.ogg' /obj/machinery/door/airlock/glass_engineering name = "Engineering Airlock" @@ -272,6 +326,8 @@ assembly_type = /obj/structure/door_assembly/door_assembly_eng glass = 1 req_one_access = list(access_engine) + department_open_powered = 'sound/machines/door/eng1o.ogg' + department_close_powered = 'sound/machines/door/eng1c.ogg' /obj/machinery/door/airlock/glass_engineeringatmos name = "Atmospherics Airlock" @@ -283,6 +339,10 @@ assembly_type = /obj/structure/door_assembly/door_assembly_eat glass = 1 req_one_access = list(access_atmospherics) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/eng1o.ogg' + department_close_powered = 'sound/machines/door/eng1c.ogg' /obj/machinery/door/airlock/glass_security name = "Security Airlock" @@ -294,6 +354,10 @@ assembly_type = /obj/structure/door_assembly/door_assembly_sec glass = 1 req_one_access = list(access_security) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/sec1o.ogg' + department_close_powered = 'sound/machines/door/sec1c.ogg' /obj/machinery/door/airlock/glass_medical name = "Medical Airlock" @@ -305,23 +369,39 @@ assembly_type = /obj/structure/door_assembly/door_assembly_med glass = 1 req_one_access = list(access_medical) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/med1o.ogg' + department_close_powered = 'sound/machines/door/med1c.ogg' /obj/machinery/door/airlock/mining name = "Mining Airlock" icon = 'icons/obj/doors/Doormining.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_min req_one_access = list(access_mining) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/cgo1o.ogg' + department_close_powered = 'sound/machines/door/cgo1c.ogg' /obj/machinery/door/airlock/atmos name = "Atmospherics Airlock" icon = 'icons/obj/doors/Dooratmo.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_atmo req_one_access = list(access_atmospherics) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/eng1o.ogg' + department_close_powered = 'sound/machines/door/eng1c.ogg' /obj/machinery/door/airlock/research name = "Research Airlock" icon = 'icons/obj/doors/Doorresearch.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_research + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/sci1o.ogg' + department_close_powered = 'sound/machines/door/sci1c.ogg' /obj/machinery/door/airlock/glass_research name = "Research Airlock" @@ -333,6 +413,10 @@ assembly_type = /obj/structure/door_assembly/door_assembly_research glass = 1 req_one_access = list(access_research) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/sci1o.ogg' + department_close_powered = 'sound/machines/door/sci1c.ogg' /obj/machinery/door/airlock/glass_mining name = "Mining Airlock" @@ -344,6 +428,10 @@ assembly_type = /obj/structure/door_assembly/door_assembly_min glass = 1 req_one_access = list(access_mining) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/cgo1o.ogg' + department_close_powered = 'sound/machines/door/cgo1c.ogg' /obj/machinery/door/airlock/glass_atmos name = "Atmospherics Airlock" @@ -355,6 +443,10 @@ assembly_type = /obj/structure/door_assembly/door_assembly_atmo glass = 1 req_one_access = list(access_atmospherics) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/eng1o.ogg' + department_close_powered = 'sound/machines/door/eng1c.ogg' /obj/machinery/door/airlock/gold name = "Gold Airlock" @@ -435,6 +527,10 @@ icon = 'icons/obj/doors/Doorsci.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_science req_one_access = list(access_research) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/sci1o.ogg' + department_close_powered = 'sound/machines/door/sci1c.ogg' /obj/machinery/door/airlock/glass_science name = "Glass Airlocks" @@ -443,6 +539,10 @@ assembly_type = /obj/structure/door_assembly/door_assembly_science glass = 1 req_one_access = list(access_research) + open_sound_powered = 'sound/machines/door/hall1o.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + close_sound_powered = 'sound/machines/door/hall1c.ogg' // VOREStation Edit: Default door sounds for fancy, department-off. + department_open_powered = 'sound/machines/door/sci1o.ogg' + department_close_powered = 'sound/machines/door/sci1c.ogg' /obj/machinery/door/airlock/highsecurity name = "Secure Airlock" @@ -451,6 +551,8 @@ secured_wires = 1 assembly_type = /obj/structure/door_assembly/door_assembly_highsecurity req_one_access = list(access_heads_vault) + open_sound_powered = 'sound/machines/door/secure1o.ogg' + close_sound_powered = 'sound/machines/door/secure1c.ogg' /obj/machinery/door/airlock/voidcraft name = "voidcraft hatch" @@ -460,11 +562,15 @@ opacity = 0 glass = 1 assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft + open_sound_powered = 'sound/machines/door/shuttle1o.ogg' + close_sound_powered = 'sound/machines/door/shuttle1c.ogg' // Airlock opens from top-bottom instead of left-right. /obj/machinery/door/airlock/voidcraft/vertical icon = 'icons/obj/doors/shuttledoors_vertical.dmi' assembly_type = /obj/structure/door_assembly/door_assembly_voidcraft/vertical + open_sound_powered = 'sound/machines/door/shuttle1o.ogg' + close_sound_powered = 'sound/machines/door/shuttle1c.ogg' /datum/category_item/catalogue/anomalous/precursor_a/alien_airlock @@ -1107,10 +1213,41 @@ About the new airlock wires panel: use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people //if the door is unpowered then it doesn't make sense to hear the woosh of a pneumatic actuator - if(arePowerSystemsOn()) - playsound(src, open_sound_powered, 50, 1) - else - playsound(src, open_sound_unpowered, 75, 1) + for(var/P in player_list) + var/mob/M = P + if(!M || !M.client) + continue + var/old_sounds = M.client.is_preference_enabled(/datum/client_preference/old_door_sounds) + var/department_door_sounds = M.client.is_preference_enabled(/datum/client_preference/department_door_sounds) + var/sound + var/volume + if(old_sounds) // Do we have old sounds enabled? Play these even if we have department door sounds enabled. + if(arePowerSystemsOn()) + sound = legacy_open_powered + volume = 50 + else + sound = open_sound_unpowered + volume = 75 + else if(!old_sounds && department_door_sounds && src.department_open_powered) // Else, we have old sounds disabled, the door has per-department door sounds, and we have chosen to play department door sounds, use these. + if(arePowerSystemsOn()) + sound = department_open_powered + volume = 50 + else + sound = open_sound_unpowered + volume = 75 + else // Else, play these. + if(arePowerSystemsOn()) + sound = open_sound_powered + volume = 50 + else + sound = open_sound_unpowered + volume = 75 + + var/turf/T = get_turf(M) + var/distance = get_dist(T, get_turf(src)) + if(distance <= world.view * 2) + if(T && T.z == get_z(src)) + M.playsound_local(get_turf(src), sound, volume, 1, null, 0, TRUE, sound(sound), volume_channel = VOLUME_CHANNEL_DOORS) if(src.closeOther != null && istype(src.closeOther, /obj/machinery/door/airlock/) && !src.closeOther.density) src.closeOther.close() @@ -1205,10 +1342,41 @@ About the new airlock wires panel: use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people has_beeped = 0 - if(arePowerSystemsOn()) - playsound(src, close_sound_powered, 50, 1) - else - playsound(src, open_sound_unpowered, 75, 1) + for(var/P in player_list) + var/mob/M = P + if(!M || !M.client) + continue + var/old_sounds = M.client.is_preference_enabled(/datum/client_preference/old_door_sounds) + var/department_door_sounds = M.client.is_preference_enabled(/datum/client_preference/department_door_sounds) + var/sound + var/volume + if(old_sounds) + if(arePowerSystemsOn()) + sound = legacy_close_powered + volume = 50 + else + sound = open_sound_unpowered + volume = 75 + else if(!old_sounds && department_door_sounds && src.department_close_powered) // Else, we have old sounds disabled, the door has per-department door sounds, and we have chosen to play department door sounds, use these. + if(arePowerSystemsOn()) + sound = department_close_powered + volume = 50 + else + sound = open_sound_unpowered + volume = 75 + else + if(arePowerSystemsOn()) + sound = close_sound_powered + volume = 50 + else + sound = open_sound_unpowered + volume = 75 + + var/turf/T = get_turf(M) + var/distance = get_dist(T, get_turf(src)) + if(distance <= world.view * 2) + if(T && T.z == get_z(src)) + M.playsound_local(get_turf(src), sound, volume, 1, null, 0, TRUE, sound(sound), volume_channel = VOLUME_CHANNEL_DOORS) for(var/turf/turf in locs) var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf) if(killthis) @@ -1222,7 +1390,7 @@ About the new airlock wires panel: if (operating && !forced) return 0 src.locked = 1 - playsound(src, bolt_down_sound, 30, 0, 3) + playsound(src, bolt_down_sound, 30, 0, 3, volume_channel = VOLUME_CHANNEL_DOORS) for(var/mob/M in range(1,src)) M.show_message("You hear a click from the bottom of the door.", 2) update_icon() @@ -1236,7 +1404,7 @@ About the new airlock wires panel: if(operating || !src.arePowerSystemsOn() || wires.is_cut(WIRE_DOOR_BOLTS)) return src.locked = 0 - playsound(src, bolt_up_sound, 30, 0, 3) + playsound(src, bolt_up_sound, 30, 0, 3, volume_channel = VOLUME_CHANNEL_DOORS) for(var/mob/M in range(1,src)) M.show_message("You hear a click from the bottom of the door.", 2) update_icon() diff --git a/code/game/machinery/doors/blast_door.dm b/code/game/machinery/doors/blast_door.dm index 569c413f94..a6b503cdbd 100644 --- a/code/game/machinery/doors/blast_door.dm +++ b/code/game/machinery/doors/blast_door.dm @@ -25,8 +25,8 @@ var/icon_state_opening = null var/icon_state_closed = null var/icon_state_closing = null - var/open_sound = 'sound/machines/blastdooropen.ogg' - var/close_sound = 'sound/machines/blastdoorclose.ogg' + var/open_sound = 'sound/machines/door/blastdooropen.ogg' + var/close_sound = 'sound/machines/door/blastdoorclose.ogg' var/damage = BLAST_DOOR_CRUSH_DAMAGE var/multiplier = 1 // The multiplier for how powerful our YEET is. @@ -125,7 +125,7 @@ // Description: Opens or closes the door, depending on current state. No checks are done inside this proc. /obj/machinery/door/blast/proc/force_toggle(var/forced = 0, mob/user as mob) if (forced) - playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1) if(src.density) src.force_open() @@ -219,13 +219,13 @@ if(src.density) visible_message("\The [user] begins forcing \the [src] open!") if(do_after(user, 15 SECONDS,src)) - playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1) visible_message("\The [user] forces \the [src] open!") force_open(1) else visible_message("\The [user] begins forcing \the [src] closed!") if(do_after(user, 5 SECONDS,src)) - playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1) visible_message("\The [user] forces \the [src] closed!") force_close(1) else diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index e31465168f..6cae2617fd 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -200,14 +200,14 @@ if(src.blocked) visible_message("\The [user] begins digging into \the [src] internals!") if(do_after(user,5 SECONDS,src)) - playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1) src.blocked = 0 update_icon() open(1) else if(src.density) visible_message("\The [user] begins forcing \the [src] open!") if(do_after(user, 2 SECONDS,src)) - playsound(src, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(src, 'sound/machines/door/airlock_creaking.ogg', 100, 1) visible_message("\The [user] forces \the [src] open!") open(1) else diff --git a/code/game/machinery/doors/multi_tile.dm b/code/game/machinery/doors/multi_tile.dm index f05419cb6d..ec5acbea73 100644 --- a/code/game/machinery/doors/multi_tile.dm +++ b/code/game/machinery/doors/multi_tile.dm @@ -4,6 +4,8 @@ appearance_flags = 0 var/obj/machinery/filler_object/filler1 var/obj/machinery/filler_object/filler2 + open_sound_powered = 'sound/machines/door/WideOpen.ogg' + close_sound_powered = 'sound/machines/door/WideClose.ogg' /obj/machinery/door/airlock/multi_tile/New() ..() diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm index 98fb1c75d8..cfd0b3706c 100644 --- a/code/game/machinery/doors/windowdoor.dm +++ b/code/game/machinery/doors/windowdoor.dm @@ -115,7 +115,7 @@ if (!operating) //in case of emag operating = 1 flick(text("[src.base_state]opening"), src) - playsound(src, 'sound/machines/windowdoor.ogg', 100, 1) + playsound(src, 'sound/machines/door/windowdoor.ogg', 100, 1) sleep(10) explosion_resistance = 0 @@ -132,7 +132,7 @@ return FALSE operating = TRUE flick(text("[]closing", src.base_state), src) - playsound(src, 'sound/machines/windowdoor.ogg', 100, 1) + playsound(src, 'sound/machines/door/windowdoor.ogg', 100, 1) density = TRUE update_icon() diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm index 75004ae7be..cab4f5c37f 100644 --- a/code/game/machinery/doppler_array.dm +++ b/code/game/machinery/doppler_array.dm @@ -45,10 +45,7 @@ var/list/doppler_arrays = list() /obj/machinery/doppler_array/power_change() ..() - if(stat & BROKEN) - icon_state = "[initial(icon_state)]-broken" + if(!(stat & NOPOWER)) + icon_state = initial(icon_state) else - if(!(stat & NOPOWER)) - icon_state = initial(icon_state) - else - icon_state = "[initial(icon_state)]-off" \ No newline at end of file + icon_state = "[initial(icon_state)]_off" diff --git a/code/game/machinery/flasher.dm b/code/game/machinery/flasher.dm index ad82ffd656..5aa42ff26a 100644 --- a/code/game/machinery/flasher.dm +++ b/code/game/machinery/flasher.dm @@ -68,6 +68,11 @@ var/flash_time = strength if(istype(O, /mob/living/carbon/human)) var/mob/living/carbon/human/H = O + //VOREStation Edit Start + if(H.nif && H.nif.flag_check(NIF_V_FLASHPROT,NIF_FLAGS_VISION)) + H.nif.notify("High intensity light detected, and blocked!",TRUE) + continue + //VOREStation Edit End if(!H.eyecheck() <= 0) continue flash_time *= H.species.flash_mod diff --git a/code/game/machinery/newscaster.dm b/code/game/machinery/newscaster.dm index b59bec3384..6ea6e58905 100644 --- a/code/game/machinery/newscaster.dm +++ b/code/game/machinery/newscaster.dm @@ -810,6 +810,7 @@ GLOBAL_LIST_BOILERPLATE(allCasters, /obj/machinery/newscaster) var/scribble="" var/scribble_page = null drop_sound = 'sound/items/drop/wrapper.ogg' + pickup_sound = 'sound/items/pickup/wrapper.ogg' obj/item/weapon/newspaper/attack_self(mob/user as mob) if(ishuman(user)) diff --git a/code/game/machinery/partslathe_vr.dm b/code/game/machinery/partslathe_vr.dm index a4a027d5e4..aab15f40f9 100644 --- a/code/game/machinery/partslathe_vr.dm +++ b/code/game/machinery/partslathe_vr.dm @@ -234,116 +234,123 @@ if(..()) return ui_interact(user) + tgui_interact(user) -/obj/machinery/partslathe/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) +/obj/machinery/partslathe/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/sheetmaterials) + ) - var/data[0] +/obj/machinery/partslathe/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "PartsLathe", name) + ui.open() + +/obj/machinery/partslathe/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) + var/list/data = ..() data["panelOpen"] = panel_open - var/materials_ui[0] + var/list/materials_ui = list() for(var/M in materials) - materials_ui[++materials_ui.len] = list( - "name" = M, - "display" = material_display_name(M), - "qty" = materials[M], - "max" = storage_capacity[M], - "percent" = (materials[M] / storage_capacity[M] * 100)) + materials_ui.Add(list(list( + "name" = M, + "amount" = materials[M], + "sheets" = round(materials[M] / SHEET_MATERIAL_AMOUNT), + "removable" = materials[M] >= SHEET_MATERIAL_AMOUNT, + ))) data["materials"] = materials_ui + data["copyBoard"] = null + data["copyBoardReqComponents"] = null if(istype(copy_board)) data["copyBoard"] = copy_board.name - var/req_components_ui[0] + var/list/req_components_ui = list() for(var/CP in (copy_board.req_components || list())) var/obj/comp_path = CP var/comp_amt = copy_board.req_components[comp_path] if(comp_amt && (comp_path in partslathe_recipies)) - req_components_ui[++req_components_ui.len] = list("name" = initial(comp_path.name), "qty" = comp_amt) + req_components_ui.Add(list(list("name" = initial(comp_path.name), "qty" = comp_amt))) data["copyBoardReqComponents"] = req_components_ui data["queue"] = list() for(var/datum/category_item/partslathe/Q in queue) data["queue"] += Q.name + data["building"] = null + data["buildPercent"] = null if(busy && queue.len > 0) var/datum/category_item/partslathe/current = queue[1] data["building"] = current.name - data["buildProgress"] = progress - data["buildTime"] = current.time data["buildPercent"] = (progress / current.time * 100) + + data["error"] = null if(queue.len > 0 && !canBuild(queue[1])) data["error"] = getLackingMaterials(queue[1]) - var/recipies_ui[0] + var/list/recipies_ui = list() for(var/T in partslathe_recipies) var/datum/category_item/partslathe/R = partslathe_recipies[T] - recipies_ui[++recipies_ui.len] = list("name" = R.name, "type" = "[T]") + recipies_ui.Add(list(list("name" = R.name, "type" = "[T]"))) data["recipies"] = recipies_ui - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "partslathe.tmpl", "Parts Lathe UI", 500, 450) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(5) + return data -/obj/machinery/partslathe/Topic(href, href_list) +/obj/machinery/partslathe/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return 1 - usr.set_machine(src) + return TRUE + add_fingerprint(usr) - - // Queue management can be done even while busy - if(href_list["queue"]) - var/type_to_build = text2path(href_list["queue"]) - var/datum/category_item/partslathe/to_build = partslathe_recipies[type_to_build] - if(to_build) - addToQueue(to_build) - updateUsrDialog() - return - - if(href_list["queueBoard"]) - if(!istype(copy_board) || !copy_board.req_components) - return - for(var/comp_path in copy_board.req_components) - var/comp_amt = copy_board.req_components[comp_path] - if(!comp_amt) - continue - var/datum/category_item/partslathe/to_build = partslathe_recipies[comp_path] - if(!to_build) - continue // We don't support building whatever this is - for(var/i in 1 to comp_amt) + switch(action) + // Queue management can be done even while busy + if("queue") + var/type_to_build = text2path(params["queue"]) + var/datum/category_item/partslathe/to_build = partslathe_recipies[type_to_build] + if(to_build) addToQueue(to_build) - return + return TRUE - if(href_list["cancel"]) - var/index = text2num(href_list["cancel"]) - if(index < 1 || index > queue.len) - return - if(busy && index == 1) - return - removeFromQueue(index) - return + if("queueBoard") + if(!istype(copy_board) || !copy_board.req_components) + return + for(var/comp_path in copy_board.req_components) + var/comp_amt = copy_board.req_components[comp_path] + if(!comp_amt) + continue + var/datum/category_item/partslathe/to_build = partslathe_recipies[comp_path] + if(!to_build) + continue // We don't support building whatever this is + for(var/i in 1 to comp_amt) + addToQueue(to_build) + return TRUE + + if("cancel") + var/index = text2num(params["cancel"]) + if(index < 1 || index > queue.len) + return + if(busy && index == 1) + return + removeFromQueue(index) + return TRUE if(busy) - to_chat(usr, "\The [src]is busy. Please wait for completion of previous operation.") + to_chat(usr, "[src] is busy. Please wait for completion of previous operation.") return - if(href_list["ejectBoard"]) - if(copy_board) - visible_message("\The [copy_board] is ejected from \the [src]'s circuit reader.") - copy_board.forceMove(src.loc) - copy_board = null - updateUsrDialog() - return + switch(action) + if("ejectBoard") + if(copy_board) + visible_message("[copy_board] is ejected from [src]'s circuit reader.") + copy_board.forceMove(src.loc) + copy_board = null + return TRUE - if(href_list["ejectMaterial"]) - var/matName = href_list["ejectMaterial"] - if(!(matName in materials)) + if("remove_mat") + // Remove a material from the fab + var/mat_id = params["id"] + var/amount = text2num(params["amount"]) + eject_materials(mat_id, amount) return - eject_materials(matName, 0) - updateUsrDialog() - return /** Build list of recipies to include all tech level 1 stock parts. */ /obj/machinery/partslathe/proc/update_recipe_list() diff --git a/code/game/machinery/seed_extractor.dm b/code/game/machinery/seed_extractor.dm index 9977e765e9..75d7542ba1 100644 --- a/code/game/machinery/seed_extractor.dm +++ b/code/game/machinery/seed_extractor.dm @@ -16,10 +16,10 @@ obj/machinery/seed_extractor/attackby(var/obj/item/O as obj, var/mob/user as mob var/datum/seed/new_seed_type if(istype(O, /obj/item/weapon/grown)) var/obj/item/weapon/grown/F = O - new_seed_type = plant_controller.seeds[F.plantname] + new_seed_type = SSplants.seeds[F.plantname] else var/obj/item/weapon/reagent_containers/food/snacks/grown/F = O - new_seed_type = plant_controller.seeds[F.plantname] + new_seed_type = SSplants.seeds[F.plantname] if(new_seed_type) to_chat(user, "You extract some seeds from [O].") diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index e7acfe1f41..e0f0695565 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -139,7 +139,7 @@ if("door") toggle_open(usr) . = TRUE - if("dispense") + if("dispense") switch(params["item"]) if("helmet") dispense_helmet(usr) @@ -653,12 +653,12 @@ name = "Vintage Pilot suit cycler" model_text = "Vintage Pilot" departments = list("Vintage Pilot (Bubble Helm)","Vintage Pilot (Closed Helm)") - + /obj/machinery/suit_cycler/vintage/medsci name = "Vintage MedSci suit cycler" model_text = "Vintage MedSci" departments = list("Vintage Medical (Bubble Helm)","Vintage Medical (Closed Helm)","Vintage Research (Bubble Helm)","Vintage Research (Closed Helm)") - + /obj/machinery/suit_cycler/vintage/rugged name = "Vintage Ruggedized suit cycler" model_text = "Vintage Ruggedized" @@ -751,7 +751,7 @@ if(istype(I,/obj/item/clothing/head/helmet/space/void/autolok)) to_chat(user, "You cannot refit an autolok helmet. In fact you shouldn't even be able to remove it in the first place. Inform an admin!") return - + //Ditto the Mk7 if(istype(I,/obj/item/clothing/head/helmet/space/void/responseteam)) to_chat(user, "The cycler indicates that the Mark VII Emergency Response Helmet is not compatible with the refitting system. How did you manage to detach it anyway? Inform an admin!") @@ -791,13 +791,13 @@ if(istype(I,/obj/item/clothing/suit/space/void/autolok)) to_chat(user, "You cannot refit an autolok suit.") return - + //Ditto the Mk7 if(istype(I,/obj/item/clothing/suit/space/void/responseteam)) to_chat(user, "The cycler indicates that the Mark VII Emergency Response Suit is not compatible with the refitting system.") return //VOREStation Edit ENDS - + to_chat(user, "You fit \the [I] into the suit cycler.") user.drop_item() I.loc = src @@ -886,7 +886,7 @@ return TRUE switch(action) - if("dispense") + if("dispense") switch(params["item"]) if("helmet") helmet.forceMove(get_turf(src)) @@ -895,23 +895,23 @@ suit.forceMove(get_turf(src)) suit = null . = TRUE - + if("department") var/choice = params["department"] if(choice in departments) target_department = choice . = TRUE - + if("species") var/choice = params["species"] if(choice in species) target_species = choice . = TRUE - + if("radlevel") radiation_level = clamp(params["radlevel"], 1, emagged ? 5 : 3) . = TRUE - + if("repair_suit") if(!suit || !can_repair) return @@ -1055,7 +1055,7 @@ if(target_species) if(helmet) helmet.refit_for_species(target_species) - if(suit) + if(suit) suit.refit_for_species(target_species) if(suit.helmet) suit.helmet.refit_for_species(target_species) @@ -1176,7 +1176,7 @@ parent_suit = /obj/item/clothing/suit/space/void/refurb/mercenary //BEGIN: Space for additional downstream variants //VOREStation Addition Start - if("Director") + if("Manager") parent_helmet = /obj/item/clothing/head/helmet/space/void/captain parent_suit = /obj/item/clothing/suit/space/void/captain if("Prototype") @@ -1217,7 +1217,7 @@ parent_suit = /obj/item/clothing/suit/space/void/refurb/mercenary/talon //VOREStation Addition End //END: downstream variant space - + //look at this! isn't it beautiful? -KK (well ok not beautiful but it's a lot cleaner) if(helmet && target_department != "No Change") var/obj/item/clothing/H = new parent_helmet @@ -1235,9 +1235,9 @@ suit.desc = initial(parent_suit.desc) suit.icon_state = initial(parent_suit.icon_state) suit.item_state = initial(parent_suit.item_state) - suit.item_state_slots = S.item_state_slots + suit.item_state_slots = S.item_state_slots qdel(S) - + //can't believe I forgot to fix this- now helmets will properly cycle if they're attached to a suit -KK if(suit.helmet && target_department != "No Change") var/obj/item/clothing/AH = new parent_helmet diff --git a/code/game/machinery/suit_storage_unit_vr.dm b/code/game/machinery/suit_storage_unit_vr.dm index cec50f5fcc..c0353dc41e 100644 --- a/code/game/machinery/suit_storage_unit_vr.dm +++ b/code/game/machinery/suit_storage_unit_vr.dm @@ -1,5 +1,5 @@ /obj/machinery/suit_cycler - departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Emergency Medical Response","Crowd Control","Exploration","Pilot Blue","Pilot","Director","Prototype") + departments = list("Engineering","Mining","Medical","Security","Atmos","HAZMAT","Construction","Biohazard","Emergency Medical Response","Crowd Control","Exploration","Pilot Blue","Pilot","Manager","Prototype") species = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_TAJ, SPECIES_TESHARI, SPECIES_AKULA, SPECIES_SERGAL, SPECIES_VULPKANIN, SPECIES_GREY_YW /*ywedit*/) // Old Exploration is too WIP to use right now @@ -11,10 +11,10 @@ req_access = list(access_pilot) /obj/machinery/suit_cycler/captain - name = "Director suit cycler" - model_text = "Director" + name = "Manager suit cycler" + model_text = "Manager" req_access = list(access_captain) - departments = list("Director") + departments = list("Manager") /obj/machinery/suit_cycler/captain/Initialize() //No Teshari Sprites species -= SPECIES_TESHARI diff --git a/code/game/machinery/vending_machines_vr.dm b/code/game/machinery/vending_machines_vr.dm index 007405b474..7261f9f66b 100644 --- a/code/game/machinery/vending_machines_vr.dm +++ b/code/game/machinery/vending_machines_vr.dm @@ -170,7 +170,7 @@ /obj/item/clothing/shoes/brown = 5, /obj/item/clothing/shoes/laceup = 5, /obj/item/clothing/shoes/green = 5, - /obj/item/clothing/shoes/leather = 5, + /obj/item/clothing/shoes/laceup/brown = 5, /obj/item/clothing/shoes/orange = 5, /obj/item/clothing/shoes/purple = 5, /obj/item/clothing/shoes/red = 5, @@ -228,7 +228,7 @@ /obj/item/clothing/shoes/brown = 50, /obj/item/clothing/shoes/laceup = 50, /obj/item/clothing/shoes/green = 50, - /obj/item/clothing/shoes/leather = 50, + /obj/item/clothing/shoes/laceup/brown = 50, /obj/item/clothing/shoes/orange = 50, /obj/item/clothing/shoes/purple = 50, /obj/item/clothing/shoes/red = 50, @@ -1172,7 +1172,19 @@ /obj/item/clothing/mask/gas/sexyclown = 3, /obj/item/clothing/under/sexyclown = 3, /obj/item/clothing/mask/gas/sexymime = 3, - /obj/item/clothing/under/sexymime = 3) + /obj/item/clothing/under/sexymime = 3, + /obj/item/clothing/suit/storage/hooded/knight_costume = 3, + /obj/item/clothing/suit/storage/hooded/knight_costume/galahad = 3, + /obj/item/clothing/suit/storage/hooded/knight_costume/lancelot = 3, + /obj/item/clothing/suit/storage/hooded/knight_costume/robin = 3, + /obj/item/clothing/suit/armor/combat/crusader_costume = 3, + /obj/item/clothing/suit/armor/combat/crusader_costume/bedevere = 3, + /obj/item/clothing/head/helmet/combat/crusader_costume = 3, + /obj/item/clothing/head/helmet/combat/bedevere_costume = 3, + /obj/item/clothing/gloves/combat/knight_costume = 3, + /obj/item/clothing/gloves/combat/knight_costume/brown = 3, + /obj/item/clothing/shoes/knight_costume = 3, + /obj/item/clothing/shoes/knight_costume/black = 3) prices = list(/obj/item/clothing/suit/storage/hooded/carp_costume = 200, /obj/item/clothing/suit/storage/hooded/carp_costume = 200, /obj/item/clothing/suit/chickensuit = 200, @@ -1225,7 +1237,19 @@ /obj/item/clothing/mask/gas/sexyclown = 600, /obj/item/clothing/under/sexyclown = 200, /obj/item/clothing/mask/gas/sexymime = 600, - /obj/item/clothing/under/sexymime = 200) + /obj/item/clothing/under/sexymime = 200, + /obj/item/clothing/suit/storage/hooded/knight_costume = 200, + /obj/item/clothing/suit/storage/hooded/knight_costume/galahad = 200, + /obj/item/clothing/suit/storage/hooded/knight_costume/lancelot = 200, + /obj/item/clothing/suit/storage/hooded/knight_costume/robin = 200, + /obj/item/clothing/suit/armor/combat/crusader_costume = 200, + /obj/item/clothing/suit/armor/combat/crusader_costume/bedevere = 200, + /obj/item/clothing/head/helmet/combat/crusader_costume = 200, + /obj/item/clothing/head/helmet/combat/bedevere_costume = 200, + /obj/item/clothing/gloves/combat/knight_costume = 200, + /obj/item/clothing/gloves/combat/knight_costume/brown = 200, + /obj/item/clothing/shoes/knight_costume = 200, + /obj/item/clothing/shoes/knight_costume/black = 200) premium = list(/obj/item/clothing/suit/imperium_monk = 3, /obj/item/clothing/suit/barding/agatha = 2, /obj/item/clothing/suit/barding/alt_agatha = 2, diff --git a/code/game/mecha/equipment/mecha_equipment.dm b/code/game/mecha/equipment/mecha_equipment.dm index 617af4849f..bec2b1a6c3 100644 --- a/code/game/mecha/equipment/mecha_equipment.dm +++ b/code/game/mecha/equipment/mecha_equipment.dm @@ -21,6 +21,8 @@ var/energy_drain = 0 var/obj/mecha/chassis = null var/range = MELEE //bitflags + /// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this. + var/mech_flags = NONE var/salvageable = 1 var/required_type = /obj/mecha //may be either a type or a list of allowed types var/equip_type = null //mechaequip2 diff --git a/code/game/mecha/equipment/tools/clamp.dm b/code/game/mecha/equipment/tools/clamp.dm index 6091764c2b..0580134f33 100644 --- a/code/game/mecha/equipment/tools/clamp.dm +++ b/code/game/mecha/equipment/tools/clamp.dm @@ -33,7 +33,7 @@ if(FD.blocked) FD.visible_message("\The [chassis] begins prying on \the [FD]!") if(do_after(chassis.occupant,10 SECONDS,FD)) - playsound(FD, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(FD, 'sound/machines/door/airlock_creaking.ogg', 100, 1) FD.blocked = 0 FD.update_icon() FD.open(1) @@ -41,7 +41,7 @@ else if(FD.density) FD.visible_message("\The [chassis] begins forcing \the [FD] open!") if(do_after(chassis.occupant, 5 SECONDS,FD)) - playsound(FD, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(FD, 'sound/machines/door/airlock_creaking.ogg', 100, 1) FD.visible_message("\The [chassis] forces \the [FD] open!") FD.open(1) else @@ -57,7 +57,7 @@ if(do_after(chassis.occupant, 15 SECONDS,AD) && chassis.Adjacent(AD)) AD.welded = FALSE AD.update_icon() - playsound(AD, 'sound/machines/airlock_creaking.ogg', 100, 1) + playsound(AD, 'sound/machines/door/airlock_creaking.ogg', 100, 1) AD.visible_message("\The [chassis] tears \the [AD] open!") if(!AD.welded) if(density) diff --git a/code/game/mecha/equipment/tools/extinguisher.dm b/code/game/mecha/equipment/tools/extinguisher.dm index 98712726c0..4579c46919 100644 --- a/code/game/mecha/equipment/tools/extinguisher.dm +++ b/code/game/mecha/equipment/tools/extinguisher.dm @@ -1,6 +1,7 @@ /obj/item/mecha_parts/mecha_equipment/tool/extinguisher name = "extinguisher" desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)" + mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT icon_state = "mecha_exting" equip_cooldown = 5 energy_drain = 0 diff --git a/code/game/mecha/equipment/tools/rcd.dm b/code/game/mecha/equipment/tools/rcd.dm index 9aa9a8bb40..5d283c852b 100644 --- a/code/game/mecha/equipment/tools/rcd.dm +++ b/code/game/mecha/equipment/tools/rcd.dm @@ -1,6 +1,7 @@ /obj/item/mecha_parts/mecha_equipment/tool/rcd name = "mounted RCD" desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)" + mech_flags = EXOSUIT_MODULE_WORKING|EXOSUIT_MODULE_COMBAT|EXOSUIT_MODULE_MEDICAL icon_state = "mecha_rcd" origin_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_POWER = 4) equip_cooldown = 10 diff --git a/code/game/mecha/equipment/tools/sleeper.dm b/code/game/mecha/equipment/tools/sleeper.dm index 861471b6ce..bdac763a5b 100644 --- a/code/game/mecha/equipment/tools/sleeper.dm +++ b/code/game/mecha/equipment/tools/sleeper.dm @@ -7,6 +7,7 @@ energy_drain = 20 range = MELEE equip_cooldown = 30 + mech_flags = EXOSUIT_MODULE_MEDICAL var/mob/living/carbon/human/occupant = null var/datum/global_iterator/pr_mech_sleeper var/inject_amount = 5 diff --git a/code/game/mecha/equipment/tools/syringe_gun.dm b/code/game/mecha/equipment/tools/syringe_gun.dm index a914839869..7449d80c0f 100644 --- a/code/game/mecha/equipment/tools/syringe_gun.dm +++ b/code/game/mecha/equipment/tools/syringe_gun.dm @@ -1,6 +1,7 @@ /obj/item/mecha_parts/mecha_equipment/tool/syringe_gun name = "syringe gun" desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)" + mech_flags = EXOSUIT_MODULE_MEDICAL icon = 'icons/obj/gun.dmi' icon_state = "syringegun" var/list/syringes diff --git a/code/game/mecha/equipment/weapons/explosive/missile.dm b/code/game/mecha/equipment/weapons/explosive/missile.dm index 9ff28ade8e..f0c73de695 100644 --- a/code/game/mecha/equipment/weapons/explosive/missile.dm +++ b/code/game/mecha/equipment/weapons/explosive/missile.dm @@ -4,9 +4,6 @@ step_delay = 0.5 -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/Fire(atom/movable/AM, atom/target, turf/aimloc) - AM.throw_at(target,missile_range, missile_speed, chassis) - /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flare name = "\improper BNI Flare Launcher" desc = "A flare-gun, but bigger." @@ -34,51 +31,19 @@ name = "\improper SRM-8 missile rack" desc = "A missile battery that holds eight missiles." icon_state = "mecha_missilerack" - projectile = /obj/item/missile + projectile = /obj/item/projectile/bullet/srmrocket fire_sound = 'sound/weapons/rpg.ogg' projectiles = 8 projectile_energy_cost = 1000 equip_cooldown = 60 -/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/Fire(atom/movable/AM, atom/target) - var/obj/item/missile/M = AM - M.primed = 1 - ..() - -/obj/item/missile - icon = 'icons/obj/grenade.dmi' - icon_state = "missile" - var/primed = null - throwforce = 15 - catchable = 0 - var/devastation = 0 - var/heavy_blast = 1 - var/light_blast = 2 - var/flash_blast = 4 - does_spin = FALSE // No fun corkscrew missiles. - -/obj/item/missile/proc/warhead_special(var/target) - explosion(target, devastation, heavy_blast, light_blast, flash_blast) - return - -/obj/item/missile/throw_impact(atom/hit_atom) - if(primed) - warhead_special(hit_atom) - qdel(src) - else - ..() - return - -/obj/item/missile/light - throwforce = 10 - heavy_blast = 0 /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive/rigged name = "jury-rigged rocket pod" desc = "A series of pipes, tubes, and cables that resembles a rocket pod." icon_state = "mecha_missilerack-rig" - projectile = /obj/item/missile/light + projectile = /obj/item/projectile/bullet/srmrocket/weak projectiles = 3 projectile_energy_cost = 800 - equip_type = EQUIP_UTILITY \ No newline at end of file + equip_type = EQUIP_UTILITY diff --git a/code/game/mecha/mech_fabricator.dm b/code/game/mecha/mech_fabricator.dm index 734c5bfa4c..521eb421de 100644 --- a/code/game/mecha/mech_fabricator.dm +++ b/code/game/mecha/mech_fabricator.dm @@ -11,47 +11,80 @@ req_access = list(access_robotics) circuit = /obj/item/weapon/circuitboard/mechfab - var/speed = 1 - var/mat_efficiency = 1 - var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, "plastic" = 0, MAT_GRAPHITE = 0, MAT_PLASTEEL = 0, "gold" = 0, "silver" = 0, MAT_LEAD = 0, "osmium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, "phoron" = 0, "uranium" = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0, MAT_METALHYDROGEN = 0, MAT_SUPERMATTER = 0) - var/list/hidden_materials = list(MAT_PLASTEEL, MAT_DURASTEEL, MAT_GRAPHITE, MAT_VERDANTIUM, MAT_MORPHIUM, MAT_METALHYDROGEN, MAT_SUPERMATTER) + /// Current items in the build queue. + var/list/queue = list() + /// Whether or not the machine is building the entire queue automagically. + var/process_queue = FALSE + + /// The current design datum that the machine is building. + var/datum/design/being_built + /// World time when the build will finish. + var/build_finish = 0 + /// World time when the build started. + var/build_start = 0 + /// Reference to all materials used in the creation of the item being_built. + var/list/build_materials + /// Part currently stored in the Exofab. + var/obj/item/stored_part + + /// Coefficient for the speed of item building. Based on the installed parts. + var/time_coeff = 1 + /// Coefficient for the efficiency of material usage in item building. Based on the installed parts. + var/component_coeff = 1 + + var/loading_icon_state = "mechfab-idle" + + var/list/materials = list( + DEFAULT_WALL_MATERIAL = 0, + "glass" = 0, + "plastic" = 0, + MAT_GRAPHITE = 0, + MAT_PLASTEEL = 0, + "gold" = 0, + "silver" = 0, + MAT_LEAD = 0, + "osmium" = 0, + "diamond" = 0, + MAT_DURASTEEL = 0, + "phoron" = 0, + "uranium" = 0, + MAT_VERDANTIUM = 0, + MAT_MORPHIUM = 0, + MAT_METALHYDROGEN = 0, + MAT_SUPERMATTER = 0) var/res_max_amount = 200000 var/datum/research/files - var/list/datum/design/queue = list() - var/progress = 0 - var/busy = 0 - - var/list/categories = list() - var/category = null - var/sync_message = "" + var/valid_buildtype = MECHFAB + /// A list of categories that valid MECHFAB design datums will broadly categorise themselves under. + var/list/part_sets = list( + "Cyborg", + "Ripley", + "Odysseus", + "Gygax", + "Durand", + "Janus", + "Vehicle", + "Rigsuit", + "Phazon", + "Gopher", // VOREStation Add + "Polecat", // VOREStation Add + "Weasel", // VOREStation Add + "Exosuit Equipment", + "Exosuit Internals", + "Exosuit Ammunition", + "Cyborg Upgrade Modules", + "Cybernetics", + "Implants", + "Control Interfaces", + "Other", + "Misc", + ) /obj/machinery/mecha_part_fabricator/Initialize() . = ..() default_apply_parts() files = new /datum/research(src) //Setup the research data holder. - update_categories() - -/obj/machinery/mecha_part_fabricator/process() - ..() - if(stat) - return - if(busy) - update_use_power(USE_POWER_ACTIVE) - progress += speed - check_build() - else - update_use_power(USE_POWER_IDLE) - update_icon() - -/obj/machinery/mecha_part_fabricator/update_icon() - overlays.Cut() - if(panel_open) - icon_state = "mechfab-o" - else - icon_state = "mechfab-idle" - if(busy) - overlays += "mechfab-active" /obj/machinery/mecha_part_fabricator/dismantle() for(var/f in materials) @@ -65,67 +98,507 @@ var/T = 0 for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) T += M.rating - mat_efficiency = max(1 - (T - 1) / 4, 0.2) // 1 -> 0.2 - for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both + component_coeff = max(1 - (T - 1) / 4, 0.2) // 1 -> 0.2 + for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; time_coeff is affected by both T += M.rating - speed = T / 2 // 1 -> 3 + time_coeff = T / 2 // 1 -> 3 + update_tgui_static_data(usr) + + +/** + * Generates an info list for a given part. + * + * Returns a list of part information. + * * D - Design datum to get information on. + * * categories - Boolean, whether or not to parse snowflake categories into the part information list. + */ +/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, var/categories = FALSE) + var/cost = list() + for(var/c in D.materials) + cost[c] = get_resource_cost_w_coeff(D, D.materials[c]) + + var/obj/built_item = D.build_path + + var/list/category_override = null + var/list/sub_category = null + + if(categories) + // Handle some special cases to build up sub-categories for the fab interface. + // Start with checking if this design builds a cyborg module. + if(built_item in typesof(/obj/item/borg/upgrade)) + var/obj/item/borg/upgrade/U = built_item + var/module_types = initial(U.module_flags) + sub_category = list() + if(module_types) + if(module_types & BORG_MODULE_SECURITY) + sub_category += "Security" + if(module_types & BORG_MODULE_MINER) + sub_category += "Mining" + if(module_types & BORG_MODULE_JANITOR) + sub_category += "Janitor" + if(module_types & BORG_MODULE_MEDICAL) + sub_category += "Medical" + if(module_types & BORG_MODULE_ENGINEERING) + sub_category += "Engineering" + else + sub_category += "All Cyborgs" + // Else check if this design builds a piece of exosuit equipment. + else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment)) + var/obj/item/mecha_parts/mecha_equipment/E = built_item + var/mech_types = initial(E.mech_flags) + sub_category = "Equipment" + if(mech_types) + category_override = list() + if(mech_types & EXOSUIT_MODULE_RIPLEY) + category_override += "Ripley" + if(mech_types & EXOSUIT_MODULE_ODYSSEUS) + category_override += "Odysseus" + if(mech_types & EXOSUIT_MODULE_GYGAX) + category_override += "Gygax" + if(mech_types & EXOSUIT_MODULE_DURAND) + category_override += "Durand" + if(mech_types & EXOSUIT_MODULE_PHAZON) + category_override += "Phazon" + + var/list/part = list( + "name" = D.name, + "desc" = initial(built_item.desc), + "printTime" = get_construction_time_w_coeff(initial(D.time))/10, + "cost" = cost, + "id" = D.id, + "subCategory" = sub_category, + "categoryOverride" = category_override, + "searchMeta" = D.search_metadata + ) + + return part + + +/** + * Generates a list of resources / materials available to this Exosuit Fab + * + * Returns null if there is no material container available. + * List format is list(material_name = list(amount = ..., ref = ..., etc.)) + */ +/obj/machinery/mecha_part_fabricator/proc/output_available_resources() + var/list/material_data = list() + + for(var/mat_id in materials) + var/amount = materials[mat_id] + var/list/material_info = list( + "name" = mat_id, + "amount" = amount, + "sheets" = round(amount / SHEET_MATERIAL_AMOUNT), + "removable" = amount >= SHEET_MATERIAL_AMOUNT + ) + + material_data += list(material_info) + + return material_data + +/** + * Intended to be called when an item starts printing. + * + * Adds the overlay to show the fab working and sets active power usage settings. + */ +/obj/machinery/mecha_part_fabricator/proc/on_start_printing() + add_overlay("fab-active") + use_power = USE_POWER_ACTIVE + +/** + * Intended to be called when the exofab has stopped working and is no longer printing items. + * + * Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing. + */ +/obj/machinery/mecha_part_fabricator/proc/on_finish_printing() + cut_overlay("fab-active") + use_power = USE_POWER_IDLE + desc = initial(desc) + process_queue = FALSE + +/** + * Calculates resource/material costs for printing an item based on the machine's resource coefficient. + * + * Returns a list of k,v resources with their amounts. + * * D - Design datum to calculate the modified resource cost of. + */ +/obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D) + var/list/resources = list() + for(var/mat_id in D.materials) + resources[mat_id] = get_resource_cost_w_coeff(D, D.materials[mat_id]) + return resources + +/** + * Checks if the Exofab has enough resources to print a given item. + * + * Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources. + * Returns TRUE if there are sufficient resources to print the item. + * * D - Design datum to calculate the modified resource cost of. + */ +/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) + if(length(D.chemicals)) // No reagents storage - no reagent designs. + return FALSE + . = TRUE + var/list/coeff_required = get_resources_w_coeff(D) + for(var/mat_id in coeff_required) + if(materials[mat_id] < coeff_required[mat_id]) + return FALSE + +/** + * Attempts to build the next item in the build queue. + * + * Returns FALSE if either there are no more parts to build or the next part is not buildable. + * Returns TRUE if the next part has started building. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE) + if(!length(queue)) + return FALSE + + var/datum/design/D = queue[1] + if(build_part(D, verbose)) + remove_from_queue(1) + return TRUE + + return FALSE + +/** + * Starts the build process for a given design datum. + * + * Returns FALSE if the procedure fails. Returns TRUE when being_built is set. + * Uses materials. + * * D - Design datum to attempt to print. + * * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build. + */ +/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE) + if(!D) + return FALSE + + if(!check_resources(D)) + if(verbose) + atom_say("Not enough resources. Processing stopped.") + return FALSE + + build_materials = get_resources_w_coeff(D) + for(var/mat_id in build_materials) + materials[mat_id] -= build_materials[mat_id] + + being_built = D + build_finish = world.time + get_construction_time_w_coeff(initial(D.time)) + build_start = world.time + desc = "It's building \a [D.name]." + + return TRUE + +/obj/machinery/mecha_part_fabricator/process() + ..() + // If there's a stored part to dispense due to an obstruction, try to dispense it. + if(stored_part) + var/turf/exit = get_step(src,(dir)) + if(exit.density) + return TRUE + + atom_say("Obstruction cleared. \The [stored_part] is complete.") + stored_part.forceMove(exit) + stored_part = null + + // If there's nothing being built, try to build something + if(!being_built) + // If we're not processing the queue anymore or there's nothing to build, end processing. + if(!process_queue || !build_next_in_queue()) + on_finish_printing() + return PROCESS_KILL + on_start_printing() + + // If there's an item being built, check if it is complete. + if(being_built && (build_finish < world.time)) + // Then attempt to dispense it and if appropriate build the next item. + dispense_built_part(being_built) + if(process_queue) + build_next_in_queue(FALSE) + return TRUE + + +/** + * Dispenses a part to the tile infront of the Exosuit Fab. + * + * Returns FALSE is the machine cannot dispense the part on the appropriate turf. + * Return TRUE if the part was successfully dispensed. + * * D - Design datum to attempt to dispense. + */ +/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D) + var/obj/item/I = D.Fabricate(src, src) + // I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this. + // I.set_custom_materials(build_materials) + + being_built = null + + var/turf/exit = get_step(src,(dir)) + if(exit.density) + atom_say("Error! Part outlet is obstructed.") + desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed." + stored_part = I + return FALSE + + atom_say("\The [I] is complete.") + I.forceMove(exit) + return I + +/** + * Adds a list of datum designs to the build queue. + * + * Will only add designs that are in this machine's stored techweb. + * Does final checks for datum IDs and makes sure this machine can build the designs. + * * part_list - List of datum design ids for designs to add to the queue. + */ +/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list) + for(var/datum/design/D in files.known_designs) + if((D.build_type & valid_buildtype) && (D.id in part_list)) + add_to_queue(D) + +/** + * Adds a datum design to the build queue. + * + * Returns TRUE if successful and FALSE if the design was not added to the queue. + * * D - Datum design to add to the queue. + */ +/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D) + if(!istype(queue)) + queue = list() + if(D) + queue[++queue.len] = D + return TRUE + return FALSE + +/** + * Removes datum design from the build queue based on index. + * + * Returns TRUE if successful and FALSE if a design was not removed from the queue. + * * index - Index in the build queue of the element to remove. + */ +/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index) + if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue))) + return FALSE + queue.Cut(index,++index) + return TRUE + +/** + * Generates a list of parts formatted for tgui based on the current build queue. + * + * Returns a formatted list of lists containing formatted part information for every part in the build queue. + */ +/obj/machinery/mecha_part_fabricator/proc/list_queue() + if(!istype(queue) || !length(queue)) + return null + + var/list/queued_parts = list() + for(var/datum/design/D in queue) + var/list/part = output_part_info(D) + queued_parts += list(part) + return queued_parts + +/obj/machinery/mecha_part_fabricator/proc/sync() + for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src))) + if(!RDC.sync) + continue + for(var/datum/tech/T in RDC.files.known_tech) + files.AddTech2Known(T) + for(var/datum/design/D in RDC.files.known_designs) + files.AddDesign2Known(D) + files.RefreshResearch() + update_tgui_static_data(usr) + atom_say("Successfully synchronized with R&D server.") + return + + atom_say("Unable to connect to local R&D server.") + return + +/** + * Calculates the coefficient-modified resource cost of a single material component of a design's recipe. + * + * Returns coefficient-modified resource cost for the given material component. + * * D - Design datum to pull the resource cost from. + * * resource - Material datum reference to the resource to calculate the cost of. + * * roundto - Rounding value for round() proc + */ +/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/amt, roundto = 1) + return round(amt * component_coeff, roundto) + +/** + * Calculates the coefficient-modified build time of a design. + * + * Returns coefficient-modified build time of a given design. + * * D - Design datum to calculate the modified build time of. + * * roundto - Rounding value for round() proc + */ +/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran + return round(construction_time * time_coeff, roundto) + +/obj/machinery/mecha_part_fabricator/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/sheetmaterials) + ) /obj/machinery/mecha_part_fabricator/attack_hand(var/mob/user) if(..()) return if(!allowed(user)) return - ui_interact(user) + tgui_interact(user) -/obj/machinery/mecha_part_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - var/datum/design/current = queue.len ? queue[1] : null - if(current) - data["current"] = current.name - data["queue"] = get_queue_names() - data["buildable"] = get_build_options() - data["category"] = category - data["categories"] = categories - data["materials"] = get_materials() - data["maxres"] = res_max_amount - data["sync"] = sync_message - if(current) - data["builtperc"] = round((progress / current.time) * 100) - - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) +/obj/machinery/mecha_part_fabricator/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) if(!ui) - ui = new(user, src, ui_key, "mechfab.tmpl", "Exosuit Fabricator UI", 800, 600) - ui.set_initial_data(data) + ui = new(user, src, "ExosuitFabricator", name) ui.open() - ui.set_auto_update(1) -/obj/machinery/mecha_part_fabricator/Topic(href, href_list) - if(..()) - return +/obj/machinery/mecha_part_fabricator/tgui_static_data(mob/user) + var/list/data = list() - if(href_list["build"]) - add_to_queue(text2num(href_list["build"])) + var/list/final_sets = list() + var/list/buildable_parts = list() - if(href_list["remove"]) - remove_from_queue(text2num(href_list["remove"])) + for(var/part_set in part_sets) + final_sets += part_set - if(href_list["category"]) - if(href_list["category"] in categories) - category = href_list["category"] + for(var/datum/design/D in files.known_designs) + if((D.build_type & valid_buildtype) && D.id != "id") // bugfix for weird null entries + // This is for us. + var/list/part = output_part_info(D, TRUE) - if(href_list["eject"]) - eject_materials(href_list["eject"], text2num(href_list["amount"])) + if(part["categoryOverride"]) + for(var/cat in part["categoryOverride"]) + buildable_parts[cat] += list(part) + if(!(cat in part_sets)) + final_sets += cat + continue - if(href_list["sync"]) - sync() + for(var/cat in part_sets) + // Find all matching categories. + if(!(cat in D.category)) + continue + + buildable_parts[cat] += list(part) + + data["partSets"] = final_sets + data["buildableParts"] = buildable_parts + + return data + +/obj/machinery/mecha_part_fabricator/tgui_data(mob/user) + var/list/data = list() + + data["materials"] = output_available_resources() + + if(being_built) + var/list/part = list( + "name" = being_built.name, + "duration" = build_finish - world.time, + "printTime" = get_construction_time_w_coeff(initial(being_built.time)) + ) + data["buildingPart"] = part else - sync_message = "" + data["buildingPart"] = null - return 1 + data["queue"] = list_queue() + + if(stored_part) + data["storedPart"] = stored_part.name + else + data["storedPart"] = null + + data["isProcessingQueue"] = process_queue + + return data + +/obj/machinery/mecha_part_fabricator/tgui_act(action, var/list/params) + if(..()) + return TRUE + + . = TRUE + + add_fingerprint(usr) + usr.set_machine(src) + + switch(action) + if("sync_rnd") + // Sync with R&D Servers + sync() + return + if("add_queue_set") + // Add all parts of a set to queue + var/part_list = params["part_list"] + add_part_set_to_queue(part_list) + return + if("add_queue_part") + // Add a specific part to queue + var/T = params["id"] + for(var/datum/design/D in files.known_designs) + if((D.build_type & valid_buildtype) && (D.id == T)) + add_to_queue(D) + break + return + if("del_queue_part") + // Delete a specific from from the queue + var/index = text2num(params["index"]) + remove_from_queue(index) + return + if("clear_queue") + // Delete everything from queue + queue.Cut() + return + if("build_queue") + // Build everything in queue + if(process_queue) + return + process_queue = TRUE + + if(!being_built) + START_PROCESSING(SSobj, src) + return + if("stop_queue") + // Pause queue building. Also known as stop. + process_queue = FALSE + return + if("build_part") + // Build a single part + if(being_built || process_queue) + return + + var/id = params["id"] + var/datum/design/D = null + for(var/datum/design/D_new in files.known_designs) + if((D_new.build_type == valid_buildtype) && (D_new.id == id)) + D = D_new + break + + if(!D) + return + + if(build_part(D)) + on_start_printing() + START_PROCESSING(SSobj, src) + + return + if("move_queue_part") + // Moves a part up or down in the queue. + var/index = text2num(params["index"]) + var/new_index = index + text2num(params["newindex"]) + if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index)) + if(ISINRANGE(new_index,1,length(queue))) + queue.Swap(index,new_index) + return + if("remove_mat") + // Remove a material from the fab + var/mat_id = params["id"] + var/amount = text2num(params["amount"]) + eject_materials(mat_id, amount) + return + + return FALSE /obj/machinery/mecha_part_fabricator/attackby(var/obj/item/I, var/mob/user) - if(busy) + if(being_built) to_chat(user, "\The [src] is busy. Please wait for completion of previous operation.") return 1 if(default_deconstruction_screwdriver(user, I)) @@ -146,15 +619,17 @@ if(materials[S.material.name] + amnt <= res_max_amount) if(S && S.get_amount() >= 1) var/count = 0 - overlays += "mechfab-load-metal" - spawn(10) - overlays -= "mechfab-load-metal" + flick("[loading_icon_state]", src) + // yess hacky but whatever + if(loading_icon_state == "mechfab-idle") + overlays += "mechfab-load-metal" + spawn(10) + overlays -= "mechfab-load-metal" while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1) materials[S.material.name] += amnt S.use(1) count++ to_chat(user, "You insert [count] [sname] into the fabricator.") - update_busy() else to_chat(user, "The fabricator cannot hold more [sname].") @@ -181,96 +656,6 @@ if(1) visible_message("[bicon(src)] [src] beeps: \"No records in User DB\"") -/obj/machinery/mecha_part_fabricator/proc/update_busy() - if(queue.len) - if(can_build(queue[1])) - busy = 1 - else - busy = 0 - else - busy = 0 - -/obj/machinery/mecha_part_fabricator/proc/add_to_queue(var/index) - var/datum/design/D = files.known_designs[index] - queue += D - update_busy() - -/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(var/index) - if(index == 1) - progress = 0 - queue.Cut(index, index + 1) - update_busy() - -/obj/machinery/mecha_part_fabricator/proc/can_build(var/datum/design/D) - for(var/M in D.materials) - if(materials[M] < (D.materials[M] * mat_efficiency)) - return 0 - return 1 - -/obj/machinery/mecha_part_fabricator/proc/check_build() - if(!queue.len) - progress = 0 - return - var/datum/design/D = queue[1] - if(!can_build(D)) - progress = 0 - return - if(D.time > progress) - return - for(var/M in D.materials) - materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency) - if(D.build_path) - var/obj/new_item = D.Fabricate(get_step(get_turf(src), src.dir), src) - visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.") - if(mat_efficiency != 1) - if(new_item.matter && new_item.matter.len > 0) - for(var/i in new_item.matter) - new_item.matter[i] = new_item.matter[i] * mat_efficiency - remove_from_queue(1) - -/obj/machinery/mecha_part_fabricator/proc/get_queue_names() - . = list() - for(var/i = 2 to queue.len) - var/datum/design/D = queue[i] - . += D.name - -/obj/machinery/mecha_part_fabricator/proc/get_build_options() - . = list() - for(var/i = 1 to files.known_designs.len) - var/datum/design/D = files.known_designs[i] - if(!D.build_path || !(D.build_type & MECHFAB)) - continue - . += list(list("name" = D.name, "id" = i, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D))) - -/obj/machinery/mecha_part_fabricator/proc/get_design_resourses(var/datum/design/D) - var/list/F = list() - for(var/T in D.materials) - F += "[capitalize(T)]: [D.materials[T] * mat_efficiency]" - return english_list(F, and_text = ", ") - -/obj/machinery/mecha_part_fabricator/proc/get_design_time(var/datum/design/D) - return time2text(round(10 * D.time / speed), "mm:ss") - -/obj/machinery/mecha_part_fabricator/proc/update_categories() - categories = list() - for(var/datum/design/D in files.known_designs) - if(!D.build_path || !(D.build_type & MECHFAB)) - continue - categories |= D.category - if(!category || !(category in categories)) - category = categories[1] - -/obj/machinery/mecha_part_fabricator/proc/get_materials() - . = list() - for(var/T in materials) - var/hidden_mat = FALSE - for(var/HM in hidden_materials) // Direct list contents comparison was failing. - if(T == HM && materials[T] == 0) - hidden_mat = TRUE - continue - if(!hidden_mat) - . += list(list("mat" = capitalize(T), "amt" = materials[T])) - /obj/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything var/recursive = amount == -1 ? 1 : 0 var/matstring = lowertext(material) @@ -287,17 +672,3 @@ materials[matstring] -= ejected * S.perunit if(recursive && materials[matstring] >= S.perunit) eject_materials(matstring, -1) - update_busy() - -/obj/machinery/mecha_part_fabricator/proc/sync() - sync_message = "Error: no console found." - for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src))) - if(!RDC.sync) - continue - for(var/datum/tech/T in RDC.files.known_tech) - files.AddTech2Known(T) - for(var/datum/design/D in RDC.files.known_designs) - files.AddDesign2Known(D) - files.RefreshResearch() - sync_message = "Sync complete." - update_categories() diff --git a/code/game/mecha/mech_prosthetics.dm b/code/game/mecha/mech_prosthetics.dm index 1615be1ff4..72e51262e7 100644 --- a/code/game/mecha/mech_prosthetics.dm +++ b/code/game/mecha/mech_prosthetics.dm @@ -1,4 +1,4 @@ -/obj/machinery/pros_fabricator +/obj/machinery/mecha_part_fabricator/pros icon = 'icons/obj/robotics.dmi' icon_state = "prosfab" name = "Prosthetics Fabricator" @@ -11,158 +11,126 @@ req_access = list(access_robotics) circuit = /obj/item/weapon/circuitboard/prosthetics - var/speed = 1 - var/mat_efficiency = 1 - var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, "plastic" = 0, MAT_GRAPHITE = 0, MAT_PLASTEEL = 0, "gold" = 0, "silver" = 0, MAT_LEAD = 0, "osmium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, "phoron" = 0, "uranium" = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0) - var/list/hidden_materials = list(MAT_DURASTEEL, MAT_GRAPHITE, MAT_VERDANTIUM, MAT_MORPHIUM) - var/res_max_amount = 200000 - - var/datum/research/files - var/list/datum/design/queue = list() - var/progress = 0 - var/busy = 0 - - var/list/categories = list() - var/category = null + // Prosfab specific stuff var/manufacturer = null var/species_types = list("Human") var/species = "Human" - var/sync_message = "" -/obj/machinery/pros_fabricator/Initialize() - . = ..() - default_apply_parts() + loading_icon_state = "prosfab_loading" - files = new /datum/research(src) //Setup the research data holder. + materials = list( + DEFAULT_WALL_MATERIAL = 0, + "glass" = 0, + "plastic" = 0, + MAT_GRAPHITE = 0, + MAT_PLASTEEL = 0, + "gold" = 0, + "silver" = 0, + MAT_LEAD = 0, + "osmium" = 0, + "diamond" = 0, + MAT_DURASTEEL = 0, + "phoron" = 0, + "uranium" = 0, + MAT_VERDANTIUM = 0, + MAT_MORPHIUM = 0) + res_max_amount = 200000 -/obj/machinery/pros_fabricator/Initialize() + valid_buildtype = PROSFAB + /// A list of categories that valid PROSFAB design datums will broadly categorise themselves under. + part_sets = list( + "Cyborg", + "Ripley", + "Odysseus", + "Gygax", + "Durand", + "Janus", + "Vehicle", + "Rigsuit", + "Phazon", + "Gopher", // VOREStation Add + "Polecat", // VOREStation Add + "Weasel", // VOREStation Add + "Exosuit Equipment", + "Exosuit Internals", + "Exosuit Ammunition", + "Cyborg Modules", + "Prosthetics", + "Prosthetics, Internal", + "Cyborg Parts", + "Cyborg Internals", + "Cybernetics", + "Implants", + "Control Interfaces", + "Other", + "Misc", + ) + +/obj/machinery/mecha_part_fabricator/pros/Initialize() . = ..() manufacturer = basic_robolimb.company - update_categories() -/obj/machinery/pros_fabricator/process() - ..() - if(stat) - return - if(busy) - update_use_power(USE_POWER_ACTIVE) - progress += speed - check_build() - else - update_use_power(USE_POWER_IDLE) - update_icon() +/obj/machinery/mecha_part_fabricator/pros/dispense_built_part(datum/design/D) + var/obj/item/I = ..() + if(isobj(I) && I.matter && I.matter.len > 0) + for(var/i in I.matter) + I.matter[i] = I.matter[i] * component_coeff -/obj/machinery/pros_fabricator/update_icon() - overlays.Cut() - icon_state = initial(icon_state) +/obj/machinery/mecha_part_fabricator/pros/tgui_data(mob/user) + var/list/data = ..() - if(panel_open) - overlays.Add(image(icon, "[icon_state]_panel")) - if(stat & NOPOWER) - return - if(busy) - icon_state = "[icon_state]_work" - -/obj/machinery/pros_fabricator/dismantle() - for(var/f in materials) - eject_materials(f, -1) - ..() - -/obj/machinery/pros_fabricator/RefreshParts() - res_max_amount = 0 - for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts) - res_max_amount += M.rating * 100000 // 200k -> 600k - var/T = 0 - for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts) - T += M.rating - mat_efficiency = max(0.2, 1 - (T - 1) / 4) // 1 -> 0.2 - for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both - T += M.rating - speed = T / 2 // 1 -> 3 - -/obj/machinery/pros_fabricator/attack_hand(var/mob/user) - if(..()) - return - if(!allowed(user)) - return - ui_interact(user) - -/obj/machinery/pros_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - var/data[0] - - var/datum/design/current = queue.len ? queue[1] : null - if(current) - data["current"] = current.name - data["queue"] = get_queue_names() - data["buildable"] = get_build_options() - data["category"] = category - data["categories"] = categories data["species_types"] = species_types data["species"] = species + if(all_robolimbs) var/list/T = list() for(var/A in all_robolimbs) var/datum/robolimb/R = all_robolimbs[A] - if(R.unavailable_to_build) continue - if(species in R.species_cannot_use) continue + if(R.unavailable_to_build) + continue + if(species in R.species_cannot_use) + continue T += list(list("id" = A, "company" = R.company)) data["manufacturers"] = T - data["manufacturer"] = manufacturer - data["materials"] = get_materials() - data["maxres"] = res_max_amount - data["sync"] = sync_message - if(current) - data["builtperc"] = round((progress / current.time) * 100) - ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open) - if(!ui) - ui = new(user, src, ui_key, "mechfab.tmpl", "Prosthetics Fab UI", 800, 600) - ui.set_initial_data(data) - ui.open() - ui.set_auto_update(1) + data["manufacturer"] = manufacturer -/obj/machinery/pros_fabricator/Topic(href, href_list) + return data + +/obj/machinery/mecha_part_fabricator/pros/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) if(..()) - return + return TRUE - if(href_list["build"]) - add_to_queue(text2num(href_list["build"])) + . = TRUE - if(href_list["remove"]) - remove_from_queue(text2num(href_list["remove"])) + add_fingerprint(usr) + usr.set_machine(src) - if(href_list["category"]) - if(href_list["category"] in categories) - category = href_list["category"] + switch(action) + if("species") + var/new_species = input(usr, "Select a new species", "Prosfab Species Selection", "Human") as null|anything in species_types + if(new_species && tgui_status(usr, state) == STATUS_INTERACTIVE) + species = new_species + return + if("manufacturer") + var/list/new_manufacturers = list() + for(var/A in all_robolimbs) + var/datum/robolimb/R = all_robolimbs[A] + if(R.unavailable_to_build) + continue + if(species in R.species_cannot_use) + continue + new_manufacturers += A - if(href_list["species"]) - if(href_list["species"] in species_types) - species = href_list["species"] + var/new_manufacturer = input(usr, "Select a new manufacturer", "Prosfab Species Selection", "Unbranded") as null|anything in new_manufacturers + if(new_manufacturer && tgui_status(usr, state) == STATUS_INTERACTIVE) + manufacturer = new_manufacturer + return + return FALSE - if(href_list["manufacturer"]) - if(href_list["manufacturer"] in all_robolimbs) - manufacturer = href_list["manufacturer"] - - if(href_list["eject"]) - eject_materials(href_list["eject"], text2num(href_list["amount"])) - - if(href_list["sync"]) - sync() - else - sync_message = "" - - return 1 - -/obj/machinery/pros_fabricator/attackby(var/obj/item/I, var/mob/user) - if(busy) - to_chat(user, "\The [src] is busy. Please wait for completion of previous operation.") +/obj/machinery/mecha_part_fabricator/pros/attackby(var/obj/item/I, var/mob/user) + if(..()) return 1 - if(default_deconstruction_screwdriver(user, I)) - return - if(default_deconstruction_crowbar(user, I)) - return - if(default_part_replacement(user, I)) - return if(istype(I,/obj/item/weapon/disk/limb)) var/obj/item/weapon/disk/limb/D = I @@ -188,168 +156,3 @@ to_chat(user, "Uploaded [D.species] files!") qdel(I) return - - if(istype(I,/obj/item/stack/material)) - var/obj/item/stack/material/S = I - if(!(S.material.name in materials)) - to_chat(user, "The [src] doesn't accept [S.material]!") - return - - var/sname = "[S.name]" - var/amnt = S.perunit - if(materials[S.material.name] + amnt <= res_max_amount) - if(S && S.get_amount() >= 1) - var/count = 0 - flick("[initial(icon_state)]_loading", src) - while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1) - materials[S.material.name] += amnt - S.use(1) - count++ - to_chat(user, "You insert [count] [sname] into the fabricator.") - update_busy() - else - to_chat(user, "The fabricator cannot hold more [sname].") - - return - - ..() - -/obj/machinery/pros_fabricator/emag_act(var/remaining_charges, var/mob/user) - switch(emagged) - if(0) - emagged = 0.5 - visible_message("[bicon(src)] [src] beeps: \"DB error \[Code 0x00F1\]\"") - sleep(10) - visible_message("[bicon(src)] [src] beeps: \"Attempting auto-repair\"") - sleep(15) - visible_message("[bicon(src)] [src] beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"") - sleep(30) - visible_message("[bicon(src)] [src] beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"") - req_access = null - emagged = 1 - return 1 - if(0.5) - visible_message("[bicon(src)] [src] beeps: \"DB not responding \[Code 0x0003\]...\"") - if(1) - visible_message("[bicon(src)] [src] beeps: \"No records in User DB\"") - -/obj/machinery/pros_fabricator/proc/update_busy() - if(queue.len) - if(can_build(queue[1])) - busy = 1 - else - busy = 0 - else - busy = 0 - -/obj/machinery/pros_fabricator/proc/add_to_queue(var/index) - var/datum/design/D = files.known_designs[index] - queue += D - update_busy() - -/obj/machinery/pros_fabricator/proc/remove_from_queue(var/index) - if(index == 1) - progress = 0 - queue.Cut(index, index + 1) - update_busy() - -/obj/machinery/pros_fabricator/proc/can_build(var/datum/design/D) - for(var/M in D.materials) - if(materials[M] < (D.materials[M] * mat_efficiency)) - return 0 - return 1 - -/obj/machinery/pros_fabricator/proc/check_build() - if(!queue.len) - progress = 0 - return - var/datum/design/D = queue[1] - if(!can_build(D)) - progress = 0 - return - if(D.time > progress) - return - for(var/M in D.materials) - materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency) - if(D.build_path) - var/obj/new_item = D.Fabricate(get_step(get_turf(src), src.dir), src) // Sometimes returns a mob. Beware! - flick("[initial(icon_state)]_finish", src) - visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.") - if(mat_efficiency != 1) - if(istype(new_item, /obj/) && new_item.matter && new_item.matter.len > 0) - for(var/i in new_item.matter) - new_item.matter[i] = new_item.matter[i] * mat_efficiency - remove_from_queue(1) - -/obj/machinery/pros_fabricator/proc/get_queue_names() - . = list() - for(var/i = 2 to queue.len) - var/datum/design/D = queue[i] - . += D.name - -/obj/machinery/pros_fabricator/proc/get_build_options() - . = list() - for(var/i = 1 to files.known_designs.len) - var/datum/design/D = files.known_designs[i] - if(D.build_path && (D.build_type & PROSFAB)) - . += list(list("name" = D.name, "id" = i, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D))) - -/obj/machinery/pros_fabricator/proc/get_design_resourses(var/datum/design/D) - var/list/F = list() - for(var/T in D.materials) - F += "[capitalize(T)]: [D.materials[T] * mat_efficiency]" - return english_list(F, and_text = ", ") - -/obj/machinery/pros_fabricator/proc/get_design_time(var/datum/design/D) - return time2text(round(10 * D.time / speed), "mm:ss") - -/obj/machinery/pros_fabricator/proc/update_categories() - categories = list() - for(var/datum/design/D in files.known_designs) - if(!D.build_path || !(D.build_type & PROSFAB)) - continue - categories |= D.category - if(!category || !(category in categories)) - category = categories[1] - -/obj/machinery/pros_fabricator/proc/get_materials() - . = list() - for(var/T in materials) - var/hidden_mat = FALSE - for(var/HM in hidden_materials) // Direct list contents comparison was failing. - if(T == HM && materials[T] == 0) - hidden_mat = TRUE - continue - if(!hidden_mat) - . += list(list("mat" = capitalize(T), "amt" = materials[T])) - -/obj/machinery/pros_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything - var/recursive = amount == -1 ? 1 : 0 - var/matstring = lowertext(material) - var/material/M = get_material_by_name(matstring) - - var/obj/item/stack/material/S = M.place_sheet(get_turf(src)) - if(amount <= 0) - amount = S.max_amount - var/ejected = min(round(materials[matstring] / S.perunit), amount) - S.amount = min(ejected, amount) - if(S.amount <= 0) - qdel(S) - return - materials[matstring] -= ejected * S.perunit - if(recursive && materials[matstring] >= S.perunit) - eject_materials(matstring, -1) - update_busy() - -/obj/machinery/pros_fabricator/proc/sync() - sync_message = "Error: no console found." - for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src))) - if(!RDC.sync) - continue - for(var/datum/tech/T in RDC.files.known_tech) - files.AddTech2Known(T) - for(var/datum/design/D in RDC.files.known_designs) - files.AddDesign2Known(D) - files.RefreshResearch() - sync_message = "Sync complete." - update_categories() diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm index bfdb4508e9..9baabe8f9b 100644 --- a/code/game/mecha/mecha.dm +++ b/code/game/mecha/mecha.dm @@ -1891,7 +1891,7 @@ update_cell_alerts() update_damage_alerts() set_dir(dir_in) - playsound(src, 'sound/machines/windowdoor.ogg', 50, 1) + playsound(src, 'sound/machines/door/windowdoor.ogg', 50, 1) if(occupant.client && cloaked_selfimage) occupant.client.images += cloaked_selfimage play_entered_noise(occupant) @@ -2243,6 +2243,16 @@ output += "