Merge branch 'master' into upstream-merge-33783
This commit is contained in:
@@ -267,6 +267,13 @@
|
||||
if(!target_turf)
|
||||
return NULLTURF_BORDER
|
||||
|
||||
var/area/target_area = get_area(target_turf)
|
||||
var/area/source_area = get_area(source)
|
||||
if(source_area.canSmoothWithAreas && !is_type_in_typecache(target_area, source_area.canSmoothWithAreas))
|
||||
return null
|
||||
if(target_area.canSmoothWithAreas && !is_type_in_typecache(source_area, target_area.canSmoothWithAreas))
|
||||
return null
|
||||
|
||||
if(source.canSmoothWith)
|
||||
var/atom/A
|
||||
if(source.smooth & SMOOTH_MORE)
|
||||
|
||||
+44
-41
@@ -1,41 +1,24 @@
|
||||
#define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend
|
||||
#define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcomm/shuttles marked as escaped
|
||||
#define POPCOUNT_GHOSTS "ghosts" //Ghosts on roundend
|
||||
#define POPCOUNT_HUMAN_ESCAPEES "human_escapees" //Same as escapees but human only
|
||||
#define POPCOUNT_HUMAN_SURVIVORS "human_survivors" //Same as survivors but human only
|
||||
#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only.
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/gather_roundend_feedback()
|
||||
//Survivor numbers
|
||||
var/clients = GLOB.player_list.len
|
||||
var/surviving_humans = 0
|
||||
var/surviving_total = 0
|
||||
var/ghosts = 0
|
||||
var/escaped_humans = 0
|
||||
var/escaped_total = 0
|
||||
var/popcount = count_survivors()
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_GHOSTS], list("ghosts"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_HUMAN_SURVIVORS], list("survivors", "human"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_SURVIVORS], list("survivors", "total"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_HUMAN_ESCAPEES], list("escapees", "human"))
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_ESCAPEES], list("escapees", "total"))
|
||||
//Antag information
|
||||
gather_antag_data()
|
||||
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
if(ishuman(M))
|
||||
if(!M.stat)
|
||||
surviving_humans++
|
||||
if(M.z == ZLEVEL_CENTCOM)
|
||||
escaped_humans++
|
||||
if(!M.stat)
|
||||
surviving_total++
|
||||
if(M.z == ZLEVEL_CENTCOM)
|
||||
escaped_total++
|
||||
|
||||
if(isobserver(M))
|
||||
ghosts++
|
||||
|
||||
if(clients)
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients"))
|
||||
if(ghosts)
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", ghosts, list("ghosts"))
|
||||
if(surviving_humans)
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_humans, list("survivors", "human"))
|
||||
if(surviving_total)
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", surviving_total, list("survivors", "total"))
|
||||
if(escaped_humans)
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_humans, list("escapees", "human"))
|
||||
if(escaped_total)
|
||||
SSblackbox.record_feedback("nested tally", "round_end_stats", escaped_total, list("escapees", "total"))
|
||||
|
||||
gather_antag_success_rate()
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/gather_antag_success_rate()
|
||||
/datum/controller/subsystem/ticker/proc/gather_antag_data()
|
||||
var/team_gid = 1
|
||||
var/list/team_ids = list()
|
||||
|
||||
@@ -169,29 +152,49 @@
|
||||
|
||||
return parts.Join()
|
||||
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/survivor_report()
|
||||
var/list/parts = list()
|
||||
/datum/controller/subsystem/ticker/proc/count_survivors()
|
||||
. = list()
|
||||
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
|
||||
var/num_survivors = 0
|
||||
var/num_escapees = 0
|
||||
var/num_shuttle_escapees = 0
|
||||
var/num_ghosts = 0
|
||||
var/num_human_survivors = 0
|
||||
var/num_human_escapees = 0
|
||||
|
||||
//Player status report
|
||||
for(var/i in GLOB.mob_list)
|
||||
var/mob/Player = i
|
||||
if(Player.mind && !isnewplayer(Player))
|
||||
if(isobserver(Player))
|
||||
num_ghosts++
|
||||
if(Player.stat != DEAD && !isbrain(Player))
|
||||
num_survivors++
|
||||
if(ishuman(Player))
|
||||
num_human_survivors++
|
||||
if(station_evacuated) //If the shuttle has already left the station
|
||||
var/list/area/shuttle_areas
|
||||
if(SSshuttle && SSshuttle.emergency)
|
||||
shuttle_areas = SSshuttle.emergency.shuttle_areas
|
||||
if(Player.onCentCom() || Player.onSyndieBase())
|
||||
num_escapees++
|
||||
if(ishuman(Player))
|
||||
num_human_escapees++
|
||||
if(shuttle_areas[get_area(Player)])
|
||||
num_shuttle_escapees++
|
||||
|
||||
.[POPCOUNT_SURVIVORS] = num_survivors
|
||||
.[POPCOUNT_ESCAPEES] = num_escapees
|
||||
.[POPCOUNT_SHUTTLE_ESCAPEES] = num_shuttle_escapees
|
||||
.[POPCOUNT_HUMAN_SURVIVORS] = num_human_survivors
|
||||
.[POPCOUNT_HUMAN_ESCAPEES] = num_human_escapees
|
||||
.[POPCOUNT_GHOSTS] = num_ghosts
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/survivor_report()
|
||||
var/list/parts = list()
|
||||
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
|
||||
var/popcount = count_survivors()
|
||||
|
||||
//Round statistics report
|
||||
var/datum/station_state/end_state = new /datum/station_state()
|
||||
end_state.count()
|
||||
@@ -203,9 +206,9 @@
|
||||
if(total_players)
|
||||
parts+= "[GLOB.TAB]Total Population: <B>[total_players]</B>"
|
||||
if(station_evacuated)
|
||||
parts += "<BR>[GLOB.TAB]Evacuation Rate: <B>[num_escapees] ([PERCENT(num_escapees/total_players)]%)</B>"
|
||||
parts += "[GLOB.TAB](on emergency shuttle): <B>[num_shuttle_escapees] ([PERCENT(num_shuttle_escapees/total_players)]%)</B>"
|
||||
parts += "[GLOB.TAB]Survival Rate: <B>[num_survivors] ([PERCENT(num_survivors/total_players)]%)</B>"
|
||||
parts += "<BR>[GLOB.TAB]Evacuation Rate: <B>[popcount[POPCOUNT_ESCAPEES]] ([PERCENT(popcount[POPCOUNT_ESCAPEES]/total_players)]%)</B>"
|
||||
parts += "[GLOB.TAB](on emergency shuttle): <B>[popcount[POPCOUNT_SHUTTLE_ESCAPEES]] ([PERCENT(popcount[POPCOUNT_SHUTTLE_ESCAPEES]/total_players)]%)</B>"
|
||||
parts += "[GLOB.TAB]Survival Rate: <B>[popcount[POPCOUNT_SURVIVORS]] ([PERCENT(popcount[POPCOUNT_SURVIVORS]/total_players)]%)</B>"
|
||||
return parts.Join("<br>")
|
||||
|
||||
/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report)
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
if(..())
|
||||
return
|
||||
var/mob/living/silicon/ai/AI = usr
|
||||
var/camera = input(AI, "Choose which camera you want to view", "Cameras") as null|anything in AI.get_camera_list()
|
||||
AI.ai_camera_list(camera)
|
||||
AI.show_camera_list()
|
||||
|
||||
/obj/screen/ai/camera_track
|
||||
name = "Track With Camera"
|
||||
|
||||
@@ -20,7 +20,7 @@ SUBSYSTEM_DEF(research)
|
||||
var/list/techweb_point_items = list() //path = value
|
||||
var/list/errored_datums = list()
|
||||
//----------------------------------------------
|
||||
var/single_server_income = 40.7
|
||||
var/single_server_income = 54.3
|
||||
var/multiserver_calculation = FALSE
|
||||
var/last_income = 0
|
||||
//^^^^^^^^ ALL OF THESE ARE PER SECOND! ^^^^^^^^
|
||||
|
||||
@@ -477,6 +477,8 @@
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/action/spell_action/spell
|
||||
|
||||
/datum/action/spell_action/spell/IsAvailable()
|
||||
if(!target)
|
||||
return FALSE
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/datum/component/forensics
|
||||
var/list/fingerprints //assoc print = print
|
||||
var/list/hiddenprints //assoc ckey = realname/gloves/ckey
|
||||
var/list/blood_DNA //assoc dna = bloodtype
|
||||
var/list/fibers //assoc print = print
|
||||
|
||||
/datum/component/forensics/InheritComponent(datum/component/forensics/F, original) //Use of | and |= being different here is INTENTIONAL.
|
||||
fingerprints = fingerprints | F.fingerprints
|
||||
hiddenprints = hiddenprints | F.hiddenprints
|
||||
blood_DNA = blood_DNA | F.blood_DNA
|
||||
fibers = fibers | F.fibers
|
||||
check_blood()
|
||||
return ..()
|
||||
|
||||
/datum/component/forensics/Initialize(new_fingerprints, new_hiddenprints, new_blood_DNA, new_fibers)
|
||||
if(!isatom(parent))
|
||||
. = COMPONENT_INCOMPATIBLE
|
||||
CRASH("Forensics datum applied incorrectly to non-atom of type [parent.type]!")
|
||||
fingerprints = new_fingerprints
|
||||
hiddenprints = new_hiddenprints
|
||||
blood_DNA = new_blood_DNA
|
||||
fibers = new_fibers
|
||||
check_blood()
|
||||
RegisterSignal(COMSIG_COMPONENT_CLEAN_ACT, .proc/clean_act)
|
||||
|
||||
/datum/component/forensics/proc/wipe_fingerprints()
|
||||
fingerprints = null
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/wipe_hiddenprints()
|
||||
return //no.
|
||||
|
||||
/datum/component/forensics/proc/wipe_blood_DNA()
|
||||
blood_DNA = null
|
||||
if(isitem(parent))
|
||||
qdel(parent.GetComponent(/datum/component/decal/blood))
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/wipe_fibers()
|
||||
fibers = null
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/clean_act(strength)
|
||||
if(strength >= CLEAN_STRENGTH_FINGERPRINTS)
|
||||
wipe_fingerprints()
|
||||
if(strength >= CLEAN_STRENGTH_BLOOD)
|
||||
wipe_blood_DNA()
|
||||
if(strength >= CLEAN_STRENGTH_FIBERS)
|
||||
wipe_fibers()
|
||||
|
||||
/datum/component/forensics/proc/add_fingerprint_list(list/_fingerprints) //list(text)
|
||||
if(!length(_fingerprints))
|
||||
return
|
||||
LAZYINITLIST(fingerprints)
|
||||
for(var/i in _fingerprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
||||
fingerprints[i] = i
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_fingerprint(mob/living/M, ignoregloves = FALSE)
|
||||
if(!M)
|
||||
return
|
||||
add_hiddenprint(M)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
add_fibers(H)
|
||||
if(H.gloves) //Check if the gloves (if any) hide fingerprints
|
||||
var/obj/item/clothing/gloves/G = H.gloves
|
||||
if(G.transfer_prints)
|
||||
ignoregloves = TRUE
|
||||
if(!ignoregloves)
|
||||
H.gloves.add_fingerprint(H, TRUE) //ignoregloves = 1 to avoid infinite loop.
|
||||
return
|
||||
var/full_print = md5(H.dna.uni_identity)
|
||||
LAZYSET(fingerprints, full_print, full_print)
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_fiber_list(list/_fibertext) //list(text)
|
||||
if(!length(_fibertext))
|
||||
return
|
||||
LAZYINITLIST(fibers)
|
||||
for(var/i in _fibertext) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
||||
fibers[i] = i
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_fibers(mob/living/carbon/human/M)
|
||||
var/fibertext
|
||||
var/item_multiplier = isitem(src)?1.2:1
|
||||
if(M.wear_suit)
|
||||
fibertext = "Material from \a [M.wear_suit]."
|
||||
if(prob(10*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
if(!(M.wear_suit.body_parts_covered & CHEST))
|
||||
if(M.w_uniform)
|
||||
fibertext = "Fibers from \a [M.w_uniform]."
|
||||
if(prob(12*item_multiplier) && !LAZYACCESS(fibers, fibertext)) //Wearing a suit means less of the uniform exposed.
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
if(!(M.wear_suit.body_parts_covered & HANDS))
|
||||
if(M.gloves)
|
||||
fibertext = "Material from a pair of [M.gloves.name]."
|
||||
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
else if(M.w_uniform)
|
||||
fibertext = "Fibers from \a [M.w_uniform]."
|
||||
if(prob(15*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
// "Added fibertext: [fibertext]"
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
if(M.gloves)
|
||||
fibertext = "Material from a pair of [M.gloves.name]."
|
||||
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
else if(M.gloves)
|
||||
fibertext = "Material from a pair of [M.gloves.name]."
|
||||
if(prob(20*item_multiplier) && !LAZYACCESS(fibers, fibertext))
|
||||
LAZYSET(fibers, fibertext, fibertext)
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_hiddenprint_list(list/_hiddenprints) //list(ckey = text)
|
||||
if(!length(_hiddenprints))
|
||||
return
|
||||
LAZYINITLIST(hiddenprints)
|
||||
for(var/i in _hiddenprints) //We use an associative list, make sure we don't just merge a non-associative list into ours.
|
||||
hiddenprints[i] = _hiddenprints[i]
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_hiddenprint(mob/living/M)
|
||||
if(!M || !M.key)
|
||||
return
|
||||
var/hasgloves = ""
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(H.gloves)
|
||||
hasgloves = "(gloves)"
|
||||
var/current_time = time_stamp()
|
||||
if(!LAZYACCESS(hiddenprints, M.key))
|
||||
LAZYSET(hiddenprints, M.key, "First: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]")
|
||||
else
|
||||
var/laststamppos = findtext(LAZYACCESS(hiddenprints, M.key), " Last: ")
|
||||
if(laststamppos)
|
||||
LAZYSET(hiddenprints, M.key, copytext(hiddenprints[M.key], 1, laststamppos))
|
||||
hiddenprints[M.key] += " Last: [M.real_name]\[[current_time]\][hasgloves]. Ckey: [M.ckey]" //made sure to be existing by if(!LAZYACCESS);else
|
||||
parent.fingerprintslast = M.ckey
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/add_blood_DNA(list/dna) //list(dna_enzymes = type)
|
||||
if(!length(dna))
|
||||
return
|
||||
LAZYINITLIST(blood_DNA)
|
||||
for(var/i in dna)
|
||||
blood_DNA[i] = dna[i]
|
||||
check_blood()
|
||||
return TRUE
|
||||
|
||||
/datum/component/forensics/proc/check_blood()
|
||||
if(!isitem(parent))
|
||||
return
|
||||
if(!length(blood_DNA))
|
||||
return
|
||||
parent.LoadComponent(/datum/component/decal/blood)
|
||||
@@ -62,6 +62,7 @@
|
||||
var/list/firealarms
|
||||
var/firedoors_last_closed_on = 0
|
||||
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
|
||||
var/list/canSmoothWithAreas //typecache to limit the areas that atoms in this area can smooth with
|
||||
|
||||
/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
|
||||
/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
|
||||
@@ -105,6 +106,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
uid = ++global_uid
|
||||
related = list(src)
|
||||
map_name = name // Save the initial (the name set in the map) name of the area.
|
||||
canSmoothWithAreas = typecacheof(canSmoothWithAreas)
|
||||
|
||||
if(requires_power)
|
||||
luminosity = 0
|
||||
|
||||
@@ -11,6 +11,11 @@
|
||||
valid_territory = FALSE
|
||||
icon_state = "shuttle"
|
||||
|
||||
/area/shuttle/Initialize()
|
||||
if(!canSmoothWithAreas)
|
||||
canSmoothWithAreas = type
|
||||
. = ..()
|
||||
|
||||
////////////////////////////Multi-area shuttles////////////////////////////
|
||||
|
||||
////////////////////////////Syndicate infiltrator////////////////////////////
|
||||
@@ -19,6 +24,7 @@
|
||||
name = "Syndicate Infiltrator"
|
||||
blob_allowed = FALSE
|
||||
ambientsounds = HIGHSEC
|
||||
canSmoothWithAreas = /area/shuttle/syndicate
|
||||
|
||||
/area/shuttle/syndicate/bridge
|
||||
name = "Syndicate Infiltrator Control"
|
||||
@@ -37,6 +43,18 @@
|
||||
/area/shuttle/syndicate/airlock
|
||||
name = "Syndicate Infiltrator Airlock"
|
||||
|
||||
////////////////////////////Pirate Shuttle////////////////////////////
|
||||
|
||||
/area/shuttle/pirate
|
||||
name = "Pirate Shuttle"
|
||||
blob_allowed = FALSE
|
||||
requires_power = TRUE
|
||||
canSmoothWithAreas = /area/shuttle/pirate
|
||||
|
||||
/area/shuttle/pirate/vault
|
||||
name = "Pirate Shuttle Vault"
|
||||
requires_power = FALSE
|
||||
|
||||
////////////////////////////Single-area shuttles////////////////////////////
|
||||
|
||||
/area/shuttle/transit
|
||||
@@ -114,12 +132,3 @@
|
||||
/area/shuttle/syndicate_scout
|
||||
name = "Syndicate Scout"
|
||||
blob_allowed = FALSE
|
||||
|
||||
/area/shuttle/pirate
|
||||
name = "Pirate Shuttle"
|
||||
blob_allowed = FALSE
|
||||
requires_power = TRUE
|
||||
|
||||
/area/shuttle/pirate/vault
|
||||
name = "Pirate Shuttle Vault"
|
||||
requires_power = FALSE
|
||||
@@ -14,7 +14,7 @@
|
||||
/obj/effect/clockwork/servant_blocker/CanPass(atom/movable/M, turf/target)
|
||||
var/list/target_contents = M.GetAllContents() + M
|
||||
for(var/mob/living/L in target_contents)
|
||||
if(is_servant_of_ratvar(L) && get_dir(M, src) != dir) //Unless we're on the side the arrow is pointing directly away from, no-go
|
||||
if(is_servant_of_ratvar(L) && get_dir(M, src) != dir && L.stat != DEAD) //Unless we're on the side the arrow is pointing directly away from, no-go
|
||||
to_chat(L, "<span class='danger'>The space beyond here can't be accessed by you or other servants.</span>")
|
||||
return
|
||||
return TRUE
|
||||
|
||||
@@ -20,7 +20,18 @@
|
||||
/mob/camera/eminence/Move(NewLoc, direct)
|
||||
var/OldLoc = loc
|
||||
if(NewLoc && !istype(NewLoc, /turf/open/indestructible/reebe_void))
|
||||
forceMove(get_turf(NewLoc))
|
||||
var/turf/T = get_turf(NewLoc)
|
||||
if(T.flags_1 & NOJAUNT_1)
|
||||
if(last_failed_turf != T)
|
||||
T.visible_message("<span class='warning'>[T] suddenly emits a ringing sound!</span>", ignore_mob = src)
|
||||
playsound(T, 'sound/machines/clockcult/ark_damage.ogg', 75, FALSE)
|
||||
last_failed_turf = T
|
||||
to_chat(src, "<span class='warning'>This turf is consecrated and can't be crossed!</span>")
|
||||
return
|
||||
if(!GLOB.ratvar_awakens && istype(get_area(T), /area/chapel))
|
||||
to_chat(src, "<span class='warning'>The Chapel is hallowed ground under a heretical deity, and can't be accessed!</span>")
|
||||
return
|
||||
forceMove(T)
|
||||
Moved(OldLoc, direct)
|
||||
if(GLOB.ratvar_awakens)
|
||||
for(var/turf/T in range(5, src))
|
||||
|
||||
@@ -576,8 +576,8 @@ Congratulations! You are now trained for invasive xenobiology research!"}
|
||||
flags_1 = DROPDEL_1
|
||||
|
||||
/obj/item/restraints/handcuffs/energy/used/dropped(mob/user)
|
||||
user.visible_message("<span class='danger'>[user]'s [src] break in a discharge of energy!</span>", \
|
||||
"<span class='userdanger'>[user]'s [src] break in a discharge of energy!</span>")
|
||||
user.visible_message("<span class='danger'>[user]'s [name] breaks in a discharge of energy!</span>", \
|
||||
"<span class='userdanger'>[user]'s [name] breaks in a discharge of energy!</span>")
|
||||
var/datum/effect_system/spark_spread/S = new
|
||||
S.set_up(4,0,user.loc)
|
||||
S.start()
|
||||
|
||||
@@ -57,19 +57,17 @@
|
||||
toggle_cam()
|
||||
|
||||
/obj/machinery/camera/Destroy()
|
||||
toggle_cam(null, 0) //kick anyone viewing out
|
||||
if(can_use())
|
||||
toggle_cam(null, 0) //kick anyone viewing out and remove from the camera chunks
|
||||
GLOB.cameranet.cameras -= src
|
||||
if(isarea(myarea))
|
||||
LAZYREMOVE(myarea.cameras, src)
|
||||
if(assembly)
|
||||
qdel(assembly)
|
||||
assembly = null
|
||||
QDEL_NULL(assembly)
|
||||
if(bug)
|
||||
bug.bugged_cameras -= src.c_tag
|
||||
if(bug.current == src)
|
||||
bug.current = null
|
||||
bug = null
|
||||
GLOB.cameranet.removeCamera(src) //Will handle removal from the camera network and the chunks, so we don't need to worry about that
|
||||
GLOB.cameranet.cameras -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/camera/emp_act(severity)
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/mob/living/silicon/ai/proc/get_camera_list()
|
||||
|
||||
track.cameras.Cut()
|
||||
|
||||
if(src.stat == DEAD)
|
||||
return
|
||||
|
||||
var/list/L = list()
|
||||
for (var/obj/machinery/camera/C in GLOB.cameranet.cameras)
|
||||
L.Add(C)
|
||||
@@ -18,25 +12,18 @@
|
||||
if (tempnetwork.len)
|
||||
T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
|
||||
|
||||
track.cameras = T
|
||||
return T
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/ai_camera_list(camera)
|
||||
if (!camera)
|
||||
return 0
|
||||
|
||||
var/obj/machinery/camera/C = track.cameras[camera]
|
||||
src.eyeobj.setLoc(C)
|
||||
|
||||
return
|
||||
/mob/living/silicon/ai/proc/show_camera_list()
|
||||
var/list/cameras = get_camera_list()
|
||||
var/camera = input(src, "Choose which camera you want to view", "Cameras") as null|anything in cameras
|
||||
switchCamera(cameras[camera])
|
||||
|
||||
/datum/trackable
|
||||
var/list/names = list()
|
||||
var/list/namecounts = list()
|
||||
var/list/humans = list()
|
||||
var/list/others = list()
|
||||
var/list/cameras = list()
|
||||
|
||||
/mob/living/silicon/ai/proc/trackable_mobs()
|
||||
|
||||
@@ -143,13 +130,9 @@
|
||||
/obj/machinery/camera/attack_ai(mob/living/silicon/ai/user)
|
||||
if (!istype(user))
|
||||
return
|
||||
if (!src.can_use())
|
||||
if (!can_use())
|
||||
return
|
||||
user.eyeobj.setLoc(get_turf(src))
|
||||
|
||||
|
||||
/mob/living/silicon/ai/attack_ai(mob/user)
|
||||
ai_camera_list()
|
||||
user.switchCamera(src)
|
||||
|
||||
/proc/camera_sort(list/L)
|
||||
var/obj/machinery/camera/a
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
/turf/closed/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && (mover.pass_flags & PASSCLOSEDTURF))
|
||||
return TRUE
|
||||
else
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/turf/closed/indestructible
|
||||
name = "wall"
|
||||
@@ -165,4 +164,4 @@
|
||||
name = "wall"
|
||||
desc = "A wall made out of a strange metal. The squares on it pulse in a predictable pattern."
|
||||
icon = 'icons/turf/walls/hierophant_wall.dmi'
|
||||
icon_state = "wall"
|
||||
icon_state = "wall"
|
||||
@@ -88,7 +88,7 @@
|
||||
/turf/open/indestructible/clock_spawn_room/proc/port_servants()
|
||||
. = FALSE
|
||||
for(var/mob/living/L in src)
|
||||
if(is_servant_of_ratvar(L))
|
||||
if(is_servant_of_ratvar(L) && L.stat != DEAD)
|
||||
. = TRUE
|
||||
L.forceMove(get_turf(pick(GLOB.servant_spawns)))
|
||||
visible_message("<span class='warning'>[L] vanishes in a flash of red!</span>")
|
||||
|
||||
@@ -452,11 +452,7 @@
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"co2_scrub" = 1,
|
||||
"tox_scrub" = 0,
|
||||
"n2o_scrub" = 0,
|
||||
"rare_scrub"= 0,
|
||||
"water_vapor_scrub"= 0,
|
||||
"set_filters" = list(/datum/gas/carbon_dioxide),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 0,
|
||||
))
|
||||
@@ -470,11 +466,18 @@
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"co2_scrub" = 1,
|
||||
"tox_scrub" = 1,
|
||||
"n2o_scrub" = 1,
|
||||
"rare_scrub"= 1,
|
||||
"water_vapor_scrub"= 1,
|
||||
"set_filters" = list(
|
||||
/datum/gas/carbon_dioxide,
|
||||
/datum/gas/plasma,
|
||||
/datum/gas/water_vapor,
|
||||
/datum/gas/hypernoblium,
|
||||
/datum/gas/nitrous_oxide,
|
||||
/datum/gas/nitryl,
|
||||
/datum/gas/tritium,
|
||||
/datum/gas/bz,
|
||||
/datum/gas/stimulum,
|
||||
/datum/gas/pluoxium
|
||||
),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 1,
|
||||
))
|
||||
@@ -501,11 +504,7 @@
|
||||
for(var/device_id in A.air_scrub_names)
|
||||
send_signal(device_id, list(
|
||||
"power" = 1,
|
||||
"co2_scrub" = 1,
|
||||
"tox_scrub" = 0,
|
||||
"n2o_scrub" = 0,
|
||||
"rare_scrub"= 0,
|
||||
"water_vapor_scrub"= 0,
|
||||
"set_filters" = list(/datum/gas/carbon_dioxide),
|
||||
"scrubbing" = 1,
|
||||
"widenet" = 0,
|
||||
))
|
||||
|
||||
@@ -242,6 +242,11 @@
|
||||
if("toggle_filter" in signal.data)
|
||||
filter_types ^= gas_id2path(signal.data["toggle_filter"])
|
||||
|
||||
if("set_filters" in signal.data)
|
||||
filter_types = list()
|
||||
for(var/gas in signal.data["set_filters"])
|
||||
filter_types += gas_id2path(gas)
|
||||
|
||||
if("init" in signal.data)
|
||||
name = signal.data["init"]
|
||||
return
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
flags_2 = SLOWS_WHILE_IN_HAND_2
|
||||
var/team = WHITE_TEAM
|
||||
var/reset_cooldown = 0
|
||||
var/anyonecanpickup = TRUE
|
||||
var/obj/effect/ctf/flag_reset/reset
|
||||
var/reset_path = /obj/effect/ctf/flag_reset
|
||||
|
||||
@@ -48,7 +49,7 @@
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
/obj/item/twohanded/ctf/attack_hand(mob/living/user)
|
||||
if(!is_ctf_target(user))
|
||||
if(!is_ctf_target(user) && !anyonecanpickup)
|
||||
to_chat(user, "Non players shouldn't be moving the flag!")
|
||||
return
|
||||
if(team in user.faction)
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
freeze_projectile(A)
|
||||
else
|
||||
return FALSE
|
||||
|
||||
into_the_negative_zone(A)
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_all()
|
||||
@@ -106,6 +109,7 @@
|
||||
return ..()
|
||||
|
||||
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_projectile(obj/item/projectile/P)
|
||||
escape_the_negative_zone(P)
|
||||
frozen_projectiles -= P
|
||||
P.paused = FALSE
|
||||
|
||||
@@ -123,9 +127,18 @@
|
||||
H.LoseTarget()
|
||||
|
||||
/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L)
|
||||
escape_the_negative_zone(L)
|
||||
L.AdjustStun(-20, 1, 1)
|
||||
L.anchored = frozen_mobs[L]
|
||||
frozen_mobs -= L
|
||||
if(ishostile(L))
|
||||
var/mob/living/simple_animal/hostile/H = L
|
||||
H.toggle_ai(initial(H.AIStatus))
|
||||
|
||||
//you don't look quite right, is something the matter?
|
||||
/datum/proximity_monitor/advanced/timestop/proc/into_the_negative_zone(atom/A)
|
||||
A.add_atom_colour(list(-1,0,0,0, 0,-1,0,0, 0,0,-1,0, 0,0,0,1, 1,1,1,0), TEMPORARY_COLOUR_PRIORITY)
|
||||
|
||||
//let's put some colour back into your cheeks
|
||||
/datum/proximity_monitor/advanced/timestop/proc/escape_the_negative_zone(atom/A)
|
||||
A.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY)
|
||||
@@ -641,7 +641,11 @@ $(function() {
|
||||
opts.updatedVolume = newVolume;
|
||||
sendVolumeUpdate();
|
||||
internalOutput('<span class="internal boldnshit">Loaded music volume of: '+savedConfig.smusicVolume+'</span>', 'internal');
|
||||
}
|
||||
}
|
||||
else{
|
||||
$('#adminMusic').prop('volume', opts.defaultMusicVolume / 100);
|
||||
}
|
||||
|
||||
if (savedConfig.smessagecombining) {
|
||||
if (savedConfig.smessagecombining == 'false') {
|
||||
opts.messageCombining = false;
|
||||
@@ -649,9 +653,7 @@ $(function() {
|
||||
opts.messageCombining = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$('#adminMusic').prop('volume', opts.defaultMusicVolume / 100);
|
||||
}
|
||||
|
||||
|
||||
(function() {
|
||||
var dataCookie = getCookie('connData');
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
genes = list(/datum/plant_gene/trait/repeated_harvest)
|
||||
mutatelist = list(/obj/item/seeds/apple/gold)
|
||||
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
|
||||
juice_results = list("applejuice" = 0)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/apple
|
||||
seed = /obj/item/seeds/apple
|
||||
@@ -25,6 +24,7 @@
|
||||
filling_color = "#FF4500"
|
||||
bitesize = 100 // Always eat the apple in one bite
|
||||
foodtype = FRUIT
|
||||
juice_results = list("applejuice" = 0)
|
||||
|
||||
// Posioned Apple
|
||||
/obj/item/seeds/apple/poisoned
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
genes = list(/datum/plant_gene/trait/slip, /datum/plant_gene/trait/repeated_harvest)
|
||||
mutatelist = list(/obj/item/seeds/banana/mime, /obj/item/seeds/banana/bluespace)
|
||||
reagents_add = list("banana" = 0.1, "potassium" = 0.1, "vitamin" = 0.04, "nutriment" = 0.02)
|
||||
juice_results = list("banana" = 0)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/banana
|
||||
seed = /obj/item/seeds/banana
|
||||
@@ -25,6 +24,7 @@
|
||||
filling_color = "#FFFF00"
|
||||
bitesize = 5
|
||||
foodtype = FRUIT
|
||||
juice_results = list("banana" = 0)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user)
|
||||
user.visible_message("<span class='suicide'>[user] is aiming [src] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
genes = list(/datum/plant_gene/trait/battery)
|
||||
mutatelist = list(/obj/item/seeds/potato/sweet)
|
||||
reagents_add = list("vitamin" = 0.04, "nutriment" = 0.1)
|
||||
juice_results = list("potato" = 0)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/potato
|
||||
seed = /obj/item/seeds/potato
|
||||
@@ -27,6 +26,7 @@
|
||||
filling_color = "#E9967A"
|
||||
bitesize = 100
|
||||
foodtype = VEGETABLES
|
||||
juice_results = list("potato" = 0)
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/potato/wedges
|
||||
|
||||
@@ -12,7 +12,7 @@ Doesn't work on other aliens/AI.*/
|
||||
var/plasma_cost = 0
|
||||
var/check_turf = FALSE
|
||||
has_action = TRUE
|
||||
datum/action/spell_action/alien/action
|
||||
base_action = /datum/action/spell_action/alien
|
||||
action_icon = 'icons/mob/actions/actions_xeno.dmi'
|
||||
action_icon_state = "spell_default"
|
||||
action_background_icon_state = "bg_alien"
|
||||
|
||||
@@ -430,20 +430,17 @@
|
||||
|
||||
|
||||
/mob/living/silicon/ai/proc/switchCamera(obj/machinery/camera/C)
|
||||
if(QDELETED(C))
|
||||
return FALSE
|
||||
|
||||
if(!tracking)
|
||||
cameraFollow = null
|
||||
|
||||
if (!C)
|
||||
return FALSE
|
||||
|
||||
if(!src.eyeobj)
|
||||
if(QDELETED(eyeobj))
|
||||
view_core()
|
||||
return
|
||||
// ok, we're alive, camera is good and in our network...
|
||||
eyeobj.setLoc(get_turf(C))
|
||||
//machine = src
|
||||
|
||||
return TRUE
|
||||
|
||||
/mob/living/silicon/ai/proc/botcall()
|
||||
|
||||
@@ -80,8 +80,7 @@ GLOBAL_DATUM_INIT(cameranet, /datum/cameranet, new)
|
||||
// Removes a camera from a chunk.
|
||||
|
||||
/datum/cameranet/proc/removeCamera(obj/machinery/camera/c)
|
||||
if(c.can_use())
|
||||
majorChunkChange(c, 0)
|
||||
majorChunkChange(c, 0)
|
||||
|
||||
// Add a camera to a chunk.
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
return
|
||||
orbiter.loc = targetloc
|
||||
orbiter.update_parallax_contents()
|
||||
orbiter.update_light()
|
||||
lastloc = orbiter.loc
|
||||
for(var/other_orbit in orbiter.orbiters)
|
||||
var/datum/orbit/OO = other_orbit
|
||||
@@ -119,4 +120,4 @@
|
||||
var/datum/orbit/O = thing
|
||||
if(O.orbiter && isobserver(O.orbiter))
|
||||
var/mob/dead/observer/D = O.orbiter
|
||||
D.ManualFollow(target)
|
||||
D.ManualFollow(target)
|
||||
|
||||
@@ -51,9 +51,9 @@ All effects don't start immediately, but rather get worse over time; the rate is
|
||||
if(reac_volume >= 5)
|
||||
var/obj/item/book/affectedbook = O
|
||||
affectedbook.dat = null
|
||||
to_chat(usr, "<span class='notice'>Through thorough application, you wash away [affectedbook]'s writing.</span>")
|
||||
O.visible_message("<span class='notice'>[O]'s writing is washed away by [name]!</span>")
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>The ink smears, but doesn't wash away!</span>")
|
||||
O.visible_message("<span class='warning'>[O]'s ink is smeared by [name], but doesn't wash away!</span>")
|
||||
return
|
||||
|
||||
/datum/reagent/consumable/ethanol/reaction_mob(mob/living/M, method=TOUCH, reac_volume)//Splashing people with ethanol isn't quite as good as fuel.
|
||||
|
||||
@@ -13,11 +13,12 @@
|
||||
var/action_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
var/action_icon_state = "spell_default"
|
||||
var/action_background_icon_state = "bg_spell"
|
||||
var/base_action = /datum/action/spell_action
|
||||
|
||||
/obj/effect/proc_holder/Initialize()
|
||||
. = ..()
|
||||
if(has_action)
|
||||
action = new(src)
|
||||
action = new base_action(src)
|
||||
|
||||
/obj/effect/proc_holder/proc/on_gain(mob/living/user)
|
||||
return
|
||||
@@ -103,6 +104,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
pass_flags = PASSTABLE
|
||||
density = FALSE
|
||||
opacity = 0
|
||||
base_action = /datum/action/spell_action/spell
|
||||
|
||||
var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
|
||||
|
||||
@@ -149,7 +151,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
action_icon = 'icons/mob/actions/actions_spells.dmi'
|
||||
action_icon_state = "spell_default"
|
||||
action_background_icon_state = "bg_spell"
|
||||
datum/action/spell_action/spell/action
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
|
||||
|
||||
@@ -255,7 +256,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
|
||||
/obj/effect/proc_holder/spell/Initialize()
|
||||
. = ..()
|
||||
action = new(src)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
still_recharging_msg = "<span class='notice'>[name] is still recharging.</span>"
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
charge_counter = 0
|
||||
stoplag(1)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/can_cast(mob/user = usr)
|
||||
if(attached_hand)
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/touch/proc/ChargeHand(mob/living/carbon/user)
|
||||
attached_hand = new hand_path(src)
|
||||
if(!user.put_in_hands(attached_hand))
|
||||
|
||||
Reference in New Issue
Block a user