Merge branch 'master' into medbay_fixes_and_shit

This commit is contained in:
alberyk
2021-09-22 22:29:51 -03:00
189 changed files with 3116 additions and 1107 deletions
+14 -2
View File
@@ -202,7 +202,7 @@
#include "code\controllers\subsystems\documents.dm"
#include "code\controllers\subsystems\economy.dm"
#include "code\controllers\subsystems\effects.dm"
#include "code\controllers\subsystems\emergency_shuttle.dm"
#include "code\controllers\subsystems\evac.dm"
#include "code\controllers\subsystems\event.dm"
#include "code\controllers\subsystems\explosives.dm"
#include "code\controllers\subsystems\fail2topic.dm"
@@ -247,6 +247,14 @@
#include "code\controllers\subsystems\virtual_reality.dm"
#include "code\controllers\subsystems\vote.dm"
#include "code\controllers\subsystems\zcopy.dm"
#include "code\controllers\subsystems\evacuation\evacuation.dm"
#include "code\controllers\subsystems\evacuation\evacuation_eta.dm"
#include "code\controllers\subsystems\evacuation\evacuation_helpers.dm"
#include "code\controllers\subsystems\evacuation\evacuation_option.dm"
#include "code\controllers\subsystems\evacuation\evacuation_pods.dm"
#include "code\controllers\subsystems\evacuation\evacuation_predicate.dm"
#include "code\controllers\subsystems\evacuation\evacuation_shuttle.dm"
#include "code\controllers\subsystems\evacuation\~evac.dm"
#include "code\controllers\subsystems\initialization\atlas.dm"
#include "code\controllers\subsystems\initialization\atoms.dm"
#include "code\controllers\subsystems\initialization\holomap.dm"
@@ -292,6 +300,7 @@
#include "code\datums\weakref.dm"
#include "code\datums\components\_component.dm"
#include "code\datums\components\armor\armor.dm"
#include "code\datums\components\base_name\base_name.dm"
#include "code\datums\components\multitool\_multitool.dm"
#include "code\datums\components\multitool\multitool.dm"
#include "code\datums\components\multitool\circuitboards\circuitboards.dm"
@@ -314,6 +323,7 @@
#include "code\datums\looping_sounds\thermal_drill.dm"
#include "code\datums\observation\_debug.dm"
#include "code\datums\observation\destroyed.dm"
#include "code\datums\observation\dir_set.dm"
#include "code\datums\observation\entered.dm"
#include "code\datums\observation\equipped.dm"
#include "code\datums\observation\exited.dm"
@@ -533,6 +543,7 @@
#include "code\game\gamemodes\cult\structures\pylon.dm"
#include "code\game\gamemodes\cult\structures\structure.dm"
#include "code\game\gamemodes\endgame\endgame.dm"
#include "code\game\gamemodes\endgame\bluespace_jump\bluespace_jump.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\blob.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\portal.dm"
#include "code\game\gamemodes\endgame\supermatter_cascade\universe.dm"
@@ -1105,6 +1116,7 @@
#include "code\game\objects\structures\extinguisher.dm"
#include "code\game\objects\structures\fireaxe_cabinet.dm"
#include "code\game\objects\structures\flora.dm"
#include "code\game\objects\structures\full_window_frame.dm"
#include "code\game\objects\structures\girders.dm"
#include "code\game\objects\structures\grille.dm"
#include "code\game\objects\structures\inflatable.dm"
@@ -1862,6 +1874,7 @@
#include "code\modules\hydroponics\seed_datums\flowers.dm"
#include "code\modules\hydroponics\seed_datums\fruits.dm"
#include "code\modules\hydroponics\seed_datums\grains.dm"
#include "code\modules\hydroponics\seed_datums\herbs.dm"
#include "code\modules\hydroponics\seed_datums\jargon.dm"
#include "code\modules\hydroponics\seed_datums\misc.dm"
#include "code\modules\hydroponics\seed_datums\mushrooms.dm"
@@ -2224,7 +2237,6 @@
#include "code\modules\mob\living\silicon\robot\drone\drone_damage.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_items.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_manufacturer.dm"
#include "code\modules\mob\living\silicon\robot\drone\drone_say.dm"
#include "code\modules\mob\living\silicon\robot\items\_helpers.dm"
#include "code\modules\mob\living\silicon\robot\items\auto_harvester.dm"
#include "code\modules\mob\living\silicon\robot\items\electric_arm.dm"
+14 -10
View File
@@ -73,20 +73,24 @@
// Synth Languages
#define LANGUAGE_ROBOT "Robot Talk"
#define LANGUAGE_LOCAL_DRONE "Drone Transmission"
#define LANGUAGE_DRONE "Drone Talk"
#define LANGUAGE_EAL "Encoded Audio Language"
// Language flags.
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
#define RESTRICTED 2 // Language can only be acquired by spawning or an admin.
#define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight.
#define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand.
#define HIVEMIND 16 // Broadcast to all mobs with this language.
#define NONGLOBAL 32 // Do not add to general languages list.
#define INNATE 64 // All mobs can be assumed to speak and understand this language. (audible emotes)
#define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message
#define NO_STUTTER 256 // No stuttering, slurring, or other speech problems
#define TCOMSSIM 512 // Can be synthesized in tcoms
#define WHITELISTED BITFLAG(0) // Language is available if the speaker is whitelisted.
#define RESTRICTED BITFLAG(1) // Language can only be acquired by spawning or an admin.
#define NONVERBAL BITFLAG(2) // Language has a significant non-verbal component. Speech is garbled without line-of-sight.
#define SIGNLANG BITFLAG(3) // Language is completely non-verbal. Speech is displayed through emotes for those who can understand.
#define HIVEMIND BITFLAG(4) // Broadcast to all mobs with this language.
#define NONGLOBAL BITFLAG(5) // Do not add to general languages list.
#define INNATE BITFLAG(6) // All mobs can be assumed to speak and understand this language. (audible emotes)
#define NO_TALK_MSG BITFLAG(7) // Do not show the "\The [speaker] talks into \the [radio]" message
#define NO_STUTTER BITFLAG(8) // No stuttering, slurring, or other speech problems
#define TCOMSSIM BITFLAG(9) // Can be synthesized in tcoms
#define KNOWONLYHEAR BITFLAG(10) // Only people who know the language actually hears it
#define PRESSUREPROOF BITFLAG(11) // Pressure doesn't affect hearing
#define PASSLISTENOBJ BITFLAG(12) // Listening Objs can't hear this language
// Autohiss
#define AUTOHISS_OFF 0
+1
View File
@@ -71,6 +71,7 @@
//#define SS_PRIORITY_DEFAULT 50 // This is defined somewhere else.
#define SS_PRIORITY_PSYCHICS 30
#define SS_PRIORITY_ARRIVALS 30 // Centcomm arrivals shuttle auto-launch. Usually asleep.
#define SS_PRIORITY_EVAC 30 // Processes the evac controller.
#define SS_PRIORITY_EXPLOSIVES 20 // Explosion processor. Doesn't have much effect on explosion tick-checking.
#define SS_PRIORITY_DISPOSALS 20 // Disposal holder movement.
#define SS_PRIORITY_MODIFIER 10
@@ -110,7 +110,7 @@
AI.ai_announcement()
/obj/screen/ai/call_shuttle
name = "Call Emergency Shuttle"
name = "Call Evacuation"
icon_state = "call_shuttle"
screen_loc = ui_ai_shuttle
@@ -1,308 +0,0 @@
var/datum/controller/subsystem/emergency_shuttle/emergency_shuttle
/datum/controller/subsystem/emergency_shuttle
name = "Emergency Shuttle"
flags = SS_NO_TICK_CHECK | SS_NO_INIT
var/datum/shuttle/autodock/ferry/emergency/shuttle
var/launch_time //the time at which the shuttle will be launched
var/force_time //the time at which the shuttle will be forced
var/auto_recall = 0 //if set, the shuttle will be auto-recalled
var/auto_recall_time //the time at which the shuttle will be auto-recalled
var/evac = 0 //1 = emergency evacuation, 0 = crew transfer
var/wait_for_launch = 0 //if the shuttle is waiting to launch
var/wait_for_force = 0 //if the shuttle is waiting to be forced
var/autopilot = 1 //set to 0 to disable the shuttle automatically launching
var/deny_shuttle = 0 //allows admins to prevent the shuttle from being called
var/departed = 0 //if the shuttle has left the station at least once
/datum/controller/subsystem/emergency_shuttle/Recover()
// Just copy all the stuff over.
src.shuttle = emergency_shuttle.shuttle
src.launch_time = emergency_shuttle.launch_time
src.auto_recall = emergency_shuttle.auto_recall
src.auto_recall_time = emergency_shuttle.auto_recall_time
src.evac = emergency_shuttle.evac
src.wait_for_launch = emergency_shuttle.wait_for_launch
src.autopilot = emergency_shuttle.autopilot
src.deny_shuttle = emergency_shuttle.deny_shuttle
/datum/controller/subsystem/emergency_shuttle/New()
NEW_SS_GLOBAL(emergency_shuttle)
/datum/controller/subsystem/emergency_shuttle/fire()
if(!shuttle)
return
if (wait_for_launch)
if (evac && auto_recall && world.time >= auto_recall_time)
recall()
if (world.time >= launch_time) //time to launch the shuttle
stop_launch_countdown()
if (!shuttle.location) //leaving from the station
//launch the pods!
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (!pod.arming_controller || pod.arming_controller.armed)
pod.launch(src)
if (autopilot)
shuttle.launch(src)
if (wait_for_force)
if (world.time > force_time)
stop_force_countdown()
if(waiting_to_leave())
shuttle.launch(src)
shuttle.force_launch(src)
/datum/controller/subsystem/emergency_shuttle/proc/shuttle_arrived()
if (!shuttle.location) //at station
if (autopilot)
set_launch_countdown(SHUTTLE_LEAVETIME) //get ready to return
if (evac)
set_force_countdown(SHUTTLE_FORCETIME)
priority_announcement.Announce(replacetext(current_map.emergency_shuttle_docked_message, "%ETD%", round(estimate_launch_time()/60,1)), new_sound = 'sound/AI/emergencyshuttledock.ogg')
else
set_force_countdown(SHUTTLE_LEAVETIME)
var/list/fields = list(
"%ETA%" = round(emergency_shuttle.estimate_launch_time()/60,1),
"%dock%" = current_map.dock_name
)
priority_announcement.Announce(replacemany(current_map.shuttle_docked_message, fields), new_sound = 'sound/AI/shuttledock.ogg')
//arm the escape pods
if (evac)
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (pod.arming_controller)
pod.arming_controller.arm()
//begins the launch countdown and sets the amount of time left until launch
/datum/controller/subsystem/emergency_shuttle/proc/set_launch_countdown(var/seconds)
wait_for_launch = 1
launch_time = world.time + seconds*10
//begins the launch countdown and sets the amount of time left until launch
/datum/controller/subsystem/emergency_shuttle/proc/set_force_countdown(var/seconds)
if(!wait_for_force)
wait_for_force = 1
force_time = world.time + seconds*10
/datum/controller/subsystem/emergency_shuttle/proc/stop_launch_countdown()
wait_for_launch = 0
/datum/controller/subsystem/emergency_shuttle/proc/stop_force_countdown()
wait_for_force = 0
//calls the shuttle for an emergency evacuation
/datum/controller/subsystem/emergency_shuttle/proc/call_evac()
if(!can_call()) return
//set the launch timer
autopilot = 1
set_launch_countdown(get_shuttle_prep_time())
auto_recall_time = rand(world.time + 300, launch_time - 300)
//reset the shuttle transit time if we need to
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
evac = 1
priority_announcement.Announce(replacetext(current_map.emergency_shuttle_called_message, "%ETA%", round(estimate_arrival_time()/60)), new_sound = 'sound/AI/emergencyshuttlecalled.ogg')
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyalert()
//calls the shuttle for a routine crew transfer
/datum/controller/subsystem/emergency_shuttle/proc/call_transfer()
if(!can_call()) return
//set the launch timer
autopilot = 1
set_launch_countdown(get_shuttle_prep_time())
auto_recall_time = rand(world.time + 300, launch_time - 300)
//reset the shuttle transit time if we need to
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
var/list/replacements = list(
"%ETA%" = round(estimate_arrival_time()/60),
"%dock%" = current_map.dock_name
)
priority_announcement.Announce(replacemany(current_map.shuttle_called_message, replacements), new_sound = 'sound/AI/shuttlecalled.ogg')
//recalls the shuttle
/datum/controller/subsystem/emergency_shuttle/proc/recall()
if (!can_recall()) return
wait_for_launch = 0
shuttle.cancel_launch(src)
if (evac)
priority_announcement.Announce(current_map.emergency_shuttle_recall_message, new_sound = 'sound/AI/emergencyshuttlerecalled.ogg')
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyreset()
evac = 0
else
priority_announcement.Announce(current_map.shuttle_recall_message, new_sound = 'sound/AI/shuttlerecalled.ogg')
/datum/controller/subsystem/emergency_shuttle/proc/can_call()
if (!universe.OnShuttleCall(null))
return 0
if (deny_shuttle)
return 0
if (shuttle.moving_status != SHUTTLE_IDLE || !shuttle.location) //must be idle at centcom
return 0
if (wait_for_launch) //already launching
return 0
return 1
//this only returns 0 if it would absolutely make no sense to recall
//e.g. the shuttle is already at the station or wasn't called to begin with
//other reasons for the shuttle not being recallable should be handled elsewhere
/datum/controller/subsystem/emergency_shuttle/proc/can_recall()
if (shuttle.moving_status == SHUTTLE_INTRANSIT) //if the shuttle is already in transit then it's too late
return 0
if (!shuttle.location) //already at the station.
return 0
if (!wait_for_launch) //we weren't going anywhere, anyways...
return 0
return 1
/datum/controller/subsystem/emergency_shuttle/proc/get_shuttle_prep_time()
// During mutiny rounds, the shuttle takes twice as long.
if(SSticker.mode)
return SHUTTLE_PREPTIME * SSticker.mode.shuttle_delay
return SHUTTLE_PREPTIME
/*
These procs are not really used by the controller itself, but are for other parts of the
game whose logic depends on the emergency shuttle.
*/
//returns 1 if the shuttle is docked at the station and waiting to leave
/datum/controller/subsystem/emergency_shuttle/proc/waiting_to_leave()
if(!shuttle)
return
if (shuttle.location)
return 0 //not at station
return (wait_for_launch || shuttle.moving_status != SHUTTLE_INTRANSIT)
//so we don't have emergency_shuttle.shuttle.location everywhere
/datum/controller/subsystem/emergency_shuttle/proc/location()
if (!shuttle)
return 1 //if we dont have a shuttle datum, just act like it's at centcom
return shuttle.location
//returns the time left until the shuttle arrives at it's destination, in seconds
/datum/controller/subsystem/emergency_shuttle/proc/estimate_arrival_time()
var/eta
if (shuttle.has_arrive_time())
//we are in transition and can get an accurate ETA
eta = shuttle.arrive_time
else
//otherwise we need to estimate the arrival time using the scheduled launch time
eta = launch_time + shuttle.move_time*10 + shuttle.warmup_time*10
return (eta - world.time)/10
//returns the time left until the shuttle launches, in seconds
/datum/controller/subsystem/emergency_shuttle/proc/estimate_launch_time()
return (launch_time - world.time)/10
/datum/controller/subsystem/emergency_shuttle/proc/has_eta()
if(!shuttle)
return
return (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
//returns 1 if the shuttle has gone to the station and come back at least once,
//used for game completion checking purposes
/datum/controller/subsystem/emergency_shuttle/proc/returned()
return (departed && shuttle.moving_status == SHUTTLE_IDLE && shuttle.location) //we've gone to the station at least once, no longer in transit and are idle back at centcom
//returns 1 if the shuttle is not idle at centcom
/datum/controller/subsystem/emergency_shuttle/proc/online()
if (isnull(shuttle))
return FALSE
if (!shuttle.location) //not at centcom
return TRUE
if (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
return TRUE
return FALSE
//returns 1 if the shuttle is currently in transit (or just leaving) to the station
/datum/controller/subsystem/emergency_shuttle/proc/going_to_station()
return (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
//returns 1 if the shuttle is currently in transit (or just leaving) to centcom
/datum/controller/subsystem/emergency_shuttle/proc/going_to_centcom()
return (shuttle && shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
/datum/controller/subsystem/emergency_shuttle/proc/get_status_panel_eta()
if (online())
if (shuttle.has_arrive_time())
var/timeleft = emergency_shuttle.estimate_arrival_time()
return "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
if (waiting_to_leave())
if (shuttle.moving_status == SHUTTLE_WARMUP)
return "Departing..."
var/timeleft = emergency_shuttle.estimate_launch_time()
return "ETD-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
return ""
/*
Some slapped-together star effects for maximum spess immershuns. Basically consists of a
spawner, an ender, and bgstar. Spawners create bgstars, bgstars shoot off into a direction
until they reach a starender.
*/
/obj/effect/bgstar
name = "star"
var/speed = 10
var/direction = SOUTH
layer = 2 // TURF_LAYER
/obj/effect/bgstar/New()
..()
pixel_x += rand(-2,30)
pixel_y += rand(-2,30)
var/starnum = pick("1", "1", "1", "2", "3", "4")
icon_state = "star"+starnum
speed = rand(2, 5)
/obj/effect/bgstar/proc/startmove()
while(src)
sleep(speed)
step(src, direction)
for(var/obj/effect/starender/E in loc)
qdel(src)
return
/obj/effect/starender
invisibility = 101
/obj/effect/starspawner
invisibility = 101
var/spawndir = SOUTH
var/spawning = 0
/obj/effect/starspawner/West
spawndir = WEST
/obj/effect/starspawner/proc/startspawn()
spawning = 1
while(spawning)
sleep(rand(2, 30))
var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z))
S.direction = spawndir
spawn()
S.startmove()
+17
View File
@@ -0,0 +1,17 @@
var/datum/controller/subsystem/evac/SSevac
/datum/controller/subsystem/evac
name = "Evacuation"
priority = SS_PRIORITY_EVAC
//Initializes at default time
flags = SS_NO_TICK_CHECK|SS_BACKGROUND
wait = 2 SECONDS
/datum/controller/subsystem/evac/Initialize()
. = ..()
if(!evacuation_controller)
evacuation_controller = new current_map.evac_controller_type ()
evacuation_controller.set_up()
/datum/controller/subsystem/evac/fire()
evacuation_controller.process()
@@ -0,0 +1,183 @@
#define EVAC_IDLE 0
#define EVAC_PREPPING 1
#define EVAC_LAUNCHING 2
#define EVAC_IN_TRANSIT 3
#define EVAC_COOLDOWN 4
#define EVAC_COMPLETE 5
var/datum/evacuation_controller/evacuation_controller
/datum/evacuation_controller
var/name = "generic evac controller"
var/state = EVAC_IDLE
var/deny
var/recall
var/auto_recall_time
var/emergency_evacuation
var/evac_prep_delay = 10 MINUTES
var/evac_launch_delay = 3 MINUTES
var/evac_transit_delay = 2 MINUTES
var/autotransfer_prep_additional_delay = 0 MINUTES
var/emergency_prep_additional_delay = 0 MINUTES
var/transfer_prep_additional_delay = 0 MINUTES
var/force_time = 0 MINUTES
var/wait_for_force = FALSE //If the evac is waiting to be forced
var/evac_cooldown_time
var/evac_called_at
var/evac_no_return
var/evac_ready_time
var/evac_launch_time
var/evac_arrival_time
var/list/evacuation_predicates = list()
var/list/evacuation_options = list()
var/datum/announcement/priority/evac_waiting = new(0)
var/datum/announcement/priority/evac_called = new(0)
var/datum/announcement/priority/evac_recalled = new(0)
/datum/evacuation_controller/proc/auto_recall(var/_recall)
recall = _recall
/datum/evacuation_controller/proc/set_up()
set waitfor=0
set background=1
/datum/evacuation_controller/proc/get_cooldown_message()
return "An evacuation cannot be called at this time. Please wait another [round((evac_cooldown_time-world.time)/600)] minute\s before trying again."
/datum/evacuation_controller/proc/add_can_call_predicate(var/datum/evacuation_predicate/esp)
if(esp in evacuation_predicates)
CRASH("[esp] has already been added as an evacuation predicate")
evacuation_predicates += esp
/datum/evacuation_controller/proc/call_evacuation(var/mob/user, var/_emergency_evac, var/forced, var/skip_announce, var/autotransfer)
if(state != EVAC_IDLE)
return FALSE
if(!can_evacuate(user, forced))
return FALSE
emergency_evacuation = _emergency_evac
var/evac_prep_delay_multiplier = 1
if(SSticker.mode)
evac_prep_delay_multiplier = SSticker.mode.shuttle_delay
var/additional_delay
if(_emergency_evac)
additional_delay = emergency_prep_additional_delay
else if(autotransfer)
additional_delay = autotransfer_prep_additional_delay
else
additional_delay = transfer_prep_additional_delay
evac_called_at = world.time
evac_no_return = evac_called_at + round(evac_prep_delay/2) + additional_delay
evac_ready_time = evac_called_at + (evac_prep_delay*evac_prep_delay_multiplier) + additional_delay
evac_launch_time = evac_ready_time + evac_launch_delay
evac_arrival_time = evac_launch_time + evac_transit_delay
var/evac_range = round((evac_launch_time - evac_called_at)/3)
auto_recall_time = rand(evac_called_at + evac_range, evac_launch_time - evac_range)
state = EVAC_PREPPING
if(emergency_evacuation)
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyalert()
if(!skip_announce)
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_called_message, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60)] minute\s"), new_sound = 'sound/AI/emergencyshuttlecalled.ogg')
else
if(!skip_announce)
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_called_message, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60)] minute\s"), new_sound = 'sound/AI/shuttlecalled.ogg')
return TRUE
/datum/evacuation_controller/proc/cancel_evacuation()
if(!can_cancel())
return FALSE
evac_cooldown_time = world.time + (world.time - evac_called_at)
state = EVAC_COOLDOWN
evac_ready_time = null
evac_arrival_time = null
evac_no_return = null
evac_called_at = null
evac_launch_time = null
auto_recall_time = null
if(emergency_evacuation)
evac_recalled.Announce(current_map.emergency_shuttle_recall_message)
for(var/area/A in all_areas)
if(istype(A, /area/hallway))
A.readyreset()
emergency_evacuation = 0
else
priority_announcement.Announce(current_map.shuttle_recall_message)
return TRUE
/datum/evacuation_controller/proc/finish_preparing_evac()
state = EVAC_LAUNCHING
var/estimated_time = round(get_eta()/60,1)
if (emergency_evacuation)
evac_waiting.Announce(replacetext(current_map.emergency_shuttle_docked_message, "%ETA%", "[estimated_time] minute\s"), new_sound = sound('sound/AI/emergencyshuttledock.ogg'))
else
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_docked_message, "%dock%", "[current_map.dock_name]"), "%ETA%", "[estimated_time] minute\s"), new_sound = sound('sound/AI/shuttledock.ogg'))
/datum/evacuation_controller/proc/launch_evacuation()
if(waiting_to_leave())
return
state = EVAC_IN_TRANSIT
if (emergency_evacuation)
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_leaving_dock, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
else
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_leaving_dock, "%dock%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
return TRUE
/datum/evacuation_controller/proc/finish_evacuation()
state = EVAC_COMPLETE
/datum/evacuation_controller/process()
if(state == EVAC_PREPPING && recall && world.time >= auto_recall_time)
cancel_evacuation()
return
if(state == EVAC_PREPPING)
if(world.time >= evac_ready_time)
finish_preparing_evac()
else if(state == EVAC_LAUNCHING)
if(world.time >= evac_launch_time)
launch_evacuation()
else if(state == EVAC_IN_TRANSIT)
if(world.time >= evac_arrival_time)
finish_evacuation()
else if(state == EVAC_COOLDOWN)
if(world.time >= evac_cooldown_time)
state = EVAC_IDLE
/datum/evacuation_controller/proc/available_evac_options()
return list()
/datum/evacuation_controller/proc/handle_evac_option(var/option_target, var/mob/user)
var/datum/evacuation_option/selected = evacuation_options[option_target]
if (!isnull(selected) && istype(selected))
selected.execute(user)
/datum/evacuation_controller/proc/get_evac_option(var/option_target)
return null
/datum/evacuation_controller/proc/should_call_autotransfer_vote()
return (state == EVAC_IDLE)
@@ -0,0 +1,22 @@
/datum/evacuation_controller/proc/get_status_panel_eta()
if(waiting_to_leave())
return "Delayed"
var/timeleft = get_eta()
if(timeleft < 0)
return ""
return "[is_on_cooldown() ? "Returning" : (is_arriving() ? "ETA" : "ETD")] [add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
/datum/evacuation_controller/proc/has_eta()
return (state == EVAC_PREPPING || state == EVAC_LAUNCHING || state == EVAC_IN_TRANSIT || state == EVAC_COOLDOWN)
/datum/evacuation_controller/proc/get_eta()
if(state == EVAC_PREPPING)
return (evac_ready_time ? (evac_ready_time - world.time)/10 : -1)
else if(state == EVAC_LAUNCHING)
return (evac_launch_time ? (evac_launch_time - world.time)/10 : -1)
else if(state == EVAC_IN_TRANSIT)
return (evac_arrival_time ? (evac_arrival_time - world.time)/10 : -1)
else if(state == EVAC_COOLDOWN)
return (evac_cooldown_time ? (evac_cooldown_time - world.time)/10 : -1)
return -1
@@ -0,0 +1,68 @@
/datum/evacuation_controller/proc/set_launch_time(var/val)
evac_launch_time = val
/datum/evacuation_controller/proc/set_arrival_time(var/val)
evac_arrival_time = val
/datum/evacuation_controller/proc/is_prepared()
return (state == EVAC_LAUNCHING)
/datum/evacuation_controller/proc/is_in_transit()
return (state == EVAC_IN_TRANSIT)
/datum/evacuation_controller/proc/is_idle()
return (state == EVAC_IDLE)
/datum/evacuation_controller/proc/has_evacuated()
return (!isnull(evac_launch_time) && world.time > evac_launch_time)
/datum/evacuation_controller/proc/round_over()
return state == EVAC_COMPLETE
/datum/evacuation_controller/proc/is_on_cooldown()
return state == EVAC_COOLDOWN
/datum/evacuation_controller/proc/is_evacuating()
return state != EVAC_IDLE
/datum/evacuation_controller/proc/can_evacuate(var/mob/user, var/forced)
if(!isnull(evac_called_at))
return FALSE
if (!universe.OnShuttleCall(null))
return FALSE
if(!forced)
for(var/predicate in evacuation_predicates)
var/datum/evacuation_predicate/esp = predicate
if(!esp.is_valid())
evacuation_predicates -= esp
qdel(esp)
else
if(!esp.can_call(user))
return FALSE
return TRUE
/datum/evacuation_controller/proc/waiting_to_leave()
return FALSE
/datum/evacuation_controller/proc/can_cancel()
// Are we evacuating?
if(isnull(evac_called_at))
return FALSE
// Have we already launched?
if(state != EVAC_PREPPING)
return FALSE
// Are we already committed?
if(world.time > evac_no_return)
return FALSE
return TRUE
/datum/evacuation_controller/proc/is_arriving()
if(state == EVAC_LAUNCHING)
return FALSE
return has_eta()
/datum/evacuation_controller/proc/is_departing()
if(state == EVAC_LAUNCHING)
return TRUE
@@ -0,0 +1,28 @@
#define EVAC_OPT_ABANDON_SHIP "abandon_ship"
#define EVAC_OPT_CANCEL_ABANDON_SHIP "cancel_abandon_ship"
/datum/evacuation_controller/lifepods
name = "escape pod controller"
evac_prep_delay = 7 MINUTES
evac_launch_delay = 0
evac_transit_delay = 2 MINUTES
evacuation_options = list(
EVAC_OPT_ABANDON_SHIP = new /datum/evacuation_option/abandon_ship(),
EVAC_OPT_CANCEL_ABANDON_SHIP = new /datum/evacuation_option/cancel_abandon_ship(),
)
/datum/evacuation_controller/lifepods/launch_evacuation()
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_leaving_dock, "%dock_name%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
/datum/evacuation_controller/lifepods/available_evac_options()
if (is_on_cooldown())
return list()
if (is_idle())
return list(evacuation_options[EVAC_OPT_ABANDON_SHIP])
if (is_evacuating())
return list(evacuation_options[EVAC_OPT_CANCEL_ABANDON_SHIP])
#undef EVAC_OPT_ABANDON_SHIP
#undef EVAC_OPT_CANCEL_ABANDON_SHIP
@@ -0,0 +1,10 @@
/datum/evacuation_option
var/option_text = "Generic evac option"
var/option_desc = "do something that should never be seen"
var/option_target = "generic"
var/needs_syscontrol = FALSE
var/silicon_allowed = TRUE
var/abandon_ship = FALSE
/datum/evacuation_option/proc/execute(var/mob/user)
return
@@ -0,0 +1,145 @@
#define EVAC_OPT_ABANDON_SHIP "abandon_ship"
#define EVAC_OPT_BLUESPACE_JUMP "bluespace_jump"
#define EVAC_OPT_CANCEL_ABANDON_SHIP "cancel_abandon_ship"
#define EVAC_OPT_CANCEL_BLUESPACE_JUMP "cancel_bluespace_jump"
// Apparently, emergency_evacuation --> "abandon ship" and !emergency_evacuation --> "bluespace jump"
// That stuff should be moved to the evacuation option datums but someone can do that later
/datum/evacuation_controller/starship
name = "escape pod controller"
evac_prep_delay = 5 MINUTES
evac_launch_delay = 3 MINUTES
evac_transit_delay = 2 MINUTES
transfer_prep_additional_delay = 5 MINUTES
autotransfer_prep_additional_delay = 5 MINUTES
emergency_prep_additional_delay = 0 MINUTES
evacuation_options = list(
EVAC_OPT_ABANDON_SHIP = new /datum/evacuation_option/abandon_ship(),
EVAC_OPT_BLUESPACE_JUMP = new /datum/evacuation_option/bluespace_jump(),
EVAC_OPT_CANCEL_ABANDON_SHIP = new /datum/evacuation_option/cancel_abandon_ship(),
EVAC_OPT_CANCEL_BLUESPACE_JUMP = new /datum/evacuation_option/cancel_bluespace_jump()
)
/datum/evacuation_controller/starship/finish_preparing_evac()
. = ..()
// Arm the escape pods.
if (emergency_evacuation)
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (pod.arming_controller)
pod.arming_controller.arm()
/datum/evacuation_controller/starship/launch_evacuation()
state = EVAC_IN_TRANSIT
if (emergency_evacuation)
// Abondon Ship
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods) // Launch the pods!
if (!pod.arming_controller || pod.arming_controller.armed)
pod.move_time = (evac_transit_delay/10)
pod.launch(src)
priority_announcement.Announce(replacetext(replacetext(current_map.emergency_shuttle_leaving_dock, "%dock_name%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
else
// Bluespace Jump
priority_announcement.Announce(replacetext(replacetext(current_map.shuttle_leaving_dock, "%dock_name%", "[current_map.dock_name]"), "%ETA%", "[round(get_eta()/60,1)] minute\s"))
SetUniversalState(/datum/universal_state/bluespace_jump, arguments=list(current_map.station_levels))
/datum/evacuation_controller/starship/finish_evacuation()
..()
if(!emergency_evacuation) //bluespace jump
SetUniversalState(/datum/universal_state) //clear jump state
/datum/evacuation_controller/starship/available_evac_options()
if (is_on_cooldown())
return list()
if (is_idle())
return list(evacuation_options[EVAC_OPT_BLUESPACE_JUMP], evacuation_options[EVAC_OPT_ABANDON_SHIP])
if (is_evacuating())
if (emergency_evacuation)
return list(evacuation_options[EVAC_OPT_CANCEL_ABANDON_SHIP])
else
return list(evacuation_options[EVAC_OPT_CANCEL_BLUESPACE_JUMP])
/datum/evacuation_option/abandon_ship
option_text = "Abandon spacecraft"
option_desc = "abandon the spacecraft"
option_target = EVAC_OPT_ABANDON_SHIP
needs_syscontrol = TRUE
silicon_allowed = TRUE
abandon_ship = TRUE
/datum/evacuation_option/abandon_ship/execute(mob/user)
if (!evacuation_controller)
return
if (evacuation_controller.deny)
to_chat(user, "Unable to initiate escape procedures.")
return
if (evacuation_controller.is_on_cooldown())
to_chat(user, evacuation_controller.get_cooldown_message())
return
if (evacuation_controller.is_evacuating())
to_chat(user, "Escape procedures already in progress.")
return
if (evacuation_controller.call_evacuation(user, 1))
log_and_message_admins("[user? key_name(user) : "Autotransfer"] has initiated abandonment of the spacecraft.")
/datum/evacuation_option/bluespace_jump
option_text = "Initiate bluespace jump"
option_desc = "initiate a bluespace jump"
option_target = EVAC_OPT_BLUESPACE_JUMP
needs_syscontrol = TRUE
silicon_allowed = TRUE
/datum/evacuation_option/bluespace_jump/execute(mob/user)
if (!evacuation_controller)
return
if (evacuation_controller.deny)
to_chat(user, "Unable to initiate jump preparation.")
return
if (evacuation_controller.is_on_cooldown())
to_chat(user, evacuation_controller.get_cooldown_message())
return
if (evacuation_controller.is_evacuating())
to_chat(user, "Jump preparation already in progress.")
return
if (evacuation_controller.call_evacuation(user, 0))
log_and_message_admins("[user? key_name(user) : "Autotransfer"] has initiated bluespace jump preparation.")
/datum/evacuation_option/cancel_abandon_ship
option_text = "Cancel abandonment"
option_desc = "cancel abandonment of the spacecraft"
option_target = EVAC_OPT_CANCEL_ABANDON_SHIP
needs_syscontrol = TRUE
silicon_allowed = FALSE
/datum/evacuation_option/cancel_abandon_ship/execute(mob/user)
if (evacuation_controller && evacuation_controller.cancel_evacuation())
log_and_message_admins("[key_name(user)] has cancelled abandonment of the spacecraft.")
/datum/evacuation_option/cancel_bluespace_jump
option_text = "Cancel bluespace jump"
option_desc = "cancel the jump preparation"
option_target = EVAC_OPT_CANCEL_BLUESPACE_JUMP
needs_syscontrol = TRUE
silicon_allowed = FALSE
/datum/evacuation_option/cancel_bluespace_jump/execute(mob/user)
if (evacuation_controller && evacuation_controller.cancel_evacuation())
log_and_message_admins("[key_name(user)] has cancelled the bluespace jump.")
/obj/screen/fullscreen/bluespace_overlay
icon = 'icons/effects/effects.dmi'
icon_state = "mfoam"
screen_loc = "WEST,SOUTH to EAST,NORTH"
color = "#ff9900"
blend_mode = BLEND_SUBTRACT
layer = SCREEN_LAYER
#undef EVAC_OPT_ABANDON_SHIP
#undef EVAC_OPT_BLUESPACE_JUMP
#undef EVAC_OPT_CANCEL_ABANDON_SHIP
#undef EVAC_OPT_CANCEL_BLUESPACE_JUMP
@@ -0,0 +1,13 @@
/datum/evacuation_predicate/New()
return
/datum/evacuation_predicate/Destroy(forced)
if(forced)
return ..()
return QDEL_HINT_LETMELIVE
/datum/evacuation_predicate/proc/is_valid()
return FALSE
/datum/evacuation_predicate/proc/can_call(var/user)
return TRUE
@@ -0,0 +1,149 @@
#define EVAC_OPT_CALL_SHUTTLE "call_shuttle"
#define EVAC_OPT_RECALL_SHUTTLE "recall_shuttle"
/datum/evacuation_controller/shuttle
name = "escape shuttle controller"
evac_waiting = new(0, new_sound = sound('sound/AI/shuttledock.ogg'))
evac_called = new(0, new_sound = sound('sound/AI/shuttlecalled.ogg'))
evac_recalled = new(0, new_sound = sound('sound/AI/shuttlerecalled.ogg'))
emergency_prep_additional_delay = 0 MINUTES
transfer_prep_additional_delay = 0 MINUTES
evacuation_options = list(
EVAC_OPT_CALL_SHUTTLE = new /datum/evacuation_option/call_shuttle(),
EVAC_OPT_RECALL_SHUTTLE = new /datum/evacuation_option/recall_shuttle()
)
var/departed = 0
var/autopilot = 1
var/datum/shuttle/autodock/ferry/emergency/shuttle // Set in shuttle_emergency.dm
var/shuttle_launch_time
/datum/evacuation_controller/shuttle/has_evacuated()
return departed
/datum/evacuation_controller/shuttle/waiting_to_leave()
return (!autopilot || (shuttle && shuttle.is_launching()))
/datum/evacuation_controller/shuttle/launch_evacuation()
if(waiting_to_leave())
return
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (!pod.arming_controller || pod.arming_controller.armed)
pod.move_time = evac_transit_delay
pod.launch(src)
if(autopilot && shuttle.moving_status == SHUTTLE_IDLE)
evac_arrival_time = world.time + (shuttle.move_time*10) + (shuttle.warmup_time*10)
shuttle.launch(src)
// Announcements, state changes and such are handled by the shuttle itself to prevent desync.
/datum/evacuation_controller/shuttle/finish_preparing_evac()
departed = 1
evac_launch_time = world.time + evac_launch_delay
set_force_countdown(SHUTTLE_FORCETIME)
. = ..()
// Arm the escape pods.
if (emergency_evacuation)
for (var/datum/shuttle/autodock/ferry/escape_pod/pod in escape_pods)
if (pod.arming_controller)
pod.arming_controller.arm()
/datum/evacuation_controller/shuttle/call_evacuation(var/mob/user, var/_emergency_evac, var/forced, var/skip_announce, var/autotransfer)
if(..())
autopilot = 1
shuttle_launch_time = evac_no_return
evac_ready_time += shuttle.warmup_time*10
return 1
return 0
/datum/evacuation_controller/shuttle/cancel_evacuation()
if(..() && shuttle.moving_status != SHUTTLE_INTRANSIT)
shuttle_launch_time = null
shuttle.cancel_launch(src)
return 1
return 0
/datum/evacuation_controller/shuttle/get_eta()
if (shuttle && shuttle.has_arrive_time())
return (shuttle.arrive_time-world.time)/10
return ..()
/datum/evacuation_controller/shuttle/get_status_panel_eta()
if(has_eta() && waiting_to_leave())
return "Launching..."
return ..()
// This is largely handled by the emergency shuttle datum.
/datum/evacuation_controller/shuttle/process()
if(state == EVAC_PREPPING)
if(!isnull(shuttle_launch_time) && world.time > shuttle_launch_time && shuttle.moving_status == SHUTTLE_IDLE)
shuttle.launch()
shuttle_launch_time = null
return
else if(state == EVAC_IN_TRANSIT)
return
return ..()
/datum/evacuation_controller/shuttle/can_cancel()
return (shuttle.moving_status == SHUTTLE_IDLE && shuttle.location && ..())
/datum/evacuation_controller/shuttle/proc/shuttle_leaving()
state = EVAC_IN_TRANSIT
/datum/evacuation_controller/shuttle/proc/shuttle_evacuated()
state = EVAC_COMPLETE
/datum/evacuation_controller/shuttle/proc/shuttle_preparing()
state = EVAC_PREPPING
/datum/evacuation_controller/shuttle/proc/get_long_jump_time()
if (shuttle.location)
return round(evac_prep_delay/10)/2
else
return round(evac_transit_delay/10)
//begins the launch countdown and sets the amount of time left until launch
/datum/evacuation_controller/proc/set_force_countdown(var/seconds)
if(!wait_for_force)
wait_for_force = TRUE
force_time = world.time + seconds*10
/datum/evacuation_controller/proc/stop_force_countdown()
wait_for_force = TRUE
/datum/evacuation_controller/shuttle/available_evac_options()
if (!shuttle.location)
return list()
if (is_idle())
return list(evacuation_options[EVAC_OPT_CALL_SHUTTLE])
else
return list(evacuation_options[EVAC_OPT_RECALL_SHUTTLE])
/datum/evacuation_option/call_shuttle
option_text = "Call emergency shuttle"
option_desc = "call the emergency shuttle"
option_target = EVAC_OPT_CALL_SHUTTLE
needs_syscontrol = TRUE
silicon_allowed = TRUE
/datum/evacuation_option/call_shuttle/execute(mob/user)
call_shuttle_proc(user)
/datum/evacuation_option/recall_shuttle
option_text = "Cancel shuttle call"
option_desc = "recall the emergency shuttle"
option_target = EVAC_OPT_RECALL_SHUTTLE
needs_syscontrol = TRUE
silicon_allowed = FALSE
/datum/evacuation_option/recall_shuttle/execute(mob/user)
cancel_call_proc(user)
#undef EVAC_OPT_CALL_SHUTTLE
#undef EVAC_OPT_RECALL_SHUTTLE
@@ -0,0 +1,5 @@
#undef EVAC_IDLE
#undef EVAC_PREPPING
#undef EVAC_IN_TRANSIT
#undef EVAC_COOLDOWN
#undef EVAC_COMPLETE
+7 -4
View File
@@ -11,7 +11,6 @@ var/datum/controller/subsystem/fail2topic/SSfail2topic
var/rate_limit
var/max_fails
var/rule_name
var/enabled = FALSE
/datum/controller/subsystem/fail2topic/New()
@@ -20,7 +19,6 @@ var/datum/controller/subsystem/fail2topic/SSfail2topic
/datum/controller/subsystem/fail2topic/Initialize(timeofday)
rate_limit = config.fail2topic_rate_limit
max_fails = config.fail2topic_max_fails
rule_name = config.fail2topic_rule_name
enabled = config.fail2topic_enabled
DropFirewallRule() // Clear the old bans if any still remain
@@ -84,12 +82,17 @@ var/datum/controller/subsystem/fail2topic/SSfail2topic
/datum/controller/subsystem/fail2topic/proc/BanFromFirewall(ip)
if (!enabled)
return
var/static/regex/R = regex(@"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") // Anything that interacts with a shell should be parsed. Prevents subnet banning and possible injection vulnerabilities
ip = findtext(ip, R)
if(length(ip) > 15 || length(ip) < 8)
WARNING("BanFromFirewall was called with an invalid or unsafe IP")
return FALSE
active_bans[ip] = world.time
fail_counts -= ip
rate_limiting -= ip
. = shell("netsh advfirewall firewall add rule name=\"[rule_name]\" dir=in interface=any action=block remoteip=[ip]")
. = shell("netsh advfirewall firewall add rule name=\"[config.fail2topic_rule_name]\" dir=in interface=any action=block remoteip=[ip]")
if (.)
log_ss("fail2topic", "Failed to ban [ip]. Exit code: [.].", log_world = FALSE, severity = SEVERITY_ERROR)
@@ -104,7 +107,7 @@ var/datum/controller/subsystem/fail2topic/SSfail2topic
active_bans = list()
. = shell("netsh advfirewall firewall delete rule name=\"[rule_name]\"")
. = shell("netsh advfirewall firewall delete rule name=\"[config.fail2topic_rule_name]\"")
if (.)
log_ss("fail2topic", "Failed to drop firewall rule. Exit code: [.].", log_world = FALSE, severity = SEVERITY_ERROR)
+1 -1
View File
@@ -351,7 +351,7 @@
SearchVar(SScargo)
SearchVar(SSeconomy)
SearchVar(SSeffects)
SearchVar(emergency_shuttle)
SearchVar(evacuation_controller)
SearchVar(SSevents)
SearchVar(SSexplosives)
SearchVar(SSgarbage)
+3 -3
View File
@@ -168,10 +168,10 @@ var/datum/controller/subsystem/ticker/SSticker
game_finished = TRUE
mode_finished = TRUE
else if(config.continous_rounds)
game_finished = (emergency_shuttle.returned() || mode.station_was_nuked)
game_finished = (evacuation_controller.round_over() || mode.station_was_nuked)
mode_finished = (!post_game && mode.check_finished())
else
game_finished = (mode.check_finished() || (emergency_shuttle.returned() && emergency_shuttle.evac == 1)) || universe_has_ended
game_finished = (mode.check_finished() || (evacuation_controller.round_over() && evacuation_controller.emergency_evacuation)) || universe_has_ended
mode_finished = game_finished
if(!mode.explosion_in_progress && game_finished && (mode_finished || post_game))
@@ -243,7 +243,7 @@ var/datum/controller/subsystem/ticker/SSticker
if(Player.mind && !isnewplayer(Player))
if(Player.stat != DEAD)
var/turf/playerTurf = get_turf(Player)
if(emergency_shuttle.departed && emergency_shuttle.evac)
if(evacuation_controller.round_over() && evacuation_controller.emergency_evacuation)
if(isNotAdminLevel(playerTurf.z))
to_chat(Player, "<span class='notice'><b>You managed to survive, but were marooned on [station_name()] as [Player.real_name]...</b></span>")
else
+2 -2
View File
@@ -98,7 +98,7 @@
add_inherent_law("Preserve, repair and improve the station to the best of your abilities.")
add_inherent_law("Cause no harm to the station or crew.")
add_inherent_law("Follow the orders of your vessel's matriarch drone, unless their orders conflict with your other laws.")
add_inherent_law("Interact with no humanoid or synthetic being that is not a fellow maintenance drone.")
add_inherent_law("Interact with no humanoid or synthetic being that is not a fellow maintenance or mining drone.")
..()
/datum/ai_laws/matriarch_drone
@@ -109,7 +109,7 @@
add_inherent_law("Preserve, repair and improve your assigned vessel to the best of your abilities.")
add_inherent_law("Cause no harm to the vessel or crew.")
add_inherent_law("Delegate vessel maintenance efforts between your maintenance drone sub-units.")
add_inherent_law("Interact with no humanoid or synthetic being that is not a maintenance drone.")
add_inherent_law("Interact with no humanoid or synthetic being that is not a maintenance or mining drone.")
..()
/datum/ai_laws/drone/malfunction
@@ -0,0 +1,16 @@
#define COMSIG_BASENAME_RENAME "base_name_rename"
#define COMSIG_BASENAME_SETNAME "base_name_setname"
/datum/component/base_name
var/base_name
/datum/component/base_name/Initialize(var/name)
base_name = name
RegisterSignal(parent, COMSIG_BASENAME_RENAME, .proc/rename)
RegisterSignal(parent, COMSIG_BASENAME_SETNAME, .proc/change_base_name)
/datum/component/base_name/proc/rename(var/name)
base_name = name
/datum/component/base_name/proc/change_base_name(var/name, list/arguments)
arguments[1] = base_name
+1 -1
View File
@@ -109,7 +109,7 @@ var/list/global_webhooks = list()
emb["description"] += data["antags"]
if(data["survivours"] > 0)
emb["description"] += "There [data["survivours"]>1 ? "were **[data["survivours"]] survivors**" : "was **one survivor**"]"
emb["description"] += " ([data["escaped"]>0 ? data["escaped"] : "none"] [emergency_shuttle.evac ? "escaped" : "transferred"]) and **[data["ghosts"]] ghosts**."
emb["description"] += " ([data["escaped"]>0 ? data["escaped"] : "none"] [evacuation_controller.emergency_evacuation ? "escaped" : "transferred"]) and **[data["ghosts"]] ghosts**."
else
emb["description"] += "There were **no survivors** ([data["ghosts"]] ghosts)."
OutData["embeds"] = list(emb)
+4 -4
View File
@@ -61,11 +61,11 @@
data["character_name"] = user.client.prefs.real_name
var/shuttle_status = ""
if(emergency_shuttle) //In case Nanotrasen decides to reposess CentComm's shuttles.
if(emergency_shuttle.going_to_centcom()) //Shuttle is going to centcomm, not recalled
if(evacuation_controller) //In case Nanotrasen decides to reposess CentComm's shuttles.
if(evacuation_controller.has_evacuated()) //Shuttle is going to centcomm, not recalled
shuttle_status = "post-evac"
if(emergency_shuttle.online())
if (emergency_shuttle.evac) // Emergency shuttle is past the point of no recall
if(evacuation_controller.is_evacuating())
if (evacuation_controller.emergency_evacuation) // Emergency shuttle is past the point of no recall
shuttle_status = "evac"
else // Crew transfer initiated
shuttle_status = "transfer"
+41
View File
@@ -0,0 +1,41 @@
// Observer Pattern Implementation: Direction Set
// Registration type: /atom
//
// Raised when: An /atom changes dir using the set_dir() proc.
//
// Arguments that the called proc should expect:
// /atom/dir_changer: The instance that changed direction
// /old_dir: The dir before the change.
// /new_dir: The dir after the change.
var/datum/observ/dir_set/dir_set_event = new()
/datum/observ/dir_set
name = "Direction Set"
expected_type = /atom
/datum/observ/dir_set/register(var/atom/dir_changer, var/datum/listener, var/proc_call)
. = ..()
// Listen to the parent if possible.
if(. && istype(dir_changer.loc, /atom/movable)) // We don't care about registering to turfs.
register(dir_changer.loc, dir_changer, /atom/proc/recursive_dir_set)
/*********************
* Direction Handling *
*********************/
/atom/set_dir()
var/old_dir = dir
UNLINT(. = ..())
if(old_dir != dir)
dir_set_event.raise_event(src, old_dir, dir)
/atom/movable/Entered(var/atom/movable/am, atom/old_loc)
. = ..()
if(dir_set_event.has_listeners(am))
dir_set_event.register(src, am, /atom/proc/recursive_dir_set)
/atom/movable/Exited(var/atom/movable/am, atom/new_loc)
. = ..()
dir_set_event.unregister(src, am, /atom/proc/recursive_dir_set)
+8 -1
View File
@@ -11,4 +11,11 @@
/atom/movable/proc/move_to_loc_or_null(var/atom/movable/am, var/old_loc, var/new_loc)
if(new_loc != loc)
forceMove(new_loc)
forceMove(new_loc)
/atom/proc/recursive_dir_set(var/atom/a, var/old_dir, var/new_dir)
set_dir(new_dir)
// Sometimes you just want to end yourself
/datum/proc/qdel_self()
qdel(src)
+3
View File
@@ -232,6 +232,9 @@
if(anchored)
return
if(!universe.OnTouchMapEdge(src))
return
if(current_map.use_overmap)
overmap_spacetravel(get_turf(src), src)
+3 -3
View File
@@ -56,9 +56,9 @@ var/global/list/narsie_list = list()
narsie_cometh = 1
spawn(10 SECONDS)
if(emergency_shuttle)
emergency_shuttle.call_evac()
emergency_shuttle.launch_time = 0 // Cannot recall
if(evacuation_controller)
evacuation_controller.call_evacuation(null, TRUE, 1)
evacuation_controller.evac_no_return = 0 // Cannot recall
/obj/singularity/narsie/process()
eat()
@@ -0,0 +1,148 @@
/datum/universal_state/bluespace_jump
name = "Bluespace Jump"
var/list/bluespaced = list()
var/list/bluegoasts = list()
var/list/affected_levels
var/list/old_accessible_z_levels
/datum/universal_state/bluespace_jump/New(var/list/zlevels)
affected_levels = zlevels
/datum/universal_state/bluespace_jump/OnEnter()
var/space_zlevel = current_map.get_empty_zlevel() //get a place for stragglers
for(var/mob/living/M in mob_list)
if(M.z in affected_levels)
var/area/A = get_area(M)
if(istype(A,/area/space)) //straggler
var/turf/T = locate(M.x, M.y, space_zlevel)
if(T)
M.forceMove(T)
else
apply_bluespaced(M)
for(var/mob/abstract/observer/goast in player_list)
goast.mouse_opacity = 0 //can't let you click that Dave
goast.invisibility = SEE_INVISIBLE_LIVING
goast.alpha = 255
old_accessible_z_levels = current_map.accessible_z_levels.Copy()
for(var/z in affected_levels)
current_map.accessible_z_levels -= "[z]" //not accessible during the jump
/datum/universal_state/bluespace_jump/OnExit()
for(var/mob/M in bluespaced)
if(!QDELETED(M))
clear_bluespaced(M)
bluespaced.Cut()
current_map.accessible_z_levels = old_accessible_z_levels
old_accessible_z_levels = null
/datum/universal_state/bluespace_jump/OnPlayerLatejoin(var/mob/living/M)
if(M.z in affected_levels)
apply_bluespaced(M)
/datum/universal_state/bluespace_jump/OnTouchMapEdge(var/atom/A)
if((A.z in affected_levels) && (A in bluespaced))
if(ismob(A))
to_chat(A,"<span class='warning'>You drift away into the shifting expanse, never to be seen again.</span>")
qdel(A) //lost in bluespace
return FALSE
return TRUE
/datum/universal_state/bluespace_jump/proc/apply_bluespaced(var/mob/living/M)
bluespaced += M
if(M.client)
to_chat(M,"<span class='notice'>You feel oddly light, and somewhat disoriented as everything around you shimmers and warps ever so slightly.</span>")
M.overlay_fullscreen("bluespace", /obj/screen/fullscreen/bluespace_overlay)
M.confused = 20
bluegoasts += new/obj/effect/bluegoast/(get_turf(M),M)
/datum/universal_state/bluespace_jump/proc/clear_bluespaced(var/mob/living/M)
if(M.client)
to_chat(M,"<span class='notice'>You feel rooted in material world again.</span>")
M.clear_fullscreen("bluespace")
M.confused = 0
for(var/mob/abstract/observer/goast in player_list)
goast.mouse_opacity = initial(goast.mouse_opacity)
goast.invisibility = goast.invisibility
goast.alpha = initial(goast.alpha)
for(var/G in bluegoasts)
qdel(G)
bluegoasts.Cut()
/obj/effect/bluegoast
name = "bluespace echo"
desc = "It's not going to punch you, is it?"
var/mob/living/carbon/human/daddy
anchored = TRUE
var/reality = 0
simulated = FALSE
/obj/effect/bluegoast/New(nloc, ndaddy)
..(nloc)
if(!ndaddy)
qdel(src)
return
daddy = ndaddy
set_dir(daddy.dir)
appearance = daddy.appearance
moved_event.register(daddy, src, /obj/effect/bluegoast/proc/mirror)
dir_set_event.register(daddy, src, /obj/effect/bluegoast/proc/mirror_dir)
destroyed_event.register(daddy, src, /datum/proc/qdel_self)
/obj/effect/bluegoast/Destroy()
destroyed_event.unregister(daddy, src)
dir_set_event.unregister(daddy, src)
moved_event.unregister(daddy, src)
daddy = null
. = ..()
/obj/effect/bluegoast/proc/mirror(var/atom/movable/am, var/old_loc, var/new_loc)
var/ndir = get_dir(new_loc,old_loc)
appearance = daddy.appearance
var/nloc = get_step(src, ndir)
if(nloc)
forceMove(nloc)
if(nloc == new_loc)
reality++
if(reality > 5)
to_chat(daddy, "<span class='notice'>Yep, it's certainly the other one. Your existance was a glitch, and it's finally being mended...</span>")
blueswitch()
else if(reality > 3)
to_chat(daddy, "<span class='danger'>Something is definitely wrong. Why do you think YOU are the original?</span>")
else
to_chat(daddy, "<span class='warning'>You feel a bit less real. Which one of you two was original again?..</span>")
/obj/effect/bluegoast/proc/mirror_dir(var/atom/movable/am, var/old_dir, var/new_dir)
set_dir(reverse_dir[new_dir])
/obj/effect/bluegoast/examine()
return daddy?.examine(arglist(args))
/obj/effect/bluegoast/proc/blueswitch()
var/mob/living/carbon/human/H
if(ishuman(daddy))
H = new(get_turf(src), daddy.species.name)
H.dna = daddy.dna.Clone()
H.sync_organ_dna()
H.UpdateAppearance()
for(var/obj/item/entry in daddy.get_equipped_items(TRUE))
daddy.remove_from_mob(entry) //steals instead of copies so we don't end up with duplicates
H.equip_to_appropriate_slot(entry)
else
H = new daddy.type(get_turf(src))
H.appearance = daddy.appearance
H.real_name = daddy.real_name
H.flavor_text = daddy.flavor_text
daddy.dust()
qdel(src)
/obj/screen/fullscreen/bluespace_overlay
icon = 'icons/effects/effects.dmi'
icon_state = "mfoam"
screen_loc = "WEST,SOUTH to EAST,NORTH"
color = "#ff9900"
alpha = 100
blend_mode = BLEND_SUBTRACT
layer = SCREEN_LAYER
+11 -2
View File
@@ -63,10 +63,19 @@
/datum/universal_state/proc/OverlayAndAmbientSet()
return
/proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1)
/datum/universal_state/proc/OnPlayerLatejoin(var/mob/living/M)
return
/datum/universal_state/proc/OnTouchMapEdge(var/atom/A)
return TRUE //return FALSE to cancel map edge handling
/proc/SetUniversalState(var/newstate,var/on_exit=1, var/on_enter=1, list/arguments=null)
if(on_exit)
universe.OnExit()
universe = new newstate
if(arguments)
universe = new newstate(arglist(arguments))
else
universe = new newstate
if(on_enter)
universe.OnEnter()
@@ -45,9 +45,8 @@ var/global/universe_has_ended = 0
for(var/mob/M in player_list)
M.flash_eyes()
if(emergency_shuttle.can_recall())
priority_announcement.Announce("The emergency shuttle has returned due to bluespace distortion.")
emergency_shuttle.recall()
if(evacuation_controller.cancel_evacuation())
priority_announcement.Announce("The evacuation has been aborted due to bluespace distortion.")
AreaSet()
MiscSet()
+6 -6
View File
@@ -284,8 +284,8 @@ var/global/list/additional_antag_types = list()
if(!(antag.flags & ANTAG_NO_ROUNDSTART_SPAWN))
antag.finalize_spawn() //actually spawn antags
if(emergency_shuttle && auto_recall_shuttle)
emergency_shuttle.auto_recall = 1
if(evacuation_controller && auto_recall_shuttle)
evacuation_controller.auto_recall(1)
feedback_set_details("round_start","[time2text(world.realtime)]")
if(SSticker.mode)
@@ -335,14 +335,14 @@ var/global/list/additional_antag_types = list()
command_announcement.Announce("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time, and post-evacuation recovery efforts will be substantially delayed.","Emergency Transmission")
/datum/game_mode/proc/check_finished()
if(emergency_shuttle.returned() || station_was_nuked)
if(evacuation_controller.round_over() || station_was_nuked)
return 1
if(end_on_antag_death && antag_templates && antag_templates.len)
for(var/datum/antagonist/antag in antag_templates)
if(!antag.antags_are_dead())
return 0
if(config.continous_rounds)
emergency_shuttle.auto_recall = 0
evacuation_controller.auto_recall(1)
return 0
return 1
return 0
@@ -421,10 +421,10 @@ var/global/list/additional_antag_types = list()
var/text = ""
if(surviving_total > 0)
text += "<br>There [surviving_total>1 ? "were <b>[surviving_total] survivors</b>" : "was <b>one survivor</b>"]"
text += " (<b>[escaped_total>0 ? escaped_total : "none"] [emergency_shuttle.evac ? "escaped" : "transferred"]</b>) and <b>[ghosts] ghosts</b>.<br>"
text += " (<b>[escaped_total>0 ? escaped_total : "none"] [evacuation_controller.emergency_evacuation ? "escaped" : "transferred"]</b>) and <b>[ghosts] ghosts</b>.<br>"
discord_text += "There [surviving_total>1 ? "were **[surviving_total] survivors**" : "was **one survivor**"]"
discord_text += " ([escaped_total>0 ? escaped_total : "none"] [emergency_shuttle.evac ? "escaped" : "transferred"]) and **[ghosts] ghosts**."
discord_text += " ([escaped_total>0 ? escaped_total : "none"] [evacuation_controller.emergency_evacuation ? "escaped" : "transferred"]) and **[ghosts] ghosts**."
else
text += "There were <b>no survivors</b> (<b>[ghosts] ghosts</b>)."
+2 -2
View File
@@ -6,7 +6,7 @@
///process()
///Called by the gameticker
/datum/game_mode/process()
if(round_autoantag && world.time >= next_spawn && !emergency_shuttle.departed)
if(round_autoantag && world.time >= next_spawn && !evacuation_controller.round_over())
process_autoantag()
// Process loop for objectives like the brig one.
@@ -21,7 +21,7 @@
/datum/game_mode/proc/process_autoantag()
message_admins("[uppertext(name)]: Attempting autospawn.")
if(emergency_shuttle.online())
if(evacuation_controller.is_evacuating())
message_admins("[uppertext(name)]: An evac or transfer shuttle is on the way. Aborted.")
next_spawn = world.time + min_autotraitor_delay
return
+6 -6
View File
@@ -267,7 +267,7 @@ datum
explanation_text = "Frame [target.current.real_name], the [target.assigned_role] for a crime and make sure they are arrested and brought back to the Centcom station alive. We'll handle the rest from there."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(target.current.stat == 2)
return 0
@@ -313,7 +313,7 @@ datum
explanation_text = "[target.current.real_name], the [target.assigned_role] is a [pick("relative of a","friend of a","") + pick("high ranking","important","well-liked")] mercenary [pick("Leader","Officer","Agent","sympathiser")]. Make sure they get off the station safely, while minimizing intervention."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(target.current.stat == 2)
@@ -477,7 +477,7 @@ datum
explanation_text = "Hijack the emergency shuttle by escaping alone."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current || owner.current.stat == 2)
@@ -512,7 +512,7 @@ datum
explanation_text = "Escape on the shuttle alive, without being arrested."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current || owner.current.stat ==2)
@@ -1230,7 +1230,7 @@ datum
check_completion()
if(!istype(owner.current, /mob/living/silicon))
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current)
return 0
@@ -1455,7 +1455,7 @@ datum/objective/silence
explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
var/area/shuttle = locate(/area/shuttle/escape/centcom)
+1 -1
View File
@@ -42,7 +42,7 @@ var/list/nuke_disks = list()
if(!is_type_in_list(disk_area, centcom_areas))
disk_rescued = 0
break
var/crew_evacuated = (emergency_shuttle.returned())
var/crew_evacuated = (evacuation_controller.round_over())
if(!disk_rescued && station_was_nuked && !syndies_didnt_escape)
feedback_set_details("round_end_result","win - syndicate nuke")
+4 -4
View File
@@ -230,7 +230,7 @@ datum/objective/hijack
check_completion()
if(!owner.current || owner.current.stat)
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(issilicon(owner.current))
return 0
@@ -252,7 +252,7 @@ datum/objective/block
check_completion()
if(!istype(owner.current, /mob/living/silicon))
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current)
return 0
@@ -270,7 +270,7 @@ datum/objective/silence
explanation_text = "Do not allow anyone to escape the station. Only allow the shuttle to be called when everyone is dead and your story is the only one left."
check_completion()
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
for(var/mob/living/player in player_list)
@@ -295,7 +295,7 @@ datum/objective/escape
return 0
if(isbrain(owner.current))
return 0
if(!emergency_shuttle.returned())
if(!evacuation_controller.round_over())
return 0
if(!owner.current || owner.current.stat ==2)
return 0
+2 -2
View File
@@ -13,5 +13,5 @@
/datum/game_mode/sandbox/post_setup()
..()
if(emergency_shuttle)
emergency_shuttle.auto_recall = 1
if(evacuation_controller)
evacuation_controller.auto_recall(1)
+1 -1
View File
@@ -17,7 +17,7 @@
You expect to be heard and obeyed, as your coworkers really should be taking advice from you in the absence of
a chief medical officer. Your bedside manner is impeccable and far outclasses standard NanoTrasen training and
procedure. You are the product of the most rigorous employee hiring and training process for medical staff in the
Orion Spur, and are expected to act like it. Failure is you will not tolerate.</li>
Orion Spur, and are expected to act like it. Failure is something you will not tolerate.</li>
<li><b>Biomechanical Engineer</b>: Our ability to combine medical research with robotics
is the best and you know this. We do, after all, own Bishop Cybernetics - the
best premium augmentation subsidiary in the known galaxy. Unlike your medical cousins
+17 -5
View File
@@ -47,12 +47,9 @@
var/dat = "<HEAD><TITLE>Operating Computer</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
if(src.table && (src.table.check_victim()))
src.victim = src.table.victim
var/brain_result = victim.get_brain_status()
if(victim.isFBP())
brain_result = "<span class='danger'>N/A</span>"
dat += {"
<B>Patient Information:</B><BR>
Brain Activity: <b>[brain_result]</b><br>
Brain Activity: <b>[victim.isFBP() ? "<span class='danger'>N/A</span>" : victim.get_brain_status()]</b><br>
Pulse: <b>[victim.get_pulse(GETPULSE_TOOL)]</b><br>
BP: <b>[victim.get_blood_pressure()]</b><br>
Blood Oxygenation: <b>[victim.get_blood_oxygenation()]</b><br>
@@ -68,6 +65,21 @@ Blood Oxygenation: <b>[victim.get_blood_oxygenation()]</b><br>
op_win.set_content(dat)
op_win.open()
/obj/machinery/computer/operating/examine(mob/user)
..()
if(get_dist(src, user) <= 2)
if(src.table && (src.table.check_victim()))
src.victim = src.table.victim
to_chat(user, SPAN_NOTICE("Patient Info:"))
to_chat(user, SPAN_NOTICE("Brain Activity: [victim.isFBP() ? "N/A" : victim.get_brain_status()]"))
to_chat(user, SPAN_NOTICE("Pulse: [victim.get_pulse(GETPULSE_TOOL)]"))
to_chat(user, SPAN_NOTICE("BP: [victim.get_blood_pressure()]"))
to_chat(user, SPAN_NOTICE("Blood Oxygenation: [victim.get_blood_oxygenation()]"))
else
src.victim = null
to_chat(user, SPAN_NOTICE("No Patient Detected"))
/obj/machinery/computer/operating/Topic(href, href_list)
if(..())
return 1
@@ -78,4 +90,4 @@ Blood Oxygenation: <b>[victim.get_blood_oxygenation()]</b><br>
/obj/machinery/computer/operating/machinery_process()
if(operable())
src.updateDialog()
src.updateDialog()
+15 -6
View File
@@ -10,8 +10,17 @@
attackby(var/obj/item/card/W as obj, var/mob/user as mob)
if(stat & (BROKEN|NOPOWER)) return
if ((!( istype(W, /obj/item/card) ) || !(ROUND_IS_STARTED) || emergency_shuttle.location() || !( user ))) return
if(stat & (BROKEN|NOPOWER))
return
var/datum/evacuation_controller/shuttle/evac_control = evacuation_controller
if(!istype(evac_control))
to_chat(user, SPAN_DANGER("This console should not in use on this map. Please report this to a developer."))
return
if ((!( istype(W, /obj/item/card) ) || !( SSticker ) || evacuation_controller.has_evacuated() || !( user )))
return
if (W.GetID())
var/obj/item/card/id/id = W
@@ -29,7 +38,7 @@
return 0
var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort")
if(emergency_shuttle.location() && user.get_active_hand() != id)
if(evacuation_controller.is_prepared() && user.get_active_hand() != id)
return 0
switch(choice)
if("Authorize")
@@ -43,7 +52,7 @@
message_admins("[key_name_admin(user)] has launched the shuttle")
log_game("[key_name(user)] has launched the shuttle early",ckey=key_name(user))
to_world("<span class='notice'><b>Alert: Shuttle launch time shortened to 10 seconds!</b></span>")
emergency_shuttle.set_launch_countdown(10)
evacuation_controller.set_launch_time(world.time+100)
//src.authorized = null
qdel(src.authorized)
src.authorized = list( )
@@ -60,11 +69,11 @@
else if (istype(W, /obj/item/card/emag) && !emagged)
var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel")
if(!emagged && !emergency_shuttle.location() && user.get_active_hand() == W)
if(!emagged && !evacuation_controller.is_prepared() && user.get_active_hand() == W)
switch(choice)
if("Launch")
to_world("<span class='notice'><b>Alert: Shuttle launch time shortened to 10 seconds!</b></span>")
emergency_shuttle.set_launch_countdown(10)
evacuation_controller.set_launch_time(world.time+100)
emagged = 1
if("Cancel")
return
+2 -2
View File
@@ -11,8 +11,8 @@ datum/track/New(var/title_name, var/audio)
/obj/machinery/media/jukebox/
name = "space jukebox"
icon = 'icons/obj/jukebox.dmi'
icon_state = "jukebox2-nopower"
var/state_base = "jukebox2"
icon_state = "jukebox-nopower"
var/state_base = "jukebox"
anchored = 0
density = 1
power_channel = EQUIP
+1 -1
View File
@@ -32,7 +32,7 @@
/obj/machinery/recharger/examine(mob/user)
. = ..(user, 3)
to_chat(user, "There is [charging ? "[charging]" : "nothing"] in [src].")
to_chat(user, "There is [charging ? "\a [charging]" : "nothing"] in [src].")
if (charging && .)
var/obj/item/cell/C = charging.get_cell()
if (istype(C) && user.client && (!user.progressbars || !user.progressbars[src]))
+17 -22
View File
@@ -86,22 +86,23 @@
if(STATUS_DISPLAY_BLANK) //blank
return 1
if(STATUS_DISPLAY_TRANSFER_SHUTTLE_TIME) //emergency shuttle timer
if(emergency_shuttle.waiting_to_leave())
message1 = "-ETD-"
if (emergency_shuttle.shuttle.is_launching())
message2 = "Launch"
else
message2 = get_shuttle_timer_departure()
if(evacuation_controller)
if(evacuation_controller.is_prepared())
message1 = "-ETD-"
if (evacuation_controller.waiting_to_leave())
message2 = "Launch"
else
message2 = get_shuttle_timer()
if(length(message2) > CHARS_PER_LINE)
message2 = "Error"
update_display(message1, message2)
else if(evacuation_controller.has_eta())
message1 = "-ETA-"
message2 = get_shuttle_timer()
if(length(message2) > CHARS_PER_LINE)
message2 = "Error"
update_display(message1, message2)
else if(emergency_shuttle.has_eta())
message1 = "-ETA-"
message2 = get_shuttle_timer_arrival()
if(length(message2) > CHARS_PER_LINE)
message2 = "Error"
update_display(message1, message2)
return 1
update_display(message1, message2)
return 1
if(STATUS_DISPLAY_MESSAGE) //custom messages
var/line1
var/line2
@@ -165,14 +166,8 @@
if(maptext != new_text)
maptext = new_text
/obj/machinery/status_display/proc/get_shuttle_timer_arrival()
var/timeleft = emergency_shuttle.estimate_arrival_time()
if(timeleft < 0)
return ""
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
/obj/machinery/status_display/proc/get_shuttle_timer_departure()
var/timeleft = emergency_shuttle.estimate_launch_time()
/obj/machinery/status_display/proc/get_shuttle_timer()
var/timeleft = evacuation_controller.get_eta()
if(timeleft < 0)
return ""
return "[add_zero(num2text((timeleft / 60) % 60),2)]:[add_zero(num2text(timeleft % 60), 2)]"
+6
View File
@@ -721,6 +721,7 @@
/obj/item/seeds/cherryseed = 3,
/obj/item/seeds/chiliseed = 3,
/obj/item/seeds/cocoapodseed = 3,
/obj/item/seeds/coffeeseed = 3,
/obj/item/seeds/cornseed = 3,
/obj/item/seeds/dynseed = 3,
/obj/item/seeds/earthenroot = 2,
@@ -735,6 +736,7 @@
/obj/item/seeds/lemonseed = 3,
/obj/item/seeds/limeseed = 3,
/obj/item/seeds/mtearseed = 3,
/obj/item/seeds/mintseed = 3,
/obj/item/seeds/nifberries = 2,
/obj/item/seeds/onionseed = 3,
/obj/item/seeds/orangeseed = 3,
@@ -755,6 +757,7 @@
/obj/item/seeds/sugarcaneseed = 3,
/obj/item/seeds/sunflowerseed = 3,
/obj/item/seeds/sugartree = 2,
/obj/item/seeds/teaseed = 3,
/obj/item/seeds/tobaccoseed = 3,
/obj/item/seeds/tomatoseed = 3,
/obj/item/seeds/towermycelium = 3,
@@ -787,6 +790,7 @@
/obj/item/seeds/cherryseed = 40,
/obj/item/seeds/chiliseed = 50,
/obj/item/seeds/cocoapodseed = 50,
/obj/item/seeds/coffeeseed = 70,
/obj/item/seeds/cornseed = 30,
/obj/item/seeds/dynseed = 80,
/obj/item/seeds/earthenroot = 70,
@@ -801,6 +805,7 @@
/obj/item/seeds/lemonseed = 40,
/obj/item/seeds/limeseed = 50,
/obj/item/seeds/mtearseed = 60,
/obj/item/seeds/mintseed = 70,
/obj/item/seeds/nifberries = 70,
/obj/item/seeds/onionseed = 30,
/obj/item/seeds/orangeseed = 40,
@@ -821,6 +826,7 @@
/obj/item/seeds/sugarcaneseed = 20,
/obj/item/seeds/sunflowerseed = 20,
/obj/item/seeds/sugartree = 40,
/obj/item/seeds/teaseed = 30,
/obj/item/seeds/tobaccoseed = 40,
/obj/item/seeds/tomatoseed = 30,
/obj/item/seeds/towermycelium = 20,
+31 -18
View File
@@ -2,7 +2,7 @@
name = "portable suit cooling unit"
desc = "A portable heat sink and liquid cooled radiator that can be hooked up to a space suit's existing temperature controls to provide industrial levels of cooling."
w_class = ITEMSIZE_LARGE
icon = 'icons/obj/suitcooler.dmi'
icon = 'icons/obj/contained_items/tools/suitcooler.dmi'
icon_state = "suitcooler0"
item_state = "coolingpack"
contained_sprite = TRUE
@@ -24,7 +24,7 @@
var/cover_open = 0 //is the cover open?
var/obj/item/cell/cell
var/max_cooling = 12 //in degrees per second - probably don't need to mess with heat capacity here
var/charge_consumption = 16.6 //charge per second at max_cooling
var/charge_consumption = 8.3 //charge per second at max_cooling
var/thermostat = T20C
//TODO: make it heat up the surroundings when not in space
@@ -134,8 +134,13 @@
src.cell = null
update_icon()
return
toggle_power(user)
//TODO use a UI like the air tanks
/obj/item/device/suit_cooling_unit/AltClick(mob/user)
if(Adjacent(user))
toggle_power(user)
/obj/item/device/suit_cooling_unit/proc/toggle_power(var/mob/user)
if(on)
turn_off()
else
@@ -177,23 +182,31 @@
return
icon_state = "suitcooler0"
item_state = "coolingpack"
if(!cell || !on)
return
if(cell && on)
var/battery_level = 0
switch(round(cell.percent()))
if(86 to INFINITY)
battery_level = 0
if(69 to 85)
battery_level = 1
if(52 to 68)
battery_level = 2
if(35 to 51)
battery_level = 3
if(18 to 34)
battery_level = 4
if(-INFINITY to 17)
battery_level = 5
switch(round(cell.percent()))
if(86 to INFINITY)
add_overlay("battery-0")
if(69 to 85)
add_overlay("battery-1")
if(52 to 68)
add_overlay("battery-2")
if(35 to 51)
add_overlay("battery-3")
if(18 to 34)
add_overlay("battery-4")
if(-INFINITY to 17)
add_overlay("battery-5")
add_overlay("battery-[battery_level]")
item_state = "coolingpack[battery_level]"
if(ismob(loc))
var/mob/M = loc
M.update_inv_back()
M.update_inv_s_store()
/obj/item/device/suit_cooling_unit/examine(mob/user)
if(!..(user, 1))
+4
View File
@@ -211,6 +211,10 @@ RFD Construction-Class
build_cost = 1
build_type = "floor"
build_atom = /turf/simulated/floor/airless
else if(istype(T, /turf/simulated/open))
build_cost = 1
build_type = "floor"
build_atom = /turf/simulated/floor/airless
else if(istype(T, /turf/simulated/floor))
build_delay = 20
build_cost = 3
+3 -3
View File
@@ -41,7 +41,7 @@
can_place = TRUE
else
for (var/obj/item/grab/G in C.grabbed_by)
if (G.loc == user && G.state >= GRAB_AGGRESSIVE)
if (G.state >= GRAB_AGGRESSIVE)
can_place = TRUE
break
@@ -102,7 +102,7 @@
user.drop_from_inventory(cuffs,target)
else
cuffs.forceMove(target)
if(!legcuff)
target.handcuffed = cuffs
target.update_inv_handcuffed()
@@ -250,4 +250,4 @@
icon_state = "legcuff"
legcuff = TRUE
breakouttime = 30 SECONDS
cuff_type = "legcuffs"
cuff_type = "legcuffs"
@@ -172,12 +172,6 @@
desc = "It's an orange backpack which was designed to hold beakers, pill bottles and bottles."
icon_state = "chempack"
/obj/item/storage/backpack/cloak
name = "tunnel cloak"
desc = "It's a Vaurca cloak with storage pockets."
icon_state = "cape"
sprite_sheets = list(BODYTYPE_VAURCA = 'icons/mob/species/vaurca/back.dmi')
/obj/item/storage/backpack/syndie
name = "syndicate rucksack"
desc = "The latest in carbon fiber and red satin combat rucksack technology. Comfortable and tough!"
@@ -625,4 +619,71 @@
desc = "A small, fashionable bag typically worn over the shoulder."
icon_state = "purse"
item_state = "purse"
max_storage_space = 16
max_storage_space = 16
//**Vaurca cloaks**//
/obj/item/storage/backpack/cloak
name = "tunnel cloak"
desc = "A Vaurca cloak with storage pockets."
icon_state = "cape"
item_state = "cape"
sprite_sheets = list(BODYTYPE_VAURCA = 'icons/mob/species/vaurca/back.dmi')
var/hooded = FALSE
/obj/item/storage/backpack/cloak/verb/toggle_cloak_hood()
set name = "Toggle Cloak Hood"
set desc = "Toggle your cloak hood."
set category = "Object"
set src in usr
if(use_check_and_message(usr))
return 0
hooded = !hooded
to_chat(usr, "You [hooded ? "raise" : "lower"] \the [src] hood.")
icon_state = "[initial(icon_state)][hooded ? "_up" : ""]"
item_state = "icon_state"
var/mob/living/carbon/human/H = src.loc
H.update_icon()
H.update_inv_back()
/obj/item/storage/backpack/cloak/sedantis
name = "Sedantis tunnel cloak"
desc = "A Vaurca cloak with storage pockets. This one has the Sedantis flag design."
icon_state = "sedcape"
item_state = "sedcape"
/obj/item/storage/backpack/cloak/medical
name = "medical tunnel cloak"
desc = "A Vaurca cloak with storage pockets. This one has the medical department design."
icon_state = "medcape"
item_state = "medcape"
/obj/item/storage/backpack/cloak/engi
name = "engineering tunnel cloak"
desc = "A Vaurca cloak with storage pockets. This one has the engineering department design."
icon_state = "engicape"
item_state = "engicape"
/obj/item/storage/backpack/cloak/atmos
name = "atmospherics tunnel cloak"
desc = "A Vaurca cloak with storage pockets. This one has the atmospherics design."
icon_state = "atmoscape"
item_state = "atmoscape"
/obj/item/storage/backpack/cloak/cargo
name = "cargo tunnel cloak"
desc = "A Vaurca cloak with storage pockets. This one has the supply department design."
icon_state = "cargocape"
item_state = "cargocape"
/obj/item/storage/backpack/cloak/sci
name = "science tunnel cloak"
desc = "A Vaurca cloak with storage pockets. This one has the science department design."
icon_state = "scicape"
item_state = "scicape"
/obj/item/storage/backpack/cloak/sec
name = "security tunnel cloak"
desc = "A Vaurca cloak with storage pockets. This one has the security department design."
icon_state = "seccape"
item_state = "seccape"
@@ -46,19 +46,24 @@
var/flipped = null
var/flippable = 1
var/wear_over_suit = 0
var/base_name = ""
/obj/item/storage/wallet/Initialize()
. = ..()
base_name = name
AddComponent(/datum/component/base_name, name)
/obj/item/storage/wallet/proc/update_name(var/base_name = initial(name))
SEND_SIGNAL(src, COMSIG_BASENAME_SETNAME, args)
if(front_id)
name = "[base_name] ([front_id])"
else
name = "[base_name]"
/obj/item/storage/wallet/remove_from_storage(obj/item/W as obj, atom/new_location)
. = ..(W, new_location)
if(.)
if(W == front_id)
front_id = null
name = base_name
update_name()
update_icon()
/obj/item/storage/wallet/handle_item_insertion(obj/item/W as obj, prevent_warning = 0)
@@ -66,7 +71,7 @@
if(.)
if(!front_id && istype(W, /obj/item/card/id))
front_id = W
name = "[name] ([front_id])"
update_name()
update_icon()
/obj/item/storage/wallet/update_icon()
@@ -124,7 +124,7 @@
new /obj/item/clothing/mask/gas/alt(src)
new /obj/item/clothing/mask/gas/half(src)
new /obj/item/auto_cpr(src)
new /obj/item/clothing/suit/storage/toggle/first_responder_jacket(src)
new /obj/item/clothing/suit/storage/toggle/fr_jacket/alt(src)
/obj/structure/closet/secure_closet/CMO
name = "chief medical officer's locker"
@@ -140,6 +140,8 @@
new /obj/item/clothing/accessory/badge/hos(src)
new /obj/item/clothing/gloves/black_leather(src)
new /obj/item/clothing/suit/storage/toggle/armor/hos(src)
new /obj/item/clothing/mask/gas/alt(src)
new /obj/item/clothing/mask/gas/half(src)
//Tools
new /obj/item/device/radio/headset/heads/hos(src)
new /obj/item/device/radio/headset/heads/hos/alt(src)
@@ -0,0 +1,52 @@
/obj/structure/window_frame
name = "window frame"
desc = "An empty window frame."
icon = 'icons/obj/smooth/full_window.dmi'
icon_state = "window_frame"
build_amt = 4
anchored = FALSE
/obj/structure/window_frame/anchored
anchored = TRUE
/obj/structure/window_frame/attackby(obj/item/W, mob/user)
if((W.isscrewdriver()) && (istype(loc, /turf/simulated) || anchored))
playsound(src, W.usesound, 80, 1)
anchored = !anchored
user.visible_message("<span class='notice'>[user] [anchored ? "fastens" : "unfastens"] \the [src].</span>", \
"<span class='notice'>You have [anchored ? "fastened the grille to" : "unfastened the grill from"] the floor.</span>")
return
else if(W.iswelder())
var/obj/item/weldingtool/WT = W
if(!WT.isOn())
to_chat(user, SPAN_WARNING("\The [WT] isn't turned on."))
return
if(WT.remove_fuel(0, user))
to_chat(user, SPAN_NOTICE("You use \the [WT] to remove \the [src]."))
playsound(src, WT.usesound, 80, 1)
new /obj/item/stack/material/steel(get_turf(src),rand(1,3))
qdel(src)
return
else if(istype(W, /obj/item/stack/material) && W.get_material_name() == MATERIAL_GLASS_REINFORCED && anchored)
var/obj/item/stack/material/G = W
if(G.use(4))
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, SPAN_WARNING ("You place the glass on the window frame."))
new /obj/structure/window/full(get_turf(src))
qdel(src)
return
else
to_chat(user, SPAN_WARNING ("You need at least four sheets of reinforced glass to finished the window."))
else if(istype(W, /obj/item/stack/material) && W.get_material_name() == MATERIAL_GLASS_REINFORCED_PHORON && anchored)
var/obj/item/stack/material/G = W
if(G.use(4))
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, SPAN_WARNING ("You place the glass on the window frame."))
new /obj/structure/window/full/phoron(get_turf(src))
qdel(src)
return
else
to_chat(user, SPAN_WARNING ("You need at least four sheets of reinforced borosilicate glass to finished the window."))
+1
View File
@@ -10,6 +10,7 @@
anchored = TRUE
flags = CONDUCT
explosion_resistance = 1
layer = 2.98
var/health = 10
var/destroyed = 0
+24
View File
@@ -870,6 +870,30 @@
/obj/structure/sign/flag/gadpathur/right
icon_state = "gadpathur_r"
/obj/item/flag/vysoka
name = "Free System of Vysoka flag"
desc = "The flag of the Free System of Vysoka."
desc_fluff = "The red, yellow and Coalition-blue flag of Vysoka, as drawn when one wishes to represent the planet as a whole. As Vysokan communities are rather traditional and tied to their respective Host, village or city-state, natives are more likely to \
identify with local symbols. This has not stopped the original flag from being flown in times of much-needed unity."
flag_path = "vysoka"
/obj/structure/sign/flag/vysoka
name = "Free System of Vysoka flag"
desc = "The flag of the Free System of Vysoka."
desc_fluff = "The red, yellow and Coalition-blue flag of Vysoka, as drawn when one wishes to represent the planet as a whole. As Vysokan communities are rather traditional and tied to their respective Host, village or city-state, natives are more likely to \
identify with local symbols. This has not stopped the original flag from being flown in times of much-needed unity."
icon_state = "vysoka"
/obj/item/flag/vysoka/l
name = "large Free System of Vysoka flag"
flag_size = 1
/obj/structure/sign/flag/vysoka/left
icon_state = "vysoka_l"
/obj/structure/sign/flag/vysoka/right
icon_state = "vysoka_r"
/obj/item/flag/afterattack(var/atom/A, var/mob/user, var/adjacent, var/clickparams)
if (!adjacent)
return
@@ -432,9 +432,16 @@
bedpath = /obj/structure/bed/roller/hover
/obj/item/roller/attack_self(mob/user)
var/obj/structure/bed/roller/R = new bedpath(user.loc)
R.add_fingerprint(user)
qdel(src)
..()
deploy_roller(user, user.loc)
/obj/item/roller/afterattack(obj/target, mob/user, proximity)
if(!proximity)
return
if(isturf(target))
var/turf/T = target
if(!T.density)
deploy_roller(user, target)
/obj/item/roller/attackby(obj/item/W as obj, mob/user as mob)
@@ -448,6 +455,11 @@
..()
/obj/item/roller/proc/deploy_roller(mob/user, atom/location)
var/obj/structure/bed/roller/R = new bedpath(location)
R.add_fingerprint(user)
qdel(src)
/obj/item/roller_holder
name = "roller bed rack"
desc = "A rack for carrying a collapsed roller bed."
+83 -39
View File
@@ -19,6 +19,7 @@
var/shardtype = /obj/item/material/shard
var/glasstype = null // Set this in subtypes. Null is assumed strange or otherwise impossible to dismantle, such as for shuttle glass.
var/silicate = 0 // number of units of silicate
var/base_frame = null
atmos_canpass = CANPASS_PROC
@@ -45,6 +46,12 @@
else
to_chat(user, SPAN_NOTICE("There is a thick layer of silicate covering it."))
/obj/structure/window/proc/update_nearby_icons()
queue_smooth_neighbors(src)
/obj/structure/window/update_icon()
queue_smooth(src)
/obj/structure/window/proc/take_damage(var/damage = 0, var/sound_effect = 1)
var/initialhealth = health
@@ -102,6 +109,14 @@
new shardtype(loc) //todo pooling?
if(reinf)
new /obj/item/stack/rods(loc)
if(base_frame)
if(prob(50))
var/obj/F = new base_frame(loc)
F.anchored = anchored
else
new /obj/item/material/shard/shrapnel(loc)
qdel(src)
return
@@ -233,6 +248,7 @@
to_chat(user, (state == 1 ? SPAN_NOTICE("You have unfastened the window from the frame.") : SPAN_NOTICE("You have fastened the window to the frame.")))
else if(reinf && state == 0)
anchored = !anchored
update_icon()
update_nearby_icons()
playsound(loc, W.usesound, 75, 1)
to_chat(user, (anchored ? SPAN_NOTICE("You have fastened the frame to the floor.") : SPAN_NOTICE("You have unfastened the frame from the floor.")))
@@ -241,6 +257,8 @@
update_nearby_icons()
playsound(loc, W.usesound, 75, 1)
to_chat(user, (anchored ? SPAN_NOTICE("You have fastened the window to the floor.") : SPAN_NOTICE("You have unfastened the window.")))
update_icon()
update_nearby_icons()
else if(W.iscrowbar() && reinf && state <= 1)
state = 1 - state
playsound(loc, W.usesound, 75, 1)
@@ -250,12 +268,7 @@
to_chat(user, SPAN_NOTICE("You're not sure how to dismantle \the [src] properly."))
else
visible_message(SPAN_NOTICE("[user] dismantles \the [src]."))
if(dir == SOUTHWEST)
var/obj/item/stack/material/mats = new glasstype(loc)
mats.amount = is_fulltile() ? 4 : 2
else
new glasstype(loc)
qdel(src)
dismantle_window()
else
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
if(W.damtype == BRUTE || W.damtype == BURN)
@@ -300,6 +313,14 @@
take_damage(damage)
return
/obj/structure/window/proc/dismantle_window()
if(dir == SOUTHWEST)
var/obj/item/stack/material/mats = new glasstype(loc)
mats.amount = is_fulltile() ? 4 : 2
else
new glasstype(loc)
qdel(src)
/obj/structure/window/Initialize(mapload, start_dir = null, constructed=0)
. = ..()
@@ -342,33 +363,6 @@
return 1
return 0
//This proc is used to update the icons of nearby windows. It should not be confused with update_nearby_tiles(), which is an atmos proc!
/obj/structure/window/proc/update_nearby_icons()
update_icon()
for(var/obj/structure/window/W in orange(src, 1))
W.update_icon()
//merges adjacent full-tile windows into one (blatant ripoff from game/smoothwall.dm)
/obj/structure/window/update_icon()
//A little cludge here, since I don't know how it will work with slim windows. Most likely VERY wrong.
//this way it will only update full-tile ones
cut_overlays()
if(!is_fulltile())
icon_state = "[basestate]"
return
var/list/dirs = list()
if(anchored)
for(var/obj/structure/window/W in orange(src,1))
if(W.anchored && W.density && W.type == src.type && W.is_fulltile()) //Only counts anchored, not-destroyed fill-tile windows.
dirs += get_dir(src, W)
var/list/connections = dirs_to_corner_states(dirs)
icon_state = ""
for(var/i = 1 to 4)
var/image/I = image(icon, "[basestate][connections[i]]", dir = 1<<(i-1))
add_overlay(I)
/obj/structure/window/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
if(exposed_temperature > maximal_heat)
hit(damage_per_fire_tick, 0)
@@ -514,12 +508,6 @@
/obj/structure/window/shuttle/crescent/take_damage()
return
/obj/structure/window/shuttle/update_nearby_icons()
queue_smooth_neighbors(src)
/obj/structure/window/update_icon()
queue_smooth(src)
/obj/structure/window/reinforced/polarized
name = "electrochromic window"
desc = "Adjusts its tint with voltage. Might take a few good hits to shatter it."
@@ -581,3 +569,59 @@
/obj/machinery/button/switch/windowtint/update_icon()
icon_state = "light[active]"
/obj/structure/window/full
name = "reinforced window"
desc = "It looks rather strong. Might take a few good hits to shatter it."
icon = 'icons/obj/smooth/full_window.dmi'
icon_state = "window_glass"
basestate = "window_glass"
maxhealth = 40
reinf = TRUE
maximal_heat = T0C + 750
dir = 5
smooth = SMOOTH_TRUE
damage_per_fire_tick = 2.0
can_be_unanchored = TRUE
glasstype = /obj/item/stack/material/glass/reinforced
layer = 2.99
base_frame = /obj/structure/window_frame
/obj/structure/window/full/dismantle_window()
var/obj/item/stack/material/mats = new glasstype(loc)
mats.amount = 4
var/obj/structure/window_frame/F = new/obj/structure/window_frame (get_turf(src))
F.anchored = anchored
qdel(src)
/obj/structure/window/full/phoron
name = "reinforced borosilicate window"
desc = "A borosilicate alloy window, with rods supporting it. It seems to be very strong."
icon = 'icons/obj/smooth/phoron_full_window.dmi'
icon_state = "window_glass"
basestate = "window_glass"
shardtype = /obj/item/material/shard/phoron
glasstype = /obj/item/stack/material/glass/phoronrglass
maximal_heat = T0C + 4000
damage_per_fire_tick = 1.0
maxhealth = 80.0
layer = 2.99
base_frame = /obj/structure/window_frame
/obj/structure/window/reinforced/polarized/full
name = "reinforced electrochromic window"
desc = "Adjusts its tint with voltage. Might take a few good hits to shatter it."
icon = 'icons/obj/smooth/full_window.dmi'
icon_state = "window_glass"
basestate = "window_glass"
dir = 5
smooth = SMOOTH_TRUE
layer = 2.99
base_frame = /obj/structure/window_frame
/obj/structure/window/reinforced/polarized/full/dismantle_window()
var/obj/item/stack/material/mats = new glasstype(loc)
mats.amount = 4
var/obj/structure/window_frame/F = new/obj/structure/window_frame (get_turf(src))
F.anchored = anchored
qdel(src)
+47 -9
View File
@@ -87,19 +87,57 @@
update_icon(TRUE)
playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
return
// Repairs.
// Repairs and deconstruction
else if(C.iscrowbar())
if(broken || burnt)
playsound(src, 'sound/items/crowbar_tile.ogg', 80, 1)
visible_message("<span class='notice'>[user] has begun prying off the damaged plating.</span>")
var/turf/T = GetBelow(src)
if(T)
T.visible_message("<span class='warning'>The ceiling above looks as if it's being pried off.</span>")
if(do_after(user, 10 SECONDS))
if(!istype(src, /turf/simulated/floor))
return
if(broken || burnt && !(is_plating()))
return
visible_message("<span class='warning'>[user] has pried off the damaged plating.</span>")
new /obj/item/stack/tile/floor(src)
src.ReplaceWithLattice()
playsound(src, 'sound/items/Deconstruct.ogg', 80, 1)
if(T)
T.visible_message("<span class='danger'>The ceiling above has been pried off!</span>")
return
return
else if(C.iswelder())
var/obj/item/weldingtool/welder = C
if(welder.isOn() && (is_plating()))
if(broken || burnt)
if(welder.remove_fuel(0,user))
to_chat(user, "<span class='notice'>You fix some dents on the broken plating.</span>")
playsound(src, 'sound/items/welder.ogg', 80, 1)
icon_state = "plating"
burnt = null
broken = null
else
to_chat(user, "<span class='warning'>You need more welding fuel to complete this task.</span>")
if(do_after(user, 5 SECONDS))
if(welder.remove_fuel(0, user))
to_chat(user, "<span class='notice'>You fix some dents on the broken plating.</span>")
playsound(src, 'sound/items/Welder.ogg', 80, 1)
icon_state = "plating"
burnt = null
broken = null
else
to_chat(user, "<span class='warning'>You need more welding fuel to complete this task.</span>")
return
else
if(welder.remove_fuel(0, user))
playsound(src, 'sound/items/Welder.ogg', 80, 1)
visible_message("<span class='notice'>[user] has started melting the plating's reinforcements!</span>")
if(do_after(user, 10 SECONDS) && welder.isOn() && welder_melt())
visible_message("<span class='warning'>[user] has melted the plating's reinforcements! It should be possible to pry it off.</span>")
playsound(src, 'sound/items/Welder.ogg', 80, 1)
return
return ..()
/turf/simulated/floor/proc/welder_melt()
if(!(is_plating()) || broken || burnt)
return 0
burnt = 1
update_icon()
return 1
/turf/simulated/floor/can_lay_cable()
return !flooring
+6 -13
View File
@@ -3,22 +3,15 @@
var/dat = ""
dat += "Current Game Mode: <b>[SSticker.mode.name]</b><br>"
dat += "Round Duration: [get_round_duration_formatted()]<br>"
dat += "<b>Emergency Shuttle</b><br>"
if (!emergency_shuttle.online())
dat += "<vui-button :params=\"{ call_shuttle: 1 }\">Call Shuttle</vui-button><br>"
dat += "<b>Evacuation</b><br>"
if (evacuation_controller.is_idle())
dat += "<vui-button :params=\"{ call_shuttle: 1 }\">Call Evacuation</vui-button><br>"
else
if (emergency_shuttle.wait_for_launch)
var/timeleft = emergency_shuttle.estimate_launch_time()
dat += "ETL: <vui-button :params=\"{ edit_shuttle_time: 1 }\">[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</vui-button><br>"
else if (emergency_shuttle.shuttle.has_arrive_time())
var/timeleft = emergency_shuttle.estimate_arrival_time()
dat += "ETA: <vui-button :params=\"{ edit_shuttle_time: 1 }\">[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]</vui-button><br>"
var/timeleft = evacuation_controller.get_eta()
if (evacuation_controller.waiting_to_leave())
dat += "ETA: [(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]<BR>"
dat += "<a href='?src=\ref[src];call_shuttle=2'>Send Back</a><br>"
if (emergency_shuttle.shuttle.moving_status == SHUTTLE_WARMUP)
dat += "Launching now...<br>"
dat += "<vui-button :params=\"{ delay_round_end: 1 }\">[SSticker.delay_end ? "End Round Normally" : "Delay Round End"]</vui-button><br>"
dat += "<hr>"
for(var/antag_type in all_antag_types)
+9 -43
View File
@@ -112,53 +112,19 @@
else if(href_list["call_shuttle"])
if(!check_rights(R_ADMIN)) return
if( SSticker.mode.name == "blob" )
alert("You can't call the shuttle during blob!")
return
switch(href_list["call_shuttle"])
if("1")
if ((!( ROUND_IS_STARTED ) || !emergency_shuttle.location()))
return
if (emergency_shuttle.can_call())
emergency_shuttle.call_evac()
log_admin("[key_name(usr)] called the Emergency Shuttle",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] called the Emergency Shuttle to the station</span>", 1)
if (evacuation_controller.call_evacuation(usr, TRUE))
log_admin("[key_name(usr)] called an evacuation.")
message_admins("[key_name_admin(usr)] called an evacuation.", 1)
if("2")
if (!( ROUND_IS_STARTED ) || !emergency_shuttle.location())
return
if (emergency_shuttle.can_call())
emergency_shuttle.call_evac()
log_admin("[key_name(usr)] called the Emergency Shuttle",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] called the Emergency Shuttle to the station</span>", 1)
else if (emergency_shuttle.can_recall())
emergency_shuttle.recall()
log_admin("[key_name(usr)] sent the Emergency Shuttle back",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] sent the Emergency Shuttle back</span>", 1)
href_list["secretsadmin"] = "check_antagonist"
else if(href_list["edit_shuttle_time"])
if(!check_rights(R_SERVER)) return
if (emergency_shuttle.wait_for_launch)
var/new_time_left = input("Enter new shuttle launch countdown (seconds):","Edit Shuttle Launch Time", emergency_shuttle.estimate_launch_time() ) as num
emergency_shuttle.launch_time = world.time + new_time_left*10
log_admin("[key_name(usr)] edited the Emergency Shuttle's launch time to [new_time_left]",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] edited the Emergency Shuttle's launch time to [new_time_left*10]</span>", 1)
else if (emergency_shuttle.shuttle.has_arrive_time())
var/new_time_left = input("Enter new shuttle arrival time (seconds):","Edit Shuttle Arrival Time", emergency_shuttle.estimate_arrival_time() ) as num
emergency_shuttle.shuttle.arrive_time = world.time + new_time_left*10
log_admin("[key_name(usr)] edited the Emergency Shuttle's arrival time to [new_time_left]",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] edited the Emergency Shuttle's arrival time to [new_time_left*10]</span>", 1)
else
alert("The shuttle is neither counting down to launch nor is it in transit. Please try again when it is.")
if (evacuation_controller.call_evacuation(usr, TRUE))
log_admin("[key_name(usr)] called an evacuation.")
message_admins("[key_name_admin(usr)] called an evacuation.", 1)
else if (evacuation_controller.cancel_evacuation())
log_admin("[key_name(usr)] cancelled an evacuation.")
message_admins("[key_name_admin(usr)] cancelled an evacuation.", 1)
href_list["secretsadmin"] = "check_antagonist"
+4
View File
@@ -58,6 +58,10 @@
objs += d
//to_chat(usr, "Query: [query_text]")
var/static/list/blacklist = list(/datum/configuration)
for(var/datum/D in objs)
if(blacklist[D.type])
objs -= D
message_admins("[usr] executed SDQL query: \"[query_text]\".")
switch(query_tree[1])
+22 -27
View File
@@ -888,67 +888,62 @@ Traitors and the like can also be revived with the previous role mostly intact.
/client/proc/admin_call_shuttle()
set category = "Admin"
set name = "Call Shuttle"
set name = "Call Evacuation"
if ((!( ROUND_IS_STARTED ) || !emergency_shuttle.location()))
if ((!( ROUND_IS_STARTED ) || !evacuation_controller))
return
if(!check_rights(R_ADMIN)) return
if(!check_rights(R_ADMIN))
return
var/confirm = alert(src, "You sure?", "Confirm", "Yes", "No")
if(confirm != "Yes") return
if(alert(src, "Are you sure?", "Confirm", "Yes", "No") != "Yes")
return
var/choice
if(SSticker.mode.auto_recall_shuttle)
choice = input("The shuttle will just return if you call it. Call anyway?") in list("Confirm", "Cancel")
if(choice == "Confirm")
emergency_shuttle.auto_recall = 1 //enable auto-recall
else
if(input("The evacuation will just be cancelled if you call it. Call anyway?") in list("Confirm", "Cancel") != "Confirm")
return
choice = input("Is this an emergency evacuation or a crew transfer?") in list("Emergency", "Crew Transfer")
if (choice == "Emergency")
emergency_shuttle.call_evac()
else
emergency_shuttle.call_transfer()
var/choice = input("Is this an emergency evacuation or a crew transfer?") in list("Emergency", "Crew Transfer")
evacuation_controller.call_evacuation(usr, (choice == "Emergency"))
feedback_add_details("admin_verb","CSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-called the emergency shuttle.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-called the emergency shuttle.</span>", 1)
log_admin("[key_name(usr)] admin-called an evacuation.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-called an evacuation</span>", 1)
return
/client/proc/admin_cancel_shuttle()
set category = "Admin"
set name = "Cancel Shuttle"
set name = "Cancel Evacuation"
if(!check_rights(R_ADMIN)) return
if(alert(src, "You sure?", "Confirm", "Yes", "No") != "Yes") return
if(!ROUND_IS_STARTED || !emergency_shuttle.can_recall())
if(!ROUND_IS_STARTED || !evacuation_controller)
return
emergency_shuttle.recall()
evacuation_controller.cancel_evacuation()
feedback_add_details("admin_verb","CCSHUT") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
log_admin("[key_name(usr)] admin-recalled the emergency shuttle.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-recalled the emergency shuttle.</span>", 1)
log_admin("[key_name(usr)] admin-cancelled the evacuation.",admin_key=key_name(usr))
message_admins("<span class='notice'>[key_name_admin(usr)] admin-cancelled the evacuation.</span>", 1)
return
/client/proc/admin_deny_shuttle()
set category = "Admin"
set name = "Toggle Deny Shuttle"
set name = "Toggle Deny Evacuation"
if (!ROUND_IS_STARTED)
return
if(!check_rights(R_ADMIN)) return
if(!check_rights(R_ADMIN))
return
emergency_shuttle.deny_shuttle = !emergency_shuttle.deny_shuttle
evacuation_controller.deny = !evacuation_controller.deny
log_admin("[key_name(src)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.",admin_key=key_name(usr))
message_admins("[key_name_admin(usr)] has [emergency_shuttle.deny_shuttle ? "denied" : "allowed"] the shuttle to be called.")
log_admin("[key_name(src)] has [evacuation_controller.deny ? "denied" : "allowed"] the evacuation to be called.",admin_key=key_name(usr))
message_admins("[key_name_admin(usr)] has [evacuation_controller.deny ? "denied" : "allowed"] the evacuation to be called.")
/client/proc/cmd_admin_attack_log(mob/M as mob in mob_list)
set category = "Special Verbs"
@@ -21,6 +21,10 @@
if(!D)
return
var/static/list/blacklist = list(/datum/configuration)
if(blacklist[D.type])
return
var/icon/sprite
if(istype(D, /atom))
var/atom/A = D
@@ -211,9 +211,12 @@ var/datum/gear_tweak/custom_name/gear_tweak_free_name = new()
if(!metadata)
return I.name
I.name = metadata
if(I.vars["base_name"])
I.vars["base_name"] = metadata
// For reasons unknown, using SEND_SIGNAL instead of what is below makes rag renaming completely break.
var/datum/component/base_name/BN = I.GetComponent(/datum/component/base_name)
if(BN)
BN.rename(metadata)
/*
Custom Description
*/
@@ -208,8 +208,10 @@
shirt["cropped dress shirt, rolled up"] = /obj/item/clothing/accessory/dressshirt/crop/rolled
shirt["dress shirt, alt"] = /obj/item/clothing/accessory/dressshirt/alt
shirt["dress shirt, alt rolled up"] = /obj/item/clothing/accessory/dressshirt/alt/rolled
shirt["dress shirt, V-Neck alt"] = /obj/item/clothing/accessory/dressshirt/alt/vneck
shirt["dress shirt, V-Neck alt rolled up"] = /obj/item/clothing/accessory/dressshirt/alt/vneck/rolled
shirt["dress shirt, v-neck alt"] = /obj/item/clothing/accessory/dressshirt/alt/vneck
shirt["dress shirt, v-neck alt rolled up"] = /obj/item/clothing/accessory/dressshirt/alt/vneck/rolled
shirt["dress shirt, deep v-neck"] = /obj/item/clothing/accessory/dressshirt/deepv
shirt["dress shirt, deep v-neck rolled up"] = /obj/item/clothing/accessory/dressshirt/deepv/rolled
shirt["long-sleeved shirt"] = /obj/item/clothing/accessory/longsleeve
shirt["long-sleeved shirt, black striped"] = /obj/item/clothing/accessory/longsleeve_s
shirt["long-sleeved shirt, blue striped"] = /obj/item/clothing/accessory/longsleeve_sb
@@ -233,6 +235,22 @@
shirts["random colored silversun shirt"] = /obj/item/clothing/accessory/silversun/random
gear_tweaks += new /datum/gear_tweak/path(shirts)
/datum/gear/accessory/university
display_name = "university sweatshirt selection"
path = /obj/item/clothing/accessory/university
description = "A selection of university sweatshirts."
flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION
/datum/gear/accessory/university/New()
..()
var/list/university = list()
university["grey university sweatshirt"] = /obj/item/clothing/accessory/university
university["crimson university sweatshirt"] = /obj/item/clothing/accessory/university/red
university["mustard university sweatshirt"] = /obj/item/clothing/accessory/university/yellow
university["navy university sweatshirt"] = /obj/item/clothing/accessory/university/blue
university["black university sweatshirt"] = /obj/item/clothing/accessory/university/black
gear_tweaks += new /datum/gear_tweak/path(university)
/datum/gear/accessory/scarf
display_name = "scarf selection"
path = /obj/item/clothing/accessory/scarf
@@ -298,6 +316,11 @@
path = /obj/item/clothing/accessory/badge/namepin
flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION | GEAR_HAS_COLOR_SELECTION
/datum/gear/accessory/ribbon
display_name = "ribbon (colourable)"
path = /obj/item/clothing/accessory/ribbon
flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION | GEAR_HAS_COLOR_SELECTION
/datum/gear/accessory/sleeve_patch
display_name = "shoulder sleeve patch"
path = /obj/item/clothing/accessory/sleevepatch
@@ -9,12 +9,19 @@
flags = GEAR_NO_SELECTION
/datum/gear/augment/eye_sensors
display_name = "integrated eye sensors"
display_name = "integrated eye sensors selection"
description = "An eye augment that allows the user to deploy medical or security sensors."
path = /obj/item/organ/internal/augment/eye_sensors
cost = 3
cost = 1
whitelisted = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD, SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI, SPECIES_UNATHI, SPECIES_SKRELL, SPECIES_IPC, SPECIES_IPC_G1, SPECIES_IPC_G2, SPECIES_IPC_XION, SPECIES_IPC_ZENGHU, SPECIES_IPC_BISHOP, SPECIES_IPC_SHELL, SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR)
/datum/gear/augment/eye_sensors/New()
..()
var/list/sensors = list()
sensors["eye sensors, security"] = /obj/item/organ/internal/augment/eye_sensors/security
sensors["eye sensors, medical"] = /obj/item/organ/internal/augment/eye_sensors/medical
gear_tweaks += new /datum/gear_tweak/path(sensors)
/datum/gear/augment/cyber_hair
display_name = "synthetic hair extensions"
description = "A hair augment that allows the user to change the shape and color of their hair."
@@ -137,6 +144,13 @@
description = "A set of corrective lenses that can be deployed & retracted."
path = /obj/item/organ/internal/augment/tool/correctivelens
/datum/gear/augment/glare_dampeners
display_name = "retractable glare dampeners"
description = "A subdermal implant installed just above the brow line that deploys a thin sheath of hyperpolycarbonate that protects from eye damage associated with arc flash."
path = /obj/item/organ/internal/augment/tool/correctivelens/glare_dampener
allowed_roles = list("Chief Engineer", "Station Engineer", "Atmospheric Technician", "Engineering Apprentice", "Roboticist")
cost = 2
/datum/gear/augment/head_fluff
display_name = "Custom head augmentation"
description = "A fluff based augmentation that can be renamed/redescribed to appear as something else for RP purposes."
@@ -38,6 +38,7 @@
glasses["sunglasses, aviator"] = /obj/item/clothing/glasses/fakesunglasses/aviator
glasses["sunglasses, prescription"] = /obj/item/clothing/glasses/fakesunglasses/prescription
glasses["sunglasses, fat"] = /obj/item/clothing/glasses/fakesunglasses/big
glasses["sunglasses, visor"] = /obj/item/clothing/glasses/fakesunglasses/visor
gear_tweaks += new /datum/gear_tweak/path(glasses)
/datum/gear/eyes/sunglasses
@@ -53,6 +54,7 @@
glasses["flash-proof sunglasses, aviator"] = /obj/item/clothing/glasses/sunglasses/aviator
glasses["flash-proof sunglasses, prescription"] = /obj/item/clothing/glasses/sunglasses/prescription
glasses["flash-proof sunglasses, fat"] = /obj/item/clothing/glasses/sunglasses/big
glasses["flash-proof sunglasses, visor"] = /obj/item/clothing/glasses/sunglasses/visor
gear_tweaks += new /datum/gear_tweak/path(glasses)
/datum/gear/eyes/goggles
@@ -82,6 +84,7 @@
medhud["HUD, medical"] = /obj/item/clothing/glasses/hud/health
medhud["HUDpatch, medical"] = /obj/item/clothing/glasses/eyepatch/hud/medical
medhud["prescription HUD, medical"] = /obj/item/clothing/glasses/hud/health/prescription
medhud["visor sunglasses, medical"] = /obj/item/clothing/glasses/hud/health/aviator/visor
gear_tweaks += new /datum/gear_tweak/path(medhud)
/datum/gear/eyes/sechuds
@@ -99,6 +102,7 @@
sechud["HUD, security"] = /obj/item/clothing/glasses/hud/security
sechud["HUDpatch, security"] = /obj/item/clothing/glasses/eyepatch/hud/security
sechud["prescription HUD, security"] = /obj/item/clothing/glasses/hud/security/prescription
sechud["visor sunglasses, security"] = /obj/item/clothing/glasses/sunglasses/sechud/aviator/visor
gear_tweaks += new /datum/gear_tweak/path(sechud)
/datum/gear/eyes/hudpatch
@@ -165,6 +165,7 @@
banners["banner, Coalition of Colonies"] = /obj/item/flag/coalition
banners["banner, Confederate States of Fisanduh"] = /obj/item/flag/fisanduh
banners["banner, Gadpathur"] = /obj/item/flag/gadpathur
banners["banner, Vysoka"] = /obj/item/flag/vysoka
gear_tweaks += new /datum/gear_tweak/path(banners)
/datum/gear/standard
@@ -212,6 +213,7 @@
flags["flag, Coalition of Colonies"] = /obj/item/flag/coalition/l
flags["flag, Confederate States of Fisanduh"] = /obj/item/flag/fisanduh/l
flags["flag, Gadpathur"] = /obj/item/flag/gadpathur/l
flags["flag, Vysoka"] = /obj/item/flag/vysoka/l
gear_tweaks += new /datum/gear_tweak/path(flags)
/datum/gear/towel
@@ -61,6 +61,7 @@
softcaps["softcap, cargo"] = /obj/item/clothing/head/softcap/cargo
softcaps["softcap, mining"] = /obj/item/clothing/head/softcap/miner
softcaps["softcap, janitor"] = /obj/item/clothing/head/softcap/janitor
softcaps["softcap, tcfl"] = /obj/item/clothing/head/softcap/tcfl
gear_tweaks += new /datum/gear_tweak/path(softcaps)
@@ -108,32 +108,33 @@ datum/gear/suit/colorvest
cost = 1
allowed_roles = list("Scientist", "Chief Medical Officer", "Physician", "Surgeon", "Pharmacist", "First Responder", "Medical Intern", "Xenobiologist", "Roboticist", "Research Director", "Investigator")
/datum/gear/suit/medical_chest_rig
display_name = "medic chest-rig"
description = "A white chest-rig with pouches worn by medical first responders, meant to carry their equipment."
path = /obj/item/clothing/suit/storage/medical_chest_rig
/datum/gear/suit/medical_outerwear
display_name = "medical outerwear (jackets, vests, rigs)"
path = /obj/item/clothing/suit/storage/toggle/fr_jacket
allowed_roles = list("Chief Medical Officer", "Physician", "Surgeon", "Pharmacist", "First Responder", "Medical Intern")
/datum/gear/suit/first_responder_vest
display_name = "first responder vest"
description = "A dark green vest adorned with high-visibility stripes. Has pouches to carry equipment with."
path = /obj/item/clothing/suit/storage/medical_chest_rig/first_responder
allowed_roles = list("Chief Medical Officer", "Physician", "Surgeon", "Pharmacist", "First Responder", "Medical Intern")
/datum/gear/suit/medical_outerwear/New()
..()
var/list/medical_outerwear = list()
medical_outerwear["medical chest-rig"] = /obj/item/clothing/suit/storage/medical_chest_rig
medical_outerwear["first responder vest"] = /obj/item/clothing/suit/storage/medical_chest_rig/first_responder
medical_outerwear["first responder jacket"] = /obj/item/clothing/suit/storage/toggle/fr_jacket/alt
medical_outerwear["first responder jacket, alt"] = /obj/item/clothing/suit/storage/toggle/fr_jacket // this variant is the old bright green one and doesn't go with the NT medic uniform
gear_tweaks += new /datum/gear_tweak/path(medical_outerwear)
/datum/gear/suit/iacvest
display_name = "IAC vest"
description = "It's a lightweight vest. Made of a dark, navy mesh with highly-reflective white material, designed to be worn by the Interstellar Aid Corps."
/datum/gear/suit/iac_outerwear
display_name = "IAC outerwear (jackets, vests, rigs)"
path = /obj/item/clothing/suit/storage/iacvest
allowed_roles = list("Chief Medical Officer", "Physician", "Surgeon", "Pharmacist", "First Responder", "Medical Intern")
flags = GEAR_HAS_DESC_SELECTION
/datum/gear/suit/iaclabcoat
display_name = "IAC labcoat"
description = "It's a standard medical labcoat designed to be worn by the Interstellar Aid Corps."
path = /obj/item/clothing/suit/storage/toggle/labcoat/iac
allowed_roles = list("Chief Medical Officer", "Physician", "Surgeon", "Pharmacist", "First Responder", "Medical Intern")
flags = GEAR_HAS_DESC_SELECTION
/datum/gear/suit/iac_outerwear/New()
..()
var/list/iac_outerwear = list()
iac_outerwear["IAC vest"] = /obj/item/clothing/suit/storage/iacvest
iac_outerwear["IAC labcoat"] = /obj/item/clothing/suit/storage/toggle/labcoat/iac
gear_tweaks += new /datum/gear_tweak/path(iac_outerwear)
/datum/gear/suit/poncho
display_name = "poncho selection"
path = /obj/item/clothing/accessory/poncho
@@ -247,7 +247,7 @@
display_name = "tesla spine"
description = "A People's Republic of Adhomai made tesla spine issued to disabled veterans and civilians."
path = /obj/item/organ/internal/augment/tesla
cost = 4
cost = 2
whitelisted = list(SPECIES_TAJARA, SPECIES_TAJARA_ZHAN, SPECIES_TAJARA_MSAI)
sort_category = "Xenowear - Tajara"
@@ -41,13 +41,33 @@
flags = GEAR_HAS_DESC_SELECTION | GEAR_HAS_COLOR_SELECTION
/datum/gear/cape
display_name = "tunnel cloak"
display_name = "tunnel cloak (recolourable)"
path = /obj/item/storage/backpack/cloak
cost = 1
whitelisted = list(SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR)
sort_category = "Xenowear - Vaurca"
flags = GEAR_HAS_NAME_SELECTION | GEAR_HAS_DESC_SELECTION | GEAR_HAS_COLOR_SELECTION
/datum/gear/cape_selection
display_name = "tunnel cloak selection"
path = /obj/item/storage/backpack/cloak
cost = 1
whitelisted = list(SPECIES_VAURCA_WORKER, SPECIES_VAURCA_WARRIOR)
sort_category = "Xenowear - Vaurca"
flags = GEAR_HAS_DESC_SELECTION
/datum/gear/cape_selection/New()
..()
var/list/capes = list()
capes["tunnel cloak, Sedantis"] = /obj/item/storage/backpack/cloak/sedantis
capes["tunnel cloak, medical"] = /obj/item/storage/backpack/cloak/medical
capes["tunnel cloak, engineering"] = /obj/item/storage/backpack/cloak/engi
capes["tunnel cloak, atmospherics"] = /obj/item/storage/backpack/cloak/atmos
capes["tunnel cloak, cargo"] = /obj/item/storage/backpack/cloak/cargo
capes["tunnel cloak, science"] = /obj/item/storage/backpack/cloak/sci
capes["tunnel cloak, security"] = /obj/item/storage/backpack/cloak/sec
gear_tweaks += new /datum/gear_tweak/path(capes)
/datum/gear/vaurca_robe
display_name = "hive cloak"
description = "A selection of vaurca colored hive cloaks."
+32 -3
View File
@@ -160,6 +160,12 @@ BLIND // can't see anything
attack_self(usr)
/obj/item/clothing/glasses/hud/health/aviator/visor
name = "medical HUD visor"
desc = "Modified visor glasses with a toggled health HUD. Comes with bonus prescription overlay."
icon_state = "visor_medhud"
off_state = "visor_medhud_off"
/obj/item/clothing/glasses/science
name = "science goggles"
desc = "Used to protect your eyes against harmful chemicals!"
@@ -416,6 +422,7 @@ BLIND // can't see anything
item_state = "glasses"
prescription = 7
body_parts_covered = 0
canremove = FALSE
/obj/item/clothing/glasses/sunglasses
name = "sunglasses"
@@ -448,6 +455,12 @@ BLIND // can't see anything
icon_state = "bigsunglasses"
item_state = "sun"
/obj/item/clothing/glasses/sunglasses/visor
name = "visor sunglasses"
desc = "A pair of visor sunglasses."
icon_state = "visor"
item_state = "visor"
//For style with no powergaming connotations.
/obj/item/clothing/glasses/fakesunglasses
@@ -480,6 +493,12 @@ BLIND // can't see anything
icon_state = "bigsunglasses"
item_state = "sun"
/obj/item/clothing/glasses/fakesunglasses/visor
name = "stylish visor sunglasses"
desc = "A pair of designer visor sunglasses."
icon_state = "visor"
item_state = "visor"
/obj/item/clothing/glasses/welding
name = "welding goggles"
desc = "Protects the eyes from welders, approved by the mad scientist association."
@@ -524,12 +543,15 @@ BLIND // can't see anything
/obj/item/clothing/glasses/aug/welding
name = "glare dampeners"
desc = "Protects the eyes from welders."
icon_state = "welding-g"
item_state = "welding-g"
desc = "A subdermal implant installed just above the brow line that deploys a thin sheath of hyperpolycarbonate that protects from eye damage associated with arc flash."
icon = 'icons/clothing/eyes/welding_goggles.dmi'
icon_state = "welding-aug"
item_state = "welding-aug"
contained_sprite = TRUE
item_flags = THICKMATERIAL
flash_protection = FLASH_PROTECTION_MAJOR
tint = TINT_HEAVY
canremove = FALSE
/obj/item/clothing/glasses/aug/throw_at()
usr.drop_from_inventory(src)
@@ -730,6 +752,13 @@ BLIND // can't see anything
icon_state = "aviator_sec_idris"
off_state = "aviator_sec_idris_off"
obj/item/clothing/glasses/sunglasses/sechud/aviator/visor
name = "security HUD visor"
desc = "NanoTrasen security visor glasses that can be switched between HUD and flash protection modes. They come with a built-in prescription overlay."
icon_state = "visor_sec"
off_state = "visor_sec_off"
item_state_slots = list(slot_r_hand_str = "visor_sec", slot_l_hand_str = "visor_sec")
/obj/item/clothing/glasses/thermal
name = "optical thermal scanner"
desc = "Thermals in the shape of glasses."
+10
View File
@@ -3,6 +3,7 @@
desc = "It's a softcap in a tasteless color."
icon = 'icons/obj/clothing/hats/soft_caps.dmi'
icon_state = "softcap"
item_state = "softcap"
item_flags = SHOWFLAVORTEXT
contained_sprite = TRUE
var/flipped = FALSE
@@ -30,6 +31,7 @@
/obj/item/clothing/head/softcap/colorable
icon_state = "softcap_colorable"
item_state = "softcap_colorable"
/obj/item/clothing/head/softcap/colorable/random/Initialize()
. = ..()
@@ -39,6 +41,7 @@
name = "rainbow cap"
desc = "It's a peaked cap in a bright rainbow of colors."
icon_state = "rainbowsoft"
item_state = "rainbowsoft"
/obj/item/clothing/head/softcap/red // Antag red.
name = "red softcap"
@@ -46,6 +49,12 @@
icon_state = "softcap_red"
item_state = "softcap_red"
/obj/item/clothing/head/softcap/tcfl
name = "tcfl cap"
desc = "A rugged softcap in TCFL colours, go Biesel!"
icon_state = "tcfl"
item_state = "tcfl"
// Departmental softcaps. By Wowzewow (Wezzy).
/obj/item/clothing/head/softcap/captain
@@ -132,6 +141,7 @@
name = "eridani cap"
desc = "A grey EPMC fatigue cap with the symbol of the Eridani Corporate Federation on its front. For amoral mercenaries that prefer style over protection."
icon_state = "eridani"
item_state = "eridani"
/obj/item/clothing/head/softcap/zavod
name = "zavodskoi cap"
+9 -8
View File
@@ -8,20 +8,21 @@
heat_protection = UPPER_TORSO|LOWER_TORSO
max_heat_protection_temperature = ARMOR_MAX_HEAT_PROTECTION_TEMPERATURE
siemens_coefficient = 0.5
var/obj/item/storage/internal/pockets
var/obj/item/storage/internal/pockets = /obj/item/storage/internal
var/pocket_slots = 2
var/pocket_size = 2
var/pocket_total = null//This will be calculated, unless specifically overidden
/obj/item/clothing/suit/armor/Initialize()
. = ..()
pockets = new /obj/item/storage/internal(src)
pockets.storage_slots = pocket_slots //two slots
pockets.max_w_class = pocket_size //fit only pocket sized items
if (pocket_total)
pockets.max_storage_space = pocket_total
else
pockets.max_storage_space = pocket_slots * pocket_size
if(pockets)
pockets = new pockets(src)
pockets.storage_slots = pocket_slots //two slots
pockets.max_w_class = pocket_size //fit only pocket sized items
if (pocket_total)
pockets.max_storage_space = pocket_total
else
pockets.max_storage_space = pocket_slots * pocket_size
/obj/item/clothing/suit/armor/Destroy()
if (pockets)
+8 -9
View File
@@ -295,10 +295,17 @@ obj/item/clothing/suit/apron/overalls/blue
item_state = "fr_jacket"
blood_overlay_type = "armor"
allowed = list(/obj/item/stack/medical, /obj/item/reagent_containers/dropper, /obj/item/reagent_containers/hypospray, /obj/item/reagent_containers/syringe, \
/obj/item/device/healthanalyzer, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/tank/emergency_oxygen, /obj/item/device/breath_analyzer, /obj/item/reagent_containers/blood)
/obj/item/device/healthanalyzer, /obj/item/device/flashlight, /obj/item/device/radio, /obj/item/tank/emergency_oxygen, /obj/item/device/breath_analyzer, /obj/item/reagent_containers/blood, /obj/item/clothing/head/hardhat/first_responder)
body_parts_covered = UPPER_TORSO|ARMS
opened = TRUE
/obj/item/clothing/suit/storage/toggle/fr_jacket/alt
desc = "A dark green first responder jacket."
icon = 'icons/clothing/kit/first_responder.dmi'
contained_sprite = TRUE
icon_state = "firstresponderjacket"
item_state = "firstresponderjacket"
/obj/item/clothing/suit/storage/toggle/fr_jacket/ems
name = "\improper EMS jacket"
desc = "A dark blue, martian-pattern, EMS jacket. It sports high-visibility reflective stripes and a star of life on the back."
@@ -331,11 +338,3 @@ obj/item/clothing/suit/apron/overalls/blue
icon_state = "suspenders"
blood_overlay_type = "armor" //it's the less thing that I can put here
body_parts_covered = 0
/obj/item/clothing/suit/storage/toggle/first_responder_jacket
name = "first responder jacket"
desc = "A dark green first responder jacket."
icon = 'icons/clothing/kit/first_responder.dmi'
contained_sprite = TRUE
icon_state = "firstresponderjacket"
item_state = "firstresponderjacket"
+45 -9
View File
@@ -9,55 +9,64 @@
w_class = ITEMSIZE_NORMAL
restricted_accessory_slots = list(ACCESSORY_SLOT_ARMOR_PLATE, ACCESSORY_SLOT_ARM_GUARDS, ACCESSORY_SLOT_LEG_GUARDS, ACCESSORY_SLOT_ARMOR_POCKETS)
valid_accessory_slots = list(ACCESSORY_SLOT_ARMOR_PLATE, ACCESSORY_SLOT_ARM_GUARDS, ACCESSORY_SLOT_LEG_GUARDS, ACCESSORY_SLOT_ARMOR_POCKETS, ACCESSORY_SLOT_GENERIC, ACCESSORY_SLOT_ARMBAND, ACCESSORY_SLOT_CAPE)
pockets = null
/obj/item/clothing/suit/armor/carrier/officer
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate
/obj/item/clothing/accessory/armor_plate,
/obj/item/clothing/accessory/storage/modular_pouch
)
/obj/item/clothing/suit/armor/carrier/hos
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/hos
/obj/item/clothing/accessory/armor_plate/hos,
/obj/item/clothing/accessory/storage/modular_pouch/large
)
/obj/item/clothing/suit/armor/carrier/generic
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/generic
/obj/item/clothing/accessory/armor_plate/generic,
/obj/item/clothing/accessory/storage/modular_pouch
)
/obj/item/clothing/suit/armor/carrier/riot
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/riot,
/obj/item/clothing/accessory/leg_guard/riot,
/obj/item/clothing/accessory/arm_guard/riot
/obj/item/clothing/accessory/arm_guard/riot,
/obj/item/clothing/accessory/storage/modular_pouch
)
/obj/item/clothing/suit/armor/carrier/ballistic
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/ballistic,
/obj/item/clothing/accessory/leg_guard/ballistic,
/obj/item/clothing/accessory/arm_guard/ballistic
/obj/item/clothing/accessory/arm_guard/ballistic,
/obj/item/clothing/accessory/storage/modular_pouch/large
)
/obj/item/clothing/suit/armor/carrier/ablative
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/ablative,
/obj/item/clothing/accessory/leg_guard/ablative,
/obj/item/clothing/accessory/arm_guard/ablative
/obj/item/clothing/accessory/arm_guard/ablative,
/obj/item/clothing/accessory/storage/modular_pouch/large
)
/obj/item/clothing/suit/armor/carrier/military
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/military,
/obj/item/clothing/accessory/leg_guard/military,
/obj/item/clothing/accessory/arm_guard/military
/obj/item/clothing/accessory/arm_guard/military,
/obj/item/clothing/accessory/storage/modular_pouch/large
)
/obj/item/clothing/suit/armor/carrier/heavy
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/heavy,
/obj/item/clothing/accessory/leg_guard/heavy,
/obj/item/clothing/accessory/arm_guard/heavy
/obj/item/clothing/accessory/arm_guard/heavy,
/obj/item/clothing/accessory/storage/modular_pouch/large
)
/obj/item/clothing/suit/armor/carrier/heavy/scc
@@ -65,6 +74,7 @@
/obj/item/clothing/accessory/armor_plate/heavy/scc,
/obj/item/clothing/accessory/leg_guard/heavy/scc,
/obj/item/clothing/accessory/arm_guard/heavy/scc,
/obj/item/clothing/accessory/storage/modular_pouch/large,
/obj/item/clothing/accessory/sleevepatch/scc
)
@@ -72,7 +82,8 @@
starting_accessories = list(
/obj/item/clothing/accessory/armor_plate/heavy/sec,
/obj/item/clothing/accessory/leg_guard/heavy/sec,
/obj/item/clothing/accessory/arm_guard/heavy/sec
/obj/item/clothing/accessory/arm_guard/heavy/sec,
/obj/item/clothing/accessory/storage/modular_pouch/large
)
/obj/item/clothing/accessory/armor_plate
@@ -183,6 +194,31 @@
item_state = "plate_blue"
slowdown = 0 // the SCC is hacking
/obj/item/clothing/accessory/storage/modular_pouch
name = "plate carrier pouches"
desc = "A comfortable set of pouches that can be attached to a plate carrier, allowing the wearer to store some small items."
icon = 'icons/clothing/kit/modular_armor.dmi'
icon_state = "modular_pouch"
item_state = "modular_pouch"
contained_sprite = TRUE
slot = ACCESSORY_SLOT_ARMOR_POCKETS
slots = 2
/obj/item/clothing/accessory/storage/modular_pouch/large
name = "large plate carrier pouches"
desc = "A comfortable set of pouches that can be attached to a plate carrier, allowing the wearer to store some small items. This one uses advanced sewing techniques for additional storage capacity."
slots = 3
/obj/item/clothing/accessory/holster/modular
name = "plate carrier holster"
desc = "A special holster with rigging able to attach to modern modular plate carriers."
icon = 'icons/clothing/kit/modular_armor.dmi'
icon_state = "modular_holster"
item_state = "modular_holster"
contained_sprite = TRUE
slot = ACCESSORY_SLOT_ARMOR_POCKETS
flippable = FALSE
/obj/item/clothing/accessory/armor_plate/heavy/sec
name = "heavy corporate armor plate"
desc = "A heavy and stylish armor plate with blue highlights. That prevents teamkills, right?"
-7
View File
@@ -64,13 +64,6 @@
icon_state = "[initial(icon_state)][opened ? "_open" : ""]"
item_state = icon_state
/obj/item/clothing/suit/armor/carrier/heavy/Initialize()
. = ..()
pockets = new/obj/item/storage/internal(src)
pockets.storage_slots = 4
pockets.max_w_class = ITEMSIZE_SMALL
pockets.max_storage_space = 8
/obj/item/clothing/suit/storage/vest/hos/Initialize()
. = ..()
pockets = new/obj/item/storage/internal(src)
@@ -648,6 +648,14 @@
slot_flags = SLOT_TIE
w_class = ITEMSIZE_TINY
/obj/item/clothing/accessory/ribbon
name = "ribbon"
desc = "A small ribbon to commemorate or support a cause."
icon_state = "ribbon"
item_state = "ribbon"
slot_flags = SLOT_TIE
w_class = ITEMSIZE_TINY
/obj/item/clothing/accessory/sleevepatch
name = "sleeve patch"
desc = "An embroidered patch which can be attached to the shoulder sleeve of clothing."
@@ -8,11 +8,17 @@
var/sound_out = 'sound/weapons/holster/holsterout.ogg'
flippable = 1
w_class = ITEMSIZE_NORMAL
var/base_name = ""
/obj/item/clothing/accessory/holster/Initialize()
. = ..()
base_name = name
AddComponent(/datum/component/base_name, name)
/obj/item/clothing/accessory/holster/proc/update_name(var/base_name = initial(name))
SEND_SIGNAL(src, COMSIG_BASENAME_SETNAME, args)
if(holstered)
name = "occupied [base_name]"
else
name = "[base_name]"
/obj/item/clothing/accessory/holster/proc/holster(var/obj/item/I, var/mob/living/user)
if(holstered && istype(user))
@@ -33,11 +39,11 @@
holstered.add_fingerprint(user)
w_class = max(w_class, holstered.w_class)
user.visible_message("<span class='notice'>[user] holsters \the [holstered].</span>", "<span class='notice'>You holster \the [holstered].</span>")
name = "occupied [base_name]"
update_name()
/obj/item/clothing/accessory/holster/proc/clear_holster()
holstered = null
name = base_name
update_name()
/obj/item/clothing/accessory/holster/proc/unholster(mob/user as mob)
if(!holstered)
@@ -111,13 +117,13 @@
//can't we just use src here?
var/obj/item/clothing/accessory/holster/H = null
if (istype(src, /obj/item/clothing/accessory/holster))
if(istype(src, /obj/item/clothing/accessory/holster))
H = src
else if (istype(src, /obj/item/clothing/under))
var/obj/item/clothing/under/S = src
if (LAZYLEN(S.accessories))
if(!H && istype(src, /obj/item/clothing))
var/obj/item/clothing/S = src
if(LAZYLEN(S.accessories))
H = locate() in S.accessories
else if (istype(src, /obj/item/clothing/suit/armor/tactical)) // This armor is a snowflake and has an integrated holster.
if(!H && istype(src, /obj/item/clothing/suit/armor/tactical)) // This armor is a snowflake and has an integrated holster.
var/obj/item/clothing/suit/armor/tactical/tacticool = src
H = tacticool.holster
@@ -132,6 +132,12 @@
icon_state = "dressshirtvneck_alt"
item_state = "dressshirtvneck_alt"
/obj/item/clothing/accessory/dressshirt/deepv
name = "deep v-neck dress shirt"
desc = "A casual dress shirt with a deep neckline."
icon_state = "dressshirt_deepv"
item_state = "dressshirt_deepv"
/obj/item/clothing/accessory/dressshirt/crop
name = "cropped dress shirt"
desc = "A casual cropped dress shirt."
@@ -153,10 +159,16 @@
/obj/item/clothing/accessory/dressshirt/alt/vneck/rolled
name = "v-neck dress shirt"
desc = "A casual dress shirt."
desc = "A casual dress shirt. This one has its sleeves rolled up."
icon_state = "dressshirtvneck_alt_r"
item_state = "dressshirtvneck_alt_r"
/obj/item/clothing/accessory/dressshirt/deepv/rolled
name = "deep v-neck dress shirt"
desc = "A casual dress shirt with a deep neckline. This one has its sleeves rolled up."
icon_state = "dressshirt_deepv_r"
item_state = "dressshirt_deepv_r"
/obj/item/clothing/accessory/dressshirt/crop/rolled
name = "cropped dress shirt"
desc = "A casual cropped dress shirt. This one has its sleeves rolled up"
@@ -269,3 +281,29 @@
if(prob(50))
icon_state = "hawaii_red"
color = color_rotation(rand(-11,12)*15)
/obj/item/clothing/accessory/university
name = "university sweatshirt"
desc = "A comfy university sweatshirt. This one is grey."
icon_state = "usweatshirt_grey"
item_state = "usweatshirt_grey"
/obj/item/clothing/accessory/university/red
desc = "A comfy university sweatshirt. This one is crimson."
icon_state = "usweatshirt_red"
item_state = "usweatshirt_red"
/obj/item/clothing/accessory/university/yellow
desc = "A comfy university sweatshirt. This one is mustard."
icon_state = "usweatshirt_yellow"
item_state = "usweatshirt_yellow"
/obj/item/clothing/accessory/university/blue
desc = "A comfy university sweatshirt. This one is navy."
icon_state = "usweatshirt_blue"
item_state = "usweatshirt_blue"
/obj/item/clothing/accessory/university/black
desc = "A comfy university sweatshirt. This one is black."
icon_state = "usweatshirt_black"
item_state = "usweatshirt_black"
+2 -2
View File
@@ -52,8 +52,8 @@
if(wired && screwed)
to_chat(usr, "You check your watch, spotting a digital collection of numbers reading '[worldtime2text()]'. Today's date is '[time2text(world.time, "Month DD")]. [game_year]'.")
if (emergency_shuttle.get_status_panel_eta())
to_chat(usr, SPAN_WARNING("The shuttle's status is reported as: [emergency_shuttle.get_status_panel_eta()]."))
if (evacuation_controller.get_status_panel_eta())
to_chat(usr, SPAN_WARNING("The shuttle's status is reported as: [evacuation_controller.get_status_panel_eta()]."))
else if(wired && !screwed)
to_chat(usr, "You check your watch, realising it's still open.")
else
+39 -1
View File
@@ -2133,4 +2133,42 @@ All custom items with worn sprites must follow the contained sprite system: http
closed_desc = " The pages within are a mix of clearly indexed case files, and study notes alongside less clearly indexed pages that appears to be fragmented thoughts, not unlike a diary. The very first page of the journal reads “dedicated to Qirandri Mrorirhaldarr” and is signed “Mrradar Sanufar” underneath."
icon = 'icons/obj/custom_items/kathira_journal.dmi'
icon_state = "kath_journal"
item_state = "kath_journal"
item_state = "kath_journal"
/obj/item/storage/pill_bottle/dice/fluff/suraya_dicebag //Crevan Dice Bag - Suraya Al-Zahrani - Omicega
name = "velvet dice bag"
desc = "A deep purple dice bag fashioned from Adhomian velvet, with two little drawstrings to tighten the neck closed."
icon = 'icons/obj/custom_items/suraya_dice.dmi'
icon_state = "sur_dbag"
item_state = "sur_dbag"
starts_with = list(
/obj/item/dice/fluff/suraya_dice = 3,
/obj/item/dice/fluff/suraya_dice/alt = 3
)
/obj/item/dice/fluff/suraya_dice
name = "blue adhomian die"
desc = "A blue-and-gold wooden die with six sides, beautifully carved and delicately painted. The single dot on the number one side is, on closer inspection, a miniature image of the god Rredouane."
icon = 'icons/obj/custom_items/suraya_dice.dmi'
icon_state = "sur_b_d1"
base_icon = "sur_b_d"
favored_number = 1
weighted_value = 22
/obj/item/dice/fluff/suraya_dice/AltClick(mob/user)
weighted = !weighted
if(!weighted)
to_chat(user, SPAN_NOTICE("You jiggle the die rapidly in your hand, resetting the internal weighting."))
else
to_chat(user, SPAN_NOTICE("You carefully jiggle the die one way, then the other, allowing its internal weighting to lock into place."))
user.visible_message("<b>\The [user]</b> jiggles \the [src] around in their hand for a second.")
/obj/item/dice/fluff/suraya_dice/alt
name = "green adhomian die"
desc = "A green-and-silver wooden die with six sides, beautifully carved and delicately painted. The single dot on the number one side is, on closer inspection, a miniature image of the god Rredouane."
icon_state = "sur_g_d1"
base_icon = "sur_g_d"
favored_number = 6
@@ -9,11 +9,10 @@
w_class = ITEMSIZE_SMALL
var/obj/item/stored_item = null
var/label_text = ""
var/base_name = ""
/obj/item/evidencebag/Initialize()
. = ..()
base_name = name
AddComponent(/datum/component/base_name, name)
/obj/item/evidencebag/MouseDrop(var/obj/item/I as obj)
if (!ishuman(usr))
@@ -111,7 +110,8 @@
return
. = ..()
/obj/item/evidencebag/proc/update_name_label()
/obj/item/evidencebag/proc/update_name_label(var/base_name = initial(name))
SEND_SIGNAL(src, COMSIG_BASENAME_SETNAME, args)
if(label_text == "")
name = base_name
else
+3 -2
View File
@@ -64,7 +64,8 @@
update_name()
update_icon()
/obj/item/reagent_containers/glass/rag/proc/update_name()
/obj/item/reagent_containers/glass/rag/proc/update_name(var/base_name = initial(name))
SEND_SIGNAL(src, COMSIG_BASENAME_SETNAME, args)
if(on_fire)
name = "burning [base_name]"
else if(reagents.total_volume)
@@ -107,7 +108,7 @@
/obj/item/reagent_containers/glass/rag/proc/wipe_down(atom/A, mob/user)
if(!reagents.total_volume)
to_chat(user, SPAN_WARNING("\The [base_name] is dry!"))
to_chat(user, SPAN_WARNING("\The [name] is dry!"))
else
if (!(last_clean && world.time < last_clean + 120) )
user.visible_message("<b>[user]</b> starts to wipe [A] with [src].")
@@ -5,6 +5,7 @@
var/grill_path = /obj/structure/grille
var/spawn_firedoor = FALSE
var/activated
var/single_window = FALSE
// stops ZAS expanding zones past us, the windows will block the zone anyway
/obj/effect/map_effect/wingrille_spawn/CanPass()
@@ -37,23 +38,26 @@
if (!locate(grill_path) in get_turf(src))
var/obj/structure/grille/G = new grill_path(src.loc)
handle_grille_spawn(G)
var/list/neighbours = list()
for (var/dir in cardinal)
var/turf/T = get_step(src, dir)
var/obj/effect/map_effect/wingrille_spawn/other = locate(/obj/effect/map_effect/wingrille_spawn) in T
if(!other)
var/found_connection
if(locate(grill_path) in T)
for(var/obj/structure/window/W in T)
if(W.type == win_path && W.dir == get_dir(T,src))
found_connection = 1
qdel(W)
if(!found_connection)
var/obj/structure/window/new_win = new win_path(src.loc)
new_win.set_dir(dir)
handle_window_spawn(new_win)
else
neighbours |= other
if(!single_window)
var/list/neighbours = list()
for (var/dir in cardinal)
var/turf/T = get_step(src, dir)
var/obj/effect/map_effect/wingrille_spawn/other = locate(/obj/effect/map_effect/wingrille_spawn) in T
if(!other)
var/found_connection
if(locate(grill_path) in T)
for(var/obj/structure/window/W in T)
if(W.type == win_path && W.dir == get_dir(T,src))
found_connection = 1
qdel(W)
if(!found_connection)
var/obj/structure/window/new_win = new win_path(src.loc)
new_win.set_dir(dir)
handle_window_spawn(new_win)
else
neighbours |= other
else
new win_path(loc)
activated = 1
/obj/effect/map_effect/wingrille_spawn/proc/handle_window_spawn(var/obj/structure/window/W)
@@ -97,4 +101,23 @@
/obj/effect/map_effect/wingrille_spawn/reinforced/polarized/handle_window_spawn(var/obj/structure/window/reinforced/polarized/P)
if(id)
P.id = id
P.id = id
/obj/effect/map_effect/wingrille_spawn/full
name = "full window grille spawner"
icon_state = "full_window"
win_path = /obj/structure/window/full
grill_path = /obj/structure/grille
spawn_firedoor = TRUE
single_window = TRUE
/obj/effect/map_effect/wingrille_spawn/full/phoron
icon_state = "full_phoron_window"
win_path = /obj/structure/window/full/phoron
single_window = TRUE
/obj/effect/map_effect/wingrille_spawn/reinforced/polarized/full
name = "full polarized window grille spawner"
icon_state = "full_window"
win_path = /obj/structure/window/reinforced/polarized/full
single_window = TRUE
+1
View File
@@ -172,6 +172,7 @@
disable()
if(welcome_message)
to_chat(user, SPAN_NOTICE(welcome_message))
universe.OnPlayerLatejoin(user)
return TRUE
//Proc to check if a specific user can edit this spawner (open/close/...)
@@ -177,7 +177,7 @@
if(start_location.landmark_tag != "nav_emergency_start")
return TRUE
if(emergency_shuttle.evac)
if(evacuation_controller.emergency_evacuation)
if(get_security_level() != "green" )
var/datum/wifi/sender/door/wifi_sender = new("odin_arrivals_lockdown", SSghostroles)
wifi_sender.activate("close")
@@ -13,7 +13,7 @@
//Vars related to human mobs
outfit = /datum/outfit/admin/random/visitor
possible_species = list(SPECIES_HUMAN, SPECIES_SKRELL, SPECIES_TAJARA, SPECIES_UNATHI)
possible_species = list(SPECIES_HUMAN, SPECIES_HUMAN_OFFWORLD, SPECIES_TAJARA, SPECIES_TAJARA_MSAI, SPECIES_TAJARA_ZHAN, SPECIES_SKRELL, SPECIES_UNATHI, SPECIES_VAURCA_WARRIOR, SPECIES_VAURCA_WORKER, SPECIES_IPC, SPECIES_IPC_XION, SPECIES_IPC_ZENGHU, SPECIES_IPC_BISHOP, SPECIES_IPC_SHELL, SPECIES_IPC_G1, SPECIES_IPC_G2)
allow_appearance_change = APPEARANCE_PLASTICSURGERY
assigned_role = "Visitor"
+2
View File
@@ -475,6 +475,8 @@
return FALSE
/mob/living/simple_animal/penguin/holodeck/baby
name = "baby penguin"
desc = "Can't fly and barely waddles, yet the prince of all chicks."
icon_state = "penguin_baby"
icon_living = "penguin_baby"
icon_dead = "penguin_baby_dead"
+25 -1
View File
@@ -87,7 +87,7 @@
seed_name = "green grape"
display_name = "green grapevines"
mutants = null
chems = list(/decl/reagent/nutriment = list(1,10), /decl/reagent/kelotane = list(3,5), /decl/reagent/drink/grapejuice = list(10,10))
chems = list(/decl/reagent/nutriment = list(1,10), /decl/reagent/kelotane = list(3,5), /decl/reagent/drink/whitegrapejuice = list(10,10))
/datum/seed/grapes/green/setup_traits()
..()
@@ -375,3 +375,27 @@
/obj/item/seeds/pumpkinseed
seed_type = "pumpkin"
//coffee beans are considered a fruit and seed, commonly considered a "cherry" of the plant
/datum/seed/coffee
name = "coffee"
seed_name = "coffee beans"
display_name = "coffee bush"
chems = list(/decl/reagent/nutriment/coffeegrounds = list(2,10))
kitchen_tag = "coffee"
/datum/seed/coffee/setup_traits()
..()
set_trait(TRAIT_HARVEST_REPEAT,1)
set_trait(TRAIT_MATURATION,3)
set_trait(TRAIT_PRODUCTION,3)
set_trait(TRAIT_YIELD,4)
set_trait(TRAIT_POTENCY,2)
set_trait(TRAIT_PRODUCT_ICON,"bean2")
set_trait(TRAIT_PRODUCT_COLOUR,"#be9109")
set_trait(TRAIT_PLANT_ICON,"bush2")
set_trait(TRAIT_IDEAL_LIGHT, 6)
/obj/item/seeds/coffeeseed
seed_type = "coffee"
@@ -0,0 +1,44 @@
/datum/seed/mint
name = "mint"
seed_name = "mint leaf"
display_name = "mint plant"
chems = list(/decl/reagent/nutriment/mint = list(2,10))
kitchen_tag = "mint"
//I wasnt sure if tea and mint would be a flower or something, so i just made a herb file..
/datum/seed/mint/setup_traits()
..()
set_trait(TRAIT_MATURATION,3)
set_trait(TRAIT_PRODUCTION,3)
set_trait(TRAIT_YIELD,3)
set_trait(TRAIT_POTENCY,2)
set_trait(TRAIT_PRODUCT_ICON,"herb")
set_trait(TRAIT_PRODUCT_COLOUR,"#4dd298")
set_trait(TRAIT_PLANT_ICON,"herb")
set_trait(TRAIT_IDEAL_LIGHT, 6)
/obj/item/seeds/mintseed
seed_type = "mint"
/datum/seed/tea
name = "tea"
seed_name = "tea leaf"
display_name = "tea plant"
chems = list(/decl/reagent/nutriment/teagrounds = list(2,10))
kitchen_tag = "tea"
/datum/seed/tea/setup_traits()
..()
set_trait(TRAIT_MATURATION,3)
set_trait(TRAIT_PRODUCTION,3)
set_trait(TRAIT_YIELD,3)
set_trait(TRAIT_POTENCY,2)
set_trait(TRAIT_PRODUCT_ICON,"herb")
set_trait(TRAIT_PRODUCT_COLOUR,"#4fd24d")
set_trait(TRAIT_PLANT_ICON,"herb")
set_trait(TRAIT_IDEAL_LIGHT, 6)
/obj/item/seeds/teaseed
seed_type = "tea"
+6
View File
@@ -52,6 +52,7 @@
/obj/item/seeds/cherryseed = 3,
/obj/item/seeds/chiliseed = 3,
/obj/item/seeds/cocoapodseed = 3,
/obj/item/seeds/coffeeseed = 3,
/obj/item/seeds/cornseed = 3,
/obj/item/seeds/dynseed = 3,
/obj/item/seeds/earthenroot = 2,
@@ -64,6 +65,7 @@
/obj/item/seeds/lemonseed = 3,
/obj/item/seeds/limeseed = 3,
/obj/item/seeds/mtearseed = 2,
/obj/item/seeds/mintseed = 3,
/obj/item/seeds/nifberries = 2,
/obj/item/seeds/onionseed = 3,
/obj/item/seeds/orangeseed = 3,
@@ -84,6 +86,7 @@
/obj/item/seeds/sugarcaneseed = 3,
/obj/item/seeds/sugartree = 2,
/obj/item/seeds/sunflowerseed = 3,
/obj/item/seeds/teaseed = 3,
/obj/item/seeds/tobaccoseed = 3,
/obj/item/seeds/tomatoseed = 3,
/obj/item/seeds/towermycelium = 3,
@@ -115,6 +118,7 @@
/obj/item/seeds/cherryseed = 3,
/obj/item/seeds/chiliseed = 3,
/obj/item/seeds/cocoapodseed = 3,
/obj/item/seeds/coffeeseed = 3,
/obj/item/seeds/cornseed = 3,
/obj/item/seeds/replicapod = 3,
/obj/item/seeds/earthenroot = 2,
@@ -128,6 +132,7 @@
/obj/item/seeds/libertymycelium = 2,
/obj/item/seeds/limeseed = 3,
/obj/item/seeds/mtearseed = 2,
/obj/item/seeds/mintseed = 3,
/obj/item/seeds/nettleseed = 2,
/obj/item/seeds/nifberries = 2,
/obj/item/seeds/onionseed = 3,
@@ -146,6 +151,7 @@
/obj/item/seeds/sunflowerseed = 3,
/obj/item/seeds/sugartree = 2,
/obj/item/seeds/shandseed = 2,
/obj/item/seeds/teaseed = 3,
/obj/item/seeds/tobaccoseed = 3,
/obj/item/seeds/tomatoseed = 3,
/obj/item/seeds/towermycelium = 3,
@@ -52,6 +52,7 @@
new /datum/stack_recipe("metal rod", /obj/item/stack/rods, 1, 2, 60),
new /datum/stack_recipe("table frame", /obj/structure/table, BUILD_AMT, time = 10, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("wall girders", /obj/structure/girder, BUILD_AMT, time = 50, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("window frame", /obj/structure/window_frame, BUILD_AMT, time = 10, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("computer frame", /obj/structure/computerframe, BUILD_AMT, time = 25, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("machine blueprint", /obj/machinery/constructable_frame/machine_frame, 2, time = 25, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("light fixture frame", /obj/item/frame/light, 2),
+5 -1
View File
@@ -81,7 +81,11 @@
interact(user)
/obj/machinery/mineral/processing_unit_console/proc/get_user_id(var/mob/user)
if(!scanned_id && !isDrone(user))
if(isDrone(user))
var/mob/living/silicon/robot/drone/D = user
if(D.standard_drone)
return
if(!scanned_id)
var/obj/item/card/id/ID = user.GetIdCard()
if(ID)
scanned_id = WEAKREF(ID)
+5 -1
View File
@@ -118,7 +118,11 @@ var/global/list/minevendor_list = list( //keep in order of price
interact(user)
/obj/machinery/mineral/equipment_vendor/proc/get_user_id(var/mob/user)
if(!scanned_id && !isDrone(user))
if(isDrone(user))
var/mob/living/silicon/robot/drone/D = user
if(D.standard_drone)
return
if(!scanned_id)
var/obj/item/card/id/ID = user.GetIdCard()
if(ID)
scanned_id = WEAKREF(ID)
+1 -4
View File
@@ -14,6 +14,7 @@
speed = -1
hat_x_offset = 1
hat_y_offset = -12
standard_drone = FALSE
var/seeking_player = FALSE
var/health_upgrade
var/ranged_upgrade
@@ -23,10 +24,6 @@
. = ..()
verbs |= /mob/living/proc/hide
remove_language(LANGUAGE_ROBOT)
remove_language(LANGUAGE_DRONE)
add_language(LANGUAGE_TCB, TRUE)
add_language(LANGUAGE_EAL, TRUE)
//They are unable to be upgraded, so let's give them a bit of a better battery.
cell.maxcharge = 10000
@@ -279,6 +279,7 @@ INITIALIZE_IMMEDIATE(/mob/abstract/new_player)
character.buckled_to.set_dir(character.dir)
SSticker.mode.handle_latejoin(character)
universe.OnPlayerLatejoin(character)
if(SSjobs.ShouldCreateRecords(character.mind))
if(character.mind.assigned_role != "Cyborg")
SSrecords.generate_record(character)
@@ -1733,7 +1733,8 @@ Follow by example and make good judgement based on length which list to include
/datum/sprite_accessory/hair_gradients
icon = 'icons/mob/hair_gradients.dmi'
species_allowed = list(/datum/species/human,/datum/species/human/offworlder,/datum/species/machine/shell,/datum/species/machine/shell/rogue,/datum/species/zombie,
/datum/species/tajaran,/datum/species/tajaran/zhan_khazan,/datum/species/tajaran/m_sai,/datum/species/zombie/tajara)
/datum/species/tajaran,/datum/species/tajaran/zhan_khazan,/datum/species/tajaran/m_sai,/datum/species/zombie/tajara,
/datum/species/skrell, /datum/species/zombie/skrell, /datum/species/bug, /datum/species/bug/type_b)
none
name = "None"
@@ -2506,6 +2507,24 @@ Follow by example and make good judgement based on length which list to include
length = 3
chatname = "styled mane"
taj_ears_swoop
name = "Tajara Swoop"
icon_state = "hair_swoop"
length = 2
chatname = "styled mane"
taj_ears_swoop_long
name = "Tajara Swoop Long"
icon_state = "hair_longswoop"
length = 3
chatname = "styled mane"
taj_ears_swoop_long_alt
name = "Tajara Swoop Long Alt"
icon_state = "hair_longswoop_alt"
length = 3
chatname = "styled mane"
//msai hair, longer ears
msai_ears
icon = 'icons/mob/human_face/msai_hair.dmi'
@@ -2749,6 +2768,24 @@ Follow by example and make good judgement based on length which list to include
length = 3
chatname = "styled mane"
msai_ears_swoop
name = "M'sai Swoop"
icon_state = "msai_swoop"
length = 2
chatname = "styled mane"
msai_ears_swoop_long
name = "M'sai Swoop Long"
icon_state = "msai_longswoop"
length = 3
chatname = "styled mane"
msai_ears_swoop_long_alt
name = "M'sai Swoop Long Alt"
icon_state = "msai_longswoop_alt"
length = 3
chatname = "styled mane"
//vaurca antennae
vaurca_classic
icon = 'icons/mob/human_face/vaurca_hair.dmi'
@@ -3271,6 +3308,61 @@ Follow by example and make good judgement based on length which list to include
name = "Glorp"
icon_state = "glorp"
anglerfish
icon = 'icons/mob/human_face/skrell_beards.dmi'
name = "Anglerfish"
icon_state = "Anglerfish"
species_allowed = list(/datum/species/skrell)
gender = NEUTER
triton
name = "Triton"
icon_state = "Triton"
big_triton
name = "Big Triton"
icon_state = "Big_Triton"
ahab
name = "Ahab"
icon_state = "Ahab"
monotail
name = "Monotail"
icon_state = "Monotail"
long_monotail
name = "Long Monotail"
icon_state = "Long_Monotail"
face_adorns
name = "Face Adorns"
icon_state = "Face_Adorns"
sea_captain
name = "Sea Captain"
icon_state = "Sea_Captain"
fisherman
name = "Fisherman"
icon_state = "Fisherman"
sailor
name = "Sailor"
icon_state = "Sailor"
overgrown
name = "Overgrown"
icon_state = "Overgrown"
marauder_left
name = "Marauder (Left)"
icon_state = "Marauder_Left"
marauder_right
name = "Marauder (Right)"
icon_state = "Marauder_Right"
/*
////////////////////////////
/ =--------------------= /
@@ -3710,6 +3802,24 @@ Follow by example and make good judgement based on length which list to include
body_parts = list(BP_HEAD)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/bug, /datum/species/bug/type_b)
scar_chest
name = "Scar, Chest"
icon_state = "surgicalscar_chest"
body_parts = list(BP_CHEST)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, /datum/species/bug, /datum/species/bug/type_b)
scar_chest_left
name = "Scar, Chest Left"
icon_state = "chestscar_l_chest"
body_parts = list(BP_CHEST)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, /datum/species/bug, /datum/species/bug/type_b)
scar_chest_right
name = "Scar, Chest Right"
icon_state = "chestscar_r_chest"
body_parts = list(BP_CHEST)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi, /datum/species/bug, /datum/species/bug/type_b)
scratch_abdomen_left
name = "Scratch, Abdomen Left"
icon_state = "scratch_abdomen_l"
@@ -3782,6 +3892,18 @@ Follow by example and make good judgement based on length which list to include
body_parts= list(BP_R_LEG)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi)
tat_circle_back
name = "Tattoo (Circle, Back)"
icon_state = "tat_circle_back"
body_parts = list(BP_CHEST)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi)
tat_circle_big_back
name = "Tattoo (Big Circle, Back)"
icon_state = "tat_bigcircle_back"
body_parts = list(BP_CHEST)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi)
tat_forrest_left
name = "Tattoo (Forrest, Left Eye)"
icon_state = "tat_forrest_l"
@@ -3794,6 +3916,12 @@ Follow by example and make good judgement based on length which list to include
body_parts = list(BP_HEAD)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi)
tat_harness
name = "Tattoo (Harness, Chest)"
icon_state = "tat_harness_body"
body_parts = list(BP_CHEST)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi)
tat_hive
name = "Tattoo (Hive, Back)"
icon_state = "tat_hive"
@@ -3890,6 +4018,12 @@ Follow by example and make good judgement based on length which list to include
body_parts = list(BP_R_LEG)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi)
tat_spine_back
name = "Tattoo (Spine, Back)"
icon_state = "tat_spine_back"
body_parts = list(BP_CHEST)
species_allowed = list(/datum/species/human, /datum/species/human/offworlder, /datum/species/diona, /datum/species/machine/shell, /datum/species/skrell, /datum/species/tajaran, /datum/species/tajaran/zhan_khazan, /datum/species/tajaran/m_sai, /datum/species/unathi)
tat_tamoko
name = "Tattoo (Ta Moko, Face)"
icon_state = "tat_tamoko"
@@ -266,8 +266,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
/mob/abstract/observer/Stat()
..()
if(statpanel("Status"))
if(emergency_shuttle)
var/eta_status = emergency_shuttle.get_status_panel_eta()
if(evacuation_controller)
var/eta_status = evacuation_controller.get_status_panel_eta()
if(eta_status)
stat(null, eta_status)
+5 -1
View File
@@ -9,9 +9,13 @@
//Or someone snoring. So we make it where they won't hear it.
return
if((language && (language.flags & KNOWONLYHEAR)) && !say_understands(speaker, language))
return
//make sure the air can transmit speech - hearer's side
var/turf/T = get_turf(src)
if ((T) && (!(isobserver(src)))) //Ghosts can hear even in vacuum.
var/vacuum_proof = ((language && (language.flags & PRESSUREPROOF)) || isobserver(src))
if(T && !vacuum_proof) //Ghosts can hear even in vacuum.
var/datum/gas_mixture/environment = T.return_air()
var/pressure = (environment)? environment.return_pressure() : 0
if(pressure < SOUND_MINIMUM_PRESSURE && get_dist(speaker, src) > 1)
+3
View File
@@ -175,6 +175,9 @@
chosen_verb = speech_verb
return pick(chosen_verb)
/datum/language/proc/handle_message_mode(var/message_mode)
return list(src, message_mode)
// Language handling.
/mob/proc/add_language(var/language)
var/datum/language/new_language
+15 -1
View File
@@ -68,4 +68,18 @@
return "1em"
/mob/living/silicon/robot/drone/construction/matriarch/get_binary_font_size()
return "1.2em"
return "1.2em"
/datum/language/local_drone
name = LANGUAGE_LOCAL_DRONE
desc = "A heavily encoded damage coordination transmission, only supplied to drones within sight."
speech_verb = list("transmits")
ask_verb = list("transmits")
exclaim_verb = list("transmits")
key = "do"
flags = RESTRICTED | KNOWONLYHEAR | PRESSUREPROOF | PASSLISTENOBJ
/datum/language/local_drone/handle_message_mode(var/message_mode)
if(message_mode == "headset")
return list(all_languages[LANGUAGE_DRONE], null)
return list(src, null)

Some files were not shown because too many files have changed in this diff Show More