diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 04bdb0d8e177..87799bb075f7 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -335,6 +335,8 @@ else parts += "
" parts += "You managed to survive the events on [station_name()] as [M.real_name]." + if(M.mind.assigned_role in GLOB.engineering_positions) // We don't actually need to even really do a check to see if assigned_role is set to anything. + SSachievements.unlock_achievement(/datum/achievement/engineering, C) else parts += "
" diff --git a/code/controllers/subsystem/achievements.dm b/code/controllers/subsystem/achievements.dm index 2119f9c2e20c..49d5f01757c2 100644 --- a/code/controllers/subsystem/achievements.dm +++ b/code/controllers/subsystem/achievements.dm @@ -1,10 +1,11 @@ SUBSYSTEM_DEF(achievements) name = "Achievements" - flags = SS_NO_FIRE + flags = SS_BACKGROUND var/list/achievements = list() var/list/cached_achievements = list() var/list/browsers = list() var/list/achievementsEarned = list() + var/mob/living/carbon/human/CE // The current guy that SSachievements believes to be the CE. /datum/controller/subsystem/achievements/Initialize(timeofday) for(var/i in subtypesof(/datum/achievement)) @@ -47,6 +48,23 @@ SUBSYSTEM_DEF(achievements) qdel(ridOldChieves) return ..() +/datum/controller/subsystem/achievements/fire(resumed) + //The solar panel achievement + if(!CE) + for(var/x in GLOB.player_list) + if(ishuman(x)) + var/mob/living/carbon/human/H = x + if(H.mind?.assigned_role == "Chief Engineer") + CE = H + break + else + for(var/n in SSmachines.powernets) + var/datum/powernet/net = n + if(is_station_level(net.z)) // If the powernet is on the station z-level + if(net.avail >= 3000 && CE.stat != DEAD && CE.client) // If there's 3 MW available (Value is in kW) + unlock_achievement(/datum/achievement/engineering/scotty, CE.client) + +//Ad-hoc procs /datum/controller/subsystem/achievements/proc/unlock_achievement(achievementPath, client/C) var/datum/achievement/achievement = get_achievement(achievementPath) if(!achievement) diff --git a/code/controllers/subsystem/machines.dm b/code/controllers/subsystem/machines.dm index c4b09d1b8741..8ebe7b4eedb8 100644 --- a/code/controllers/subsystem/machines.dm +++ b/code/controllers/subsystem/machines.dm @@ -18,7 +18,7 @@ SUBSYSTEM_DEF(machines) for(var/obj/structure/cable/PC in GLOB.cable_list) if(!PC.powernet) - var/datum/powernet/NewPN = new() + var/datum/powernet/NewPN = new(PC.loc.z) NewPN.add_cable(PC) propagate_network(PC,PC.powernet) @@ -53,7 +53,7 @@ SUBSYSTEM_DEF(machines) for(var/A in cables) var/obj/structure/cable/PC = A if(!PC.powernet) - var/datum/powernet/NewPN = new() + var/datum/powernet/NewPN = new(PC.loc.z) NewPN.add_cable(PC) propagate_network(PC,PC.powernet) diff --git a/code/datums/achievements/achievements.dm b/code/datums/achievements/achievements.dm index 568ad226ba0a..458bf0476cfc 100644 --- a/code/datums/achievements/achievements.dm +++ b/code/datums/achievements/achievements.dm @@ -3,6 +3,7 @@ //TO BE HONEST THIS OFFSET DOESN'T EVEN NEED TO BE POWER OF TWO, THOUGH. #define GREENTEXT 256 // An offset for new greentext-related achievements, to keep the incremental pattern. #define REDTEXT 512 // Offset for redtexts. +#define ENGIEDEPT 768 // Offset for engineering-related achievements. /datum/achievement var/name = "achievement" @@ -25,7 +26,7 @@ desc = "Successfully defibrillate someone" id = 3 -/datum/achievement/pa_emag +/datum/achievement/engineering/pa_emag name = "Catastrophe" desc = "Emag a particle accelerator" id = 4 @@ -100,13 +101,13 @@ id = 17 hidden = TRUE -/datum/achievement/Poly_silent +/datum/achievement/engineering/Poly_silent name = "Silence Bird!" desc = "As a signal technician, create a script that mutes poly" id = 18 hidden = TRUE -/datum/achievement/Poly_loud +/datum/achievement/engineering/Poly_loud name = "Embrace the Bird!" desc = "As a signal technician, create a script that makes poly LOUD" id = 19 @@ -143,6 +144,12 @@ desc = "Trigger a keycard authentication device event, by yourself." id = 23 +/datum/achievement/dab + name = "Brain Damage" + desc = "Dab." + id = 24 + hidden = TRUE + // The achievements that are basically just "greentext as this sort of antag" /datum/achievement/greentext @@ -245,5 +252,25 @@ hidden = TRUE //end-redtext +//start-engineering +/datum/achievement/engineering + name = "Isaac Clarke" + desc = "Survive a full round as part of the Engineering team." + id = ENGIEDEPT + 1 +/datum/achievement/engineering/solar + name = "Honest Work" + desc = "Set up one of the solar arrays as part of the Engineering team." + id = ENGIEDEPT + 2 +/datum/achievement/engineering/scotty + name = "\"I'm givin' it all she's got, Captain!\"" + desc = "As Chief Engineer, produce more than three megawatts of power." + id = ENGIEDEPT + 3 +/datum/achievement/engineering/toasty + name = "Nice and Toasty" + desc = "Get set on fire in a fire-resistant suit." + id = ENGIEDEPT + 4 +//end-engineering + #undef GREENTEXT -#undef REDTEXT \ No newline at end of file +#undef REDTEXT +#undef ENGIEDEPT diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 4f213e55d98a..57320f133592 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -150,6 +150,8 @@ //If have no DNA or can be Ignited, call parent handling to light user //If firestacks are high enough if(!dna || dna.species.CanIgniteMob(src)) + if(get_thermal_protection() > FIRE_SUIT_MAX_TEMP_PROTECT*0.95) // If they're resistant to fire (slightly undercut to make sure get_thermal_protection doesn't fuck over this achievement due to floating-point errors + SSachievements.unlock_achievement(/datum/achievement/engineering/toasty,src.client) // Fear the reaper man! return ..() . = FALSE //No ignition diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 22e5b0bcce8f..d42110d582a1 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -260,7 +260,7 @@ By design, d1 is the smallest direction and d2 is the highest if(C.d1 == (direction^3) || C.d2 == (direction^3)) //we've got a diagonally matching cable if(!C.powernet) //if the matching cable somehow got no powernet, make him one (should not happen for cables) - var/datum/powernet/newPN = new() + var/datum/powernet/newPN = new(C.loc.z) newPN.add_cable(C) if(powernet) //if we already have a powernet, then merge the two powernets @@ -280,7 +280,7 @@ By design, d1 is the smallest direction and d2 is the highest continue if(C.d1 == (direction^12) || C.d2 == (direction^12)) //we've got a diagonally matching cable if(!C.powernet) //if the matching cable somehow got no powernet, make him one (should not happen for cables) - var/datum/powernet/newPN = new() + var/datum/powernet/newPN = new(C.loc.z) newPN.add_cable(C) if(powernet) //if we already have a powernet, then merge the two powernets @@ -308,7 +308,7 @@ By design, d1 is the smallest direction and d2 is the highest if(C.d1 == fdir || C.d2 == fdir) //we've got a matching cable in the neighbor turf if(!C.powernet) //if the matching cable somehow got no powernet, make him one (should not happen for cables) - var/datum/powernet/newPN = new() + var/datum/powernet/newPN = new(C.loc.z) newPN.add_cable(C) if(powernet) //if we already have a powernet, then merge the two powernets @@ -321,7 +321,7 @@ By design, d1 is the smallest direction and d2 is the highest var/list/to_connect = list() if(!powernet) //if we somehow have no powernet, make one (should not happen for cables) - var/datum/powernet/newPN = new() + var/datum/powernet/newPN = new(loc.z) newPN.add_cable(src) //first let's add turf cables to our powernet @@ -410,7 +410,7 @@ By design, d1 is the smallest direction and d2 is the highest var/list/powerlist = power_list(T1,src,0,0) //find the other cables that ended in the centre of the turf, with or without a powernet if(powerlist.len>0) - var/datum/powernet/PN = new() + var/datum/powernet/PN = new(loc.z) propagate_network(powerlist[1],PN) //propagates the new powernet beginning at the source cable if(PN.is_empty()) //can happen with machines made nodeless when smoothing cables @@ -418,7 +418,7 @@ By design, d1 is the smallest direction and d2 is the highest /obj/structure/cable/proc/auto_propogate_cut_cable(obj/O) if(O && !QDELETED(O)) - var/datum/powernet/newPN = new()// creates a new powernet... + var/datum/powernet/newPN = new(loc.z)// creates a new powernet... propagate_network(O, newPN)//... and propagates it to the other side of the cable // cut the cable's powernet at this cable and updates the powergrid @@ -620,7 +620,7 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai C.update_icon() //create a new powernet with the cable, if needed it will be merged later - var/datum/powernet/PN = new() + var/datum/powernet/PN = new(loc.z) PN.add_cable(C) C.mergeConnectedNetworks(C.d2) //merge the powernet with adjacents powernets @@ -692,7 +692,7 @@ GLOBAL_LIST_INIT(cable_coil_recipes, list (new/datum/stack_recipe("cable restrai NC.update_icon() //create a new powernet with the cable, if needed it will be merged later - var/datum/powernet/newPN = new() + var/datum/powernet/newPN = new(loc.z) newPN.add_cable(NC) NC.mergeConnectedNetworks(NC.d2) //merge the powernet with adjacents powernets diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm index 9660e8359c55..64727cd9edf0 100644 --- a/code/modules/power/powernet.dm +++ b/code/modules/power/powernet.dm @@ -14,9 +14,11 @@ var/viewload = 0 // the load as it appears on the power console (gradually updated) var/netexcess = 0 // excess power on the powernet (typically avail-load)/////// var/delayedload = 0 // load applied to powernet between power ticks. + var/z = 0 // the Z coordinate of this powernet. Only used by some random achievement, at the moment. -/datum/powernet/New() +/datum/powernet/New(newz) SSmachines.powernets += src + z = newz /datum/powernet/Destroy() //Go away references, you suck! diff --git a/code/modules/power/solar.dm b/code/modules/power/solar.dm index 9316a145251a..b9f8bf009aaa 100644 --- a/code/modules/power/solar.dm +++ b/code/modules/power/solar.dm @@ -273,6 +273,7 @@ var/nexttime = 0 // time for a panel to rotate of 1 degree in manual tracking var/obj/machinery/power/tracker/connected_tracker = null var/list/connected_panels = list() + var/mob/living/carbon/human/last_user // The last guy to open up the console /obj/machinery/power/solar_control/Initialize() . = ..() @@ -344,6 +345,8 @@ if(!ui) ui = new(user, src, ui_key, "solar_control", name, 380, 230, master_ui, state) ui.open() + if(ishuman(user)) + last_user = user /obj/machinery/power/solar_control/ui_data() var/data = list() @@ -398,7 +401,11 @@ set_panels(targetdir) return TRUE if(action == "refresh") + var/was_not_connected = !(connected_tracker && connected_panels.len) search_for_connected() + if(last_user && last_user.client && was_not_connected && connected_tracker && connected_panels.len) // If this guy finished up the solars + if(last_user.stat != DEAD && (last_user.mind?.assigned_role in GLOB.engineering_positions)) // and he's an engineer who isn't long-dead or adminbussing + SSachievements.unlock_achievement(/datum/achievement/engineering/solar, last_user.client) // Give him the achievement if(connected_tracker && track == 2) connected_tracker.set_angle(SSsun.angle) set_panels(currentdir) diff --git a/yogstation/code/game/machinery/telecomms/machines/server.dm b/yogstation/code/game/machinery/telecomms/machines/server.dm index f2e348e8f4b5..80bc569aa9eb 100644 --- a/yogstation/code/game/machinery/telecomms/machines/server.dm +++ b/yogstation/code/game/machinery/telecomms/machines/server.dm @@ -75,15 +75,11 @@ signal.data["reject"] = 0 Compiler.Run(signal) if(signal.data["reject"] == 0) - SSachievements.unlock_achievement(/datum/achievement/Poly_silent, user.client) + SSachievements.unlock_achievement(/datum/achievement/engineering/Poly_silent, user.client) else for(var/sample in signal.data["spans"]) if(sample == SPAN_COMMAND) - signal.data["name"] = "" - signal.data["spans"] = list() - Compiler.Run(signal) - for(var/S in signal.data["spans"]) - if(S == SPAN_COMMAND) - SSachievements.unlock_achievement(/datum/achievement/Poly_loud, user.client) + SSachievements.unlock_achievement(/datum/achievement/engineering/Poly_loud, user.client) + break // Not having this break leaves us open to a potential DoS attack. return compileerrors //end-NTSL diff --git a/yogstation/code/modules/mob/living/emote.dm b/yogstation/code/modules/mob/living/emote.dm index ee6e02e506e4..1f3d9c7a0098 100644 --- a/yogstation/code/modules/mob/living/emote.dm +++ b/yogstation/code/modules/mob/living/emote.dm @@ -74,3 +74,4 @@ var/light_dab_speed = rand(3,7) H.DabAnimation(angle = light_dab_angle , speed = light_dab_speed) H.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5) + SSachievements.unlock_achievement(/datum/achievement/dab,H.client) diff --git a/yogstation/code/modules/power/singularity/particle_accelerator/particle_control.dm b/yogstation/code/modules/power/singularity/particle_accelerator/particle_control.dm index 64b7b68c32d4..0ec34ca74ed2 100644 --- a/yogstation/code/modules/power/singularity/particle_accelerator/particle_control.dm +++ b/yogstation/code/modules/power/singularity/particle_accelerator/particle_control.dm @@ -5,7 +5,7 @@ if(obj_flags & EMAGGED) return to_chat(user, "The laws of physics no longer apply in the future, god help you...") - SSachievements.unlock_achievement(/datum/achievement/pa_emag, user.client) + SSachievements.unlock_achievement(/datum/achievement/engineering/pa_emag, user.client) do_sparks(5, 0, src) obj_flags |= EMAGGED