diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm index 218fdbc5a7a..29a93ae94f9 100644 --- a/code/__DEFINES/subsystems.dm +++ b/code/__DEFINES/subsystems.dm @@ -61,6 +61,7 @@ #define INIT_ORDER_LANGUAGE 6 #define INIT_ORDER_MACHINES 5 #define INIT_ORDER_CIRCUIT 4 +#define INIT_ORDER_HOLIDAY 3 #define INIT_ORDER_ALARMS 2 #define INIT_ORDER_TIMER 1 #define INIT_ORDER_DEFAULT 0 diff --git a/code/__HELPERS/names.dm b/code/__HELPERS/names.dm index 930a8ee9de5..5b90cda376e 100644 --- a/code/__HELPERS/names.dm +++ b/code/__HELPERS/names.dm @@ -49,10 +49,10 @@ var/religion_name = null name = "" // Prefix - for(var/holiday_name in holiday_master.holidays) + for(var/holiday_name in SSholiday.holidays) if(holiday_name == "Friday the 13th") random = 13 - var/datum/holiday/holiday = holiday_master.holidays[holiday_name] + var/datum/holiday/holiday = SSholiday.holidays[holiday_name] name = holiday.getStationPrefix() //get normal name if(!name) diff --git a/code/_globalvars/misc.dm b/code/_globalvars/misc.dm index f0bb813a336..0b8c8d58a95 100644 --- a/code/_globalvars/misc.dm +++ b/code/_globalvars/misc.dm @@ -1,8 +1,6 @@ var/global/obj/effect/overlay/plmaster = null var/global/obj/effect/overlay/slmaster = null -// Event Manager, the manager for events. -var/datum/event_manager/event_manager = new() // Announcer intercom, because too much stuff creates an intercom for one message then hard del()s it. var/global/obj/item/radio/intercom/global_announcer = create_global_announcer() var/global/obj/item/radio/intercom/command/command_announcer = create_command_announcer() diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm index 24a2442faeb..e3d423130e5 100644 --- a/code/_onclick/hud/_defines.dm +++ b/code/_onclick/hud/_defines.dm @@ -154,6 +154,12 @@ #define ui_bot_radio "EAST-1:28,SOUTH:7" #define ui_bot_pull "EAST-2:26,SOUTH:7" +//Ghosts +#define ui_ghost_jumptomob "SOUTH:6,CENTER-2:24" +#define ui_ghost_orbit "SOUTH:6,CENTER-1:24" +#define ui_ghost_reenter_corpse "SOUTH:6,CENTER:24" +#define ui_ghost_teleport "SOUTH:6,CENTER+1:24" + //HUD styles. Please ensure HUD_VERSIONS is the same as the maximum index. Index order defines how they are cycled in F12. #define HUD_STYLE_STANDARD 1 #define HUD_STYLE_REDUCED 2 diff --git a/code/_onclick/hud/ghost.dm b/code/_onclick/hud/ghost.dm new file mode 100644 index 00000000000..4e92395f4cc --- /dev/null +++ b/code/_onclick/hud/ghost.dm @@ -0,0 +1,61 @@ +/mob/dead/observer/create_mob_hud() + if(client && !hud_used) + hud_used = new /datum/hud/ghost(src) + +/obj/screen/ghost + icon = 'icons/mob/screen_ghost.dmi' + +/obj/screen/ghost/MouseEntered() + flick(icon_state + "_anim", src) + +/obj/screen/ghost/jumptomob + name = "Jump to mob" + icon_state = "jumptomob" + +/obj/screen/ghost/jumptomob/Click() + var/mob/dead/observer/G = usr + G.jumptomob() + +/obj/screen/ghost/orbit + name = "Orbit" + icon_state = "orbit" + +/obj/screen/ghost/orbit/Click() + var/mob/dead/observer/G = usr + G.follow() + +/obj/screen/ghost/reenter_corpse + name = "Re-enter corpse" + icon_state = "reenter_corpse" + +/obj/screen/ghost/reenter_corpse/Click() + var/mob/dead/observer/G = usr + G.reenter_corpse() + +/obj/screen/ghost/teleport + name = "Teleport" + icon_state = "teleport" + +/obj/screen/ghost/teleport/Click() + var/mob/dead/observer/G = usr + G.dead_tele() + +/datum/hud/ghost/New(mob/owner) + ..() + var/obj/screen/using + + using = new /obj/screen/ghost/jumptomob() + using.screen_loc = ui_ghost_jumptomob + static_inventory += using + + using = new /obj/screen/ghost/orbit() + using.screen_loc = ui_ghost_orbit + static_inventory += using + + using = new /obj/screen/ghost/reenter_corpse() + using.screen_loc = ui_ghost_reenter_corpse + static_inventory += using + + using = new /obj/screen/ghost/teleport() + using.screen_loc = ui_ghost_teleport + static_inventory += using diff --git a/code/controllers/Processes/event.dm b/code/controllers/Processes/event.dm index 42e8c4bcc1d..ee3e1310f1c 100644 --- a/code/controllers/Processes/event.dm +++ b/code/controllers/Processes/event.dm @@ -1,18 +1,3 @@ -/datum/controller/process/event/setup() - name = "event" - schedule_interval = 20 // every 2 seconds - if(!holiday_master) - holiday_master = new - holiday_master.Setup() - -/datum/controller/process/event/doWork() - event_manager.process() - holiday_master.process() - -///////// -//Holiday controller -///////// - var/global/datum/controller/holiday/holiday_master //This has to be defined before world. /datum/controller/holiday diff --git a/code/modules/events/event_manager.dm b/code/controllers/subsystem/events.dm similarity index 73% rename from code/modules/events/event_manager.dm rename to code/controllers/subsystem/events.dm index 1545ddbbdf0..7d0b20b129d 100644 --- a/code/modules/events/event_manager.dm +++ b/code/controllers/subsystem/events.dm @@ -1,19 +1,25 @@ -/datum/event_manager +SUBSYSTEM_DEF(events) + name = "Events" + init_order = INIT_ORDER_EVENTS + runlevels = RUNLEVEL_GAME + // Report events at the end of the rouund + var/report_at_round_end = 0 + + // UI vars var/window_x = 700 var/window_y = 600 - var/report_at_round_end = 0 var/table_options = " align='center'" var/head_options = " style='font-weight:bold;'" var/row_options1 = " width='85px'" var/row_options2 = " width='260px'" var/row_options3 = " width='150px'" + + // Event vars var/datum/event_container/selected_event_container = null - - var/list/datum/event/active_events = list() - var/list/datum/event/finished_events = list() - - var/list/datum/event/allEvents - var/list/datum/event_container/event_containers = list( + var/list/active_events = list() + var/list/finished_events = list() + var/list/allEvents + var/list/event_containers = list( EVENT_LEVEL_MUNDANE = new/datum/event_container/mundane, EVENT_LEVEL_MODERATE = new/datum/event_container/moderate, EVENT_LEVEL_MAJOR = new/datum/event_container/major @@ -21,18 +27,19 @@ var/datum/event_meta/new_event = new -/datum/event_manager/New() +/datum/controller/subsystem/events/Initialize() allEvents = subtypesof(/datum/event) + ..() -/datum/event_manager/proc/process() - for(var/datum/event/E in event_manager.active_events) +/datum/controller/subsystem/events/fire() + for(var/datum/event/E in active_events) E.process() for(var/i = EVENT_LEVEL_MUNDANE to EVENT_LEVEL_MAJOR) var/list/datum/event_container/EC = event_containers[i] EC.process() -/datum/event_manager/proc/event_complete(var/datum/event/E) +/datum/controller/subsystem/events/proc/event_complete(var/datum/event/E) if(!E.event_meta) // datum/event is used here and there for random reasons, maintaining "backwards compatibility" log_debug("Event of '[E.type]' with missing meta-data has completed.") return @@ -57,11 +64,11 @@ log_debug("Event '[EM.name]' has completed at [station_time_timestamp()].") -/datum/event_manager/proc/delay_events(var/severity, var/delay) +/datum/controller/subsystem/events/proc/delay_events(var/severity, var/delay) var/list/datum/event_container/EC = event_containers[severity] EC.next_event_time += delay -/datum/event_manager/proc/Interact(var/mob/living/user) +/datum/controller/subsystem/events/proc/Interact(var/mob/living/user) var/html = GetInteractWindow() @@ -69,7 +76,7 @@ popup.set_content(html) popup.open() -/datum/event_manager/proc/RoundEnd() +/datum/controller/subsystem/events/proc/RoundEnd() if(!report_at_round_end) return @@ -89,7 +96,7 @@ to_chat(world, message) -/datum/event_manager/proc/GetInteractWindow() +/datum/controller/subsystem/events/proc/GetInteractWindow() var/html = "Refresh" if(selected_event_container) @@ -197,7 +204,7 @@ return html -/datum/event_manager/Topic(href, href_list) +/datum/controller/subsystem/events/Topic(href, href_list) if(..()) return @@ -290,123 +297,3 @@ EC.next_event = null Interact(usr) - -/client/proc/forceEvent(var/type in event_manager.allEvents) - set name = "Trigger Event (Debug Only)" - set category = "Debug" - - if(!holder) - return - - if(ispath(type)) - new type(new /datum/event_meta(EVENT_LEVEL_MAJOR)) - message_admins("[key_name_admin(usr)] has triggered an event. ([type])", 1) - -/client/proc/event_manager_panel() - set name = "Event Manager Panel" - set category = "Event" - if(event_manager) - event_manager.Interact(usr) - feedback_add_details("admin_verb","EMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! - return - -/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in! - var/area/candidate = null - - var/list/safe_areas = list( - /area/turret_protected/ai, - /area/turret_protected/ai_upload, - /area/engine, - /area/solar, - /area/holodeck, - /area/shuttle/arrival, - /area/shuttle/escape, - /area/shuttle/escape_pod1/station, - /area/shuttle/escape_pod2/station, - /area/shuttle/escape_pod3/station, - /area/shuttle/escape_pod5/station, - /area/shuttle/specops/station, - /area/shuttle/prison/station, - /area/shuttle/administration/station - ) - - //These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up. - var/list/danger_areas = list( - /area/engine/break_room, - /area/engine/chiefs_office) - - var/list/event_areas = list() - - for(var/areapath in the_station_areas) - event_areas += typesof(areapath) - for(var/areapath in safe_areas) - event_areas -= typesof(areapath) - for(var/areapath in danger_areas) - event_areas += typesof(areapath) - - while(event_areas.len > 0) - var/list/event_turfs = null - candidate = locate(pick_n_take(event_areas)) - event_turfs = get_area_turfs(candidate) - if(event_turfs.len > 0) - break - - return candidate - -/datum/event/proc/num_players() - var/players = 0 - for(var/mob/living/carbon/human/P in GLOB.player_list) - if(P.client) - players++ - return players - -// 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() - var/list/active_with_role = list() - active_with_role["Engineer"] = 0 - active_with_role["Medical"] = 0 - active_with_role["Security"] = 0 - active_with_role["Scientist"] = 0 - active_with_role["AI"] = 0 - active_with_role["Cyborg"] = 0 - active_with_role["Janitor"] = 0 - active_with_role["Botanist"] = 0 - active_with_role["Any"] = GLOB.player_list.len - - for(var/mob/M in GLOB.player_list) - if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive - continue - - if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "engineering robot module") - active_with_role["Engineer"]++ - if(M.mind.assigned_role in list("Chief Engineer", "Station Engineer")) - active_with_role["Engineer"]++ - - if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "medical robot module") - active_with_role["Medical"]++ - if(M.mind.assigned_role in list("Chief Medical Officer", "Medical Doctor")) - active_with_role["Medical"]++ - - if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "security robot module") - active_with_role["Security"]++ - if(M.mind.assigned_role in security_positions) - active_with_role["Security"]++ - - if(M.mind.assigned_role in list("Research Director", "Scientist")) - active_with_role["Scientist"]++ - - if(M.mind.assigned_role == "AI") - active_with_role["AI"]++ - - if(M.mind.assigned_role == "Cyborg") - active_with_role["Cyborg"]++ - - if(M.mind.assigned_role == "Janitor") - active_with_role["Janitor"]++ - - if(M.mind.assigned_role == "Botanist") - active_with_role["Botanist"]++ - - return active_with_role diff --git a/code/controllers/subsystem/holiday.dm b/code/controllers/subsystem/holiday.dm new file mode 100644 index 00000000000..a5eb957a80f --- /dev/null +++ b/code/controllers/subsystem/holiday.dm @@ -0,0 +1,31 @@ +SUBSYSTEM_DEF(holiday) + name = "Holiday" + init_order = INIT_ORDER_HOLIDAY // 3 + flags = SS_NO_FIRE + var/list/holidays + +/datum/controller/subsystem/holiday/Initialize(start_timeofday) + if(!config.allow_holidays) + return ..() //Holiday stuff was not enabled in the config! + + var/YY = text2num(time2text(world.timeofday, "YY")) // get the current year + var/MM = text2num(time2text(world.timeofday, "MM")) // get the current month + var/DD = text2num(time2text(world.timeofday, "DD")) // get the current day + + for(var/H in subtypesof(/datum/holiday)) + var/datum/holiday/holiday = new H() + if(holiday.shouldCelebrate(DD, MM, YY)) + holiday.celebrate() + if(!holidays) + holidays = list() + holidays[holiday.name] = holiday + + if(holidays) + holidays = shuffle(holidays) + world.update_status() + for(var/datum/holiday/H in holidays) + if(H.eventChance) + if(prob(H.eventChance)) + H.handle_event() + + ..() \ No newline at end of file diff --git a/code/controllers/subsystem/tickets/mentor_tickets.dm b/code/controllers/subsystem/tickets/mentor_tickets.dm index 708bc682634..32f7faf4abb 100644 --- a/code/controllers/subsystem/tickets/mentor_tickets.dm +++ b/code/controllers/subsystem/tickets/mentor_tickets.dm @@ -9,7 +9,7 @@ GLOBAL_REAL(SSmentor_tickets, /datum/controller/subsystem/tickets/mentor_tickets ticket_system_name = "Mentor Tickets" ticket_name = "Mentor Ticket" span_text = "" - close_rights = R_MENTOR + close_rights = R_MENTOR | R_ADMIN /datum/controller/subsystem/tickets/mentor_tickets/message_staff(var/msg) message_mentorTicket(msg) diff --git a/code/controllers/verbs.dm b/code/controllers/verbs.dm index 98b1f89f4ab..eeef65bd2e2 100644 --- a/code/controllers/verbs.dm +++ b/code/controllers/verbs.dm @@ -60,7 +60,7 @@ debug_variables(cameranet) feedback_add_details("admin_verb","DCameras") if("Event") - debug_variables(event_manager) + debug_variables(SSevents) feedback_add_details("admin_verb","DEvent") if("Alarm") debug_variables(SSalarms) diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 674557bc839..6fdb8a359c2 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -621,6 +621,33 @@ src.give_spell(M) href_list["datumrefresh"] = href_list["give_spell"] + else if(href_list["givemartialart"]) + if(!check_rights(R_SERVER|R_EVENT)) return + + var/mob/living/carbon/C = locateUID(href_list["givemartialart"]) + if(!istype(C)) + to_chat(usr, "This can only be done to instances of type /mob/living/carbon") + return + + var/list/artpaths = subtypesof(/datum/martial_art) + var/list/artnames = list() + for(var/i in artpaths) + var/datum/martial_art/M = i + artnames[initial(M.name)] = M + + var/result = input(usr, "Choose the martial art to teach", "JUDO CHOP") as null|anything in artnames + if(!usr) + return + if(QDELETED(C)) + to_chat(usr, "Mob doesn't exist anymore") + return + + if(result) + var/chosenart = artnames[result] + var/datum/martial_art/MA = new chosenart + MA.teach(C) + + href_list["datumrefresh"] = href_list["givemartialart"] else if(href_list["give_disease"]) if(!check_rights(R_SERVER|R_EVENT)) return diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 024b2a924cf..0a1aa19bcf7 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -642,15 +642,22 @@ var/list/blood_splatter_icons = list() update_icons() //apply the now updated overlays to the mob -/atom/proc/add_vomit_floor(mob/living/carbon/M as mob, var/toxvomit = 0) - if( istype(src, /turf/simulated) ) - var/obj/effect/decal/cleanable/vomit/this = new /obj/effect/decal/cleanable/vomit(src) +/atom/proc/add_vomit_floor(toxvomit = 0, green = FALSE) + playsound(src, 'sound/effects/splat.ogg', 50, 1) + if(!isspaceturf(src)) + var/type = green ? /obj/effect/decal/cleanable/vomit/green : /obj/effect/decal/cleanable/vomit + var/vomit_reagent = green ? "green_vomit" : "vomit" + for(var/obj/effect/decal/cleanable/vomit/V in get_turf(src)) + if(V.type == type) + V.reagents.add_reagent(vomit_reagent, 5) + return + + var/obj/effect/decal/cleanable/vomit/this = new type(src) // Make toxins vomit look different if(toxvomit) this.icon_state = "vomittox_[pick(1,4)]" - /atom/proc/get_global_map_pos() if(!islist(global_map) || isemptylist(global_map)) return var/cur_x = null diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm index ca1dffbfa74..7ec1ec3b3f0 100644 --- a/code/game/gamemodes/blob/overmind.dm +++ b/code/game/gamemodes/blob/overmind.dm @@ -98,7 +98,7 @@ if(isovermind(M) || isobserver(M)) M.show_message(rendered, 2) -/mob/camera/blob/emote(var/act,var/m_type=1,var/message = null) +/mob/camera/blob/emote(act, m_type = 1, message = null, force) return /mob/camera/blob/blob_act() diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm index c2268063822..a68f2db4e53 100644 --- a/code/game/gamemodes/gameticker.dm +++ b/code/game/gamemodes/gameticker.dm @@ -172,10 +172,10 @@ var/round_start_time = 0 to_chat(world, "Enjoy the game!") world << sound('sound/AI/welcome.ogg')// Skie - if(holiday_master.holidays) + if(SSholiday.holidays) to_chat(world, "and...") - for(var/holidayname in holiday_master.holidays) - var/datum/holiday/holiday = holiday_master.holidays[holidayname] + for(var/holidayname in SSholiday.holidays) + var/datum/holiday/holiday = SSholiday.holidays[holidayname] to_chat(world, "

[holiday.greet()]

") spawn(0) // Forking dynamic room selection @@ -506,7 +506,7 @@ var/round_start_time = 0 mode.declare_station_goal_completion() //Ask the event manager to print round end information - event_manager.RoundEnd() + SSevents.RoundEnd() return 1 diff --git a/code/game/gamemodes/miniantags/borer/borer.dm b/code/game/gamemodes/miniantags/borer/borer.dm index 34d1f64f0d0..fa797ac929b 100644 --- a/code/game/gamemodes/miniantags/borer/borer.dm +++ b/code/game/gamemodes/miniantags/borer/borer.dm @@ -32,7 +32,7 @@ return FALSE return B.host.say_understands(other, speaking) -/mob/living/captive_brain/emote(var/message) +/mob/living/captive_brain/emote(act, m_type = 1, message = null, force) return /mob/living/captive_brain/resist() @@ -157,7 +157,7 @@ if(!istype(S.speaking, /datum/language/corticalborer) && loc == host && !talk_inside_host) to_chat(src, "You've disabled audible speech while inside a host! Re-enable it under the borer tab, or stick to borer communications.") return - + . = ..() /mob/living/simple_animal/borer/verb/Communicate() @@ -475,7 +475,7 @@ set category = "Borer" set name = "Dominate Victim" set desc = "Freeze the limbs of a potential host with supernatural fear." - + if(world.time - used_dominate < 150) to_chat(src, "You cannot use that ability again so soon.") return @@ -487,22 +487,22 @@ if(stat) to_chat(src, "You cannot do that in your current state.") return - + if(attempting_to_dominate) to_chat(src, "You're already targeting someone!") return - + var/list/choices = list() for(var/mob/living/carbon/C in view(3,src)) if(C.stat != DEAD) choices += C - + if(world.time - used_dominate < 300) to_chat(src, "You cannot use that ability again so soon.") return - + attempting_to_dominate = TRUE - + var/mob/living/carbon/M = input(src,"Who do you wish to dominate?") in null|choices if(!M) @@ -519,8 +519,8 @@ if(incapacitated()) attempting_to_dominate = FALSE - return - + return + if(get_dist(src, M) > 7) //to avoid people remotely doing from across the map etc, 7 is the default view range to_chat(src, "You're too far away!") attempting_to_dominate = FALSE @@ -760,10 +760,9 @@ to_chat(src, "Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body.") visible_message("[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!") B.chemicals -= 100 - - new /obj/effect/decal/cleanable/vomit(get_turf(src)) - playsound(loc, 'sound/effects/splat.ogg', 50, 1) - new /mob/living/simple_animal/borer(get_turf(src),B.generation + 1) + var/turf/T = get_turf(src) + T.add_vomit_floor() + new /mob/living/simple_animal/borer(T, B.generation + 1) else to_chat(src, "You need 100 chemicals to reproduce!") diff --git a/code/game/gamemodes/shadowling/shadowling_abilities.dm b/code/game/gamemodes/shadowling/shadowling_abilities.dm index 30c79798b2f..ea95f62af57 100644 --- a/code/game/gamemodes/shadowling/shadowling_abilities.dm +++ b/code/game/gamemodes/shadowling/shadowling_abilities.dm @@ -335,7 +335,7 @@ include_user = 1 var/blind_smoke_acquired var/screech_acquired - var/drainLifeAcquired + var/nullChargeAcquired var/reviveThrallAcquired action_icon_state = "collective_mind" @@ -370,10 +370,11 @@ It will create a choking cloud that will blind any non-thralls who enter.
") target.mind.AddSpell(new /obj/effect/proc_holder/spell/targeted/blindness_smoke(null)) - if(thralls >= CEILING(7 * ticker.mode.thrall_ratio, 1) && !drainLifeAcquired) - drainLifeAcquired = 1 - to_chat(target, "The power of your thralls has granted you the Drain Life ability. You can now drain the health of nearby humans to heal yourself.") - target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/drainLife(null)) + if(thralls >= CEILING(7 * ticker.mode.thrall_ratio, 1) && !nullChargeAcquired) + nullChargeAcquired = 1 + to_chat(user, "The power of your thralls has granted you the Null Charge ability. This ability will drain an APC's contents to the void, preventing it from recharging \ + or sending power until repaired.") + target.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/null_charge(null)) if(thralls >= CEILING(9 * ticker.mode.thrall_ratio, 1) && !reviveThrallAcquired) reviveThrallAcquired = 1 @@ -491,45 +492,57 @@ for(var/obj/structure/window/W in T.contents) W.take_damage(rand(80, 100)) -/obj/effect/proc_holder/spell/aoe_turf/drainLife - name = "Drain Life" - desc = "Damages nearby humans, draining their life and healing your own wounds." +/obj/effect/proc_holder/spell/aoe_turf/null_charge + name = "Null Charge" + desc = "Empties an APC, preventing it from recharging until fixed." panel = "Shadowling Abilities" - range = 3 - charge_max = 100 - clothes_req = 0 - var/targetsDrained - var/list/nearbyTargets - action_icon_state = "drain_life" + charge_max = 600 + clothes_req = FALSE + action_icon_state = "null_charge" -/obj/effect/proc_holder/spell/aoe_turf/drainLife/cast(list/targets, mob/user = usr) +/obj/effect/proc_holder/spell/aoe_turf/null_charge/cast(mob/user = usr) if(!shadowling_check(user)) charge_counter = charge_max return - var/mob/living/carbon/human/U = usr - targetsDrained = 0 - nearbyTargets = list() - for(var/turf/T in targets) - for(var/mob/living/carbon/M in T.contents) - if(M == src) - continue - targetsDrained++ - nearbyTargets.Add(M) - if(!targetsDrained) + + var/list/local_objs = view(1, user) + var/obj/machinery/power/apc/target_apc + for(var/object in local_objs) + if(istype(object, /obj/machinery/power/apc)) + target_apc = object + break + + if(!target_apc) + to_chat(user, "You must stand next to an APC to drain it!") charge_counter = charge_max - to_chat(U, "There were no nearby humans for you to drain.") return - for(var/mob/living/carbon/M in nearbyTargets) - U.heal_organ_damage(10, 10) - U.adjustToxLoss(-10) - U.adjustOxyLoss(-10) - U.adjustStaminaLoss(-20) - U.AdjustWeakened(-1) - U.AdjustStunned(-1) - M.adjustOxyLoss(20) - M.adjustStaminaLoss(20) - to_chat(M, "You feel a wave of exhaustion and a curious draining sensation directed towards [U]!") - to_chat(U, "You draw life from those around you to heal your wounds.") + + if(target_apc.cell?.charge == 0) + to_chat(user, "APC must have a power to drain!") + charge_counter = charge_max + return + + target_apc.operating = 0 + target_apc.update() + target_apc.update_icon() + target_apc.visible_message("The [target_apc] flickers and begins to grow dark.") + + to_chat(user, "You dim the APC's screen and carefully begin siphoning its power into the void.") + if(!do_after(user, 200, target=target_apc)) + //Whoops! The APC's powers back on + to_chat(user, "Your concentration breaks and the APC suddenly repowers!") + target_apc.operating = 1 + target_apc.update() + target_apc.update_icon() + target_apc.visible_message("The [target_apc] begins glowing brightly!") + else + //We did it! + to_chat(user, "You sent the APC's power to the void while overloading all it's lights!") + target_apc.cell?.charge = 0 //Sent to the shadow realm + target_apc.chargemode = 0 //Won't recharge either until an someone hits the button + target_apc.charging = 0 + target_apc.null_charge() + target_apc.update_icon() diff --git a/code/game/gamemodes/vampire/vampire_powers.dm b/code/game/gamemodes/vampire/vampire_powers.dm index f78520ac7eb..5e7b8f9a237 100644 --- a/code/game/gamemodes/vampire/vampire_powers.dm +++ b/code/game/gamemodes/vampire/vampire_powers.dm @@ -226,6 +226,7 @@ target.Weaken(5) target.stuttering = 20 to_chat(target, "You are blinded by [user]'s glare.") + add_attack_logs(user, target, "(Vampire) Glared at") /obj/effect/proc_holder/spell/vampire/self/shapeshift name = "Shapeshift (50)" diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 66cdff69b3f..0a1340d885b 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -469,6 +469,24 @@ dat += "Already cast!
" return dat +/datum/spellbook_entry/summon/ghosts + name = "Summon Ghosts" + desc = "Spook the crew out by making them see dead people. Be warned, ghosts are capricious and occasionally vindicative, and some will use their incredibly minor abilities to frustrate you." + cost = 0 + +/datum/spellbook_entry/summon/ghosts/IsAvailible() + if(!ticker.mode) + return FALSE + else + return TRUE + +/datum/spellbook_entry/summon/ghosts/Buy(mob/living/carbon/human/user, obj/item/spellbook/book) + new /datum/event/wizard/ghost() + active = TRUE + to_chat(user, "You have cast summon ghosts!") + playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, 1) + return TRUE + /datum/spellbook_entry/summon/guns name = "Summon Guns" category = "Rituals" diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index 6d360a2ddb3..54841a78a08 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -470,7 +470,7 @@ M.nutrition -= 50 //lose a lot of food var/turf/location = usr.loc if(istype(location, /turf/simulated)) - location.add_vomit_floor(src, 1) + location.add_vomit_floor(TRUE) if(ORION_TRAIL_FLUX) if(prob(75)) M.Weaken(3) diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 9a7c3f0e27c..88dc4ed6542 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -14,7 +14,7 @@ flags = DROPDEL -/obj/item/implant/proc/trigger(emote, mob/source) +/obj/item/implant/proc/trigger(emote, mob/source, force) return /obj/item/implant/proc/activate() diff --git a/code/game/objects/items/weapons/implants/implant_chem.dm b/code/game/objects/items/weapons/implants/implant_chem.dm index 5f0fea79da9..f1c4dd4126b 100644 --- a/code/game/objects/items/weapons/implants/implant_chem.dm +++ b/code/game/objects/items/weapons/implants/implant_chem.dm @@ -33,8 +33,8 @@ -/obj/item/implant/chem/trigger(emote, mob/source) - if(emote == "deathgasp") +/obj/item/implant/chem/trigger(emote, mob/source, force) + if(force && emote == "deathgasp") activate(reagents.total_volume) /obj/item/implant/chem/activate(cause) diff --git a/code/game/objects/items/weapons/implants/implant_explosive.dm b/code/game/objects/items/weapons/implants/implant_explosive.dm index 30113ea4e96..f37e148bee6 100644 --- a/code/game/objects/items/weapons/implants/implant_explosive.dm +++ b/code/game/objects/items/weapons/implants/implant_explosive.dm @@ -20,8 +20,8 @@ "} return dat -/obj/item/implant/explosive/trigger(emote, mob/source) - if(emote == "deathgasp") +/obj/item/implant/explosive/trigger(emote, mob/source, force) + if(force && emote == "deathgasp") activate("death") /obj/item/implant/explosive/activate(cause) @@ -148,8 +148,8 @@ "} return dat -/obj/item/implant/dust/trigger(emote, mob/source) - if(emote == "deathgasp") +/obj/item/implant/dust/trigger(emote, mob/source, force) + if(force && emote == "deathgasp") activate("death") /obj/item/implant/dust/activate(cause) diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm index e7078cb6877..6b4072a800b 100644 --- a/code/modules/admin/admin_verbs.dm +++ b/code/modules/admin/admin_verbs.dm @@ -224,6 +224,8 @@ var/list/admin_verbs_snpc = list( var/list/admin_verbs_ticket = list( /client/proc/openAdminTicketUI, /client/proc/toggleticketlogs, + /client/proc/openMentorTicketUI, + /client/proc/toggleMentorTicketLogs, /client/proc/resolveAllAdminTickets, /client/proc/resolveAllMentorTickets ) @@ -926,10 +928,10 @@ var/list/admin_verbs_ticket = list( to_chat(usr, "You now will get admin log messages.") /client/proc/toggleMentorTicketLogs() - set name = "Toggle Mentor Ticket Messgaes" + set name = "Toggle Mentor Ticket Messages" set category = "Preferences" - if(!check_rights(R_MENTOR)) + if(!check_rights(R_MENTOR|R_ADMIN)) return prefs.toggles ^= CHAT_NO_MENTORTICKETLOGS diff --git a/code/modules/admin/tickets/mentorticketsverbs.dm b/code/modules/admin/tickets/mentorticketsverbs.dm index 765a1afb9da..1122b770107 100644 --- a/code/modules/admin/tickets/mentorticketsverbs.dm +++ b/code/modules/admin/tickets/mentorticketsverbs.dm @@ -5,7 +5,7 @@ set name = "Open Mentor Ticket Interface" set category = "Admin" - if(!holder || !check_rights(R_MENTOR)) + if(!holder || !check_rights(R_MENTOR|R_ADMIN)) return SSmentor_tickets.showUI(usr) diff --git a/code/modules/events/event.dm b/code/modules/events/event.dm index 0f5c43059e8..a5e07840d34 100644 --- a/code/modules/events/event.dm +++ b/code/modules/events/event.dm @@ -137,12 +137,12 @@ end() endedAt = world.time - event_manager.active_events -= src - event_manager.event_complete(src) + SSevents.active_events -= src + SSevents.event_complete(src) /datum/event/New(var/datum/event_meta/EM) // event needs to be responsible for this, as stuff like APLUs currently make their own events for curious reasons - event_manager.active_events += src + SSevents.active_events += src if(!EM) EM = new /datum/event_meta(EVENT_LEVEL_MAJOR, "Unknown, Most likely admin called", src.type) diff --git a/code/modules/events/event_procs.dm b/code/modules/events/event_procs.dm new file mode 100644 index 00000000000..02ae1454597 --- /dev/null +++ b/code/modules/events/event_procs.dm @@ -0,0 +1,120 @@ + +/client/proc/forceEvent(var/type in SSevents.allEvents) + set name = "Trigger Event (Debug Only)" + set category = "Debug" + + if(!holder) + return + + if(ispath(type)) + new type(new /datum/event_meta(EVENT_LEVEL_MAJOR)) + message_admins("[key_name_admin(usr)] has triggered an event. ([type])", 1) + +/client/proc/event_manager_panel() + set name = "Event Manager Panel" + set category = "Event" + if(SSevents) + SSevents.Interact(usr) + feedback_add_details("admin_verb","EMP") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + return + +/proc/findEventArea() //Here's a nice proc to use to find an area for your event to land in! + var/area/candidate = null + + var/list/safe_areas = list( + /area/turret_protected/ai, + /area/turret_protected/ai_upload, + /area/engine, + /area/solar, + /area/holodeck, + /area/shuttle/arrival, + /area/shuttle/escape, + /area/shuttle/escape_pod1/station, + /area/shuttle/escape_pod2/station, + /area/shuttle/escape_pod3/station, + /area/shuttle/escape_pod5/station, + /area/shuttle/specops/station, + /area/shuttle/prison/station, + /area/shuttle/administration/station + ) + + //These are needed because /area/engine has to be removed from the list, but we still want these areas to get fucked up. + var/list/danger_areas = list( + /area/engine/break_room, + /area/engine/chiefs_office) + + var/list/event_areas = list() + + for(var/areapath in the_station_areas) + event_areas += typesof(areapath) + for(var/areapath in safe_areas) + event_areas -= typesof(areapath) + for(var/areapath in danger_areas) + event_areas += typesof(areapath) + + while(event_areas.len > 0) + var/list/event_turfs = null + candidate = locate(pick_n_take(event_areas)) + event_turfs = get_area_turfs(candidate) + if(event_turfs.len > 0) + break + + return candidate + +// 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() + var/list/active_with_role = list() + active_with_role["Engineer"] = 0 + active_with_role["Medical"] = 0 + active_with_role["Security"] = 0 + active_with_role["Scientist"] = 0 + active_with_role["AI"] = 0 + active_with_role["Cyborg"] = 0 + active_with_role["Janitor"] = 0 + active_with_role["Botanist"] = 0 + active_with_role["Any"] = GLOB.player_list.len + + for(var/mob/M in GLOB.player_list) + if(!M.mind || !M.client || M.client.inactivity > 10 * 10 * 60) // longer than 10 minutes AFK counts them as inactive + continue + + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "engineering robot module") + active_with_role["Engineer"]++ + if(M.mind.assigned_role in list("Chief Engineer", "Station Engineer")) + active_with_role["Engineer"]++ + + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "medical robot module") + active_with_role["Medical"]++ + if(M.mind.assigned_role in list("Chief Medical Officer", "Medical Doctor")) + active_with_role["Medical"]++ + + if(istype(M, /mob/living/silicon/robot) && M:module && M:module.name == "security robot module") + active_with_role["Security"]++ + if(M.mind.assigned_role in security_positions) + active_with_role["Security"]++ + + if(M.mind.assigned_role in list("Research Director", "Scientist")) + active_with_role["Scientist"]++ + + if(M.mind.assigned_role == "AI") + active_with_role["AI"]++ + + if(M.mind.assigned_role == "Cyborg") + active_with_role["Cyborg"]++ + + if(M.mind.assigned_role == "Janitor") + active_with_role["Janitor"]++ + + if(M.mind.assigned_role == "Botanist") + active_with_role["Botanist"]++ + + return active_with_role + +/datum/event/proc/num_players() + var/players = 0 + for(var/mob/living/carbon/human/P in GLOB.player_list) + if(P.client) + players++ + return players diff --git a/code/modules/events/false_alarm.dm b/code/modules/events/false_alarm.dm index e63805d6a1d..a0aa17596fd 100644 --- a/code/modules/events/false_alarm.dm +++ b/code/modules/events/false_alarm.dm @@ -4,7 +4,7 @@ /datum/event/falsealarm/announce() var/weight = pickweight(list(EVENT_LEVEL_MUNDANE = 60, EVENT_LEVEL_MODERATE = 30, EVENT_LEVEL_MAJOR = 10)) - var/datum/event_container/container = event_manager.event_containers[weight] + var/datum/event_container/container = SSevents.event_containers[weight] var/datum/event/E = container.acquire_event() var/datum/event/Event = new E message_admins("False Alarm: [Event]") diff --git a/code/modules/events/wizard/ghost.dm b/code/modules/events/wizard/ghost.dm new file mode 100644 index 00000000000..11529e3080d --- /dev/null +++ b/code/modules/events/wizard/ghost.dm @@ -0,0 +1,5 @@ +/datum/event/wizard/ghost //The spook is real + +/datum/event/wizard/ghost/start() + var/msg = "You suddenly feel extremely obvious..." + set_observer_default_invisibility(0, msg) diff --git a/code/modules/holiday/holiday.dm b/code/modules/holiday/holiday.dm index 414df7f7589..f87422e2ad1 100644 --- a/code/modules/holiday/holiday.dm +++ b/code/modules/holiday/holiday.dm @@ -345,9 +345,9 @@ if(!istype(H)) return H.celebrate() - if(!holiday_master.holidays) - holiday_master.holidays = list() - holiday_master.holidays[H.name] = H + if(!SSholiday.holidays) + SSholiday.holidays = list() + SSholiday.holidays[H.name] = H //update our hub status world.update_status() diff --git a/code/modules/mining/equipment_locker.dm b/code/modules/mining/equipment_locker.dm index b0eafcbc8bb..38d5436ecfb 100644 --- a/code/modules/mining/equipment_locker.dm +++ b/code/modules/mining/equipment_locker.dm @@ -701,8 +701,7 @@ H.nutrition -= 20 H.adjustToxLoss(-3) var/turf/T = get_turf(H) - T.add_vomit_floor(H) - playsound(H, 'sound/effects/splat.ogg', 50, 1) + T.add_vomit_floor() else visible_message("[src] flickers and fails, due to bluespace interference!") qdel(src) diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm index dfd4e1e3332..db59a79ec21 100644 --- a/code/modules/mob/dead/observer/observer.dm +++ b/code/modules/mob/dead/observer/observer.dm @@ -3,6 +3,8 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for things ghosts should still be able to see when they toggle darkness +GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER) + /mob/dead/observer name = "ghost" desc = "It's a g-g-g-g-ghooooost!" //jinkies! @@ -29,6 +31,8 @@ var/list/image/ghost_darkness_images = list() //this is a list of images for thi var/ghost_orbit = GHOST_ORBIT_CIRCLE /mob/dead/observer/New(var/mob/body=null, var/flags=1) + set_invisibility(GLOB.observer_default_invisibility) + sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF see_invisible = SEE_INVISIBLE_OBSERVER_AI_EYE see_in_dark = 100 @@ -384,7 +388,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp to_chat(usr, "AntagHud Toggled OFF") M.antagHUD = 0 -/mob/dead/observer/proc/dead_tele(A in ghostteleportlocs) +/mob/dead/observer/proc/dead_tele() set category = "Ghost" set name = "Teleport" set desc= "Teleport to a location" @@ -397,6 +401,7 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp spawn(30) usr.verbs += /mob/dead/observer/proc/dead_tele + var/area/A = input("Area to jump to", "BOOYEA") as null|anything in ghostteleportlocs var/area/thearea = ghostteleportlocs[A] if(!thearea) return @@ -410,13 +415,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp usr.forceMove(pick(L)) following = null -/mob/dead/observer/verb/follow(input in getmobs()) +/mob/dead/observer/verb/follow() set category = "Ghost" set name = "Orbit" // "Haunt" set desc = "Follow and orbit a mob." - var/target = getmobs()[input] - if(!target) return + var/list/mobs = getpois(skip_mindless=1) + var/input = input("Please, select a mob!", "Haunt", null, null) as null|anything in mobs + var/mob/target = mobs[input] ManualFollow(target) // This is the ghost's follow verb with an argument @@ -484,24 +490,29 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp update_following() return ..() -/mob/dead/observer/verb/jumptomob(target in getmobs()) //Moves the ghost instead of just changing the ghosts's eye -Nodrak +/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak set category = "Ghost" set name = "Jump to Mob" set desc = "Teleport to a mob" - if(istype(usr, /mob/dead/observer)) //Make sure they're an observer! + if(isobserver(usr)) //Make sure they're an observer! + var/list/dest = list() //List of possible destinations (mobs) + var/target = null //Chosen target. - if(!target)//Make sure we actually have a target + dest += getpois(mobs_only=1) //Fill list, prompt user with list + target = input("Please, select a mob!", "Jump to Mob", null, null) as null|anything in dest + + if(!target) //Make sure we actually have a target return else - var/mob/M = getmobs()[target] //Destination mob + var/mob/M = dest[target] //Destination mob + var/mob/A = src //Source mob var/turf/T = get_turf(M) //Turf of the destination mob if(T && isturf(T)) //Make sure the turf exists, then move the source to that destination. - forceMove(T) - following = null + A.forceMove(T) else - to_chat(src, "This mob is not located in the game world.") + to_chat(A, "This mob is not located in the game world.") /* Now a spell. See spells.dm @@ -742,6 +753,26 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp /mob/dead/observer/is_literate() return TRUE + +/mob/dead/observer/proc/set_invisibility(value) + invisibility = value + if(!value) + set_light(1, 2) + else + set_light(0, 0) + +/mob/dead/observer/vv_edit_var(var_name, var_value) + . = ..() + if(var_name == "invisibility") + set_invisibility(invisibility) // updates light + +/proc/set_observer_default_invisibility(amount, message=null) + for(var/mob/dead/observer/G in GLOB.player_list) + G.set_invisibility(amount) + if(message) + to_chat(G, message) + GLOB.observer_default_invisibility = amount + /mob/dead/observer/proc/open_spawners_menu() set name = "Mob spawners menu" set desc = "See all currently available ghost spawners" diff --git a/code/modules/mob/dead/observer/say.dm b/code/modules/mob/dead/observer/say.dm index ab47a84ee76..41c1d89f603 100644 --- a/code/modules/mob/dead/observer/say.dm +++ b/code/modules/mob/dead/observer/say.dm @@ -17,7 +17,7 @@ . = src.say_dead(message) -/mob/dead/observer/emote(var/act, var/type, var/message) +/mob/dead/observer/emote(act, type, message, force) message = sanitize(copytext(message, 1, MAX_MESSAGE_LEN)) if(!message) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 0ec193c69e8..989decdb395 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -2,15 +2,20 @@ //Emote Cooldown System (it's so simple!) /mob/proc/handle_emote_CD(cooldown = EMOTE_COOLDOWN) - if(emote_cd == 2) return 1 // Cooldown emotes were disabled by an admin, prevent use - if(src.emote_cd == 1) return 1 // Already on CD, prevent use + if(emote_cd == 3) //Spam those emotes + return FALSE + if(emote_cd == 2) // Cooldown emotes were disabled by an admin, prevent use + return TRUE + if(emote_cd == 1) // Already on CD, prevent use + return TRUE - src.emote_cd = 1 // Starting cooldown + emote_cd = TRUE // Starting cooldown spawn(cooldown) - if(emote_cd == 2) return 1 // Don't reset if cooldown emotes were disabled by an admin during the cooldown - src.emote_cd = 0 // Cooldown complete, ready for more! + if(emote_cd == 2) + return TRUE // Don't reset if cooldown emotes were disabled by an admin during the cooldown + emote_cd = FALSE // Cooldown complete, ready for more! + return FALSE // Proceed with emote - return 0 // Proceed with emote //--FalseIncarnate /mob/proc/handle_emote_param(var/target, var/not_self, var/vicinity, var/return_mob) //Only returns not null if the target param is valid. diff --git a/code/modules/mob/living/carbon/alien/humanoid/emote.dm b/code/modules/mob/living/carbon/alien/humanoid/emote.dm index f159abebbe4..7412120cff0 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/emote.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/emote.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/alien/humanoid/emote(var/act,var/m_type=1,var/message = null) +/mob/living/carbon/alien/humanoid/emote(act, m_type = 1, message = null, force) var/param = null if(findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) @@ -25,7 +25,7 @@ if("flip") on_CD = handle_emote_CD() - if(on_CD) + if(!force && on_CD == 1) return switch(act) @@ -138,4 +138,4 @@ playsound(src.loc, 'sound/voice/hiss1.ogg', 30, 1, 1) if(act == "gnarl") playsound(src.loc, 'sound/voice/hiss4.ogg', 30, 1, 1) - ..(act, m_type, message) \ No newline at end of file + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/alien/larva/emote.dm b/code/modules/mob/living/carbon/alien/larva/emote.dm index 82ebcf943f6..3b18889176b 100644 --- a/code/modules/mob/living/carbon/alien/larva/emote.dm +++ b/code/modules/mob/living/carbon/alien/larva/emote.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/alien/larva/emote(var/act,var/m_type=1,var/message = null) +/mob/living/carbon/alien/larva/emote(act, m_type = 1, message = null, force) var/param = null if(findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) diff --git a/code/modules/mob/living/carbon/brain/emote.dm b/code/modules/mob/living/carbon/brain/emote.dm index bf7962464da..dd1876e223f 100644 --- a/code/modules/mob/living/carbon/brain/emote.dm +++ b/code/modules/mob/living/carbon/brain/emote.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/brain/emote(var/act,var/m_type=1,var/message = null) +/mob/living/carbon/brain/emote(act,m_type = 1, message = null, force) if(!(container && istype(container, /obj/item/mmi)))//No MMI, no emotes return @@ -48,4 +48,4 @@ to_chat(src, "alarm, alert, notice, flash,blink, whistle, beep, boop") if(message && !stat) - ..(act, m_type, message) \ No newline at end of file + ..() \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 277bbbd8789..77373021727 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -109,7 +109,7 @@ adjustBruteLoss(3) else if(T) - T.add_vomit_floor(src) + T.add_vomit_floor() nutrition -= lost_nutrition if(stun) adjustToxLoss(-3) diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm index 7259a455154..6d245674fd1 100644 --- a/code/modules/mob/living/carbon/human/death.dm +++ b/code/modules/mob/living/carbon/human/death.dm @@ -93,7 +93,7 @@ /mob/living/carbon/human/death(gibbed) if(can_die() && !gibbed && deathgasp_on_death) - emote("deathgasp") //let the world KNOW WE ARE DEAD + emote("deathgasp", force = TRUE) //let the world KNOW WE ARE DEAD // Only execute the below if we successfully died . = ..(gibbed) diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 442d7aaf044..416fd911777 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/human/emote(var/act,var/m_type=1,var/message = null,var/force) +/mob/living/carbon/human/emote(act, m_type = 1, message = null, force) if((stat == DEAD) || (status_flags & FAKEDEATH)) return // No screaming bodies @@ -13,22 +13,22 @@ if(muzzled) var/obj/item/clothing/mask/muzzle/M = wear_mask if(M.mute == MUZZLE_MUTE_NONE) - muzzled = 0 //Not all muzzles block sound + muzzled = FALSE //Not all muzzles block sound if(!can_speak()) - muzzled = 1 + muzzled = TRUE //var/m_type = 1 for(var/obj/item/implant/I in src) if(I.implanted) - I.trigger(act, src) + I.trigger(act, src, force) - var/miming = 0 + var/miming = FALSE if(mind) miming = mind.miming //Emote Cooldown System (it's so simple!) - // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] - var/on_CD = 0 + //handle_emote_CD() located in [code\modules\mob\emote.dm] + var/on_CD = FALSE act = lowertext(act) switch(act) //Cooldown-inducing emotes @@ -61,16 +61,16 @@ else return if("squish", "squishes") - var/found_slime_bodypart = 0 + var/found_slime_bodypart = FALSE if(isslimeperson(src)) //Only Slime People can squish on_CD = handle_emote_CD() //proc located in code\modules\mob\emote.dm' - found_slime_bodypart = 1 + found_slime_bodypart = TRUE else for(var/obj/item/organ/external/L in bodyparts) // if your limbs are squishy you can squish too! if(istype(L.dna.species, /datum/species/slime)) on_CD = handle_emote_CD() - found_slime_bodypart = 1 + found_slime_bodypart = TRUE break if(!found_slime_bodypart) //Everyone else fails, skip the emote attempt @@ -118,9 +118,9 @@ on_CD = handle_emote_CD() //Everything else, including typos of the above emotes else - on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown + on_CD = FALSE //If it doesn't induce the cooldown, we won't check for the cooldown - if(on_CD == 1) // Check if we need to suppress the emote attempt. + if(!force && on_CD == 1) // Check if we need to suppress the emote attempt. return // Suppress emote, you're still cooling off. switch(act) diff --git a/code/modules/mob/living/carbon/slime/emote.dm b/code/modules/mob/living/carbon/slime/emote.dm index a07f1ba3b2e..c938ac17214 100644 --- a/code/modules/mob/living/carbon/slime/emote.dm +++ b/code/modules/mob/living/carbon/slime/emote.dm @@ -1,4 +1,4 @@ -/mob/living/carbon/slime/emote(act, m_type = 1, message = null) +/mob/living/carbon/slime/emote(act, m_type = 1, message = null, force) if(findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) //param = copytext(act, t1 + 1, length(act) + 1) diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm index 003b5c3d4fe..37077881350 100644 --- a/code/modules/mob/living/death.dm +++ b/code/modules/mob/living/death.dm @@ -57,7 +57,7 @@ SetLoseBreath(0) if(!gibbed && deathgasp_on_death) - emote("deathgasp") + emote("deathgasp", force = TRUE) if(mind && suiciding) mind.suicided = TRUE diff --git a/code/modules/mob/living/say.dm b/code/modules/mob/living/say.dm index cf5fff66caa..95b44b15862 100644 --- a/code/modules/mob/living/say.dm +++ b/code/modules/mob/living/say.dm @@ -275,7 +275,7 @@ proc/get_radio_key_from_channel(var/channel) /mob/living/proc/GetVoice() return name -/mob/living/emote(var/act, var/type, var/message) //emote code is terrible, this is so that anything that isn't already snowflaked to shit can call the parent and handle emoting sanely +/mob/living/emote(act, type, message, force) //emote code is terrible, this is so that anything that isn't already snowflaked to shit can call the parent and handle emoting sanely if(client) if(client.prefs.muted & MUTE_IC) to_chat(src, "You cannot speak in IC (Muted).") @@ -284,7 +284,7 @@ proc/get_radio_key_from_channel(var/channel) if(stat) return 0 - if(..(act, type, message)) + if(..()) return 1 if(act && type && message) //parent call @@ -306,7 +306,8 @@ proc/get_radio_key_from_channel(var/channel) return 1 else //everything else failed, emote is probably invalid - if(act == "help") return //except help, because help is handled individually + if(act == "help") + return //except help, because help is handled individually to_chat(src, "Unusable emote '[act]'. Say *help for a list.") /mob/living/whisper(message as text) diff --git a/code/modules/mob/living/silicon/emote.dm b/code/modules/mob/living/silicon/emote.dm index 3385c4ce622..1b1ee4f7f48 100644 --- a/code/modules/mob/living/silicon/emote.dm +++ b/code/modules/mob/living/silicon/emote.dm @@ -1,4 +1,4 @@ -/mob/living/silicon/emote(var/act, var/m_type=1, var/message = null) +/mob/living/silicon/emote(act, m_type=1, message = null, force) var/param = null if(findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) @@ -6,7 +6,7 @@ act = copytext(act, 1, t1) //Emote Cooldown System (it's so simple!) - // proc/handle_emote_CD() located in [code\modules\mob\emote.dm] + //handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 act = lowertext(act) switch(act) @@ -20,7 +20,7 @@ else on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown - if(on_CD == 1) // Check if we need to suppress the emote attempt. + if(!force && on_CD == 1) // Check if we need to suppress the emote attempt. return // Suppress emote, you're still cooling off. //--FalseIncarnate @@ -78,4 +78,4 @@ if("help") to_chat(src, "yes, no, beep, ping, buzz, scream, buzz2") - ..(act, m_type, message) + ..() diff --git a/code/modules/mob/living/silicon/pai/emote.dm b/code/modules/mob/living/silicon/pai/emote.dm deleted file mode 100644 index a418c0972d5..00000000000 --- a/code/modules/mob/living/silicon/pai/emote.dm +++ /dev/null @@ -1,2 +0,0 @@ -/mob/living/silicon/pai/emote(var/act, var/m_type=1, var/message = null) - ..(act, m_type, message) diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm index fec27db5df8..989dcba3783 100644 --- a/code/modules/mob/living/silicon/pai/recruit.dm +++ b/code/modules/mob/living/silicon/pai/recruit.dm @@ -57,12 +57,6 @@ var/datum/paiController/paiController // Global handler for pAI candidates usr << browse(null, "window=findPai") - if(candidate) - if(candidate.key && usr.key && candidate.key != usr.key) - message_admins("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)") - log_debug("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)") - return - if("signup" in href_list) var/mob/dead/observer/O = locate(href_list["signup"]) if(!O) @@ -75,6 +69,11 @@ var/datum/paiController/paiController // Global handler for pAI candidates recruitWindow(O) return + if(candidate) + if(candidate.key && usr.key && candidate.key != usr.key) + message_admins("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)") + log_debug("Warning: possible href exploit by [key_name(usr)] (paiController/Topic, candidate and usr are different mobs)") + return if(href_list["new"]) var/option = href_list["option"] diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index 21a09eed8a8..7402c4a65c9 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -50,7 +50,7 @@ /mob/living/silicon/robot/death(gibbed) if(can_die()) if(!gibbed && deathgasp_on_death) - emote("deathgasp") + emote("deathgasp", force = TRUE) if(module) module.handle_death(gibbed) diff --git a/code/modules/mob/living/silicon/robot/emote.dm b/code/modules/mob/living/silicon/robot/emote.dm index 9c130780d81..bec1e1ae668 100644 --- a/code/modules/mob/living/silicon/robot/emote.dm +++ b/code/modules/mob/living/silicon/robot/emote.dm @@ -1,4 +1,4 @@ -/mob/living/silicon/robot/emote(var/act, var/m_type=1, var/message = null) +/mob/living/silicon/robot/emote(act, m_type=1, message = null, force) var/param = null if(findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) @@ -6,7 +6,7 @@ act = copytext(act, 1, t1) //Emote Cooldown System (it's so simple!) - //proc/handle_emote_CD() located in [code\modules\mob\emote.dm] + //handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 act = lowertext(act) switch(act) @@ -17,7 +17,7 @@ else on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown - if(on_CD == 1) // Check if we need to suppress the emote attempt. + if(!force && on_CD == 1) // Check if we need to suppress the emote attempt. return // Suppress emote, you're still cooling off. //--FalseIncarnate @@ -160,7 +160,7 @@ if("help") to_chat(src, "salute, bow-(none)/mob, clap, flap, aflap, twitch, twitches, nod, deathgasp, glare-(none)/mob, stare-(none)/mob, look,\n law, halt") - ..(act, m_type, message) + ..() /mob/living/silicon/robot/verb/powerwarn() set category = "Robot Commands" diff --git a/code/modules/mob/living/silicon/say.dm b/code/modules/mob/living/silicon/say.dm index 17a7e67adf7..8092947919f 100644 --- a/code/modules/mob/living/silicon/say.dm +++ b/code/modules/mob/living/silicon/say.dm @@ -103,7 +103,7 @@ return return 1 -/mob/living/silicon/ai/emote(var/act, var/type, var/message) +/mob/living/silicon/ai/emote(act, type, message, force) var/obj/machinery/hologram/holopad/T = current if(istype(T) && T.masters[src])//Is the AI using a holopad? src.holopad_emote(message) diff --git a/code/modules/mob/living/simple_animal/bot/emote.dm b/code/modules/mob/living/simple_animal/bot/emote.dm index eb6a18e8657..c59e044cc67 100644 --- a/code/modules/mob/living/simple_animal/bot/emote.dm +++ b/code/modules/mob/living/simple_animal/bot/emote.dm @@ -1,4 +1,4 @@ -/mob/living/simple_animal/bot/emote(act, m_type=1, message = null) +/mob/living/simple_animal/bot/emote(act, m_type = 1, message = null, force) var/param = null if(findtext(act, "-", 1, null)) var/t1 = findtext(act, "-", 1, null) @@ -9,7 +9,7 @@ act = copytext(act,1,length(act)) //Emote Cooldown System (it's so simple!) - //proc/handle_emote_CD() located in [code\modules\mob\emote.dm] + //handle_emote_CD() located in [code\modules\mob\emote.dm] var/on_CD = 0 act = lowertext(act) switch(act) @@ -22,7 +22,7 @@ else on_CD = 0 //If it doesn't induce the cooldown, we won't check for the cooldown - if(on_CD == 1) // Check if we need to suppress the emote attempt. + if(!force && on_CD == 1) // Check if we need to suppress the emote attempt. return // Suppress emote, you're still cooling off. //--FalseIncarnate @@ -71,4 +71,4 @@ if("help") to_chat(src, "scream(s), yes, no, beep, buzz, ping") - ..(act, m_type, message) + ..() diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm index 9532daabab8..38787198a5f 100644 --- a/code/modules/mob/living/simple_animal/friendly/cat.dm +++ b/code/modules/mob/living/simple_animal/friendly/cat.dm @@ -147,7 +147,7 @@ stop_automated_movement = 1 walk_to(src,movement_target,0,3) -/mob/living/simple_animal/pet/cat/emote(act, m_type=1, message = null) +/mob/living/simple_animal/pet/cat/emote(act, m_type = 1, message = null, force) if(stat != CONSCIOUS) return @@ -163,9 +163,9 @@ else on_CD = 0 - if(on_CD == 1) + if(!force && on_CD == 1) return - + switch(act) if("meow") message = "[src] [pick(emote_hear)]!" @@ -225,9 +225,9 @@ maxHealth = 50 harm_intent_damage = 10 butcher_results = list( - /obj/item/organ/internal/brain = 1, - /obj/item/organ/internal/heart = 1, - /obj/item/reagent_containers/food/snacks/birthdaycakeslice = 3, + /obj/item/organ/internal/brain = 1, + /obj/item/organ/internal/heart = 1, + /obj/item/reagent_containers/food/snacks/birthdaycakeslice = 3, /obj/item/reagent_containers/food/snacks/meat/slab = 2 ) response_harm = "takes a bite out of" diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm index 832d92c9d8f..3ff26f7850c 100644 --- a/code/modules/mob/living/simple_animal/friendly/corgi.dm +++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm @@ -368,7 +368,7 @@ name = "Definitely Not [real_name]" desc = "That's Definitely Not [real_name]" valid = 1 - + if(/obj/item/clothing/head/beret/centcom/officer, /obj/item/clothing/head/beret/centcom/officer/navy) name = "Blueshield [real_name]" desc = "Will stand by you until the bitter end." @@ -407,7 +407,7 @@ playsound(src, yelp_sound, 75, 1) ..() -/mob/living/simple_animal/pet/corgi/emote(act, m_type=1, message = null) +/mob/living/simple_animal/pet/corgi/emote(act, m_type = 1, message = null, force) if(stat != CONSCIOUS) return @@ -421,9 +421,9 @@ else on_CD = 0 - if(on_CD == 1) + if(!force && on_CD == 1) return - + switch(act) if("bark") message = "[src] [pick(src.speak_emote)]!" diff --git a/code/modules/mob/living/simple_animal/friendly/diona.dm b/code/modules/mob/living/simple_animal/friendly/diona.dm index 07a5fcf0131..355d756288b 100644 --- a/code/modules/mob/living/simple_animal/friendly/diona.dm +++ b/code/modules/mob/living/simple_animal/friendly/diona.dm @@ -60,7 +60,7 @@ /datum/action/innate/diona/merge/Activate() var/mob/living/simple_animal/diona/user = owner user.merge() - + /datum/action/innate/diona/evolve name = "Evolve" icon_icon = 'icons/obj/cloning.dmi' @@ -109,7 +109,7 @@ forceMove(M) else get_scooped(M) - else + else ..() /mob/living/simple_animal/diona/proc/merge() @@ -151,7 +151,7 @@ to_chat(loc, "You feel a pang of loss as [src] splits away from your biomass.") to_chat(src, "You wiggle out of the depths of [loc]'s biomass and plop to the ground.") forceMove(T) - + var/hasMobs = FALSE for(var/atom/A in D.contents) if(istype(A, /mob/) || istype(A, /obj/item/holder)) @@ -163,9 +163,9 @@ return TRUE /mob/living/simple_animal/diona/proc/evolve() - if(stat != CONSCIOUS) + if(stat != CONSCIOUS) return FALSE - + if(donors.len < evolve_donors) to_chat(src, "You need more blood in order to ascend to a new state of consciousness...") return FALSE @@ -176,7 +176,7 @@ if(isdiona(loc) && !split()) //if it's merged with diona, needs to able to split before evolving return FALSE - + visible_message("[src] begins to shift and quiver, and erupts in a shower of shed bark as it splits into a tangle of nearly a dozen new dionaea.","You begin to shift and quiver, feeling your awareness splinter. All at once, we consume our stored nutrients to surge with growth, splitting into a tangle of at least a dozen new dionaea. We have attained our gestalt form.") var/mob/living/carbon/human/diona/adult = new(get_turf(loc)) @@ -202,14 +202,14 @@ qdel(src) return TRUE -/mob/living/simple_animal/diona/proc/steal_blood() - if(stat != CONSCIOUS) +/mob/living/simple_animal/diona/proc/steal_blood() + if(stat != CONSCIOUS) return FALSE - + var/list/choices = list() for(var/mob/living/carbon/human/H in oview(1,src)) if(Adjacent(H) && H.dna && !(NO_BLOOD in H.dna.species.species_traits)) - choices += H + choices += H if(!choices.len) to_chat(src, "No suitable blood donors nearby.") @@ -260,7 +260,7 @@ to_chat(src, "You don't have any hands!") return -/mob/living/simple_animal/diona/emote(act, m_type=1, message = null) +/mob/living/simple_animal/diona/emote(act, m_type = 1, message = null, force) if(stat != CONSCIOUS) return @@ -272,7 +272,7 @@ else on_CD = 0 - if(on_CD == 1) + if(!force && on_CD == 1) return switch(act) //IMPORTANT: Emotes MUST NOT CONFLICT anywhere along the chain. @@ -283,4 +283,4 @@ if("help") to_chat(src, "scream, chirp") - ..(act, m_type, message) \ No newline at end of file + ..() \ No newline at end of file diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm index c84947c7363..ae19106e1af 100644 --- a/code/modules/mob/living/simple_animal/friendly/mouse.dm +++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm @@ -109,7 +109,7 @@ if(client) client.time_died_as_mouse = world.time -/mob/living/simple_animal/mouse/emote(act, m_type=1, message = null) +/mob/living/simple_animal/mouse/emote(act, m_type = 1, message = null, force) if(stat != CONSCIOUS) return @@ -121,7 +121,7 @@ else on_CD = 0 - if(on_CD == 1) + if(!force && on_CD == 1) return switch(act) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 02f15a59709..b4019cff988 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -258,7 +258,7 @@ adjustBruteLoss(20) return -/mob/living/simple_animal/emote(var/act, var/m_type=1, var/message = null) +/mob/living/simple_animal/emote(act, m_type = 1, message = null, force) if(stat) return act = lowertext(act) @@ -269,7 +269,7 @@ if("help") to_chat(src, "scream") - ..(act, m_type, message) + ..() /mob/living/simple_animal/bullet_act(var/obj/item/projectile/Proj) if(!Proj) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index ee04e624f02..821710490bc 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -1176,12 +1176,11 @@ var/list/slot_equipment_priority = list( \ if(green) if(!no_text) visible_message("[src] vomits up some green goo!","You vomit up some green goo!") - new /obj/effect/decal/cleanable/vomit/green(location) + location.add_vomit_floor(FALSE, TRUE) else if(!no_text) visible_message("[src] pukes all over [p_them()]self!","You puke all over yourself!") - location.add_vomit_floor(src, 1) - playsound(location, 'sound/effects/splat.ogg', 50, 1) + location.add_vomit_floor(TRUE) /mob/proc/AddSpell(obj/effect/proc_holder/spell/S) mob_spell_list += S @@ -1299,6 +1298,7 @@ var/list/slot_equipment_priority = list( \ .["Show player panel"] = "?_src_=vars;mob_player_panel=[UID()]" .["Give Spell"] = "?_src_=vars;give_spell=[UID()]" + .["Give Martial Art"] = "?_src_=vars;givemartialart=[UID()]" .["Give Disease"] = "?_src_=vars;give_disease=[UID()]" .["Toggle Godmode"] = "?_src_=vars;godmode=[UID()]" .["Toggle Build Mode"] = "?_src_=vars;build_mode=[UID()]" diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm index aeb6d8f14bf..93eb035b187 100644 --- a/code/modules/mob/say.dm +++ b/code/modules/mob/say.dm @@ -98,7 +98,7 @@ return verb -/mob/proc/emote(var/act, var/type, var/message) +/mob/proc/emote(act, type, message, force) if(act == "me") return custom_emote(type, message) @@ -184,7 +184,7 @@ var/current = prefix_locations[i] // ["Common", keypos] // There are a few things that will make us want to ignore all other languages in - namely, HIVEMIND languages. - var/datum/language/L = current[1] + var/datum/language/L = current[1] if(L && L.flags & HIVEMIND) . = new /datum/multilingual_say_piece(L, trim(strip_prefixes(message))) break diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index d5ca6b0b0f8..528864b18a6 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -108,7 +108,7 @@ /obj/item/paper/attack_self(mob/living/user as mob) user.examinate(src) - if(rigged && (holiday_master.holidays && holiday_master.holidays[APRIL_FOOLS])) + if(rigged && (SSholiday.holidays && SSholiday.holidays[APRIL_FOOLS])) if(spam_flag == 0) spam_flag = 1 playsound(loc, 'sound/items/bikehorn.ogg', 50, 1) diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index e8643c97cff..c9169a09757 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -72,7 +72,7 @@ papers.Remove(P) else P = new /obj/item/paper - if(holiday_master.holidays && holiday_master.holidays[APRIL_FOOLS]) + if(SSholiday.holidays && SSholiday.holidays[APRIL_FOOLS]) if(prob(30)) P.info = "HONK HONK HONK HONK HONK HONK HONK
HOOOOOOOOOOOOOOOOOOOOOONK
APRIL FOOLS
" P.rigged = 1 diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index 20145573b9d..c7adce7f533 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1353,6 +1353,11 @@ L.broken(0, 1) stoplag() +/obj/machinery/power/apc/proc/null_charge() + for(var/obj/machinery/light/L in area) + L.broken(0, 1) + stoplag() + /obj/machinery/power/apc/proc/setsubsystem(val) if(cell && cell.charge > 0) return (val==1) ? 0 : val diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm index a2ecc811e6a..d4199c3dcec 100644 --- a/code/modules/reagents/chemistry/reagents.dm +++ b/code/modules/reagents/chemistry/reagents.dm @@ -169,7 +169,7 @@ return if(M.mind && M.mind.changeling && M.mind.changeling.regenerating) //no messing with changeling's fake death return - M.visible_message("[M] seizes up and falls limp, [M.p_their()] eyes dead and lifeless...") //so you can't trigger deathgasp emote on people. Edge case, but necessary. + M.emote("deathgasp") M.status_flags |= FAKEDEATH M.update_stat("fakedeath reagent") M.med_hud_set_health() diff --git a/code/modules/reagents/chemistry/reagents/food.dm b/code/modules/reagents/chemistry/reagents/food.dm index 9b1aca91f8d..bf2417a192e 100644 --- a/code/modules/reagents/chemistry/reagents/food.dm +++ b/code/modules/reagents/chemistry/reagents/food.dm @@ -905,8 +905,7 @@ /datum/reagent/vomit/reaction_turf(turf/T, volume) if(volume >= 5 && !isspaceturf(T)) - new /obj/effect/decal/cleanable/vomit(T) - playsound(T, 'sound/effects/splat.ogg', 50, 1, -3) + T.add_vomit_floor() /datum/reagent/greenvomit name = "Green vomit" @@ -918,8 +917,7 @@ /datum/reagent/greenvomit/reaction_turf(turf/T, volume) if(volume >= 5 && !isspaceturf(T)) - new /obj/effect/decal/cleanable/vomit/green(T) - playsound(T, 'sound/effects/splat.ogg', 50, 1, -3) + T.add_vomit_floor(FALSE, TRUE) ////Lavaland Flora Reagents//// diff --git a/code/modules/response_team/ert.dm b/code/modules/response_team/ert.dm index 8cb29ecf3b4..0bac5824780 100644 --- a/code/modules/response_team/ert.dm +++ b/code/modules/response_team/ert.dm @@ -90,22 +90,13 @@ var/ert_request_answered = FALSE return 0 var/index = 1 - var/ert_spawn_seconds = 120 - spawn(ert_spawn_seconds * 10) // to account for spawn() using deciseconds - var/list/unspawnable_ert = list() - for(var/mob/M in response_team_members) - if(M) - unspawnable_ert |= M - if(unspawnable_ert.len) - message_admins("ERT SPAWN: The following ERT members could not be spawned within [ert_spawn_seconds] seconds:") - for(var/mob/M in unspawnable_ert) - message_admins("- Unspawned ERT: [ADMIN_FULLMONTY(M)]") for(var/mob/M in response_team_members) if(index > emergencyresponseteamspawn.len) index = 1 if(!M || !M.client) continue + log_debug("Spawning as ERT: [M.ckey] ([M])") var/client/C = M.client var/mob/living/new_commando = C.create_response_team(emergencyresponseteamspawn[index]) if(!M || !new_commando) diff --git a/code/modules/station_goals/shield.dm b/code/modules/station_goals/shield.dm index a4444938d96..09ccb3ce36b 100644 --- a/code/modules/station_goals/shield.dm +++ b/code/modules/station_goals/shield.dm @@ -175,7 +175,7 @@ change_meteor_chance(0.5) /obj/machinery/satellite/meteor_shield/proc/change_meteor_chance(mod) - for(var/datum/event_container/container in event_manager.event_containers) + for(var/datum/event_container/container in SSevents.event_containers) for(var/datum/event_meta/M in container.available_events) if(M.event_type == /datum/event/meteor_wave) M.weight *= mod diff --git a/html/changelogs/AutoChangeLog-pr-11278.yml b/html/changelogs/AutoChangeLog-pr-11278.yml new file mode 100644 index 00000000000..24f9c3ab4cc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11278.yml @@ -0,0 +1,4 @@ +author: "Arkatos" +delete-after: True +changes: + - rscadd: "Added new Wizard Spell - Summon Ghosts! This nefarious spell will make all ghosts visible to the living. Be careful though, as while they cannot harm you in any way, they might prove a bit.. annoying. Costs 0 points in the Wizard's spellbook." diff --git a/html/changelogs/AutoChangeLog-pr-11283.yml b/html/changelogs/AutoChangeLog-pr-11283.yml new file mode 100644 index 00000000000..9056578d68b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11283.yml @@ -0,0 +1,4 @@ +author: "Fox McCloud" +delete-after: True +changes: + - bugfix: "Fixes a few potential exploits with forcing chem, dust, and explosive implants activating with the deathgasp emote, prior to death" diff --git a/html/changelogs/AutoChangeLog-pr-11284.yml b/html/changelogs/AutoChangeLog-pr-11284.yml new file mode 100644 index 00000000000..433a7fb3f68 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11284.yml @@ -0,0 +1,6 @@ +author: "Arkatos" +delete-after: True +changes: + - rscadd: "Added new Shadowling Ability - Null Charge! This new ability allows Shadowling to completely drain an APC of it's power after a moderate delay. Shadowling must not be interrupted, or the whole process will fail." + - imageadd: "Added custom icon for the Null Charge ability" + - rscdel: "Shadowling Drain Life ability removed" diff --git a/html/changelogs/AutoChangeLog-pr-11292.yml b/html/changelogs/AutoChangeLog-pr-11292.yml new file mode 100644 index 00000000000..814c8530858 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11292.yml @@ -0,0 +1,5 @@ +author: "farie82" +delete-after: True +changes: + - tweak: "Makes puke less lag inducing" + - tweak: "Puke can now appear on all kinds of turfs except spess" diff --git a/html/changelogs/AutoChangeLog-pr-11300.yml b/html/changelogs/AutoChangeLog-pr-11300.yml new file mode 100644 index 00000000000..b949b7f91f5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11300.yml @@ -0,0 +1,5 @@ +author: "Arkatos" +delete-after: True +changes: + - rscadd: "Added Observer HUD buttons for Jump to Mob, Orbit, Re-enter corpse, and Teleport" + - imageadd: "Added custom icons for Observer HUD buttons" diff --git a/html/changelogs/AutoChangeLog-pr-11328.yml b/html/changelogs/AutoChangeLog-pr-11328.yml new file mode 100644 index 00000000000..e91103f07cd --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11328.yml @@ -0,0 +1,5 @@ +author: "farie82" +delete-after: True +changes: + - bugfix: "Admins can now use all mhelp related things again" + - spellcheck: "Fixed the toggle mentor ticket messages text" diff --git a/html/changelogs/AutoChangeLog-pr-11329.yml b/html/changelogs/AutoChangeLog-pr-11329.yml new file mode 100644 index 00000000000..e25e56b8828 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11329.yml @@ -0,0 +1,4 @@ +author: "farie82" +delete-after: True +changes: + - bugfix: "Vampiric glaring is logged now" diff --git a/html/changelogs/AutoChangeLog-pr-11332.yml b/html/changelogs/AutoChangeLog-pr-11332.yml new file mode 100644 index 00000000000..f76e2e2b48b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11332.yml @@ -0,0 +1,4 @@ +author: "Arkatos" +delete-after: True +changes: + - rscadd: "Added an option to grant Martial Arts via administrative Var menu" diff --git a/html/changelogs/AutoChangeLog-pr-11355.yml b/html/changelogs/AutoChangeLog-pr-11355.yml new file mode 100644 index 00000000000..934e85808ba --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11355.yml @@ -0,0 +1,4 @@ +author: "Kyep" +delete-after: True +changes: + - bugfix: "Fixed an error message being inappropriately generated for admins when someone signs up as a pAI." diff --git a/html/changelogs/AutoChangeLog-pr-11360.yml b/html/changelogs/AutoChangeLog-pr-11360.yml new file mode 100644 index 00000000000..3fb01b5b8f9 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-11360.yml @@ -0,0 +1,6 @@ +author: "AffectedArc07" +delete-after: True +changes: + - rscadd: "SSevents" + - rscadd: "SSholiday" + - tweak: "We no longer check if its Christmas every tick. Dont ask." diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index d21323c80b1..b4d8a34a6e0 100644 Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ diff --git a/icons/mob/screen_ghost.dmi b/icons/mob/screen_ghost.dmi new file mode 100644 index 00000000000..6519d00aa97 Binary files /dev/null and b/icons/mob/screen_ghost.dmi differ diff --git a/paradise.dme b/paradise.dme index eae920316f3..19f2cfd10bb 100644 --- a/paradise.dme +++ b/paradise.dme @@ -137,6 +137,7 @@ #include "code\_onclick\hud\constructs.dm" #include "code\_onclick\hud\devil.dm" #include "code\_onclick\hud\fullscreen.dm" +#include "code\_onclick\hud\ghost.dm" #include "code\_onclick\hud\guardian.dm" #include "code\_onclick\hud\hud.dm" #include "code\_onclick\hud\human.dm" @@ -197,7 +198,6 @@ #include "code\controllers\master.dm" #include "code\controllers\subsystem.dm" #include "code\controllers\verbs.dm" -#include "code\controllers\Processes\event.dm" #include "code\controllers\Processes\fast_process.dm" #include "code\controllers\Processes\lighting.dm" #include "code\controllers\Processes\npcai.dm" @@ -209,8 +209,10 @@ #include "code\controllers\subsystem\alarm.dm" #include "code\controllers\subsystem\assets.dm" #include "code\controllers\subsystem\atoms.dm" +#include "code\controllers\subsystem\events.dm" #include "code\controllers\subsystem\fires.dm" #include "code\controllers\subsystem\garbage.dm" +#include "code\controllers\subsystem\holiday.dm" #include "code\controllers\subsystem\icon_smooth.dm" #include "code\controllers\subsystem\jobs.dm" #include "code\controllers\subsystem\machinery.dm" @@ -1418,7 +1420,7 @@ #include "code\modules\events\electrical_storm.dm" #include "code\modules\events\event.dm" #include "code\modules\events\event_container.dm" -#include "code\modules\events\event_manager.dm" +#include "code\modules\events\event_procs.dm" #include "code\modules\events\false_alarm.dm" #include "code\modules\events\floorcluwne.dm" #include "code\modules\events\grid_check.dm" @@ -1450,6 +1452,7 @@ #include "code\modules\events\vent_clog.dm" #include "code\modules\events\wallrot.dm" #include "code\modules\events\wormholes.dm" +#include "code\modules\events\wizard\ghost.dm" #include "code\modules\examine\examine.dm" #include "code\modules\examine\descriptions\atmospherics.dm" #include "code\modules\examine\descriptions\engineering.dm" @@ -1805,7 +1808,6 @@ #include "code\modules\mob\living\silicon\decoy\decoy.dm" #include "code\modules\mob\living\silicon\decoy\life.dm" #include "code\modules\mob\living\silicon\pai\death.dm" -#include "code\modules\mob\living\silicon\pai\emote.dm" #include "code\modules\mob\living\silicon\pai\life.dm" #include "code\modules\mob\living\silicon\pai\pai.dm" #include "code\modules\mob\living\silicon\pai\personality.dm"