diff --git a/code/WorkInProgress/virus2/base.dm b/code/WorkInProgress/virus2/base.dm index 7950389ad32..3d8954fc996 100644 --- a/code/WorkInProgress/virus2/base.dm +++ b/code/WorkInProgress/virus2/base.dm @@ -235,7 +235,6 @@ proc/airborne_can_reach(turf/source, turf/target) if(prob(1)) majormutate() if(mob.reagents.has_reagent("spaceacillin")) - mob.reagents.remove_reagent("spaceacillin",0.3) return if(mob.reagents.has_reagent("virusfood")) mob.reagents.remove_reagent("virusfood",0.1) @@ -599,4 +598,4 @@ proc/airborne_can_reach(turf/source, turf/target) getrandomeffect_greater() /proc/dprob(var/p) - return(prob(sqrt(p)) && prob(sqrt(p))) \ No newline at end of file + return(prob(sqrt(p)) && prob(sqrt(p))) diff --git a/code/ZAS/Airflow.dm b/code/ZAS/Airflow.dm index 58d28f0aee5..47e47b4baa7 100644 --- a/code/ZAS/Airflow.dm +++ b/code/ZAS/Airflow.dm @@ -255,7 +255,7 @@ proc/play_wind_sound(var/turf/random_border, var/n) if(61 to 1000000) windsound = pick('sound/effects/wind/wind_5_1.ogg') - playsound(random_border, windsound, 50, 1, 1) + playsound(random_border, windsound, 100, 1, 1) atom/movable var/tmp/turf/airflow_dest diff --git a/code/ZAS/ZAS_Zones.dm b/code/ZAS/ZAS_Zones.dm index 4b8e7a01ef3..b3fd2704ae3 100644 --- a/code/ZAS/ZAS_Zones.dm +++ b/code/ZAS/ZAS_Zones.dm @@ -258,7 +258,7 @@ var/list/sharing_lookup_table = list(0.06, 0.11, 0.15, 0.18, 0.20, 0.21) proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles) //Shares a specific ratio of gas between mixtures using simple weighted averages. var - ratio = 0.41 + ratio = 0.99 size = max(1,A.group_multiplier) share_size = max(1,B.group_multiplier) @@ -342,7 +342,7 @@ proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles) var // Depressurize very, very fast(it's fine since many rooms are internally multiple zones) - ratio = 0.81 + ratio = 0.99 old_pressure = A.return_pressure() diff --git a/code/game/gamemodes/events.dm b/code/game/gamemodes/events.dm index facc5f88eb6..f2952026556 100644 --- a/code/game/gamemodes/events.dm +++ b/code/game/gamemodes/events.dm @@ -10,24 +10,56 @@ dust_swarm("weak")*/ if (!event) //CARN: checks to see if random events are enabled. - if(config.allow_random_events && prob(eventchance)) - event() - hadevent = 1 + if(config.allow_random_events) + hadevent = event() else Holiday_Random_Event() else event = 0 sleep(2400) +// Doesn't necessarily trigger an event, but might. Returns 1 if it did. /proc/event() event = 1 - var/eventNumbersToPickFrom = list(1,2,4,5,6,7,8,9,10,11,12,13,14, 15) //so ninjas don't cause "empty" events. + var/minutes_passed = world.time/600 - if((world.time/10)>=3600 && toggle_space_ninja && !sent_ninja_to_station)//If an hour has passed, relatively speaking. Also, if ninjas are allowed to spawn and if there is not already a ninja for the round. - eventNumbersToPickFrom += 3 - switch(pick(eventNumbersToPickFrom)) - if(1) + var/engineer_count = number_active_with_role("Engineer") + var/security_count = number_active_with_role("Security") + var/medical_count = number_active_with_role("Medical") + var/AI_count = number_active_with_role("AI") + + // Maps event names to event chances + // For each chance, 100 represents "normal likelihood", anything below 100 is "reduced likelihood", anything above 100 is "increased likelihood" + var/list/possibleEvents = list() + + // Check for additional possible events + possibleEvents["Carp"] = 50 + 50 * engineer_count + possibleEvents["Lights"] = 100 + possibleEvents["Communications"] = 50 + 50 * AI_count + possibleEvents["Alien"] = 10 + if(AI_count >= 1) + possibleEvents["Ion Storm"] = AI_count * 50 + engineer_count * 10 + if(engineer_count >= 1 && minutes_passed >= 30) // Give engineers time to set up engine + possibleEvents["Meteor"] = 80 * engineer_count + possibleEvents["Blob"] = 30 * engineer_count + possibleEvents["Spacevine"] = 30 * engineer_count + if(medical_count >= 1) + possibleEvents["Radiation"] = medical_count * 100 + possibleEvents["Virus"] = medical_count * 50 + possibleEvents["Appendicitis"] = medical_count * 50 + if(security_count >= 1) + possibleEvents["Prison Break"] = security_count * 50 + + var/picked_event = pick(possibleEvents) + var/chance = possibleEvents[picked_event] + + // Trigger the event based on how likely it currently is. + if(!prob(chance * eventchance)) + return 0 + + switch(picked_event) + if("Meteor") command_alert("Meteors have been detected on collision course with the station.", "Meteor Alert") world << sound('sound/AI/meteors.ogg') spawn(100) @@ -36,67 +68,31 @@ spawn(700) meteor_wave() spawn_meteors() - - /*if(2) - command_alert("Gravitational anomalies detected on the station. There is no additional data.", "Anomaly Alert") - world << sound('sound/AI/granomalies.ogg') - var/turf/T = pick(blobstart) - var/obj/effect/bhole/bh = new /obj/effect/bhole( T.loc, 30 ) - spawn(rand(50, 300)) - del(bh)*/ - /* - if(3) //Leaving the code in so someone can try and delag it, but this event can no longer occur randomly, per SoS's request. --NEO - command_alert("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert") - world << sound('sound/AI/spanomalies.ogg') - var/list/turfs = new - var/turf/picked - for(var/turf/simulated/floor/T in world) - if(T.z == 1) - turfs += T - for(var/turf/simulated/floor/T in turfs) - if(prob(20)) - spawn(50+rand(0,3000)) - picked = pick(turfs) - var/obj/effect/portal/P = new /obj/effect/portal( T ) - P.target = picked - P.creator = null - P.icon = 'icons/obj/objects.dmi' - P.failchance = 0 - P.icon_state = "anom" - P.name = "wormhole" - spawn(rand(300,600)) - del(P) - */ - if(3) - if((world.time/10)>=3600 && toggle_space_ninja && !sent_ninja_to_station)//If an hour has passed, relatively speaking. Also, if ninjas are allowed to spawn and if there is not already a ninja for the round. - space_ninja_arrival()//Handled in space_ninja.dm. Doesn't announce arrival, all sneaky-like. - if(4) + if("Blob") mini_blob_event() - - if(5) + if("Radiation") high_radiation_event() - if(6) + if("Virus") viral_outbreak() - if(7) - if(prob(10)) - alien_infestation() - if(8) + if("Alien") + alien_infestation() + if("Prison Break") prison_break() - if(9) + if("Carp") carp_migration() - /*if(10) - immovablerod()*/ - if(11) + if("Lights") lightsout(1,2) - if(12) + if("Appendicitis") appendicitis() - if(13) + if("Ion Storm") IonStorm() - if(14) + if("Spacevine") spacevine_infestation() - if(15) + if("Communications") communications_blackout() + return 1 + /proc/communications_blackout(var/silent = 1) if(!silent) @@ -204,61 +200,16 @@ break /proc/viral_outbreak(var/virus = null) -// command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") -// world << sound('sound/AI/outbreak7.ogg') - var/virus_type - if(!virus) - virus_type = pick(/datum/disease/dnaspread,/datum/disease/flu,/datum/disease/cold,/datum/disease/brainrot,/datum/disease/magnitis,/datum/disease/pierrot_throat) - else - switch(virus) - if("fake gbs") - virus_type = /datum/disease/fake_gbs - if("gbs") - virus_type = /datum/disease/gbs - if("magnitis") - virus_type = /datum/disease/magnitis - if("rhumba beat") - virus_type = /datum/disease/rhumba_beat - if("brain rot") - virus_type = /datum/disease/brainrot - if("cold") - virus_type = /datum/disease/cold - if("retrovirus") - virus_type = /datum/disease/dnaspread - if("flu") - virus_type = /datum/disease/flu -// if("t-virus") -// virus_type = /datum/disease/t_virus - if("pierrot's throat") - virus_type = /datum/disease/pierrot_throat - for(var/mob/living/carbon/human/H in living_mob_list) - - var/foundAlready = 0 // don't infect someone that already has the virus - for(var/datum/disease/D in H.viruses) - foundAlready = 1 - if(H.stat == 2 || foundAlready) + for(var/mob/living/carbon/human/H in world) + if((H.virus2) || (H.stat == 2) || prob(30)) continue - if(virus_type == /datum/disease/dnaspread) //Dnaspread needs strain_data set to work. - if((!H.dna) || (H.sdisabilities & BLIND)) //A blindness disease would be the worst. - continue - var/datum/disease/dnaspread/D = new - D.strain_data["name"] = H.real_name - D.strain_data["UI"] = H.dna.uni_identity - D.strain_data["SE"] = H.dna.struc_enzymes - D.carrier = 1 - D.holder = H - D.affected_mob = H - H.viruses += D - break - else - var/datum/disease/D = new virus_type - D.carrier = 1 - D.holder = H - D.affected_mob = H - H.viruses += D - break - spawn(rand(1500, 3000)) //Delayed announcements to keep the crew on their toes. + infect_mob_random_lesser(H) + break + + command_alert("An unknown virus has been detected onboard the ship.", "Virus Alert") + + spawn(rand(0, 3000)) //Delayed announcements to keep the crew on their toes. command_alert("Confirmed outbreak of level 7 viral biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert") world << sound('sound/AI/outbreak7.ogg') @@ -524,4 +475,39 @@ Would like to add a law like "Law x is _______" where x = a number, and _____ is world << "Finished processing FIREDOORS. Processed: [firedoornum]" world << "Ion Storm Main Done" - */ \ No newline at end of file + */ + +// Returns how many characters are currently active(not logged out, not AFK for more than 10 minutes) +// with a specific role. +// Note that this isn't sorted by department, because e.g. having a roboticist shouldn't make meteors spawn. +proc/number_active_with_role(role) + var/count = 0 + for(var/mob/M in player_list) + if(!M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive + continue + switch(role) + if("Engineer") + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "engineering robot module") + count++ + if(M.mind.assigned_role in list("Chief Engineer", "Station Engineer")) + count++ + if("Medical") + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "medical robot module") + count++ + if(M.mind.assigned_role in list("Chief Medical Officer", "Medical Doctor")) + count++ + if("Security") + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "security robot module") + count++ + if(M.mind.assigned_role in security_positions) + count++ + if("Scientist") + if(M.mind.assigned_role in list("Research Director", "Scientist")) + count++ + if("AI") + if(M.mind.assigned_role == "AI") + count++ + if("Cyborg") + if(M.mind.assigned_role == "Cyborg") + count++ + return count diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index 40acaf36c90..610307dde8e 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -378,6 +378,84 @@ datum/objective/survive return 0 return 1 +// Similar to the anti-rev objective, but for traitors +datum/objective/brig + var/already_completed = 0 + + find_target() + ..() + if(target && target.current) + explanation_text = "Have [target.current.real_name], the [target.assigned_role] brigged for 10 minutes." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Have [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role] brigged for 10 minutes." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(already_completed) + return 1 + + if(target && target.current) + if(target.current.stat == DEAD) + return 0 + // Make the actual required time a bit shorter than the official time + if(target.is_brigged(10 * 60 * 5)) + already_completed = 1 + return 1 + return 0 + return 0 + +// Harm a crew member, making an example of them +datum/objective/harm + var/already_completed = 0 + + find_target() + ..() + if(target && target.current) + explanation_text = "Make an example of [target.current.real_name], the [target.assigned_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." + else + explanation_text = "Free Objective" + return target + + + find_target_by_role(role, role_type=0) + ..(role, role_type) + if(target && target.current) + explanation_text = "Make an example of [target.current.real_name], the [!role_type ? target.assigned_role : target.special_role]. Break one of their bones, detach one of their limbs or disfigure their face. Make sure they're alive when you do it." + else + explanation_text = "Free Objective" + return target + + check_completion() + if(already_completed) + return 1 + + if(target && target.current && istype(target.current, /mob/living/carbon/human)) + if(target.current.stat == DEAD) + return 0 + + var/mob/living/carbon/human/H = target.current + for(var/datum/organ/external/E in H.organs) + if(E.status & ORGAN_BROKEN) + already_completed = 1 + return 1 + if(E.status & ORGAN_DESTROYED && !E.amputated) + already_completed = 1 + return 1 + + var/datum/organ/external/head/head = H.get_organ("head") + if(head.disfigured) + return 1 + return 0 + datum/objective/nuclear explanation_text = "Destroy the station with a nuclear device." diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index 9e7483e96d2..d94b99026bf 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -94,11 +94,21 @@ else switch(rand(1,100)) - if(1 to 50) + if(1 to 33) var/datum/objective/assassinate/kill_objective = new kill_objective.owner = traitor kill_objective.find_target() traitor.objectives += kill_objective + if(34 to 50) + var/datum/objective/brig/brig_objective = new + brig_objective.owner = traitor + brig_objective.find_target() + traitor.objectives += brig_objective + if(51 to 66) + var/datum/objective/harm/harm_objective = new + harm_objective.owner = traitor + harm_objective.find_target() + traitor.objectives += harm_objective else var/datum/objective/steal/steal_objective = new steal_objective.owner = traitor @@ -273,4 +283,4 @@ else traitor_mob << "Unfortunately, the Syndicate did not provide you with a code response." traitor_mob << "Use the code words in the order provided, during regular conversation, to identify other agents. Proceed with caution, however, as everyone is a potential foe." - //End code phrase. \ No newline at end of file + //End code phrase. diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index 0dbd1dd272c..07df4849d87 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -274,7 +274,7 @@ if(E.name == "l_hand" || E.name == "l_arm") if(hand && equipped()) drop_item() - emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!") + emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!") var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() spark_system.set_up(5, 0, src) spark_system.attach(src) @@ -284,7 +284,7 @@ else if(E.name == "r_hand" || E.name == "r_arm") if(!hand && equipped()) drop_item() - emote("custom v drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!") + emote("me", 1, "drops what they were holding, their [E.display_name?"[E.display_name]":"[E]"] malfunctioning!") var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() spark_system.set_up(5, 0, src) spark_system.attach(src) @@ -799,6 +799,10 @@ var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. if(adjusted_pressure > HAZARD_HIGH_PRESSURE) adjustBruteLoss( min( (adjusted_pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT , MAX_PRESSURE_DAMAGE) ) + else if(pressure <= 50) + var/adjusted_pressure = calculate_affecting_pressure(pressure) //Returns how much pressure actually affects the mob. + if(adjusted_pressure < 50) + adjustBruteLoss( (50 - adjusted_pressure) / 50 ) return /* diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 355ee6a84d9..f5e80c183f8 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -1552,8 +1552,8 @@ datum color = "#C8A5DC" // rgb: 200, 165, 220 on_mob_life(var/mob/living/M as mob)//no more mr. panacea + // Only consume 0.1 units per tick holder.remove_reagent(src.id, 0.2) - ..() return carpotoxin @@ -2147,6 +2147,7 @@ datum if(!M) M = holder.my_atom M.druggy = max(M.druggy, 30) if(!data) data = 1 + switch(data) if(1 to 5) if (!M.stuttering) M.stuttering = 1