diff --git a/code/_onclick/hud/action_button.dm b/code/_onclick/hud/action_button.dm index fd7abb1257f..9afcfeaf73e 100644 --- a/code/_onclick/hud/action_button.dm +++ b/code/_onclick/hud/action_button.dm @@ -43,13 +43,11 @@ else icon_state = "bg_default" UpdateIcon() - return /obj/screen/movable/action_button/hide_toggle/proc/UpdateIcon() cut_overlays() var/image/img = image(icon, src, hidden ? "show" : "hide") add_overlay(img) - return /obj/screen/movable/action_button/MouseEntered(location,control,params) diff --git a/code/controllers/subsystem/augury.dm b/code/controllers/subsystem/augury.dm new file mode 100644 index 00000000000..1aed514f37e --- /dev/null +++ b/code/controllers/subsystem/augury.dm @@ -0,0 +1,74 @@ +var/datum/subsystem/augury/SSaugury + +/datum/subsystem/augury + name = "Augury" + flags = SS_NO_INIT + + var/list/watchers = list() + var/list/doombringers = list() + + var/list/observers_given_action = list() + +/datum/subsystem/augury/New() + NEW_SS_GLOBAL(SSaugury) + +/datum/subsystem/augury/stat_entry(msg) + ..("W:[watchers.len]|D:[doombringers.len]") + +/datum/subsystem/augury/proc/register_doom(atom/A, severity) + doombringers[A] = severity + +/datum/subsystem/augury/fire() + var/biggest_doom = null + var/biggest_threat = null + + for(var/d in doombringers) + if(!d || qdeleted(d)) + doombringers -= d + continue + var/threat = doombringers[d] + if((biggest_threat == null) || (biggest_threat < threat)) + biggest_doom = d + biggest_threat = threat + + if(doombringers.len) + for(var/i in player_list) + if(isobserver(i) && (!(observers_given_action[i]))) + var/datum/action/innate/augury/A = new + A.Grant(i) + observers_given_action[i] = TRUE + + for(var/w in watchers) + if(!w) + watchers -= w + continue + var/mob/dead/observer/O = w + if(O.orbiting) + continue + else if(biggest_doom) + addtimer(O, "orbit", 0, FALSE, biggest_doom) + +/datum/action/innate/augury + name = "Auto Follow Debris" + icon_icon = 'icons/obj/meteor.dmi' + button_icon_state = "flaming" + +/datum/action/innate/augury/Activate() + SSaugury.watchers[owner] = TRUE + owner << "You are now auto-following debris." + active = TRUE + UpdateButtonIcon() + +/datum/action/innate/augury/Deactivate() + SSaugury.watchers -= owner + owner << "You are no longer auto-following \ + debris." + active = FALSE + UpdateButtonIcon() + +/datum/action/innate/augury/UpdateButtonIcon() + ..() + if(active) + button.icon_state = "bg_default_on" + else + button.icon_state = background_icon_state diff --git a/code/datums/action.dm b/code/datums/action.dm index dd04d7e95a3..2498f4d7c5c 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -11,8 +11,10 @@ var/processing = 0 var/obj/screen/movable/action_button/button = null var/button_icon = 'icons/mob/actions.dmi' - var/button_icon_state = "default" var/background_icon_state = "bg_default" + + var/icon_icon = 'icons/mob/actions.dmi' + var/button_icon_state = "default" var/mob/owner /datum/action/New(Target) @@ -88,9 +90,9 @@ /datum/action/proc/ApplyIcon(obj/screen/movable/action_button/current_button) current_button.cut_overlays() - if(button_icon && button_icon_state) + if(icon_icon && button_icon_state) var/image/img - img = image(button_icon, current_button, button_icon_state) + img = image(icon_icon, current_button, button_icon_state) img.pixel_x = 0 img.pixel_y = 0 current_button.add_overlay(img) diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm index ad6679ea9bc..3a90b3499d8 100644 --- a/code/game/gamemodes/meteor/meteors.dm +++ b/code/game/gamemodes/meteor/meteors.dm @@ -1,3 +1,4 @@ +#define DEFAULT_METEOR_LIFETIME 1800 /var/const/meteor_wave_delay = 625 //minimum wait between waves in tenths of seconds //set to at least 100 unless you want evarr ruining every round @@ -39,7 +40,8 @@ var/obj/effect/meteor/M = new Me(pickedstart) M.dest = pickedgoal M.z_original = 1 - addtimer(GLOBAL_PROC, "walk_towards", 0, FALSE, M, M.dest, 1) + spawn(0) + walk_towards(M, M.dest, 1) /proc/spaceDebrisStartLoc(startSide, Z) var/starty @@ -57,8 +59,7 @@ if(WEST) starty = rand((TRANSITIONEDGE+1), world.maxy-(TRANSITIONEDGE+1)) startx = (TRANSITIONEDGE+1) - var/turf/T = locate(startx, starty, Z) - return T + . = locate(startx, starty, Z) /proc/spaceDebrisFinishLoc(startSide, Z) var/endy @@ -76,8 +77,7 @@ if(WEST) endy = rand(TRANSITIONEDGE,world.maxy-TRANSITIONEDGE) endx = world.maxx-TRANSITIONEDGE - var/turf/T = locate(endx, endy, Z) - return T + . = locate(endx, endy, Z) /////////////////////// //The meteor effect @@ -97,6 +97,8 @@ var/heavy = 0 var/meteorsound = 'sound/effects/meteorimpact.ogg' var/z_original = 1 + var/threat = 0 // used for determining which meteors are most interesting + var/lifetime = DEFAULT_METEOR_LIFETIME var/list/meteordrop = list(/obj/item/weapon/ore/iron) var/dropamt = 2 @@ -117,11 +119,14 @@ /obj/effect/meteor/Destroy() walk(src,0) //this cancels the walk_towards() proc - return ..() + . = ..() /obj/effect/meteor/New() ..() + if(SSaugury) + SSaugury.register_doom(src, threat) SpinAnimation() + QDEL_IN(src, lifetime) /obj/effect/meteor/Bump(atom/A) if(A) @@ -149,7 +154,7 @@ hits-- if(hits <= 0) make_debris() - meteor_effect(heavy) + meteor_effect() qdel(src) /obj/effect/meteor/ex_act() @@ -160,16 +165,18 @@ make_debris() qdel(src) else - return ..() + . = ..() /obj/effect/meteor/proc/make_debris() for(var/throws = dropamt, throws > 0, throws--) var/thing_to_spawn = pick(meteordrop) new thing_to_spawn(get_turf(src)) -/obj/effect/meteor/proc/meteor_effect(sound=1) - if(sound) +/obj/effect/meteor/proc/meteor_effect() + if(heavy) for(var/mob/M in player_list) + if((M.orbiting) && (SSaugury.watchers[M])) + continue var/turf/T = get_turf(M) if(!T || T.z != src.z) continue @@ -190,14 +197,16 @@ hitpwr = 3 meteorsound = 'sound/weapons/Gunshot_smg.ogg' meteordrop = list(/obj/item/weapon/ore/glass) + threat = 1 //Medium-sized /obj/effect/meteor/medium name = "meteor" dropamt = 3 + threat = 5 /obj/effect/meteor/medium/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 0, 1, 2, 3, 0) //Large-sized @@ -207,9 +216,10 @@ hits = 6 heavy = 1 dropamt = 4 + threat = 10 /obj/effect/meteor/big/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 1, 2, 3, 4, 0) //Flaming meteor @@ -220,9 +230,10 @@ heavy = 1 meteorsound = 'sound/effects/bamf.ogg' meteordrop = list(/obj/item/weapon/ore/plasma) + threat = 20 /obj/effect/meteor/flaming/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 1, 2, 3, 4, 0, 0, 5) //Radiation meteor @@ -231,10 +242,11 @@ icon_state = "glowing" heavy = 1 meteordrop = list(/obj/item/weapon/ore/uranium) + threat = 15 /obj/effect/meteor/irradiated/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 0, 0, 4, 3, 0) new /obj/effect/decal/cleanable/greenglow(get_turf(src)) radiation_pulse(get_turf(src), 2, 5, 50, 1) @@ -249,6 +261,7 @@ meteorsound = 'sound/effects/blobattack.ogg' meteordrop = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/human, /obj/item/weapon/reagent_containers/food/snacks/meat/slab/human/mutant, /obj/item/organ/heart, /obj/item/organ/lungs, /obj/item/organ/tongue, /obj/item/organ/appendix/) var/meteorgibs = /obj/effect/gibspawner/generic + threat = 2 /obj/effect/meteor/meaty/New() for(var/path in meteordrop) @@ -269,7 +282,7 @@ /obj/effect/meteor/meaty/ram_turf(turf/T) if(!istype(T, /turf/open/space)) - new /obj/effect/decal/cleanable/blood (T) + new /obj/effect/decal/cleanable/blood(T) /obj/effect/meteor/meaty/Bump(atom/A) A.ex_act(hitpwr) @@ -287,21 +300,28 @@ /obj/effect/meteor/meaty/xeno/ram_turf(turf/T) if(!istype(T, /turf/open/space)) - new /obj/effect/decal/cleanable/xenoblood (T) + new /obj/effect/decal/cleanable/xenoblood(T) //Station buster Tunguska /obj/effect/meteor/tunguska name = "tunguska meteor" icon_state = "flaming" - desc = "Your life briefly passes before your eyes the moment you lay them on this monstruosity" + desc = "Your life briefly passes before your eyes the moment you lay \ + them on this monstrosity." hits = 30 hitpwr = 1 heavy = 1 meteorsound = 'sound/effects/bamf.ogg' meteordrop = list(/obj/item/weapon/ore/plasma) + threat = 50 + +/obj/effect/meteor/tunguska/Move() + . = ..() + if(.) + PoolOrNew(/obj/effect/overlay/temp/revenant, get_turf(src)) /obj/effect/meteor/tunguska/meteor_effect() - ..(heavy) + ..() explosion(src.loc, 5, 10, 15, 20, 0) /obj/effect/meteor/tunguska/Bump() @@ -324,8 +344,10 @@ heavy = 1 dropamt = 1 meteordrop = list(/obj/item/clothing/head/hardhat/pumpkinhead, /obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin) + threat = 100 /obj/effect/meteor/pumpkin/New() ..() meteorsound = pick('sound/hallucinations/im_here1.ogg','sound/hallucinations/im_here2.ogg') ////////////////////////// +#undef DEFAULT_METEOR_LIFETIME diff --git a/code/modules/events/dust.dm b/code/modules/events/dust.dm index 6a9685186d9..61a792384c5 100644 --- a/code/modules/events/dust.dm +++ b/code/modules/events/dust.dm @@ -1,21 +1,15 @@ -/datum/round_event_control/meteor_wave/dust +/datum/round_event_control/space_dust name = "Minor Space Dust" - typepath = /datum/round_event/meteor_wave/dust + typepath = /datum/round_event/space_dust weight = 200 max_occurrences = 1000 earliest_start = 0 alertadmins = 0 - -/datum/round_event/meteor_wave/dust + +/datum/round_event/space_dust startWhen = 1 endWhen = 2 announceWhen = 0 -/datum/round_event/meteor_wave/dust/announce() - return - -/datum/round_event/meteor_wave/dust/start() +/datum/round_event/space_dust/start() spawn_meteors(1, meteorsC) - -/datum/round_event/meteor_wave/dust/tick() - return diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod.dm index eb5d3223d5c..5495c652189 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod.dm @@ -38,6 +38,8 @@ In my current plan for it, 'solid' will be defined as anything with density == 1 /obj/effect/immovablerod/New(atom/start, atom/end) ..() + if(SSaugury) + SSaugury.register_doom(src, 2000) z_original = z destination = end notify_ghosts("\A [src] is inbound!", diff --git a/code/modules/events/major_dust.dm b/code/modules/events/major_dust.dm new file mode 100644 index 00000000000..678a419670e --- /dev/null +++ b/code/modules/events/major_dust.dm @@ -0,0 +1,19 @@ +/datum/round_event_control/meteor_wave/major_dust + name = "Major Space Dust" + typepath = /datum/round_event/meteor_wave/major_dust + weight = 30 + +/datum/round_event/meteor_wave/major_dust + wave_name = "space dust" + +/datum/round_event/meteor_wave/major_dust/announce() + var/reason = pick( + "The station is passing through a debris cloud, expect minor damage \ + to external fittings and fixtures.", + "Nanotrasen Superweapons Division is testing a new prototype \ + [pick("field","projection","nova","super-colliding","reactive")] \ + [pick("cannon","artillery","tank","cruiser","\[REDACTED\]")], \ + some mild debris is expected.", + "A neighbouring station is throwing rocks at you. (Perhaps they've \ + grown tired of your messages.)") + priority_announce(pick(reason), "Collision Alert") diff --git a/code/modules/events/meateor_wave.dm b/code/modules/events/meateor_wave.dm index fa26633e90f..204d901a3c3 100644 --- a/code/modules/events/meateor_wave.dm +++ b/code/modules/events/meateor_wave.dm @@ -1,12 +1,11 @@ /datum/round_event_control/meteor_wave/meaty - name = "Meaty Ore Wave" + name = "Meteor Wave: Meaty" typepath = /datum/round_event/meteor_wave/meaty - weight = 1 + weight = 2 max_occurrences = 1 +/datum/round_event/meteor_wave/meaty + wave_name = "meaty" + /datum/round_event/meteor_wave/meaty/announce() priority_announce("Meaty ores have been detected on collision course with the station.", "Oh crap, get the mop.",'sound/AI/meteors.ogg') - -/datum/round_event/meteor_wave/meaty/tick() - if(IsMultiple(activeFor, 3)) - spawn_meteors(5, meteorsB) //meteor list types defined in gamemode/meteor/meteors.dm \ No newline at end of file diff --git a/code/modules/events/meteor_wave.dm b/code/modules/events/meteor_wave.dm index b670df5bdf2..786ab768d38 100644 --- a/code/modules/events/meteor_wave.dm +++ b/code/modules/events/meteor_wave.dm @@ -1,5 +1,7 @@ +// Normal strength + /datum/round_event_control/meteor_wave - name = "Meteor Wave" + name = "Meteor Wave: Normal" typepath = /datum/round_event/meteor_wave weight = 5 min_players = 5 @@ -10,25 +12,57 @@ endWhen = 66 announceWhen = 1 var/list/wave_type + var/wave_name = "normal" /datum/round_event/meteor_wave/New() ..() - random_wave_type() + if(!wave_type) + determine_wave_type() -/datum/round_event/meteor_wave/proc/random_wave_type() - var/picked_wave = pickweight(list("normal" = 50, "threatening" = 40, "catastrophic" = 10)) - switch(picked_wave) +/datum/round_event/meteor_wave/proc/determine_wave_type() + if(!wave_name) + wave_name = pickweight(list( + "normal" = 50, + "threatening" = 40, + "catastrophic" = 10)) + switch(wave_name) if("normal") wave_type = meteors_normal if("threatening") wave_type = meteors_threatening if("catastrophic") wave_type = meteors_catastrophic + if("meaty") + wave_type = meteorsB + if("space dust") + wave_type = meteorsC + else + WARNING("Wave name of [wave_name] not recognised.") + kill() /datum/round_event/meteor_wave/announce() priority_announce("Meteors have been detected on collision course with the station.", "Meteor Alert", 'sound/AI/meteors.ogg') - /datum/round_event/meteor_wave/tick() if(IsMultiple(activeFor, 3)) spawn_meteors(5, wave_type) //meteor list types defined in gamemode/meteor/meteors.dm + +/datum/round_event_control/meteor_wave/threatening + name = "Meteor Wave: Threatening" + typepath = /datum/round_event/meteor_wave/threatening + weight = 4 + min_players = 5 + max_occurrences = 3 + +/datum/round_event/meteor_wave/threatening + wave_name = "threatening" + +/datum/round_event_control/meteor_wave/catastrophic + name = "Meteor Wave: Catastrophic" + typepath = /datum/round_event/meteor_wave/catastrophic + weight = 1 + min_players = 5 + max_occurrences = 3 + +/datum/round_event/meteor_wave/catastrophic + wave_name = "catastrophic" diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 6d41c309c92..ac9b1fdffb1 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -487,11 +487,10 @@ if(3) return if(2) - if (prob(20)) + if(prob(20)) src.gets_dug() if(1) src.gets_dug() - return /turf/open/floor/plating/asteroid/attackby(obj/item/weapon/W, mob/user, params) //note that this proc does not call ..() diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index 7ea02593ac8..abe9e6335e9 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -57,10 +57,10 @@ var/list/image/ghost_images_simple = list() //this is a list of all ghost images /mob/dead/observer/New(mob/body) verbs += /mob/dead/observer/proc/dead_tele - + if(global.cross_allowed) verbs += /mob/dead/observer/proc/server_hop - + ghostimage = image(src.icon,src,src.icon_state) if(icon_state in ghost_forms_with_directions_list) ghostimage_default = image(src.icon,src,src.icon_state + "_nodir") @@ -563,7 +563,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp set desc= "Jump to the other server" if (alert(src, "Jump to server running at [global.cross_address]?", "Server Hop", "Yes", "No") != "Yes") return 0 - if (client && global.cross_allowed) + if (client && global.cross_allowed) src << "Sending you to [global.cross_address]." winset(src, null, "command=.options") //other wise the user never knows if byond is downloading resources client << link(global.cross_address) diff --git a/tgstation.dme b/tgstation.dme index 57a8652b793..74a3db9c8d3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -133,6 +133,7 @@ #include "code\controllers\subsystem.dm" #include "code\controllers\subsystem\air.dm" #include "code\controllers\subsystem\assets.dm" +#include "code\controllers\subsystem\augury.dm" #include "code\controllers\subsystem\diseases.dm" #include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\fastprocess.dm" @@ -1079,6 +1080,7 @@ #include "code\modules\events\immovable_rod.dm" #include "code\modules\events\ion_storm.dm" #include "code\modules\events\mass_hallucination.dm" +#include "code\modules\events\major_dust.dm" #include "code\modules\events\meateor_wave.dm" #include "code\modules\events\meteor_wave.dm" #include "code\modules\events\operative.dm"