Merge branch 'master' into ss-alarms

This commit is contained in:
AffectedArc07
2019-04-23 20:37:42 +01:00
committed by GitHub
76 changed files with 593 additions and 356 deletions
+1
View File
@@ -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
+2 -2
View File
@@ -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)
-2
View File
@@ -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()
+6
View File
@@ -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
+61
View File
@@ -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
-15
View File
@@ -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
@@ -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 = "<A align='right' href='?src=[UID()];refresh=1'>Refresh</A>"
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
+31
View File
@@ -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()
..()
@@ -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 = "<span class='mentorhelp'>"
close_rights = R_MENTOR
close_rights = R_MENTOR | R_ADMIN
/datum/controller/subsystem/tickets/mentor_tickets/message_staff(var/msg)
message_mentorTicket(msg)
+1 -1
View File
@@ -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)
+27
View File
@@ -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
+11 -4
View File
@@ -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
+1 -1
View File
@@ -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()
+4 -4
View File
@@ -172,10 +172,10 @@ var/round_start_time = 0
to_chat(world, "<FONT color='blue'><B>Enjoy the game!</B></FONT>")
world << sound('sound/AI/welcome.ogg')// Skie
if(holiday_master.holidays)
if(SSholiday.holidays)
to_chat(world, "<font color='blue'>and...</font>")
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, "<h4>[holiday.greet()]</h4>")
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
+13 -14
View File
@@ -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, "<span class='warning'>You've disabled audible speech while inside a host! Re-enable it under the borer tab, or stick to borer communications.</span>")
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, "<span class='warning'>You're too far away!</span>")
attempting_to_dominate = FALSE
@@ -760,10 +760,9 @@
to_chat(src, "<span class='danger'>Your host twitches and quivers as you rapdly excrete several larvae from your sluglike body.</span>")
visible_message("<span class='danger'>[src] heaves violently, expelling a rush of vomit and a wriggling, sluglike creature!</span>")
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!")
@@ -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.</i></span>")
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, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Drain Life</b> ability. You can now drain the health of nearby humans to heal yourself.</i></span>")
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, "<span class='shadowling'><i>The power of your thralls has granted you the <b>Null Charge</b> ability. This ability will drain an APC's contents to the void, preventing it from recharging \
or sending power until repaired.</i></span>")
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, "<span class='warning'>You must stand next to an APC to drain it!</span>")
charge_counter = charge_max
to_chat(U, "<span class='warning'>There were no nearby humans for you to drain.</span>")
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, "<span class='boldannounce'>You feel a wave of exhaustion and a curious draining sensation directed towards [U]!</span>")
to_chat(U, "<span class='shadowling'>You draw life from those around you to heal your wounds.</span>")
if(target_apc.cell?.charge == 0)
to_chat(user, "<span class='warning'>APC must have a power to drain!</span>")
charge_counter = charge_max
return
target_apc.operating = 0
target_apc.update()
target_apc.update_icon()
target_apc.visible_message("<span class='warning'>The [target_apc] flickers and begins to grow dark.</span>")
to_chat(user, "<span class='shadowling'>You dim the APC's screen and carefully begin siphoning its power into the void.</span>")
if(!do_after(user, 200, target=target_apc))
//Whoops! The APC's powers back on
to_chat(user, "<span class='shadowling'>Your concentration breaks and the APC suddenly repowers!</span>")
target_apc.operating = 1
target_apc.update()
target_apc.update_icon()
target_apc.visible_message("<span class='warning'>The [target_apc] begins glowing brightly!</span>")
else
//We did it!
to_chat(user, "<span class='shadowling'>You sent the APC's power to the void while overloading all it's lights!</span>")
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()
@@ -226,6 +226,7 @@
target.Weaken(5)
target.stuttering = 20
to_chat(target, "<span class='warning'>You are blinded by [user]'s glare.</span>")
add_attack_logs(user, target, "(Vampire) Glared at")
/obj/effect/proc_holder/spell/vampire/self/shapeshift
name = "Shapeshift (50)"
+18
View File
@@ -469,6 +469,24 @@
dat += "<b>Already cast!</b><br>"
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, "<span class='notice'>You have cast summon ghosts!</span>")
playsound(get_turf(user), 'sound/effects/ghost2.ogg', 50, 1)
return TRUE
/datum/spellbook_entry/summon/guns
name = "Summon Guns"
category = "Rituals"
+1 -1
View File
@@ -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)
@@ -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()
@@ -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)
@@ -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)
+4 -2
View File
@@ -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
@@ -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)
+3 -3
View File
@@ -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)
+120
View File
@@ -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
+1 -1
View File
@@ -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]")
+5
View File
@@ -0,0 +1,5 @@
/datum/event/wizard/ghost //The spook is real
/datum/event/wizard/ghost/start()
var/msg = "<span class='warning'>You suddenly feel extremely obvious...</span>"
set_observer_default_invisibility(0, msg)
+3 -3
View File
@@ -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()
+1 -2
View File
@@ -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("<span class='warning'>[src] flickers and fails, due to bluespace interference!</span>")
qdel(src)
+42 -11
View File
@@ -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"
+1 -1
View File
@@ -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)
+11 -6
View File
@@ -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.
@@ -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)
..()
@@ -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)
@@ -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)
..()
+1 -1
View File
@@ -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)
@@ -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)
+12 -12
View File
@@ -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)
@@ -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)
+1 -1
View File
@@ -57,7 +57,7 @@
SetLoseBreath(0)
if(!gibbed && deathgasp_on_death)
emote("deathgasp")
emote("deathgasp", force = TRUE)
if(mind && suiciding)
mind.suicided = TRUE
+4 -3
View File
@@ -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, "<span class='danger'>You cannot speak in IC (Muted).</span>")
@@ -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, "<span class='notice'>Unusable emote '[act]'. Say *help for a list.</span>")
/mob/living/whisper(message as text)
+4 -4
View File
@@ -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)
..()
@@ -1,2 +0,0 @@
/mob/living/silicon/pai/emote(var/act, var/m_type=1, var/message = null)
..(act, m_type, message)
@@ -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"]
@@ -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)
@@ -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"
+1 -1
View File
@@ -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)
@@ -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)
..()
@@ -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 = "<B>[src]</B> [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"
@@ -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 = "<B>[src]</B> [pick(src.speak_emote)]!"
@@ -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, "<span class='warning'>You need more blood in order to ascend to a new state of consciousness...</span>")
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("<span class='danger'>[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.</span>","<span class='danger'>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.</span>")
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, "<span class='warning'>No suitable blood donors nearby.</span>")
@@ -260,7 +260,7 @@
to_chat(src, "<span class='warning'>You don't have any hands!</span>")
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)
..()
@@ -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)
@@ -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)
+3 -3
View File
@@ -1176,12 +1176,11 @@ var/list/slot_equipment_priority = list( \
if(green)
if(!no_text)
visible_message("<span class='warning'>[src] vomits up some green goo!</span>","<span class='warning'>You vomit up some green goo!</span>")
new /obj/effect/decal/cleanable/vomit/green(location)
location.add_vomit_floor(FALSE, TRUE)
else
if(!no_text)
visible_message("<span class='warning'>[src] pukes all over [p_them()]self!</span>","<span class='warning'>You puke all over yourself!</span>")
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()]"
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -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 = "<font face=\"[P.crayonfont]\" color=\"red\"><b>HONK HONK HONK HONK HONK HONK HONK<br>HOOOOOOOOOOOOOOOOOOOOOONK<br>APRIL FOOLS</b></font>"
P.rigged = 1
+5
View File
@@ -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
+1 -1
View File
@@ -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("<B>[M]</B> 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()
@@ -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////
+1 -10
View File
@@ -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)
+1 -1
View File
@@ -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